【OpenGL ES】EGL
OpenGL、OpenGL ES、EGL
OpenGL:”OpenGL 是图形硬件的一种软件接口???“。OpenGL 是一套定义计算机图形操作的 API,和一般代码编写时使用的 API 不同的是,OpenGL API 只定义规范而不实现,实现交由支持 OpenGL 的具体的平台去实现,所以说 OpenGL 是一种跨语言、跨平台的 API。
OpenGL ES:OpenGL 的删减版本,用于手机等嵌入设备。
EGL :OpenGL 的跨平台,意味着它不会直接与平台的窗口系统交互,所以需要一个中间层进行适配。OpenGL(ES) 在 android 系统上的适配层就是 EGL,EGL 为 OpenGL 提供了操作窗口的上下文、进行窗口配置等功能。
EGL 参与绘图流程
图为 OpenGL ES 的整个绘制流程,其中 draw 是通过 OpenGL ES API 进行绘制, 其他流程则通过 EGL 接口完成。简单地说,就是通过 EGL 创建 OpenGL 绘制所需的环境,然后就可以通过 OpenGL 进行绘制了。
eglGetDisplay & eglInitialize
首先通过 eglGetDisplay(int display_id)
获取一个 EGLDisplay 对象。函数输入一个显示设备的 ID,一般情况下使用EGL14.EGL_DEFAULT_DISPLAY
(多显示屏怎么获得多个 displayId ?)。函数返回一个 EGLDisplay 对象,EGLDisplay 是显示系统的抽象。
得到 EGLDisplay 对象后,使用eglInitialize(EGLDisplay dpy,int[] major, int majorOffset, int[] minor, int minorOffset)
对 EGL 进行初始化,初始化成功意味着 EGL 可以使用必要的系统资源。输入的两个数组用于存放 EGL 的主版本号和次版本号。
其他相关函数
eglTerminate(EGLDisplay display)
,使 EGL 无效(即不再可以使用系统的资源以及对已分配的资源引用无效)。eglReleaseThread()
,使 EGL 释放分配给当前线程的所有资源。
eglChooseConfig & eglCreateWindowSurface
在进行 EGL 初始化之后,需要再选择合适的配置渲染表面,OpenGL 将在渲染表面进行绘制,这是一个”当屏渲染“ (显示在屏幕上)的 surface,此外还有”离屏渲染“ 的 surface。
boolean eglChooseConfig(EGLDisplay dpy,int[] attrib_list,int attrib_listOffset,EGLConfig[] configs, int configsOffset, int config_size,int[] num_config,int num_configOffset)
,此函数用于查询与输入配置列表(attrib_list)相符的所有配置,attrib_list 只需列出重视的(根据需要)的部分配置,其他未列出的部分将使用默认值。可在返回的配置中选择一个用于创建渲染表面。eglGetConfigs(EGLDisplay dpy, EGLConfig[] configs, int configsOffset,int config_size, int[] num_config, int num_configOffset)
则是查询输入的 display 所支持的所有配置,获得所有配置之后需要对重视的配置进行分析选择。
EGLSurface eglCreateWindowSurface(EGLDisplay dpy,EGLConfig config,Object win,int[] attrib_list,int offset)
,选择配置之后可使用用此函数创建渲染 surface。关于 attrib_list (出自 传送门):
EGL 和 OpenGL ES 支持两种绘制模式,back buffer 和 single buffer,windows surface 和 pbuffersurface 都是使用的 back buffer,顾名思义,也就是一块显存(GPU)中的 buffer,当绘制完毕的时候,由于 windows surface 于 window 有关联,那么可以使用 eglswapbuffer 将其转移到 window 上进行显示。
attrib_list ,类似于 eglChooseConfig 的第二个参数,是需求信息, 格式也类似,都是 key-value 对,刚才的 key 是 EGLConfig 的属性,这里的 key 是 EGL_RENDER_BUFFER 等属性,它也是提供了一个接口,可以给一些特殊的平台创建 surface 的时候规定一些特殊的属性,类似 EGL extension。这里我们拿一个属性进行解释,比如 EGL_RENDER_BUFFER,它就定义了绘制 API 绘制的时候应该会绘制到哪个 buffer 中,可以绘制到 single buffer,也可以绘制到 back buffer, 我们已经知道了 windowsurface 创建的是 backbuffer,那么如果绘制到 single buffer,则相当于直接绘制到屏幕上,如果绘制到 back buffer,那么就会先绘制到 back buffer,再通过 eglswapbuffer 转移到屏幕上。
这个参数也可以直接写成 NULL,或者第一个值就是 EGL_NONE,那么所有的属性对应的 value 就按照默认值处理,比如 EGL_RENDER_BUFFER 的默认值为 back buffer。
相对于创建,销毁渲染表面的方法为boolean eglDestroySurface(EGLDisplay dpy, EGLSurface surface)
。
eglCreateContext & eglMakeCurrent
OpenGL 是一个状态机,包含了渲染时需要的所有状态,这些状态需要一个 context 保存。使用 EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context, int[] attrib_list, int offset)
创建一个 context,其中 share_context 可以在不同的 context 共享纹理、着色器等资源,当它为 EGL_NO_CONTEXT 时,不与任何 context 共享资源。
可使用 boolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
销毁 context。
在 OpenGL 绘制过程中,可以存在多个的 context,所以在绘制前需要指定使用的 context,boolean eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx)
函数可用来指定 context,它表明当前环境的 display 作为渲染的显示, surface 作为渲染的对象(surface 保存了渲染内容),当前的线程可用 OpenGL 进行绘制或读取 surface 内容。
eglSwapBuffers
使用 OpenGL 对 surface 进行绘制之后,需要使用函数 boolean eglSwapBuffers(EGLDisplay dpy, EGLSurface surface)
将 surface 的颜色缓冲去显示到 display 上。