【Android】Android SurfaceFlinger之OpenGL ES

1、OpenGL ES

在Android系统中,直接面向终端用户的便是GUI,可以说任何一款产品的UI都是至关重要的,是用户可以实实在在感受到的东西,是最直观的、最易被感知的东西。SurfaceFlinger作为Android GUI系统的核心模块,与OpenGL ES息息相关,所以在分析SurfaceFlinger之前有必要先了解一下OpenGL ES。

OpenGL即Open Graphics Library,是一款跨语言的、跨平台的开源图形库,包括2D、3D图形,不过OpenGL的运行对设备要求较高,很难被直接应用在CPU和内存资源匮乏、用电量需要严格控制甚至没有浮点数硬件协助的嵌入式设备上,于是OpenGL ES应运而生,OpenGL ES即OpenGL for Embeded System,是专门面向嵌入式系统的OpenGL API子集,可以理解为OpenGL的一个精简版。OpenGL ES现有三个版本(与OpengGL的版本不同),1.x版用于fixed function hardware,2.x版用于programmable hardware,3.x版则加入了更多新特性,如着色语言的完善、支持更多缓冲区对象、支持几何体实例化、统一的纹理压缩格式等。更多信息可查看如下khronos官网:
https://www.khronos.org/

在现实生活中,我们很容易感知到3D物体,但是在计算机屏幕上,物体实际上是2D的,只是通过一定的技术手段产生了3D效果,如3D电影的光影技术、计算机图形处理的透视效果。OpenGL ES支持三种基本的几何元素,点、线段和三角形,但通过这三种元素可以绘制任何复杂的几何体。图形渲染支持不同的pipeline,如1.x版的固定功能管线和2.x版的可编程管线,现在用的较多的是可编程管线,之所以称之为管线,是因为以3D数据作为输入后经过一系列的流水线式处理并最终输出2D光栅图形。

2、Android中的OpenGL ES

下面是Android中OpenGL ES的框架简图:

【Android】Android SurfaceFlinger之OpenGL ES_第1张图片

下面是Android源码中OpenGL ES相关的几个代码路径——

Java层SDK:frameworks/base/opengl/java
JNI层实现:frameworks/base/core/jni
C++代码实现:frameworks/native/opengl
Mesa3D引擎库:external/mesa3d

3、EGL

上面的OpenGL ES框架简图中有个EGL,它是图形渲染API(如OpenGL ES)与本地平台窗口系统的一层接口,保证了OpenGL ES的平台独立性。EGL提供了若干功能:创建rendering surface、创建graphics context、同步应用程序和本地平台渲染API、提供对显示设备的访问、提供对渲染配置的管理等。下面分析一下EGL的用法。

图形渲染可通过硬件或软件实现,是在系统启动后动态确定的。如果是硬件加速,首先要加载libhgl库,否则加载libagl库由CPU进行图形处理。具体哪种渲染方式,是由系统解析egl.cfg文件后决定的。若egl.cfg不存在,则说明硬件不支持图形渲染加速;若egl.cfg存在的话,一般放在源码device/[Manufacture]目录下,然后编译、烧机到设备/system/lib/egl/egl.cfg。例如,device/google/marlin/egl.cfg,可能有如下内容:

0 0 android
0 1 adreno

egl.cfg文件中,第一个数字表示显示屏编号,Android系统理论上支持多个显示设备,但到目前位置还只能支持一个,所以这个数值必须为0;第二个数字表示渲染方式,1为硬件加速,2为软件描画;第三个参数是库的名称,需要将对应的实现库放在/system/lib/egl或/vendor/lib/egl目录下,库的名称格式如下:

libEGL_<Lib_Name>.so
libGLES_<Lib_Name>.so
libGLESv1_CM_<Lib_Name>.so
libGLESv2_<Lib_Name>.so

如上device/google/marlin/egl.cfg,“0 0 android”为默认配置,“0 1 adreno”表示采用高通adreno GPU进行硬件加速。egl.cfg可以配置多个库,优先级逐行递减。

4、EGL API

EGL的API名字基本以egl关键字开头,格式固定,头文件位置如下:

