EGLSurface 和 OpenGL ES

Android 使用 OpenGL ES (GLES) API 渲染图形。为了创建 GLES 上下文并为 GLES 渲染提供窗口系统,Android 使用 EGL 库。GLES 调用渲染纹理多边形,而 EGL 调用将渲染结果放到屏幕上。

在使用 GLES 绘图之前,您需要创建一个 GL 上下文。在 EGL 中,这意味着创建 EGLContext 和 EGLSurface。GLES 操作应用于当前上下文,该上下文通过线程局部存储访问,而不是作为参数传递。渲染代码应在当前的 GLES 线程上执行,而不是在 UI 线程上执行。

EGLSurface

EGLSurface 可以是由 EGL 分配的屏幕外缓冲区(称为 pbuffer),也可以是由操作系统分配的窗口。调用 eglCreateWindowSurface() 函数会创建 EGL 窗口 surface。eglCreateWindowSurface() 接受一个窗口对象作为参数,在 Android 上,该对象是一个 surface。Surface 是 BufferQueue 的生产者端。消费者(即 SurfaceView、SurfaceTexture、TextureView 或 ImageReader)会创建 surface。当您调用 eglCreateWindowSurface() 时,EGL 会创建一个新的 EGLSurface 对象,并将其连接到窗口对象的 BufferQueue 的生产者接口。从那时起,渲染到该 EGLSurface 将导致缓冲区被出队、渲染到其中,并排队以供消费者使用。

EGL 不提供锁定/解锁调用。发出绘制命令,然后调用 eglSwapBuffers() 以提交当前帧。该方法名称来自传统的前后缓冲区交换,但实际实现可能有所不同。

一次只能将一个 EGLSurface 与一个 surface 相关联(您只能有一个生产者连接到 BufferQueue),但是如果您销毁 EGLSurface,它将与 BufferQueue 断开连接,并允许其他内容连接。

给定的线程可以通过更改当前内容在多个 EGLSurface 之间切换。一个 EGLSurface 一次只能在一个线程上处于当前状态。

EGL 不是 surface 的另一个方面(如 SurfaceHolder)。EGLSurface 是一个相关但独立的概念。您可以在没有 surface 支持的 EGLSurface 上绘制,也可以在不使用 EGL 的情况下使用 surface。EGLSurface 只是为 GLES 提供了一个绘制位置。

有关 OpenGL ES 和 EGL 要求,请参阅 Android 兼容性定义文档。

ANativeWindow

公共 surface 类是在 Java 编程语言中实现的。C/C++ 中的等效类是 ANativeWindow 类,它由 Android NDK 半公开。您可以使用 ANativeWindow_fromSurface() 调用从 surface 获取 ANativeWindow。就像它的 Java 语言表亲一样,您可以锁定它、在软件中渲染以及解锁并发布。基本的原生窗口类型是 BufferQueue 的生产者端。

要从原生代码创建 EGL 窗口图面,请将 EGLNativeWindowType 的实例传递给 eglCreateWindowSurface()。EGLNativeWindowType 是 ANativeWindow 的同义词,因此您可以将一个强制转换为另一个。