EGL簡介以及窗口初始化

屏幕上可見的幀緩沖區(qū)由一個像素數(shù)據(jù)的二維數(shù)組表示。直接在可顯示緩沖區(qū)上更新像素由一個嚴(yán)重的問題——用戶在部分更新幀緩沖區(qū)時看到偽像或者閃爍的現(xiàn)象

為了解決這個問題,引入了雙緩沖區(qū)。

OpenGLES應(yīng)用程序中,這種活動通過EGL函數(shù)eglSwapBuffers控制:

eglSwapBuffers(exContext->eglDisplay, esContext->eglSurface);

EGL提供以下機(jī)制:

與設(shè)備的原生窗口系統(tǒng)通信

查詢繪圖表面的可用類型和配置

創(chuàng)建繪圖表面

在OpenGLES3.0和其它圖形渲染API(如桌面OpenGL和OpenVG——硬件加速矢量圖形的跨平臺API,活著窗口系統(tǒng)的原生繪圖命令)之間同步渲染

管理紋理貼圖等渲染資源

與窗口系統(tǒng)通信

Apple提供自己的EGL API的iOS 實現(xiàn),稱為EAGL

因為每個窗口系統(tǒng)都有不同語義,所以EGL提供基本的不透明類型——EGLDisplay,該類封裝了所有系統(tǒng)相關(guān)性,用于和原生窗口系統(tǒng)接口交互。

任何使用EGL的應(yīng)用程序必須執(zhí)行的第一個操作是創(chuàng)建和初始化與本地EGL顯示的連接。

一、初始化EGL

EGLConfig config;

EGLint majorVersion;

EGLint minorVersion;

EGLint contextAttribs[] = {

EGL_CONTEXT_CLIENT_VERSION,? ? ? ? 3,? ? ? ? EGL_NONE

};

// 獲取寬和高

esContext->width = ANativeWindow_getWidth(esContext->eglNativeWindow);esContext->height = ANativeWindow_getHeight(esContext->eglNativeWindow);

// 打開與EGL顯示服務(wù)器的連接,默認(rèn)為EGL_DEFAULT_DISPLAY

esContext->eglDisplay = eglGetDisplay(esContext->eglNativeDisplay);

// 如果顯示連接不可用,則返回EGL_NO_DISPLAY標(biāo)志,此時無法創(chuàng)建窗口

if (esContext->eglDisplay == EGL_NO_DISPLAY) {

return GL_FALSE;

}

// 初始化egl并回傳版本號

if (!eglInitialize(esContext->eglDisplay, &majorVersion, &minorVersion)) {

return GL_FALSE;

}

成功打開連接后,需要初始化EGL,這通過調(diào)用如下函數(shù)完成:

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

dpy —— 指定EGL顯示連接

major —— 返回EGL的主版本號

minor —— 返回EGL的副版本號

二、確定可用表面配置

一旦初始化了EGL,就可以確定可用渲染表面的類型和配置,有兩種方法:

查詢每個表面配置,找出最好的選擇

指定一組需求,讓EGL推薦最佳配置

通常使用第二種方法更簡單,而且最有可能得到匹配。

任何一種情況下,EGL將返回一個EGLConfig,這是包含有關(guān)特定表面及其特性(每個顏色變量分量的位數(shù)、與EGLConfig相關(guān)的深度緩沖區(qū)(如果存在))的EGL內(nèi)部數(shù)據(jù)結(jié)構(gòu)的標(biāo)識符。

EGLint numConfigs = 0;

EGLint attribList[] = {

EGL_RED_SIZE, 5,

EGL_GREEN_SIZE, 6,

EGL_BLUE_SIZE, 5,

EGL_ALPHA_SIZE, (flags & ES_WINDOW_ALPHA) ? 8 : EGL_DONT_CARE,

EGL_DEPTH_SIZE, (flags & ES_WINDOW_DEPTH) ? 8 : EGL_DONT_CARE,

EGL_STENCIL_SIZE, (flags & ES_WINDOW_STENCIL) ? 8 : EGL_DONT_CARE,

EGL_SAMPLE_BUFFERS, (flags & ES_WINDOW_MULTISAMPLE) ? 1 : 0,

EGL_RENDERABLE_TYPE, getContextRenderableType(esContext->eglDisplay),

EGL_NONE

};

// 選擇Config

if (!eglChooseConfig(esContext->eglDisplay, attribList, &config, 1, &numConfigs)) {

return GL_FALSE;

}

if (numConfigs < 1) {

return GL_FALSE;

}

三、查詢EGLConfig屬性

EGLConfig包含關(guān)于EGL啟用的表面的所有信息??捎妙伾⑴c配置相關(guān)的其它緩沖區(qū)(深度和模板緩沖區(qū)等)、表面類型和其它特性

// Android需要獲取EGL_NATIVE_VISUAL_ID的值并將其放如ANativeWindow_setBuffersGeometry函數(shù)中

EGLint format = 0;

eglGetConfigAttrib(esContext->eglDisplay, config, EGL_NATIVE_VISUAL_ID, &format);

ANativeWindow_setBuffersGeometry(esContext->eglNativeWindow, 0, 0, format);

四、創(chuàng)建屏幕上的渲染區(qū)域:EGL窗口

EGLAPI EGLSurface EGLAPIENTRY eglCreateWindowSurface(EGLDisplay dpy,

EGLConfig config,

EGLNativeWindowType win,

const EGLint *attrib_list);