frameworks/native/opengl/include/EGL/egl.h
frameworks/native/opengl/include/EGL/eglext.h
frameworks/native/opengl/include/EGL/eglplatform.h

egl.h声明了EGL API,eglext.h是对EGL的扩展,eglplatform.h保证了EGL的平台独立性。下面是EGL常用的类型及常量,可以看出EGL的最新版本为EGL1.4。

typedef int EGLint;
typedef unsigned int EGLBoolean;
typedef unsigned int EGLenum;
typedef void *EGLConfig;
typedef void *EGLContext;
typedef void *EGLDisplay;
typedef void *EGLSurface;
typedef void *EGLClientBuffer;
#define EGL_FALSE            0
#define EGL_TRUE            1
#define EGL_VERSION_1_0            1
#define EGL_VERSION_1_1            1
#define EGL_VERSION_1_2            1
#define EGL_VERSION_1_3            1
#define EGL_VERSION_1_4            1
#define EGL_DEFAULT_DISPLAY        EGL_CAST(EGLNativeDisplayType, 0)
#define EGL_NO_CONTEXT            EGL_CAST(EGLContext, 0)
#define EGL_NO_DISPLAY            EGL_CAST(EGLDisplay, 0)
#define EGL_NO_SURFACE            EGL_CAST(EGLSurface, 0)
#define EGL_DONT_CARE            EGL_CAST(EGLint, -1)

下面简单介绍一下EGL API,更多信息可查看如下khronos官网
https://www.khronos.org/registry/EGL/sdk/docs/man/

eglGetError——

EGLAPI EGLint EGLAPIENTRY eglGetError(void);

eglGetError用于获取当前线程的上一个EGL操作的结果,初始值为EGL_SUCCESS,下面是可能的返回值:

#define EGL_SUCCESS            0x3000
#define EGL_NOT_INITIALIZED        0x3001
#define EGL_BAD_ACCESS            0x3002
#define EGL_BAD_ALLOC            0x3003
#define EGL_BAD_ATTRIBUTE        0x3004
#define EGL_BAD_CONFIG            0x3005
#define EGL_BAD_CONTEXT            0x3006
#define EGL_BAD_CURRENT_SURFACE        0x3007
#define EGL_BAD_DISPLAY            0x3008
#define EGL_BAD_MATCH            0x3009
#define EGL_BAD_NATIVE_PIXMAP        0x300A
#define EGL_BAD_NATIVE_WINDOW        0x300B
#define EGL_BAD_PARAMETER        0x300C
#define EGL_BAD_SURFACE            0x300D
#define EGL_CONTEXT_LOST        0x300E

eglGetDisplay——

EGLAPI EGLDisplay EGLAPIENTRY eglGetDisplay(EGLNativeDisplayType display_id);

eglGetDisplay用于获取display,display_id一般取值为EGL_DEFAULT_DISPLAY,无法获取display时返回EGL_NO_DISPLAY而不产生错误。

eglInitialize——

EGLAPI EGLBoolean EGLAPIENTRY eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor);

eglInitialize用于对display进行初始化,并获取当前的EGL版本号major和minor,返回EGL_FALSE时可能的错误为EGL_BAD_DISPLAY、EGL_NOT_INITIALIZED。

eglTerminate——

EGLAPI EGLBoolean EGLAPIENTRY eglTerminate(EGLDisplay dpy);

eglTerminate用于释放display资源,包括surface和context,如果还有其它线程使用这些资源时,会等到它们通过eglMakeCurrent失效后再释放,返回EGL_FALSE时可能的错误为EGL_BAD_DISPLAY。

eglQueryString——

EGLAPI const char * EGLAPIENTRY eglQueryString(EGLDisplay dpy, EGLint name);

eglQueryString用于获取display的某些信息,返回NULL时可能的错误为EGL_BAD_DISPLAY、EGL_NOT_INITIALIZED、EGL_BAD_PARAMETER,name取值如下:

#define EGL_VENDOR            0x3053
#define EGL_VERSION            0x3054
#define EGL_EXTENSIONS            0x3055
#define EGL_CLIENT_APIS            0x308D

eglGetConfigs——

