Articles of surfaceview

最小化Android GLSurfaceView滞后

关于Stack Overflow的一些其他问题,我已经从这里阅读了Android Surfaces,SurfaceViews等内部指南: https://source.android.com/devices/graphics/architecture.html 该指南让我对Android上所有不同部分的组合方式有了更好的理解。 它介绍了eglSwapBuffers如何将渲染帧推送到队列中,该队列在准备下一帧进行显示时将由SurfaceFlinger使用。 如果队列已满,那么它将等到缓冲区在返回之前可用于下一帧。 上面的文档将其描述为“填充队列”并依赖交换缓冲区的“反压”来限制渲染到显示的vsync。 这是使用GLSurfaceView的默认连续渲染模式发生的情况。 如果渲染很简单并且在比帧周期少得多的情况下完成,那么这是由BufferQueue引起的额外延迟,因为SwapBuffers上的等待直到队列满了才会发生,因此我们’重新渲染始终位于队列的后面,因此不会立即显示在下一个vsync上,因为队列中可能存在缓冲区。 相比之下,按需渲染通常比显示更新速率发生的频率低得多,因此这些视图的BufferQueues通常为空,因此推送到这些队列的任何更新都将被SurfaceFlinger在下一个vsync上抓取。 所以问题在于:如何设置连续渲染器,但延迟最小? 目标是每个vsync开始时缓冲区队列为空,我在16ms内渲染我的内容,将其推送到队列(缓冲区计数= 1),然后SurfaceFlinger将其用于下一个vsync(缓冲区计数) = 0),重复一遍。 队列中的缓冲区数量可以在systrace中看到,因此目标是使此替换在0和1之间。 我上面提到的文档介绍了Choreographer作为在每个vsync上获得回调的方法。 但是我不相信这足以让我能够实现我追求的最小滞后行为。 我已经测试了在vsync回调上使用非常小的onDrawFrame()执行requestRender(),它确实展示了0/1缓冲区计数行为。 但是,如果SurfaceFlinger无法在一个帧周期内完成所有工作(可能是通知popup或其他),该怎么办? 在这种情况下,我希望我的渲染器很乐意为每个vsync生成1帧,但该BufferQueue的消费者端已经丢弃了一帧。 结果:我们现在在队列中交替使用1到2个缓冲区,并且我们在渲染和查看帧之间获得了一段滞后。 该文档似乎建议查看报告的vsync时间与回调运行时间之间的时间偏差。 我可以看到,如果你的回调是由于你的主线程由于布局传递或其他东西而延迟传递的话会有什么帮助。 但是我认为这不会允许检测到SurfaceFlinger跳过节拍而不能消耗帧。 应用程序是否有任何方法可以解决SurfaceFlinger丢帧的问题? 似乎无法告诉队列的长度打破了使用vsync时间进行游戏状态更新的想法,因为在实际显示渲染的帧之前,队列中存在未知数量的帧。 减少队列的最大长度并依赖背压将是实现这一目标的一种方法,但我不认为有一个API来设置GLSurfaceView BufferQueue中的最大缓冲区数量?

Android:如何在曲面视图中添加按钮

我正在绘制一些图形,我想添加几个按钮。 但是使用表面视图,我们如何以编程方式添加这些按钮?

BufferQueue被放弃后我该怎么办?

我正在使用纹理视图在我的Android应用程序中显示相机的预览。 然而,我注意到,每次我的应用程序暂停时,我都会收到此错误: 03-18 18:23:44.315: W/BufferQueue(19582): [unnamed-19582-20] cancelBuffer: BufferQueue has been abandoned! 有人能告诉我这里发生了什么吗? 当我的应用程序暂停时,我所做的就是从onSurfaceTextureDestroyed()所有这样的内容 public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) { mCamera.setPreviewCallback(null); mCamera.stopPreview(); mCamera.release(); return true; }

Surfaceview和TextureView有什么区别?

