1.获取Display:
Display代表显示器,在有些系统上可以有多个显示器,也就会有多个Display。(Sam觉得这个观点有点牵强,Sam觉得Display理解为显存Framebuffer比较合适一些)。获得Display要调用EGLbooleaneglGetDisplay(NativeDisplay dpy),参数一般为EGL_DEFAULT_DISPLAY 。该参数实际的意义是平台实现相关的,在X-Window下是XDisplay ID,在MSWindows下是Window DC。EGL(Boardcom)为NativeDisplayType。
Sam: 所以在不同平台开发时,第一件需要确认的就是:这个平台上的display概念是的实现是什么?
现在分Broadcom和Hi3716平台做分别的分析:
Broadcom:
GLAPI EGLDisplay APIENTRY eglGetDisplay( NativeDisplay display)
Hi3716:
EGLAPI EGLDisplay EGLAPIENTRY eglGetDisplay(EGLNativeDisplayTypedisplay_id);
请注意参数类型,所有用到本地窗口系统的地方都用屏蔽指针来处理.这样保证了它可移植性. 返回值EGLDisplay也只是个指针。
其语义如下:
eglGetDisplay()通过nativeDisplay得到Display,Dispaly为EGLDisplay类型的值,是一个关联系统物理屏幕的通用数据类型。
1.1 : Broadcom平台中eglGetDisplay()动作如下:
首先它做了一些硬件方面的准备工作。并返回了类型为EGL_P_Display的一个struct 地址。
typedef struct
{
NativeDisplay nativeDisplay;
BMEM_Handle hMem;
BP3D_Handle hP3d;
EGLint iError;
EGL_P_Context *pContext;
EGL_P_Surface *pDrawSurface;
EGL_P_Surface *pReadSurface;
GLboolean bGenerateMipmaps;
}
EGL_P_Display;
其中NativeDisplay就是参数1--NativeDisplay display。
BP3D_Handle则为3D句柄。
1.2: Hi3716平台使用GC800 芯片。所以实现被放在_vdkEGL中了。暂时没法看到。
2.EGL初始化:
EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint*minor);
每个 EGLDisplay在使用前都需要初始化。初始化 EGLDisplay的同时,你可以得到系统中 EGL 的实现版本号。
2.1Broadcom平台的eglInitialize ()
GLAPIEGLBoolean APIENTRY eglInitialize( EGLDisplay dpy, EGLint *major,EGLint *minor )
它只是非常简单的返回了主次版本号。
eglQueryString() 函数是另外一个获取版本信息和其他信息的途径。通过 eglQueryString()获取版本信息需要解析版本字符串。
GLAPI const char * APIENTRY eglQueryString(EGLDisplay dpy, EGLint name )
支持的name有:EGL_VENDOR,EGL_VERSION。 分别返回:"Broadcom","1.0"
2.2 Hi3716平台:
3. 得到平台可用EGL配置:
EGLConfigs 是一个用来描述 EGL surface 配置信息的数据类型。要获取正确的渲染结果, Surface的格式是非常重要的。根据平台的不同, surface 配置可能会有限制,比如某个设备只支持 16 位色深显示,或是不支持stencil buffer ,还有其他的功能限制或精度的差异。
下面是获取系统可用的 EGL 配置信息的函数原型:
EGLBooleaneglGetConfigs (EGLDisplay dpy, EGLConfig *configs,EGLintconfig_size, EGLint *num_config);
3.1Broadcom 平台:
GLAPIEGLBoolean APIENTRY eglGetConfigs(
EGLDisplay dpy,
EGLConfig *configs,
EGLint config_size,
EGLint *num_config )
EGLboolean eglGetConfigs(EGLDisplay dpy,EGLConfig * config, EGLint config_size, EGLint *num_config)来获得所有config。
参数1:dpy, display.
参数2:输出参数,会在其中放置config.
参数3:config_size: 取config的个数。
参数4:num_config: 当参数2为空时,返回全部config个数。当参数2不为空时,返回读取config的个数。
注意:参数4num_config不能为空。
当参数2为空时,返回可支持的EGL Surface的个数。
当参数2不为空时,则返回参数4num_config个支持的EGL Surface 配置到参数2中。
4.察看选定EGL配置的具体特性:
GLAPIEGLBoolean APIENTRY eglGetConfigAttrib(
EGLDisplay dpy,
EGLConfig config,
EGLint attribute,
EGLint *value )
参数1:dpy, display.
参数2:config:指定config.
参数3:attribute:输入参数,想要知道的特性号。
参数4:value:输出参数,输入参数号的值。
5.选择一个配置:
以上得到了所有配置,可以通过一个类似filter的机制选择一个尽可能有效的配置。
EGLBoolean eglChooseConfig(EGLDisplay dpy,const EGLint *attrib_list, EGLConfig *configs, EGLint config_size,EGLint * num_config);
5.1: Broadcom平台:
EGLboolean eglChooseConfig(EGLDisplay dpy,const EGLint * attr_list, EGLConfig * config, EGLint config_size,EGLint *num_config);
参数1:dpy: display.
参数2:attr_list: 使用这个参数,来选中符合的config.
参数3:config: 将符合的config,放到这里。
参数4:想要选中符合的config的最大个数。
参数5:真正选中的符合的config的个数。
其中attr_list是以EGL_NONE结束的参数数组,通常以id,value依次存放,对于个别标识性的属性可以只有id,没有value。
6.建立Context
GLAPI EGLContext APIENTRY eglCreateContext(
EGLDisplay dpy,
EGLConfig config,
EGLContext share_list,
const EGLint *attrib_list )
建立display的EGL 配置为参数2config的Context.
主要是硬件做动作。
注意: 此处可以选择OpenGLES版本。
attrib_list[1]:为版本号。
1为1.0.
2为2.0
7.创建Display Window:
注意,这里是EGL的第二个输入概念点-NativeWindow.与之前的NativeDisplay对应。
所以在设置EGL时,要首先知道此平台NativeDisaplay和NativeWindow对应为什么概念。
GLAPI EGLSurface APIENTRY eglCreateWindowSurface(
EGLDisplay dpy,
EGLConfig config,
NativeWindow window,
const EGLint *attrib_list )
参数1:dpy: display.
参数2:要建立Surface的config.
参数3:本地window概念。
8.设置Display的当前Sruface.
GLAPI EGLBoolean APIENTRY eglMakeCurrent(
EGLDisplaydpy, //参数1:dpy:display.
EGLSurfacedraw, //参数2:正在绘制的surface. 由eglCreateWindowSurface创建
EGLSurface read,
EGLContext ctx )
9.交换current Surface来绘制。
应用程序通过OpenGL API进行绘制,一帧完成之后,调用eglSwapBuffers(EGLDisplay dpy,EGLContext ctx)来显示。