EGLAPI EGLBoolean EGLAPIENTRY eglGetConfigs(EGLDisplay dpy, EGLConfig *configs,
             EGLint config_size, EGLint *num_config);

eglGetConfigs用于获取display的frame buffer配置列表,返回EGL_FALSE时可能的错误为EGL_BAD_DISPLAY、EGL_NOT_INITIALIZED、EGL_BAD_PARAMETER。

eglGetConfigAttrib——

EGLAPI EGLBoolean EGLAPIENTRY eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config,
                  EGLint attribute, EGLint *value);

eglGetConfigAttrib用于获取display的frame buffer配置列表的某个具体的属性值,返回EGL_FALSE时可能的错误为EGL_BAD_DISPLAY、EGL_NOT_INITIALIZED、 EGL_BAD_CONFIG、EGL_BAD_ATTRIBUTE,attribute取值如下:

#define EGL_BUFFER_SIZE            0x3020
#define EGL_ALPHA_SIZE            0x3021
#define EGL_BLUE_SIZE            0x3022
#define EGL_GREEN_SIZE            0x3023
#define EGL_RED_SIZE            0x3024
#define EGL_DEPTH_SIZE            0x3025
#define EGL_STENCIL_SIZE        0x3026
#define EGL_CONFIG_CAVEAT        0x3027
#define EGL_CONFIG_ID            0x3028
#define EGL_LEVEL            0x3029
#define EGL_MAX_PBUFFER_HEIGHT        0x302A
#define EGL_MAX_PBUFFER_PIXELS        0x302B
#define EGL_MAX_PBUFFER_WIDTH        0x302C
#define EGL_NATIVE_RENDERABLE        0x302D
#define EGL_NATIVE_VISUAL_ID        0x302E
#define EGL_NATIVE_VISUAL_TYPE        0x302F
#define EGL_SAMPLES            0x3031
#define EGL_SAMPLE_BUFFERS        0x3032
#define EGL_SURFACE_TYPE        0x3033
#define EGL_TRANSPARENT_TYPE        0x3034
#define EGL_TRANSPARENT_BLUE_VALUE    0x3035
#define EGL_TRANSPARENT_GREEN_VALUE    0x3036
#define EGL_TRANSPARENT_RED_VALUE    0x3037
#define EGL_NONE            0x3038
#define EGL_BIND_TO_TEXTURE_RGB        0x3039
#define EGL_BIND_TO_TEXTURE_RGBA    0x303A
#define EGL_MIN_SWAP_INTERVAL        0x303B
#define EGL_MAX_SWAP_INTERVAL        0x303C
#define EGL_LUMINANCE_SIZE        0x303D
#define EGL_ALPHA_MASK_SIZE        0x303E
#define EGL_COLOR_BUFFER_TYPE        0x303F
#define EGL_RENDERABLE_TYPE        0x3040
#define EGL_MATCH_NATIVE_PIXMAP        0x3041
#define EGL_CONFORMANT            0x3042

eglChooseConfig——

EGLAPI EGLBoolean EGLAPIENTRY eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list,
               EGLConfig *configs, EGLint config_size,
               EGLint *num_config);

eglChooseConfig用于获取display的frame buffer配置列表,不过这个配置列表要与指定的属性列表attrib_list匹配,返回EGL_FALSE时可能的错误为EGL_BAD_DISPLAY、EGL_NOT_INITIALIZED、EGL_BAD_PARAMETER、EGL_BAD_ATTRIBUTE。attrib_list有固定的格式,属性及属性值成对出现,每个属性的属性值也都有一定的要求,最后以EGL_NONE结尾,例子如下:

EGLint const attrib_list[] = {
        EGL_RED_SIZE, 4,
        EGL_GREEN_SIZE, 4,
        EGL_BLUE_SIZE, 4,
        EGL_NONE
};

eglCreateWindowSurface——

EGLAPI EGLSurface EGLAPIENTRY eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config,
                  EGLNativeWindowType win,
                  const EGLint *attrib_list);

