OpenGL ES 2.0 知识串讲二---EGL详解

兄弟们,打扰一下,OpenGL ES 2.0 知识串讲二---EGL详解
最新回答
平胸小欧巴

2024-06-27 06:38:51


回顾上节:我们已经初步了解了OpenGL ES、EGL和GLSL的关系,EGL作为桥梁,负责与手机设备交互并获取绘图缓冲。


EGL API概览:EGL由34个功能丰富的API构成,其中7个专门与手机设备交互,获取关键配置信息,比如支持的buffer格式;16个用于生成表面和上下文,确保显示在屏幕上;另有1个用于指定OpenGL ES版本并建立联系。


具体细节:在获取配置时,EGL会考虑手机硬件的差异,以确保兼容性;生成的表面通常包括Color、Depth和Stencil buffer,这些是图形绘制的核心组件;而context则承载着OpenGL ES的运行状态。EGL支持创建多个表面和上下文,但每个都需对应特定的OpenGL ES版本,以保持一致性。


指定OpenGL ES版本在EGL中至关重要,如1.1、2.0(增加了可编程模块)、3.0/3.1等。EGL还提供了6个API,用于管理纹理和多线程高级功能,例如纹理贴图。在绘制缓冲的生成中,EGL虽支持多线程,但格式选择有限。基础API和进阶功能将在后续章节深入探讨。


EGLGetError是个关键助手,它接收无输入,返回执行中的错误代码,涵盖15种可能的错误状态。连续调用它可清除错误标记,确保代码的稳定运行。


EGLGetDisplay则是获取操作系统提供的Display handle,输入参数是display_id,用于后续与系统的交互。


EGL的优势在于跨平台兼容性:不同的display_id代表着操作系统和屏幕类型,如默认屏幕或物理屏幕。通过eglInitialize,我们可以指定display和EGL版本(如1.4,major 1,minor 4),返回初始化结果(EGL_TRUE或EGL_FALSE),并用eglGetError检测初始化是否成功。已初始化的display允许在多个线程中重置版本,无需单独初始化。


要获取display支持的配置信息,eglGetConfigs是必不可少的,它接收display、配置信息的存储指针、期望获取的配置数量和实际匹配数量。


EGLBoolean eglInitialize(EGLDisplay dpy, EGLint* major, EGLint* minor); —— 初始化display并指定EGL版本。


EGLBoolean eglGetConfigs(EGLDisplay dpy, EGLConfig* configs, EGLint config_size, EGLint* num_config); —— 获取display支持的配置信息,根据需求进行筛选。




简化参数说明:

函数eglChooseConfig看似五个输入,实则三个核心参数:display、需求配置数组和配置数量,通过返回值EGL_TRUE或EGL_FALSE来指示匹配或不匹配。它根据需求从display中挑选出合适的配置,这些需求以键值对的形式表达,如EGL_RED_SIZE、EGL_STENCIL_SIZE。




忽略Config属性值为EGL_DONT_CARE的匹配。如果传入NULL或EGL_NONE,系统将选择默认配置,并按标准顺序排列。默认处理未定义属性,如EGL_RED_SIZE设为0。eglBindAPI设置当前线程的绘图API,支持OpenGL ES、OpenGL和OpenVG,选EGL_OPENGL_ES_API适用于移动设备。




创建EGLSurface


  • EGLDisplay: 指定display

  • EGLConfig: 配置信息,通常选择第一个匹配的

  • 窗口句柄(native window handle): 平台特定的参数

  • 额外属性(EGL_RENDER_BUFFER): 设定绘制目标




成功创建的EGLSurface返回表面handle,失败则返回EGL_NO_SURFACE,错误可能包括不匹配的配置、非法窗口句柄或内存分配失败。




EGLContext的生成与绑定

EGLContext eglCreateContext根据需求创建渲染上下文,与表面配合使用,保存OpenGL ES状态。通过指定版本,如1.x、2.x或3.x,创建成功返回handle,失败则返回EGL_NO_CONTEXT,错误代码揭示了原因,如不支持的API、配置不匹配或上下文不兼容。




eglMakeCurrent是关键步骤,它将context与绘制线程和表面绑定,允许执行绘制和读取操作。每个native窗口对应一个rendering context,且同一线程只能绑定一个API的context。




在EGL库中,可以创建多个surface和context,但每个context必须与特定的API相关联。当遇到surface或context损坏时,务必注意可能引发的未定义行为。使用完毕后,通过eglTerminate释放资源,此时surface和context将变为invalid,再次使用将导致错误。




OpenGL ES视口与缓冲交换

视口定义了绘制buffer在屏幕上的显示区域。当通过eglMakeCurrent绑定context时,它会获取窗口尺寸作为初始视口。通过EGLSwapBuffers将color buffer显示到屏幕上,这个操作需要EGLDisplay和EGLSurface作为参数,成功返回EGL_TRUE,否则返回EGL_FALSE。




EGLSwapBuffers
- 参数:EGLDisplay, EGLSurface
- 功能:将surface内容显示到屏幕上,仅显示color buffer
- 返回:EGL_TRUE 成功,EGL_FALSE 失败




EGLTerminate用于释放EGLDisplay的资源,包括surface和context,后续使用这些对象将引发错误。这个操作一旦完成,display的状态将更新为已终止。




状态概览
- 初始化:eglInitialize成功
- 终止:eglTerminate成功

EGL的基本API(如eglInitializeeglTerminateeglMakeCurrenteglReleaseThread)即使在display终止后仍可用。EGL的常用功能包括获取Display handle、初始化配置、处理surface和context的创建、绑定和释放。后续章节将详述更多高级API,如eglGetConfigAttribeglDestroySurfaceeglDestroyContext。在ShineEngine项目中,我们通过GLSurfaceView简化了EGL环境,不过高级API的使用还需在实际项目中进一步探索。GL API在C文件中通过target_link_libraries链接GLESv2库,确保程序正常运行。这部分内容来源于王烁2017年7月9日的文章。