28

我对 EGL 感到困惑。

我的 GLSurfaceView 创建了一个 EGLContext。现在我创建一个共享上下文。现在我需要使用 EGLExtension。

我必须使用的方法称为(> = API18):

EGLExt.eglPresentationTimeANDROID(android.opengl.EGLDisplay display, android.opengl.EGLSurface surface, long time);

问题是, GLSurfaceView 只创建 javax.microedition.khronos.egl.EGLContext s。

这告诉我,不要使用 GLSurfaceView。所以我尝试了 TextureView,它有点相似,不同的是你必须处理你自己的 EGL 东西。这对这个目的有好处。

但是:TextureView 比较慢,至少看起来是这样的,所以我用 Method Profiler 记录了一些图表:

这里是带有自己的 EGL 处理的 TextureView: 在此处输入图像描述 顶部的 Thread 是一个时钟,用于唤醒中间的 Thread,它会渲染到 TextureView 上。之后将调用主线程,用于重绘 TextureView。

...这里是带有自己的EGL处理的GLSurfaceView 这次时钟在中间,它调用顶部的线程将我的图像渲染到帧缓冲区中,我将其直接提供给SurfaceView(RENDERMODE_WHEN_DIRTY)并调用requestRender请求要渲染的视图。 在此处输入图像描述

正如您已经看到的那样,使用 GLSurfaceView 看起来比使用 TextureView 更干净。

在这两个示例中,我在屏幕上没有任何其他内容,它们使用相同的着色器渲染完全相同的网格。

我的问题:有没有办法将 GLSurfaceView 与 EGL14 上下文一起使用?

我做错什么了吗?

4

2 回答 2

50

您可能想要做的是使用普通的SurfaceView

这是简短的版本:

  • SurfaceView有两个部分,Surface和 中的一些假东西ViewSurface直接传递给表面合成器(SurfaceFlinger),因此当您使用 OpenGL 在其上绘制时,开销相对较小。这使它很快,但它也使它不能很好地与 View 层次结构配合,因为Surface它在一个层上,而基于 View 的 UI 在不同的层上。
  • TextureView也有两个部分,但你画的部分生活在幕后(这就是SurfaceTexture进来的地方)。帧完成后,您绘制的内容会被粘贴到视图层上。GPU 可以快速做到这一点,但“一些工作”总是比“没有工作”慢。
  • GLSurfaceViewSurfaceView一个包装类,它为您完成所有 EGL 设置和线程间消息传递。

编辑:长版本可在此处获得。

如果你可以自己进行 GL/EGL 设置和线程管理——如果你现在在 TextureView 上运行,你显然可以——那么你应该使用普通的SurfaceView.

说了这么多,应该可以使您的原始代码与GLSurfaceView. 我希望您希望调用eglPresentationTimeANDROID()与 共享的 EGL 上下文,GLSurfaceView而不是从其内部调用,因此在内部使用 EGL10GLSurfaceView并不重要。GLSurfaceView共享上下文重要的是上下文客户端版本(例如 GLES2 与 GLES3),而不是用于配置上下文的 EGL 接口版本。

您可以在Grafika中看到所有这些工作的示例。尤其:

  • “显示 + 捕获相机”使用GLSurfaceView、 相机和视频编码器。请注意,EGL 上下文是共享的。该示例令人费解且有些痛苦,主要是因为它故意尝试使用GLSurfaceView和共享 EGL 上下文。(更新:注意这个关于共享上下文的竞争条件的问题。)
  • “播放视频(TextureView)”和“TextureView 中的基本 GL”展示TextureView了实际效果。
  • “使用 FBO 记录 GL 应用程序”使用普通的SurfaceView.
于 2014-01-24T01:14:18.203 回答
9

感谢法登!它按预期工作。

对于所有想做类似事情的人:

使用 (GL)SurfaceView 在其上渲染图像具有优点和缺点。

我在上面帖子中的测试结果除了渲染图像本身之外,屏幕上没有其他任何内容。如果您在屏幕上有其他 UI 元素,尤其是如果它们经常更新,您应该重新考虑我更喜欢 (GL)SurfaceView 的选择。

SurfaceView 在 Android Windowsystem 中创建一个新窗口。它的优点是,如果 SurfaceView 被刷新,只有这个窗口会被刷新。如果您另外更新 UI 元素(在窗口系统的另一个窗口中),那么两个刷新操作都会阻止自己(尤其是当 ui 绘图是硬件支持时),因为 opengl 无法正确处理多线程绘图。

对于这种情况,最好使用 TextureView,因为它不是 Android Windowsystem 的另一个窗口。所以如果你刷新你的视图,所有的 UI 元素也会被刷新。(可能)一个线程中的所有内容。

希望我能帮助你们中的一些人!

于 2014-05-06T12:36:06.453 回答