eglCreateWindowSurface用于创建window surface,失败时返回EGL_NO_SURFACE,可能的错误为EGL_BAD_DISPLAY、EGL_NOT_INITIALIZED、EGL_BAD_CONFIG、EGL_BAD_NATIVE_WINDOW、EGL_BAD_ATTRIBUTE、EGL_BAD_ALLOC、EGL_BAD_MATCH。attrib_list的属性可以是EGL_RENDER_BUFFER、EGL_VG_ALPHA_FORMAT、EGL_VG_COLORSPACE。

eglCreatePbufferSurface——

EGLAPI EGLSurface EGLAPIENTRY eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config,
                   const EGLint *attrib_list);

eglCreatePbufferSurface用于创建off-screen的pixel buffer surface,失败时返回EGL_NO_SURFACE,可能的错误为EGL_BAD_DISPLAY、EGL_NOT_INITIALIZED、EGL_BAD_CONFIG、EGL_BAD_ATTRIBUTE、EGL_BAD_ALLOC、EGL_BAD_MATCH。attrib_list的属性可以是EGL_HEIGHT、EGL_LARGEST_PBUFFER、EGL_MIPMAP_TEXTURE、EGL_TEXTURE_FORMAT、EGL_TEXTURE_TARGET、EGL_VG_ALPHA_FORMAT、EGL_VG_COLORSPACE、EGL_WIDTH。

eglCreatePixmapSurface——

EGLAPI EGLSurface EGLAPIENTRY eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config,
                  EGLNativePixmapType pixmap,
                  const EGLint *attrib_list);

eglCreatePixmapSurface用于创建off-screen的pixmap surface,失败时返回EGL_NO_SURFACE,可能的错误为EGL_BAD_DISPLAY、EGL_NOT_INITIALIZED、EGL_BAD_CONFIG、EGL_BAD_NATIVE_PIXMAP、EGL_BAD_ATTRIBUTE、EGL_BAD_ALLOC、EGL_BAD_MATCH。attrib_list的属性可以是EGL_VG_ALPHA_FORMAT、EGL_VG_COLORSPACE。

eglDestroySurface——

EGLAPI EGLBoolean EGLAPIENTRY eglDestroySurface(EGLDisplay dpy, EGLSurface surface);

eglDestroySurface用于销毁surface,有其它线程使用这个surface时要等到不使用时在销毁,返回EGL_FALSE时可能的错误为EGL_BAD_DISPLAY、EGL_NOT_INITIALIZED、EGL_BAD_SURFACE。

eglQuerySurface——

EGLAPI EGLBoolean EGLAPIENTRY eglQuerySurface(EGLDisplay dpy, EGLSurface surface,
               EGLint attribute, EGLint *value);

eglQuerySurface用于获取surface信息,返回EGL_FALSE时可能的错误为EGL_BAD_DISPLAY、EGL_NOT_INITIALIZED、EGL_BAD_SURFACE、EGL_BAD_ATTRIBUTE。attribute取值为:EGL_CONFIG_ID、EGL_HEIGHT、EGL_HORIZONTAL_RESOLUTION、EGL_LARGEST_PBUFFER、EGL_MIPMAP_LEVEL、EGL_MIPMAP_TEXTURE、EGL_MULTISAMPLE_RESOLVE、EGL_PIXEL_ASPECT_RATIO、EGL_RENDER_BUFFER、EGL_SWAP_BEHAVIOR、EGL_TEXTURE_FORMAT、EGL_TEXTURE_TARGET、EGL_VERTICAL_RESOLUTION、EGL_WIDTH。

eglBindAPI——

EGLAPI EGLBoolean EGLAPIENTRY eglBindAPI(EGLenum api);

eglBindAPI用于设置调用线程的渲染API,返回EGL_FALSE时可能的错误为EGL_BAD_PARAMETER。api取值为:EGL_OPENGL_API、EGL_OPENGL_ES_API、EGL_OPENVG_API。

eglQueryAPI——

EGLAPI EGLenum EGLAPIENTRY eglQueryAPI(void);

eglQueryAPI用于获取调用线程的渲染API,可能返回EGL_NONE。

eglWaitClient——

EGLAPI EGLBoolean EGLAPIENTRY eglWaitClient(void);