該函數(shù)用于創(chuàng)建一個窗口,以我們得到的原生顯示管理器的連接和前一步得到的EGLConfig為參數(shù)。它需要原生窗口系統(tǒng)事先創(chuàng)建一個窗口。

創(chuàng)建窗口示例:

// 創(chuàng)建一個EGL窗口表面示例

EGLint list[] = {

EGL_RENDER_BUFFER, EGL_BACK_BUFFER, EGL_NONE

};

EGLSurface window = eglCreateWindowSurface(esContext->eglDisplay, config,

esContext->eglNativeWindow, list);

if (window == EGL_NO_SURFACE) {

switch (eglGetError()) {

case EGL_BAD_MATCH:

break;

case EGL_BAD_CONFIG:

break;

case EGL_BAD_NATIVE_WINDOW:

break;

case EGL_BAD_ALLOC:

break;

}

}

上面的代碼是創(chuàng)建一個繪圖場景,但是我們還必須完成兩個步驟,才能成功地用OpenGLES繪圖。然而窗口不是唯一可用的渲染表面,也可以使用屏幕外渲染區(qū)域,也就是離屏渲染。

屏幕外渲染區(qū)域(離屏渲染):EGL Pbuffer

OpenGLES3.0除了可以進(jìn)行屏幕渲染,也可以在不可見的屏幕外渲染,也就是在像素緩沖區(qū)上進(jìn)行渲染,支持硬件加速。Pbuffer最常用于紋理貼圖。

創(chuàng)建Pbuffer 和 創(chuàng)建EGL窗口非常相似,只有少數(shù)微笑的不同。

創(chuàng)建Pbuffer需要和窗口一樣找到EGLConfig,并作一些修改:需要擴(kuò)增EGL_SURFACE_TYPE的值,使其包含EGL_PBUFFER_BIT。

創(chuàng)建EGL像素緩沖區(qū)示例如下:

EGLint bufferList[] = {

EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,

EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT_KHR,

EGL_RED_SIZE, 5,

EGL_GREEN_SIZE, 6,

EGL_BLUE_SIZE, 5,

EGL_DEPTH_SIZE, 1,

EGL_NONE

};

const EGLint MaxConfigs = 10;

EGLConfig configs[MaxConfigs];

EGLint numConfigs;

if (!eglChooseConfig(esContext->eglDisplay, bufferList, configs, MaxConfigs, &numConfigs)) {

return GL_FALSE;

}

EGLSurface pbuffer;

EGLint attribufferList[] = {

EGL_WIDTH, 512,

EGL_HEIGHT, 512,

EGL_LARGEST_PBUFFER, EGL_TRUE,

EGL_NONE

};

pbuffer = eglCreatePbufferSurface(esContext->eglDisplay, config, attribufferList);

if (pbuffer == EGL_NO_SURFACE) {

switch (eglGetError()) {

case EGL_BAD_ALLOC:

break;

case EGL_BAD_CONFIG:

break;

case EGL_BAD_PARAMETER:

break;

case EGL_BAD_MATCH:

break;

}

}

// 檢查pbuffer 分配的內(nèi)存大小

EGLint width;

EGLint height;

if (!eglQuerySurface(esContext->eglDisplay, pbuffer, EGL_WIDTH, &width)

|| !eglQuerySurface(esContext->eglDisplay, pbuffer, EGL_HEIGHT, &height)) {

// 不能查詢 surface的信息

return GL_FALSE;

}

五、創(chuàng)建渲染上下文

渲染上下文是OpenGLES3.0的內(nèi)部數(shù)據(jù)結(jié)構(gòu),包含操作所需要的所有狀態(tài)信息。它包含了對頂點(diǎn)著色器和片元著色器數(shù)據(jù)的引用。

// 5.創(chuàng)建上下文

esContext->eglContext = eglCreateContext(esContext->eglDisplay, config,

EGL_NO_CONTEXT, contextAttribs);

// 判斷上下文是否創(chuàng)建成功

if (esContext->eglContext == EGL_NO_CONTEXT) {

return GL_FALSE;

}

// 根據(jù)之前的配置構(gòu)建上下文

if (!eglMakeCurrent(esContext->eglDisplay, esContext->eglSurface, esContext->eglSurface, esContext->eglContext)) {

return GL_FALSE;

}

六、指定某個EGLContext為當(dāng)前上下文

// 指定某個EGLContext為當(dāng)前上下文

if (!eglMakeCurrent(esContext->eglDisplay, esContext->eglSurface,

esContext->eglSurface, esContext->eglContext)) {

return GL_FALSE;

}

同步渲染

多個圖形API在單個窗口中的渲染,此時需要使用同步渲染,需要應(yīng)用程序允許多個庫渲染到共享窗口。

如果不止使用OpenGLES3.0渲染,則不能簡單地調(diào)用glFinish來抱著個所有渲染已經(jīng)發(fā)生,你可以調(diào)用:

EGLBoolean eglWaitClient()

延遲客戶端的執(zhí)行,直到某個API的所有渲染完成,成功返回EGL_TRUE,失敗時返回EGL_FALSE并發(fā)送EGL_BAD_CURRENT_SURFACE錯誤

同樣,如果你需要保證原生窗口系統(tǒng)的渲染完成,則調(diào)用如下函數(shù):

EGLBoolean eglWaitNative(EGLint engine)

engine,指定渲染程序等待渲染完成

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容