标签:ring 表格 方式 栅栏 com 通过 http 请求 iss
说明:Khronos 是 OpenGL, OpenGL ES, OpenVG 和 EGL 等规范的定义者。以下的代码主要是用 Android 书写,但规范是 EGL 规范。
EGL 是 Khronos 组织定义的用于管理绘图表面(窗口只是绘图表面的一种类型,还有其他的类型)的 API,EGL 提供了 OpenGL ES(以及其他 Khronos 图形 API(如 OpenVG))和不同操作系统(Android、Windows 等)之间的一个 “结合层次”。即 EGL 定义了 Khronos API 如何与底层窗口系统交流,是 Khronos 定义的规范,相当于一个框架,具体的实现由各个操作系统确定。它是在 OpenGL ES 等规范中讨论的概念,故应和这些规范的文档结合起来阅读,且其 API 的说明文档也应在 Khronos 网站上寻找。注意:IOS 提供了自己的 EGL API 实现,称为 EAGL。
通常,在 Android 中,EGL14 实现的是 EGL 1.4 规范。其相当于 Google 官方对 JAVA 的 EGL10(EGL 1.0 规范)的一次重新设计。通常,我们使用 EGL14 中的函数。而 EGL15 是 EGL 1.5 规范,其在设计时,仅仅是做了规范的补充,并未重新设计。通常 EGL14、EGL15 与 GLES20 等一起使用。GLES20 是 OpenGL ES 2.0 规范的实现。OpenGL ES 1.x 规范因为是早期版本,受限于机器性能和架构设计等,基本可以不再使用。而 OpenGL ES 2.x 规范从 Android 2.3 版本后开始支持,目前市面上的所有手机都支持。相比于 1.0,OpenGL ES 2.0 引入了可编程图形管线,具体的渲染相关使用专门的着色语言来表达。
下面,介绍一下 EGL 的使用流程。
在 EGL 能够确定可用的绘制表面类型之前,它必须打开和窗口系统的通信渠道。因为每个窗口系统都有不同的语义,所以 EGL 提供了基本的不对操作系统透明的类型---EGLDisplay。该类型封装了所有系统相关性,用于和原生窗口系统交流。任何使用 EGL 的应用程序,第一个操作必须是创建和初始化与本地 EGL 显示的连接。以下代码展示如何创建连接:
/**
* EGL14 实现了 EGL1.4 定义的规范
* EGL15 等主要是 EGL 新增规范的补充
*
* eglGetDisplay 方法定义了如何获取本地 EGL 显示。
*
* EGL_DEFAULT_DISPLAY 是默认的连接。
* EGL_NO_DISPLAY 表示连接不可用,进而说明 EGL 与 OpenGL ES 不可用
* */
private void initEGLDisplay() {
// 获取本地默认的显示
EGLDisplay display = EGL14.eglGetDisplay(EGL14.EGL_DEFAULT_DISPLAY);
if(display == EGL14.EGL_NO_DISPLAY) {
// 具体的错误查询方法下面讲述
Log.e("NO", "Link Error");
return;
}
// 做接下来的操作
}
上面的代码中,我们已经知道 EGL 会发生错误,也可以获取错误。
EGL 中的大部分函数,在成功时会返回 EGL_TRUE,否则返回 EGL_FALSE。但是,EGL 所做的不仅是告诉我们调用是否失败,它还将记录错误,指示故障原因。不过,这个错误代码并不会直接告诉我们,我们需要查询规范,才能知道每个的含义。可以调用 eglGetError() 函数获取错误,以下是错误的说明:
private void getError() {
int errorCode = EGL14.eglGetError();
switch (errorCode) {
case EGL14.EGL_SUCCESS:
println("函数执行成功,无错误---没有错误");
break;
case EGL14.EGL_NOT_INITIALIZED:
println("对于特定的 Display, EGL 未初始化,或者不能初始化---没有初始化");
break;
case EGL14.EGL_BAD_ACCESS:
println("EGL 无法访问资源(如 Context 绑定在了其他线程)---访问失败");
break;
case EGL14.EGL_BAD_ALLOC:
println("对于请求的操作,EGL 分配资源失败---分配失败");
break;
case EGL14.EGL_BAD_ATTRIBUTE:
println("未知的属性,或者属性已失效---错误的属性");
break;
case EGL14.EGL_BAD_CONTEXT:
println("EGLContext(上下文) 错误或无效---错误的上下文");
break;
case EGL14.EGL_BAD_CONFIG:
println("EGLConfig(配置) 错误或无效---错误的配置");
break;
case EGL14.EGL_BAD_DISPLAY:
println("EGLDisplay(显示) 错误或无效---错误的显示设备对象");
break;
case EGL14.EGL_BAD_SURFACE:
println("未知的属性,或者属性已失效---错误的Surface对象");
break;
case EGL14.EGL_BAD_CURRENT_SURFACE:
println("窗口,缓冲和像素图(三种 Surface)的调用线程的 Surface 错误或无效---当前Surface对象错误");
break;
case EGL14.EGL_BAD_MATCH:
println("参数不符(如有效的 Context 申请缓冲,但缓冲不是有效的 Surface 提供)---无法匹配");
break;
case EGL14.EGL_BAD_PARAMETER:
println("错误的参数");
break;
case EGL14.EGL_BAD_NATIVE_PIXMAP:
println("NativePixmapType 对象未指向有效的本地像素图对象---错误的像素图");
break;
case EGL14.EGL_BAD_NATIVE_WINDOW:
println("NativeWindowType 对象未指向有效的本地窗口对象---错误的本地窗口对象");
break;
case EGL14.EGL_CONTEXT_LOST:
println("电源错误事件发生,Open GL重新初始化,上下文等状态重置---上下文丢失");
break;
default:
break;
}
}
private void println(String s) {
System.out.println(s);
}
成功打开连接之后,需要初始化 EGL。可以调用如下函数完成:
// 标准的 EGL 定义
EGLBoolean eglInitialize(EGLDisplay display, EGLint *majorVersion, EGLint *minorVersion);
// display: 指定 EGL 的显示连接
// majorVersion: 存储指定 EGL 实现,返回的主版本号,可能为 NULL
// minorVersion: 存储指定 EGL 实现,返回的次版本号,可能为 NULL
在 Android 中,其具体实现如下:
// 定义一个 2 维数组,用于存放获取到的版本号,主版本号放在 version[0],次版本号放在 version[1]
int[] version = new int[2];
// 初始化 EGL, eglDisplay 的获取在上面讲述了
boolean isSuccess = EGL14.eglInitialize(eglDisplay, version, 0, version, 1);
if(!isSuccess) {
switch (EGL14.eglGetError()) {
case EGL14.EGL_BAD_DISPLAY:
println("无效的 EGLDisplay 参数");
break;
case EGL14.EGL_NOT_INITIALIZED:
println("EGL 不能初始化");
break;
default:
println("发生错误:" + EGL14.eglGetError());
break;
}
return;
}
// 初始化成功,往下走
// ......
这个函数初始化 EGL 内部数据结构,返回 EGL 实现的主版本号和次版本号。如果 EGL 无法初始化,函数会返回 EGL_FALSE,并将 EGL 错误代码设置为:
一旦初始化了 EGL,就可以确定可用渲染表面的类型和配置,这有两种方法:
在许多情况下,使用第二种方法更简单,而且最有可能得到用第一种方法找到的匹配。
在任何一种情况下,EGL 都将返回一个 EGLConfig,这是包含有关特定表面及其特征(如每个颜色分量的位数、与 EGLConfig 相关的深度缓冲区(如果有的话))的 EGL 内部数据结构的标识符。可以用 eglGetConfigAttrib 函数查询 EGLConfig 的任何属性。后面会讲。
调用以下函数,可以查询系统支持的所有 EGL 表面配置:
boolean eglGetConfigs(EGLDisplay display, EGLConfig[] configs, int configsOffset, int config_size, int[] num_config, int num_configOffset);
// display: EGL 连接的显示
// configs: 指定的 configs 列表(第 2 个参数)
// configsOffset: 列表取值的起始偏移值
// config_size: 指定的 configs 列表的尺寸
// num_config: 存放获取到的配置数量。一般来说,此列表仅存放大小,列表长度设置为 1 即可(第 5 个参数)
// num_configOffset: 存值时的起始偏移值(第 6 个参数)
函数在调用成功时,会返回 EGL_TRUE。失败时,会返回 EGL_FALSE,并将 EGL 错误代码设置为:
调用 eglGetConfigs 有两种方法。
此处,说明一下与 EGLConfig 相关的 EGL 值,并说明如果检索这些值。
EGLConfig 包含关于 EGL 启用的表面的所有信息。其包括关于可用颜色、与配置相关的其他缓冲区(深度和模板缓冲区)、表面类型等等。可以用下面的函数查询与 EGLConfig 相关的特定属性:
boolean eglGetConfigAttrib(EGLDisplay display, EGLConfig config, int attribute, int[] value, int offset);
// display: EGL 的显示连接
// config: 待查询的配置
// attribute: 指定返回的特定属性
// value: 指定的返回值
// offset: 结果放入数组时的偏移值,一般为 0
上述函数在调用成功时返回 EGL_TRUE,失败时返回 EGL_FALSE,并将 EGL 错误代码设置为:
下面是在 eglGetConfigAttrib 函数中所有的可用的 EGLConfig 属性列表:
属性名 | 描述 | 默认值 |
---|---|---|
EGL_ALPHA_SIZE | 颜色缓冲区中的 Alpha 值位数 | 0 |
EGL_ALPHA_MASK_SIZE | 掩码缓冲区中的 Alpha 掩码位数0,掩码缓冲区只被 OpenVG 使用 | 0 |
EGL_BIND_TO_TEXTURE_RGB | 如果可以绑定到 RGB 纹理,则返回 EGL_TRUE,否则返回 EGL_FALSE | EGL_DONT_CARE |
EGL_BIND_TO_TEXTURE_RGBA | 如果可以绑定到 RGBA 纹理,则返回 EGL_TRUE,否则返回 EGL_FALSE | EGL_DONT_CARE |
EGL_BLUE_SIZE | 颜色缓冲区中蓝色分量的位数 | 0 |
EGL_BUFFER_SIZE | 颜色缓冲区中所有颜色分量的位数,其值是 EGL_RED_SIZE, EGL_GREEN_SIZE, EGL_BLUE_SIZE, 和 EGL_ALPHA_SIZE 的位数之和 | 0 |
EGL_COLOR_BUFFER_TYPE | 颜色缓冲区类型:EGL_RGB_BUFFER 或者 EGL_LUMINANCE_BUFFER | EGL_RGB_BUFFER |
EGL_CONFIG_CAVEAT | 和配置相关的任何注意事项,可取的值为:EGL_NONE, EGL_SLOW_CONFIG, 和 EGL_NON_CONFORMANT | EGL_DONT_CARE |
EGL_CONFIG_ID | EGLConfig的唯一标识符的值 | EGL_DONT_CARE |
EGL_CONFORMANT | 如果用此配置创建的上下文是有效的,则返回真 | --- |
EGL_DEPTH_SIZE | 深度缓冲区位数 | 0 |
EGL_GREEN_SIZE | 颜色缓冲区中绿色分量的位数 | 0 |
EGL_LEVEL | 帧缓冲区的级别 | 0 |
EGL_LUMINANCE_SIZE | 颜色缓冲区中的亮度位数 | 0 |
EGL_MAX_PBUFFER_WIDTH | 像素缓冲区表面(pixel buffer surface)的最大宽度 | --- |
EGL_MAX_PBUFFER_HEIGHT | 像素缓冲区表面(pixel buffer surface)的最大高度 | --- |
EGL_MAX_PBUFFER_PIXELS | 像素缓冲区表面(pixel buffer surface)的最大尺寸 | --- |
EGL_MAX_SWAP_INTERVAL | 最大缓冲区交换间隔(参见 eglSwapInterval 函数) | EGL_DONT_CARE |
EGL_MIN_SWAP_INTERVAL | 最小缓冲区交换间隔(参见 eglSwapInterval 函数) | EGL_DONT_CARE |
EGL_NATIVE_RENDERABLE | 如果原生渲染 API 可以渲染此 EGLConfig 创建的表面,则为真 | EGL_DONT_CARE |
EGL_NATIVE_VISUAL_ID | 原生窗口系统的可视 ID 的句柄 | EGL_DONT_CARE |
EGL_NATIVE_VISUAL_TYPE | 原生窗口系统的可视类型 | EGL_DONT_CARE |
EGL_RED_SIZE | 颜色缓冲区中红色分量的位数 | 0 |
EGL_RENDERABLE_TYPE | 位掩码,代表 EGL 支持的渲染类型的接口。由 EGL_OPENGL_ES_BIT、EGL_OPENGL_ES2_BIT、EGL_OPENGL_ES3 _BIT_KHR(需要 EGL_KHR_create_context 扩展)、EGL_OPENGL_BIT 或 EGL_OPENVG_BIT 组成 | EGL_OPENGL_ES_BIT |
EGL_SAMPLE_BUFFERS | 可用的多重采用缓冲区的数量 | 0 |
EGL_SAMPLES | 每个像素的样本数量 | 0 |
EGL_STENCIL_SIZE | 模板缓冲区位数 | 0 |
EGL_SURFACE_TYPE | 支持的 EGL 表面类型。可能是:EGL_WINDOW_BIT、EGL_PIXMAP_BIT、EGL_PBUFFER_BIT、EGL_MULTISAMPLE_RESOLVE_BOX_BIT、EGL_SWAP_BEHAVIOR_PRESERVED_BIT、EGL_VG_COLORSPACE_LINEAR_BIT 或 EGL_VG_ALPHA_FORMAT_PRE_BIT | EGL_WINDOW_BIT |
EGL_TRANSPARENT_TYPE | 支持的透明度类型:EGL_NONE 或者 EGL_TRANSPARENT_RGB | EGL_NONE |
EGL_TRANSPARENT_RED_VALUE | 透明的红色值 | EGL_DONT_CARE |
EGL_TRANSPARENT_GREEN_VALUE | 透明的绿色值 | EGL_DONT_CARE |
EGL_TRANSPARENT_BLUE_VALUE | 透明的蓝色值 | EGL_DONT_CARE |
EGL_MATCH_NATIVE_PIXMAP | 匹配本地的像素图,该属性只能通过 eglChooseConfig 获取到,无法通过 eglGetConfigAttrib 获取到 | EGL_NONE |
如果我们不关心所有的属性,那么可以使用 eglChooseConfig 函数,此函数可以指定我们关心的重要的属性,并返回最佳匹配结果:
boolean eglChooseConfig(EGLDisplay display, int[] attrib_list, int attrib_listOffset, EGLConfig[] configs, int configsOffset, int config_size, int[] num_config, int num_configOffset);
// display: 连接的 EGL 显示
// attrib_list: 指定待查询的 EGLConfig 匹配的属性列表
// attrib_listOffset: 属性列表的取值位移
// configs: EGLConfig 的配置列表
// configsOffset: 配置的取值偏移
// config_size: 配置列表的尺寸
// num_config: 指定返回的配置大小,数组长度一般设置为 1 即可
// num_configOffset: 取值偏移0
函数调用成功时,返回 EGL_TRUE,否则返回 EGL_FALSE,并将错误码置为以下的值:
我们在设置属性列表时,需要设置相关属性的默认值。如果不设置,则会使用上述表格中的默认值。例如,我们需要获取支持 5 位红色和蓝色分量、6 位绿色分量(常用的 RGB565 格式)的渲染表面、一个深度缓冲区和 OpenGL 3.0 的 EGLConfig,则可以指定以下的数组:
int[] attrs = new int[] {
// 属性名 默认值
EGL14.EGL_RENDERABLE_TYPE, EGLExt.EGL_OPENGL_ES3_BIT_KHR,
EGL14.EGL_RED_SIZE, 5,
EGL14.EGL_GREEN_SIZE, 6,
EGL14.EGL_BLUE_SIZE, 5,
EGL14.EGL_DEPTH_SIZE, 1,
// 属性定义结束
EGL14.EGL_NONE
};
// 注:使用 EGL_OPENGL_ES3_BIT_KHR 需要使用 EGL_KHR_create_context 扩展。该属性在 eglext.h (EGL v1.4) 中定义
下面是一个查询的代码示范:
// 存储返回的配置数量
int []numConfigs = new int[1];
EGLConfig[]configs = new EGLConfig[1];
if (!EGL14.eglChooseConfig(eglDisplay, attrs, 0, configs, 0, configs.length, numConfigs, 0)) {
// 获取属性出错
return;
}
// 获取属性成功
如果 eglChooseConfig 匹配成功,则将返回一组匹配相应属性列表的标准的 EGLConfig。如果 EGLConfig 的数量超过一个(最多是我们指定的最大配置数量),则将按如下顺序排列:
上述列表中未提及到的参数不用于排列过程
同时,需要注意以下事项:
一旦我们有了符合渲染需求的 EGLConfig,就为创建窗口做好了准备。可以调用以下函数来创建窗口:
EGLSurface eglCreateWindowSurface(EGLDisplay display, EGLConfig config, Object window, int[] attrib_list, int offset);
// display 指定 EGL 的显示连接
// config 指定的配置
// window 指定原生窗口,在 Android 中,可传入 SurfaceHolder 对象
// attrib_list 指定窗口属性列表,可能为 NULL
// offset 属性列表的取值偏移
上面的属性列表可以取以下值,因为 EGL 还可以支持其他 API(如 Open VG),故创建时,有些属性不适用。下面是 OpenGL ES 支持的属性:
属性名 | 描述 | 默认值 |
---|---|---|
EGL_RENDER_BUFFER | 指定渲染用的缓冲区(EGL_SINGLE_BUFFER,或者后台缓冲区 EGL_BACK_BUFFER) | EGL_BACK_BUFFER |
EGL_GL_COLORSPACE | 指定 Open GL 和 Open GL ES 渲染表面时,用到的颜色空间,此属性在 EGL1.5 中被定义 | EGL_GL_COLORSPACE_SRGB |
说明,对于 OpenGL ES 3.0,只支持双缓冲区窗口。
当属性列表 attrib_list 为空,或者 EGL_NONE 作为属性第一个元素时,所有的属性值都将使用默认值。当调用失败时,函数会返回 EGL_NO_SURFACE,并设置以下错误:
下面是一个创建 EGL 窗口的代码,参照了 GLSurfaceView:
EGLSurface surface = EGL14.eglCreateWindowSurface(display, config, view.getHolder(), null, 0);
if(surface == null) {
Log.e("Test", "窗口为空");
return;
}
if(surface == EGL14.EGL_NO_SURFACE) {
int error = EGL14.eglGetError();
// 处理错误
return;
}
// 函数执行成功,往下走
下面,介绍另外一种 EGL 渲染区域:EGL Pbuffer。
除了可以用 OpenGL ES 在屏幕上的窗口渲染之外,还可以渲染被称为 Pbuffer(像素缓冲区 Pixel buffer 的简写) 的不可见屏幕外表面。和窗口一样,Pbuffer 可以利用 OpenGL ES 中的任何硬件加速。Pbuffer 常用于生成纹理贴图。当然,如果想要的是渲染到一个纹理,建议使用帧缓冲区对象代替 Pbuffer,因为帧缓冲区更高效。不过,在某些帧缓冲区无法使用的情况下,Pbuffer 仍然有效,比如用 OpenGL ES 在屏幕外表面渲染,然后将其作为其他 API(如 OpenVG)中的纹理。
和窗口一样,Pbuffer 支持 OpenGL ES 的所有渲染机制。主要的区别是:
创建 Pbuffer 和创建 EGL 窗口非常类似。为了创建 Pbuffer,需要和窗口一样找到 EGLConfig,并作一处修改;我们需要扩增 EGL_SURFACE_TYPE 的值,使其包含 EGL_PBUFFER_BIT。拥有适用的 EGLConfig 之后,就可以用如下函数创建 Pbuffer:
EGLSurface eglCreatePbufferSurface(EGLDisplay display, EGLConfig config, int[] attrib_list, int offset);
// display 指定的 EGL 显示
// config 指定的配置
// attrib_list 指定像素缓冲区的属性列表,可能为 NULL
// offset 属性数组取值的偏移值
在 OpenGL ES 中,下面是可用的属性列表:
属性名 | 描述 | 默认值 |
---|---|---|
EGL_WIDTH | 指定 Pbuffer 的宽度(以像素表示) | 0 |
EGL_HEIGHT | 指定 Pbuffer 的高度(以像素表示) | 0 |
EGL_LARGEST_PBUFFER | 如果请求的大小不可用,则选择最大的可用 Pbuffer,有效值为 EGL_TRUE 和 EGL_FALSE | EGL_FALSE |
EGL_TEXTURE_FORMAT | 如果 Pbuffer 指定到一个纹理贴图,则指定纹理格式类型,有效值是 EGL_NO_TEXTURE, EGL_TEXTURE_RGB, 和 EGL_TEXTURE_RGBA | EGL_NO_TEXTURE(表示 Pbuffer 不能直接指定到纹理) |
EGL_TEXTURE_TARGET | 指定 Pbuffer 作为纹理贴图时,应该连接到的相关纹理目标,有效值是 EGL_NO_TEXTURE, 和 EGL_TEXTURE_2D | EGL_NO_TEXTURE |
EGL_MIPMAP_TEXTURE | 指定 是否应该为 纹理mipmap 分配存储,有效值是 EGL_TRUE 和 EGL_FALSE | EGL_FALSE |
EGL_GL_COLORSPACE | 指定 Open GL 和 Open GL ES 渲染表面时,用到的颜色空间,此属性在 EGL1.5 中被定义 | EGL_GL_COLORSPACE_SRGB |
和窗口创建一样,函数调用失败时,会返回 EGL_NO_SURFACE,并设置以下错误码:
渲染上下文是 OpenGL ES 的内部数据结构,包含操作所需的所有状态信息。在 OpenGL ES 中,必须要有个上下文才能绘图。可以用如下函数创建上下文:
EGLContext eglCreateContext(EGLDisplay display, EGLConfig config, EGLContext share_context, int[] attrib_list, int offset);
// display 指定的 EGL 显示
// config 指定的配置
// share_context 允许多个 EGL 上下文共享特定类型的数据,比如着色器程序和纹理贴图,使用 EGL_NO_CONTEXT 表示没有共享
// attrib_list 指定上下文使用的属性列表,只有一个可接受的属性: EGL_CONTEXT_CLIENT_VERSION。该属性用于指定与我们所使用的 OpenGL ES 版本相关的上下文类型。默认值是1(即指定 OpenGL ES 1.X 版本的上下文类型)
// offset 属性列表的取值偏移
函数执行成功时,会返回一个指向新创建上下文的句柄。如果失败,则会返回 EGL_NO_CONTEXT,并设置如以下错误码(不全,官方文档未说明。以实际返回为准):
下面是创建上下文的一段示范代码:
int []contextAttribs = {
EGL14.EGL_CONTEXT_CLIENT_VERSION, 2, // EGL14 一般与 GLES20 结合使用
EGL14.EGL_NONE
};
eglContext = EGL14.eglCreateContext(eglDisplay, eglConfig, EGL14.EGL_NO_CONTEXT, contextAttribs,0);
if(eglContext== EGL14.EGL_NO_CONTEXT) {
throw new RuntimeException("EGL error "+EGL14.eglGetError());
}
终于,我们来到了最后一步,完成这一步后,我们就能开始渲染了。
因为一个应用程序可能创建多个 EGLContext 用于不同的用途,所以我们需要关联特定的 EGLContext 和渲染表面。这一步骤通常叫做 "指定当前上下文"。使用下列函数,关联特定的 EGLContext 和 EGLSurface:
boolean eglMakeCurrent(EGLDisplay display, EGLSurface draw, EGLSurface read, EGLContext context);
// display 指定的 EGL 显示
// draw 指定的 EGL 绘图表面
// read 指定的 EGL 读取表面
// context 指定连接到该表面的渲染上下文
函数执行成功时,会返回 EGL_TRUE,否则返回 EGL_FALSE,并设置以下错误码:
我们注意到函数需要两个 EGLSurface 表面。尽管这种方法具有灵活性(在 EGL 的高级用法中将被利用到),但是通常我们把 draw 和 read 设置为同一个值---我们前面创建的渲染表面(窗口或者 Pbuffer)。注意,因为 EGL 规范要求 eglMakeCurrent 实现进行一次刷新,所以这一调用对于基于图块的架构代价很高。
讲述完用 EGL 渲染前的所有准备后,我们正式整合所有步骤,输出一个完整的代码示范。
此部分是扩展内容,不是必须的步骤。不想看的可以跳过,看下面的代码示范。
有时我们会碰到,协调多个图形 API 在单个窗口中渲染的情况。在这种情况下,需要让应用程序允许多个库渲染到共享窗口。EGL 提供了几个函数来处理这种同步任务。
下面是一段示范,可能无法运行,但是说明了 EGL 执行与初始化的流程。
/**
* 初始化 EGL,初始化成功,返回 true,否则返回 false
* */
@RequiresApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
private boolean initWindow() {
// 1. 获取 EAL 显示
EGLDisplay eglDisplay = EGL14.eglGetDisplay(EGL14.EGL_DEFAULT_DISPLAY);
if(eglDisplay == EGL14.EGL_NO_DISPLAY) {
Log.e("initWindow", EGL14.eglGetError() + "");
return false;
}
// 2. 初始化 EGL
int[] version = new int[2];
if(!EGL14.eglInitialize(eglDisplay, version, 0, version, 1)) {
Log.e("initWindow", EGL14.eglGetError() + "");
return false;
}
// 3. 确定配置
int[] configAttribs = new int[] {
EGL14.EGL_RENDERABLE_TYPE, EGL14.EGL_WINDOW_BIT,
EGL14.EGL_RED_SIZE, 8,
EGL14.EGL_GREEN_SIZE, 8,
EGL14.EGL_BLUE_SIZE, 8,
EGL14.EGL_DEPTH_SIZE, 24,
EGL14.EGL_NONE
};
EGLConfig[] configs = new EGLConfig[1];
int[] numConfigs = new int[1];
if(!EGL14.eglChooseConfig(eglDisplay, configAttribs, 0, configs, 0,
configs.length, numConfigs, 0)) {
Log.e("initWindow", EGL14.eglGetError() + "");
return false;
}
if(configs[0] == null) {
return false;
}
// 4. 创建渲染表面,此处是创建窗口
EGLSurface window = EGL14.eglCreateWindowSurface(eglDisplay,
configs[0], glSurfaceView.getHolder(), null, 0);
if(window == EGL14.EGL_NO_SURFACE) {
Log.e("initWindow", EGL14.eglGetError() + "");
return false;
}
// 5. 创建上下文
int[] contextAttribs = new int[] {
EGL14.EGL_CONTEXT_CLIENT_VERSION, 2,
EGL14.EGL_NONE
};
EGLContext eglContext = EGL14.eglCreateContext(eglDisplay, configs[0],
EGL14.EGL_NO_CONTEXT, contextAttribs, 0);
if(eglContext == EGL14.EGL_NO_CONTEXT) {
Log.e("initWindow", EGL14.eglGetError() + "");
return false;
}
// 6. 绑定上下文与表面
if(!EGL14.eglMakeCurrent(eglDisplay, window, window, eglContext)) {
Log.e("initWindow", EGL14.eglGetError() + "");
return false;
}
Log.d("initWindow", "初始化成功");
return true;
}
从上述的说明中,我们可以得到下面的关于 EGL 的使用的流程图:
以上便是关于 EGL 的使用的一些基本介绍。
标签:ring 表格 方式 栅栏 com 通过 http 请求 iss
原文地址:https://www.cnblogs.com/wellcherish/p/12727906.html