eglWaitClient用于等待client API执行完毕才继续后面的渲染工作,返回EGL_FALSE时可能的错误为EGL_BAD_CURRENT_SURFACE。

eglReleaseThread——

EGLAPI EGLBoolean EGLAPIENTRY eglReleaseThread(void);

eglReleaseThread用于清空每个线程的状态为初始值,如错误、API、context等。

eglCreatePbufferFromClientBuffer——

EGLAPI EGLSurface EGLAPIENTRY eglCreatePbufferFromClientBuffer(
          EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer,
          EGLConfig config, const EGLint *attrib_list);

eglCreatePbufferFromClientBuffer用于创建绑定到OpenVG图片的off-screen的pixel buffer surface,失败时返回EGL_NO_SURFACE,可能的错误为EGL_BAD_DISPLAY、EGL_NOT_INITIALIZED、EGL_BAD_CONFIG、EGL_BAD_PARAMETER、EGL_BAD_ACCESS、EGL_BAD_ATTRIBUTE、EGL_BAD_ALLOC、EGL_BAD_MATCH。buftype值为EGL_OPENVG_IMAGE,attrib_list的属性可以是EGL_MIPMAP_TEXTURE、EGL_TEXTURE_FORMAT、EGL_TEXTURE_TARGET。

eglSurfaceAttrib——

EGLAPI EGLBoolean EGLAPIENTRY eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface,
                EGLint attribute, EGLint value);

eglSurfaceAttrib用于设置surface属性,返回EGL_FALSE时可能的错误为EGL_BAD_DISPLAY、EGL_BAD_MATCH、EGL_NOT_INITIALIZED、EGL_BAD_SURFACE、EGL_BAD_ATTRIBUTE。attribute值为EGL_MIPMAP_LEVEL、EGL_MULTISAMPLE_RESOLVE、EGL_SWAP_BEHAVIOR。

eglBindTexImage——

EGLAPI EGLBoolean EGLAPIENTRY eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer);

eglBindTexImage用于定义二维纹理图片,返回EGL_FALSE时可能的错误为EGL_BAD_ACCESS、EGL_BAD_MATCH、EGL_BAD_SURFACE。

eglReleaseTexImage——

EGLAPI EGLBoolean EGLAPIENTRY eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer);

eglReleaseTexImage用于释放用作纹理的color buffer,返回EGL_FALSE时可能的错误为EGL_BAD_MATCH、EGL_BAD_SURFACE。

eglSwapInterval——

EGLAPI EGLBoolean EGLAPIENTRY eglSwapInterval(EGLDisplay dpy, EGLint interval);

eglSwapInterval用于设置buffer交换时的最小帧数,返回EGL_FALSE时可能的错误为EGL_BAD_CONTEXT、EGL_BAD_SURFACE。

eglCreateContext——

EGLAPI EGLContext EGLAPIENTRY eglCreateContext(EGLDisplay dpy, EGLConfig config,
                EGLContext share_context,
                const EGLint *attrib_list);

eglCreateContext用于创建渲染context,失败时返回EGL_NO_CONTEXT,可能的错误为EGL_BAD_MATCH、EGL_BAD_DISPLAY、EGL_NOT_INITIALIZED、EGL_BAD_CONFIG、EGL_BAD_CONTEXT、EGL_BAD_ATTRIBUTE、EGL_BAD_ALLOC。attrib_list属性值为EGL_CONTEXT_CLIENT_VERSION。

eglDestroyContext——

EGLAPI EGLBoolean EGLAPIENTRY eglDestroyContext(EGLDisplay dpy, EGLContext ctx);

eglDestroyContext用于销毁渲染context,如果有其它线程使用这个context时就等到不使用时再销毁,返回EGL_FALSE时可能的错误为EGL_BAD_DISPLAY、EGL_NOT_INITIALIZED、EGL_BAD_CONTEXT。

eglMakeCurrent——

EGLAPI EGLBoolean EGLAPIENTRY eglMakeCurrent(EGLDisplay dpy, EGLSurface draw,
              EGLSurface read, EGLContext ctx);

