OpenGL ES 是Android绘图API,但OpenGL ES是平台通用的,在特定设备上使用需要一个中间层做适配,这个中间层就是EGL。
EGL架构
- EGLDisplay 是对实际显示设备的抽象。
- EGLSurface 是对用来存储图像的内存区域 FrameBuffer 的抽象,包括 Color Buffer, Stencil Buffer ,Depth Buffer。
- EGLContext 存储 OpenGL ES绘图的一些状态信息。
创建流程
第一步通常就获取默认的显示设备 EGL_DEFAULT_DISPLAY。
比较复杂的是选择合适的配置项,平台会提供多种预置模式供选择。
- 要先通过 eglGetConfig 获取平台所支持的 config 列表,
- 然后逐个调用 eglGetConfigAttrib 获取详细的属性配置,筛选到自己需要的配置,
- 最后调用eglChooseConfig 选定配置项。
然后就按顺序创建 context 和 surface 就好了,最后切换到当前环境。至此EGL环境就创建成功了,然后就可以进行opengl操作。
注意
因为在创建 eglSurface 的时候,一般会选择BACK_BUFFER,也就是双缓冲机制,所以,在每帧绘制完成以后,一般还需要 eglSwapBuffers 才能上屏显示。
另外还有一种离屏显示的,用 eglCreatePbufferSurface 创建,在多线程渲染的应用中会用到。因为 NativeWindow 只能链接一个 surface,所以除了最终上屏的那个线程以外,其他线程应绑定 PbufferSurface 。
在Android平台上,有时候还需要设置一下native window属性,否则可能会出现横竖方向错误问题。调用接口如下:
/*
* Change the format and size of the window buffers.
*
* The width and height control the number of pixels in the buffers, not the
* dimensions of the window on screen. If these are different than the
* window's physical size, then it buffer will be scaled to match that size
* when compositing it to the screen.
*
* For all of these parameters, if 0 is supplied then the window's base
* value will come back in force.
*
* width and height must be either both zero or both non-zero.
*
*/
int32_t ANativeWindow_setBuffersGeometry(ANativeWindow* window,
int32_t width, int32_t height, int32_t format);
下面是一段比较完整的创建代码:
bool initialize(ANativeWindow *_window) {
EGLConfig config;
EGLint maxConfig;
EGLint format;
EGLint width;
EGLint height;
EGLint major;
EGLint minor;
EGLBoolean result;
m_display = eglGetDispl