我一直在研究Android特别是View系统。 我有一个问题,但我母语中没有文件或参考文献。 所以我想知道你们。

将相机预览适合大于显示器的SurfaceView

我有一个Android应用程序需要全屏显示相机预览,无论getSupportedPreviewSizes()给出的预览大小没有失真。 我希望这会在高度或宽度上裁剪一些预览,但这并不关心我。 我之所以这样做是因为某些安卓摄像头(例如三星Galaxy SII前置摄像头)不会返回任何与显示器具有相同宽高比的预览,因此需要进行拉伸和剪裁。 是否可以将相机预览完全增加到大于显示尺寸的视图? 通过简单地将曲面视图的布局参数设置为match_parent,可以使SurfaceView大于返回的预览像素尺寸,但这会导致某些方向的失真,并且只有在预览填充显示之前才可能。 这似乎表明在显示器外部进行预览是不可能的,并且硬件(或OS)限制了这种行为。 关于这个主题还有另一个问题 ,但是这个问题声称不可能创建大于屏幕尺寸的SurfaceView,这是错误的,正如我在日志记录中发现的那样。 然而,似乎情况是摄像机预览无法增长到巨大的SurfaceView的全尺寸。 我的尝试: 我有一个相对布局,在它内部是一个FrameLayout,在其中我创建了一个SurfaceView。 整个相对布局的宽度设置在635dp以下,这是设备屏幕尺寸的两倍。 FrameLayout匹配此大小调整,SurfaceView也是如此(稍后以编程方式添加) 以下是获取和设置预览大小的代码。 在这里,我想让相机预览展开以填充整个FrameLayout(屏幕宽度的两倍)。 视图完全正常显示和破坏,因此我删除与此特定问题无关的代码,因为它分散了基本问题,并且我尝试轻松简单地将视图扩展为大于显示大小的视图。 public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback { … public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { Camera.Parameters parameters = mCamera.getParameters(); final DisplayMetrics dm = this.getResources().getDisplayMetrics(); //getBestPreviewSize returns the best preview size, don’t worry //but […]

Android截图表面视图显示黑屏

我试图通过代码获取我的游戏截图并通过意图分享。 我可以做这些事情,但屏幕截图总是显示为黑色。 以下是与共享屏幕截图相关的代码: View view = MainActivity.getView(); view.setDrawingCacheEnabled(true); Bitmap screen = Bitmap.createBitmap(view.getDrawingCache(true)); .. save Bitmap 这是在MainActivity中: view = new GameView(this); view.setLayoutParams(new RelativeLayout.LayoutParams( RelativeLayout.LayoutParams.FILL_PARENT, RelativeLayout.LayoutParams.FILL_PARENT)); public static SurfaceView getView() { return view; } 而观点本身: public class GameView extends SurfaceView implements SurfaceHolder.Callback { private static SurfaceHolder surfaceHolder; …etc 这就是我绘制一切的方式: Canvas canvas = surfaceHolder.lockCanvas(null); if (canvas != null) […]

Android相机无法使用。 startPreview失败

我从LogCat收到这些错误: 10-30 00:31:51.494: D/CameraHal(1205): CameraHal setOverlay/1/00000000/00000000 10-30 00:31:51.494: E/CameraHal(1205): Trying to set overlay, but overlay is null!, line:3472 10-30 00:31:51.494: W/CameraService(1205): Overlay create failed – retrying … 10-30 00:31:52.526: E/CameraService(1205): Overlay Creation Failed! … 10-30 00:31:52.588: E/AndroidRuntime(5040): FATAL EXCEPTION: main 10-30 00:31:52.588: E/AndroidRuntime(5040): java.lang.RuntimeException: startPreview failed 10-30 00:31:52.588: E/AndroidRuntime(5040): at android.hardware.Camera.startPreview(Native Method) 10-30 00:31:52.588: E/AndroidRuntime(5040): […]

尽管在任何地方使用RGBA_8888,但颜色条带和渐变的人工制品

我知道色带是一个问题的老板栗,之前已经讨论了很多次提供了各种解决方案(基本上可以归结为使用32位,或者使用抖动)。 事实上不久前我问过并随后回答了我自己的问题 。 那时候,我认为我在这个问题的答案中提出的解决方案(将setFormat(PixelFormat.RGBA_8888)应用于Window并在SurfaceView的情况下应用于Holder )解决了我的应用程序中的问题好。 至少解决方案使得渐变在我当时开发的设备上看起来非常好(很可能是Android 2.2)。 我现在正在使用HTC One X(Android 4.0)和Asus Nexus 7(Android 4.1)进行开发。 我尝试做的是在SurfaceView的整个区域应用灰色渐变。 虽然我认为确保包含Window和Holder配置为32位颜色,但我得到了可怕的绑定伪像。 事实上,在Nexus 7上, 我甚至看到了文物的移动 。 这不仅出现在当然连续绘制的SurfaceView上,而且还出现在我添加的普通View ,以便为测试目的绘制完全相同的渐变,这将绘制一次。 这些工件的存在方式当然看起来非常糟糕, 实际上就像观看信号较差的模拟电视一样 。 View和SurfaceView展示了完全相同的工件,它们一起移动。 我的目的是在整个过程中使用32位,而不是使用抖动。 我的印象是,在Android 4.0之前, Window默认为32位。 通过在SurfaceView应用RGBA_8888 ,我希望所有内容都是32位,从而避免任何瑕疵。 我注意到在SO上还有其他一些问题,人们已经观察到RGBA_8888在4.0 / 4.1平台上似乎不再有效。 这是我的Nexus 7的屏幕截图,顶部是普通View ,下面是SurfaceView ,两者都将相同的渐变应用于Canvas 。 当然,它不会像在显示屏上那样显示工件,因此显示此屏幕抓取可能毫无意义。 我想强调的是,在Nexus的屏幕上,条带真的看起来很糟糕。 编辑:事实上,截图实际上根本没有显示工件。 我在Nexus 7上看到的文物不是均匀的条带; 它本质上看起来随意。 用于创建上述测试的Activity : import android.app.Activity; import android.content.Context; import android.graphics.Canvas; import […]

BUG:createWindowSurface失败了EGL_BAD_ALLOC

我在Google Play上有一个应用程序,用于倒计时数字和字母。 在这个应用程序中,我有以下活动: google sigin archivements 服务 我使用Google Analytics和ACRA进行错误报告。 我不使用GLsurfaceView,但我每天使用一次或两次ACRA,这给了我这些错误: java.lang.RuntimeException: createWindowSurface failed EGL_BAD_ALLOC at android.view.HardwareRenderer$GlRenderer.createSurface(HardwareRenderer.java:763) at android.view.HardwareRenderer$GlRenderer.createEglSurface(HardwareRenderer.java:663) at android.view.HardwareRenderer$GlRenderer.initialize(HardwareRenderer.java:502) at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1325) at android.view.ViewRootImpl.handleMessage(ViewRootImpl.java:2467) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loop(Looper.java:137) at android.app.ActivityThread.main(ActivityThread.java:4424) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:511) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551) at dalvik.system.NativeStart.main(Native Method) 有谁知道发生了什么? 我不使用surfaceView; 谁能帮我?

重新启动/暂停onResume / onPause中的线程

我有一个使用SurfaceView实现来显示对象的游戏。 我有一个线程绘制SurfaceView时间到屏幕。 游戏正在运行。 不幸的是,每当游戏中断时,都需要暂停function。 那么,我知道我需要操纵onResume和onPause 。 但是我不明白。 这个错误指出我已经回到了surfaceCreated ,在那里我开始线程告诉我线程已经启动了。 我尝试使用resume并suspend在onResume和onPause但没有任何改变。 我怎样才能做到这一点? 我已经完成了如何使用File-I / O处理来保存对象的位置。 提前致谢。