eglMakeCurrent用于绑定渲染context和surface,返回EGL_FALSE时可能的错误为EGL_BAD_DISPLAY、EGL_NOT_INITIALIZED、EGL_BAD_SURFACE、EGL_BAD_CONTEXT、EGL_BAD_MATCH、EGL_BAD_ACCESS 、EGL_BAD_NATIVE_PIXMAP、EGL_BAD_NATIVE_WINDOW、EGL_BAD_CURRENT_SURFACE、EGL_BAD_ALLOC、EGL_CONTEXT_LOST。

eglGetCurrentContext——

EGLAPI EGLContext EGLAPIENTRY eglGetCurrentContext(void);

eglGetCurrentContext用于获取当前的渲染context。

eglGetCurrentSurface——

EGLAPI EGLSurface EGLAPIENTRY eglGetCurrentSurface(EGLint readdraw);

eglGetCurrentSurface用于获取当前的surface。

eglGetCurrentDisplay——

EGLAPI EGLDisplay EGLAPIENTRY eglGetCurrentDisplay(void);

eglGetCurrentDisplay用于获取当前的display。

eglQueryContext——

EGLAPI EGLBoolean EGLAPIENTRY eglQueryContext(EGLDisplay dpy, EGLContext ctx,
               EGLint attribute, EGLint *value);

eglQueryContext用于获取context信息,返回EGL_FALSE时可能的错误为EGL_BAD_DISPLAY、EGL_NOT_INITIALIZED、EGL_BAD_CONTEXT、EGL_BAD_ATTRIBUTE。attribute值为EGL_CONFIG_ID、EGL_CONTEXT_CLIENT_TYPE、EGL_CONTEXT_CLIENT_VERSION、EGL_RENDER_BUFFER。

eglWaitGL——

EGLAPI EGLBoolean EGLAPIENTRY eglWaitGL(void);

eglWaitGL用于执行GL操作完毕后才继续后面的渲染工作,返回EGL_FALSE时可能的错误为EGL_BAD_CURRENT_SURFACE。

eglWaitNative——

EGLAPI EGLBoolean EGLAPIENTRY eglWaitNative(EGLint engine);

eglWaitNative用于native操作执行完毕之后才继续后面GL渲染,返回EGL_FALSE时可能的错误为EGL_BAD_CURRENT_SURFACE。engine值为EGL_CORE_NATIVE_ENGINE。

eglSwapBuffers——

EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffers(EGLDisplay dpy, EGLSurface surface);

eglSwapBuffers用于置换surface的颜色buffer到native window,返回EGL_FALSE时可能的原因为EGL_BAD_DISPLAY、EGL_NOT_INITIALIZED、EGL_BAD_SURFACE、EGL_CONTEXT_LOST。

eglCopyBuffers——

EGLAPI EGLBoolean EGLAPIENTRY eglCopyBuffers(EGLDisplay dpy, EGLSurface surface,
              EGLNativePixmapType target);

eglCopyBuffers用于拷贝surface的颜色buffer到native pixmap,返回EGL_FALSE时可能的原因为EGL_BAD_DISPLAY、EGL_NOT_INITIALIZED、EGL_BAD_SURFACE、EGL_BAD_NATIVE_PIXMAP、EGL_BAD_MATCH、EGL_CONTEXT_LOST。

eglGetProcAddress——

typedef void (*__eglMustCastToProperFunctionPointerType)(void);
EGLAPI __eglMustCastToProperFunctionPointerType EGLAPIENTRY
       eglGetProcAddress(const char *procname);

eglGetProcAddress用于获取GL或EGL的扩展函数。

5、EGL综述

