@cxm-2016
2016-11-21T12:31:33.000000Z
字数 5619
阅读 8855
APIs
版本:1
作者:陈小默
声明:禁止商业,禁止转载
发布于:作业部落
EGL 是 OpenGL ES 和底层 Native 平台视窗系统之间的接口。OpenGL ES 本质上是一个图形渲染管线的状态机,而 EGL 则是用于监控这些状态以及维护 Frame buffer 和其他渲染 Surface 的外部层。EGL提供如下机制:
EGL中的布尔类型。
typedef unsigned int EGLBoolean;
不透明类型,封装了与底层系统的交互,用于充当与原生窗口之间的接口。
typedef void * EGLDisplay;
EGL整数类型。
typedef int32_t EGLint;
用于匹配原生窗口系统的显示类型。
typedef void * EGLNativeDisplayType;
在初始化EGL时,我们需要列出并让EGL选择最合适的配置。
EGLBoolean eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config);
- dpy:已连接的设备
- attrib_list:传入的配置信息数组
- configs:保存返回的配置信息的数组
- config_size:传入的配置数组的长度
- num_config:保存返回的配置信息的数组的长度
EGLConfig config;
EGLint numConfigs = 0;
EGLint attribList[] =
{
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT,
EGL_RED_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_BLUE_SIZE, 8,
EGL_ALPHA_SIZE, 8,
EGL_DEPTH_SIZE, 16,
EGL_NONE
};
if (!eglChooseConfig(context->eglDisplay, attribList, &config, 1, &numConfigs)) {
return GL_FALSE;
}
渲染上下文是OpenGL ES的内部数据结构,包含操作所需的所有状态信息。例如程序中使用的顶点着色器或者片元着色器的引用。OpenGL ES必须有一个可用的上下文才能绘图。使用下面的函数可以创建一个上下文:
EGLContext eglCreateContext(EGLDisplay display, EGLConfig config, EGLContext shareContext, const EGLint *attribList);
- display:指定显示连接
- config:指定配置对象
- shareContext:允许多个EGL上下文共享特定的数据,EGL_NO_CONTEXT参数表示没有共享
- attribList:指定创建上下文使用的属性列表
- return:创建的上下文对象
EGLint contextAttribs[] = {EGL_CONTEXT_CLIENT_VERSION, 3, EGL_NONE};
context->eglContext = eglCreateContext(context->eglDisplay, config, EGL_NO_CONTEXT, contextAttribs);
if (context->eglContext == EGL_NO_CONTEXT) {
return GL_FALSE;
}
一旦我们有了符合渲染需求的EGLConfig,就为窗口创建做好了准备。调用如下函数可以创建一个窗口。
EGLSurface eglCreateWindowSurface(EGLDisplay display, EGLConfig config, EGLNativeWindowType window,const EGLint *attribList);
- display:已连接的设备对象
- config:指定的配置对象
- window:指定原生窗口对象
- attriList:指定窗口的属性列表
- return:EGL渲染区域对象
这个函数以我们到原生显示管理器的连接和前一步获得的EGLConfig为参数。此外,它需要原生窗口系统事先创建一个窗口。因为EGL是许多不同窗口系统和OpenGL ES之间的软件接口层。最后这个函数需要一个属性列表;但是,这个列表中的属性与参数属性不完全相同,并且额外使用到了创建窗口的属性。该函数在多种情况下都有可能失败。
context->eglSurface = eglCreateWindowSurface(context->eglDisplay, config, context->nativeWindow,
NULL);
if (context->eglSurface == EGL_NO_SURFACE) {
EGLint error;
while((error = eglGetError()) != EGL_SUCCESS){
switch(error) {
case EGL_BAD_MATCH:{
//提供的原生窗口不匹配或者不支持渲染
}
case EGL_BAD_CONFIG:{
//系统不支持该配置
}
case EGL_BAD_NATIVE_WINDOW:{
//提供的原生窗口无效
}
case EGL_BAD_ALLOC:{
//无法为新的EGL分配资源或者该窗口已经被关联
}
}
}
}
如果我们获获取了一个EGL配置对象,我们可以通过下列函数查询该对象中指定属性的值。
EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value);
在初始化EGL之后,我们需要给EGL选择一组配置。
EGLBoolean eglGetConfigs(EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config);
- dpy:已连接设备对象
- configs:保存配置信息的列表
- size:configs的长度
- num_config:EGL返回的配置信息数量
- return:查询结果状态
通常情况下,我们有两种方式使用该函数。首先,我们指定configs参数为NULL,此时EGL会查询所有可用的EGLConfigs数量并赋值给num_config,但此时不会有任何其他信息返回。
另外,我们也可以创建一个未初始化的EGLConfig,并作为函数的参数传入。此时,EGL将会查询不超过config_size数量的配置信息存入到configs,并通过num_config返回保存数据的数量。
获得并与可用设备进行连接。
EGLDisplay eglGetDisplay(EGLNativeDisplayType display_id);
- display_id:当前需要连接的设备类型
- return:已经连接上的设备对象
EGLDisplay eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
EGL中大部分函数在成功时都会返回EGL_TRUE,否则返回EGL_FALSE。但是,我们仅从这个返回值上并不能看出错误原因是什么。如果想要明确的知道EGL的错误代码,应该调用下列函数。
EGLint eglGetError(void);
- return:见 [EGL常量-错误代码]
一般在成功打开设备连接之后需要初始化EGL。初始化过程将会对EGL内部的数据结构进行设置,然后返回EGL的主次版本号。
EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor);
- dpy:指定EGL设备对象。
- major:设备主版本号。
- minor:设备次版本号。
GLint majorVersion;
GLint minorVersion;
if (!eglInitialize(eglDisplay, &majorVersion, &minorVersion)) {
return EGL_FALSE;
}
因为一个应用程序可能创建多个EGLContext用作不同的用途,所以我们需要指定关联特定的EGLContext和渲染表面——这一过程被称为“指定当前上下文”。
EGLBoolean eglMakeCurrent(EGLDisplay display, EGLSurface draw, EGLSurface read, EGLContext context);
- display:指定EGL显示设备
- draw:指定EGL绘图表面
- read:指定EGL读取表面
- context:指定连接到该表面的渲染上下文
- return:函数时候执行成功
[1]OpenGL ES 3.0 编程指南 第二版 机械工业出版社