(以下内容翻译自https://www.khronos.org/registry/EGL/sdk/docs/man/html/eglIntro.xhtml)

EGL(The Khronos Platform Graphics Interface)提供了一种方法用于通过客户端API和本地窗口系统进行渲染,客户端API包括用于嵌入式系统的3D渲染器OpenGL ES、用于桌面系统的的OpenGL ES的超集OpenGL、2D矢量图形渲染器OpenVG,本地窗口系统包括Windows、X。

基于EGL的实现,它或多或少与本地窗口系统紧密关联,大多数EGL功能都需要一个显示连接,这可以通过函数eglGetDisplay获得,然后通过函数eglInitialize初始化显示连接并获得EGL版本号。

本地窗口系统使得EGL的一系列图形可用于客户端API的渲染,这些图形可能是pixel格式、frame buffer配置等,通过这些图形还可能通过本地窗口系统的API创建window和pixmap。

EGL的surface从本地window或pixmap扩展而来,还带有一些额外的buffer,包括color buffer、depth buffer、stencil buffer和alpha mask buffer,在EGL的frame buffer配置中包含这些额外buffer的部分或全部。

EGL支持三种类型的surface渲染,分别是window、pixmap和pixel buffer。其中,window和pixmap类型的surface与本地窗口系统对应的资源息息相关;而pixel buffer则是EGL资源独享的,不可通过本地窗口系统进行渲染。

为了能够在EGL的surface上使用客户端API进行渲染,必须使用应用程序需要的渲染特性来配置合适的EGL frame buffer,相关的三个函数为eglChooseConfig、eglGetConfigs和eglGetConfigAttrib。对于window和pixmap类型的EGL surface来说,合适的本地window或pixmap匹配了本地图形时,应该首先被创建出来;对于一个给定个EGL frame buffer配置,可以通过eglGetConfigAttrib获取本地图形的类型和ID;而对于pixpel buffer来说,则不需本地资源。

从本地窗口创建EGL的window surface时调用eglCreateWindowSurface,从本地pixmap创建EGL的pixmap surface时调用eglCreatePixmapSurface,而创建与本地buffer无关联的EGL pixel buffer surface时,则使用eglCreatePbufferSurface,通过eglCreatePbufferFromClientBuffer创建的pbuffer surface的color buffer则是由OpenVG提供的,使用eglDestroySurface可以释放之前分配的资源。

绑定客户端的渲染与EGL的surface时,需要用到EGL渲染context,context与surface的frame buffer配置必须是兼容的,通过eglCreateContext创建EGL渲染context,客户端API的类型还会被第一次调用eglBindAPI而设定。

通过eglMakeCurrent可能绑定了一个EGL渲染context到一个或多个EGL surface,这样context和surface就建立了关系,后面的客户端API渲染都使用了同样的context,直到以不同的参数来再次调用eglMakeCurrent。

在同一个surface上可能同时执行了本地和客户端API的命令,但它们不是同步的,同步需要调用eglWaitClient或eglWaitNative,或者是其它的本地窗口系统命令。

下面是一个非常简单的例子,用于创建RGBA格式的window,通过OpenGL ES进行渲染,程序运行后,window颜色为黄色。

#include 
#include 
#include 
#include 
typedef ... NativeWindowType;
extern NativeWindowType createNativeWindow(void);
static EGLint const attribute_list[] = {
        EGL_RED_SIZE, 1,
        EGL_GREEN_SIZE, 1,
        EGL_BLUE_SIZE, 1,
        EGL_NONE
};
int main(int argc, char ** argv)
{
        EGLDisplay display;
        EGLConfig config;
        EGLContext context;
        EGLSurface surface;
        NativeWindowType native_window;
        EGLint num_config;
        /* get an EGL display connection */
        display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
        /* initialize the EGL display connection */
        eglInitialize(display, NULL, NULL);
        /* get an appropriate EGL frame buffer configuration */
        eglChooseConfig(display, attribute_list, &config, 1, &num_config);
        /* create an EGL rendering context */
        context = eglCreateContext(display, config, EGL_NO_CONTEXT, NULL);
        /* create a native window */
        native_window = createNativeWindow();
        /* create an EGL window surface */
        surface = eglCreateWindowSurface(display, config, native_window, NULL);
        /* connect the context to the surface */
        eglMakeCurrent(display, surface, surface, context);
        /* clear the color buffer */
        glClearColor(1.0, 1.0, 0.0, 1.0);
        glClear(GL_COLOR_BUFFER_BIT);
        glFlush();
        eglSwapBuffers(display, surface);
        sleep(10);
        return EXIT_SUCCESS;
}

你可能感兴趣的:(Android知识库)