【ATU Book-GPU 系列】EGL 簡介及操作流程

一、 EGL簡介 

EGL (Embedded-System Graphics Library) 函式庫是一個介於 Khronos 渲染函式庫 (如 OpenGL、OpenGL ES、OpenVG 等) 與下層平台視窗系統 (如 Microsoft Windows、Linux X Window、Mac Quartz) 之間的介面。EGL 用於圖形上下文管理 (graphics context management)、表層 / 緩衝區綁定 (surface/buffer binding)、渲染同步 (rendering synchronization) 與激活 Khronos 高效能 2D / 3D 渲染函式庫。EGL 函式庫實現了 OpenGL、OpenGL ES 等函式庫的跨平台特性。 

舉個例子來說,EGL 是一個畫廊的工作員,負責的工作就是將畫家會使用到得工具準備好 (Initial),例如:畫架、畫布、調色盤等等 。然後讓畫家 OpenGL 在準備好的環境裡作畫。等 OpenGL 完成畫作後, EGL 要把先前準備給畫家使用的工具都收好 (Destroy) ,所以 EGL 的工作只有 Initial 與 Destroy 兩件事,下面會針對這兩件工作的操作流程作說明。 

 


圖1.1、EGL / 渲染函式庫 / 平台視窗系統關係示意圖 

 

二、 EGL初始化操作流程 

 

圖 2.1、EGL 初始化流程圖 

 

  1. 定義EGL 設備的結構 (EGL device structure),初始化 EGL 會使用到的項目 (item),並將項目集成一個結構。其中包含:顯示類型、顯示、配置屬性、配置、視窗、表面、上下文屬性、上下文。如下面代碼: 

struct egl_device { 

    EGLNativeDisplayType display_type; 

    EGLDisplay display; 

    const EGLint *config_attributes; 

    EGLConfig config; 

    EGLNativeWindowType window; 

    EGLSurface surface; 

    const EGLint *context_attributes; 

    EGLContext context; 

}; 

  1. 使用fbGetDisplayByIndex() API 與 FB 系統申請用於顯示的 Frame Buffer。 

        使用說明: 

            fbGetDisplayByIndex(Num); 

                Num:frame buffer 的索引 

  1. 使用eglGetDisplay() API 將申請到的 Frame Buffer 作為 EGL 顯示設備。 

        使用說明: 

            eglGetDisplay(DisType) 

                DisType:從 fbGetDisplayByIndex() API 取得的顯示類型 

  1. 使用eglInitialize() API 作 EGL 初始化。 

        使用說明: 

            eglInitialize(display, major, minor) 

                display:指定 EGL 顯示裝置 

                major:EGL 主要版本的回傳值,可為 NULL 

                minor:EGL 主要版本的回傳值,可為 NULL 

  1. 使用eglBindAPI() AP 將 EGL 顯示設備與渲染函式庫作連接。 

        使用說明: 

            eglBindAPI(api) 

                api: 指定渲染函式庫,可為 EGL_OPENGL_API、EGL_OPENGL_ES_API、EGL_OPENVG_API 

  1. 設定EGL 配置屬性,屬性設定結尾必須使用 EGL_NONE 作為結尾。詳細的屬性設定請參考 Khronos 官方網站: 

        https://www.khronos.org/registry/EGL/sdk/docs/man/html/eglChooseConfig.xhtml 

  1. 使用eglChooseConfig() API 設定最佳配置屬性。 

        使用說明: 

            eglChooseConfig(display, attrib_list, configs, config_size, num_config) 

                display: 指定 EGL 顯示設備 

                attrib_list: 指定 EGL 配置屬性 

                configs: 最佳配置屬性的回傳值 

                config_size: 指定配置屬性的陣列大小 

                num_config: 配置屬性個數的回傳值 

  1. 使用fbCreateWindow() API 開啟顯示視窗。 

        使用說明: 

            fbCreateWindow(display, x, y, width, height) 

                display: 指定 EGL 顯示設備 

                x: 指定視窗的水平位置 

                y: 指定視窗的垂直位置 

                width: 指定視窗的寬度 

                height: 指定視窗的高度 

  1. 使用eglCreateWindowSurface() API 開啟顯示視窗表面。 

        使用說明: 

            eglCreateWindowSurface(display, config, native_window, attrib_list) 

                display: 指定 EGL 顯示設備 

                config: 指定 EGL 配置屬性 

                native_window: 指定顯示視窗 

                attrib_list: 指定表面屬性,可為 NULL 

  1. 設定上下文屬性,屬性設定結尾必須使用EGL_NONE 作為結尾。詳細的屬性設定請參考 Khronos 官方網站: 

        https://www.khronos.org/registry/EGL/sdk/docs/man/html/eglCreateContext.xhtml 

  1. 使用eglCreateContext() API 開啟上下文。 

        使用說明: 

            eglCreateContext(display, config, share_context, attrib_list) 

                display: 指定 EGL 顯示設備 

                config: 指定 EGL 配置屬性 

                share_context: 指定共享資訊的上下文,設定為 EGL_NO_CONTEXT 表示不分享資訊 

                attrib_list: 指定上下文屬性 

  1. 使用eglMakeCurrent() API 將目前 EGL 設定作為顯示。 

        使用說明: 

            eglMakeCurrent(display, draw, read, context) 

                display: 指定 EGL 顯示設備 

                draw: 指定EGL 寫入的顯示視窗表面 

                read: 指定EGL 讀取的顯示視窗表面 

                context: 指定 EGL 用於渲染的上下文 

依照上述步驟就可以完成 EGL 初始化,參考代碼如下: 


device->display_type = (EGLNativeDisplayType)fbGetDisplayByIndex(0); 

device->display = eglGetDisplay(device->display_type); 

eglInitialize(device->display, NULL, NULL); 

eglBindAPI(EGL_OPENGL_ES_API); 

static const EGLint config_attributes[] = { 

    EGL_SAMPLES, 0, 

    EGL_RED_SIZE,8, 

    EGL_GREEN_SIZE,8, 

    EGL_BLUE_SIZE,8, 

    EGL_ALPHA_SIZE,EGL_DONT_CARE, 

    EGL_DEPTH_SIZE,0, 

    EGL_SURFACE_TYPE,EGL_WINDOW_BIT, 

    EGL_NONE 

}; 

EGLint config_count = 0; 

eglChooseConfig(device->display, config_attributes, &device->config, 1, &config_count); 

device->config_attributes = config_attributes; 

device->window = fbCreateWindow(device->display_type, 0, 0, 1080, 1080); 

device->surface = eglCreateWindowSurface(device->display, device->config, device->window, NULL); 

static const EGLint context_attributes[] = { 

    EGL_CONTEXT_CLIENT_VERSION,2, 

    EGL_NONE 

}; 

device->context = eglCreateContext(device->display, device->config, EGL_NO_CONTEXT, context_attributes); 

device->context_attributes = context_attributes; 

eglMakeCurrent(device->display, device->surface, device->surface, device->context);

 

三、 EGL 去初始化操作流程 

當你使用完渲染函式庫,要結束應用成事時,需要將 EGL 作去初始化的動作,以便將占用到的資源返還給系統。EGL 去初始化的流程需要符合類似 FILO (First In Last Out) 的原則。因此,去初始化的操作流程會如下面流程圖: 


圖 2.2、EGL 去初始化流程圖 

 

  1. 使用 eglMakeCurrent() API 設定 EGL 設備為無表面、無上下文。 

        使用說明: 

            eglMakeCurrent(display, draw, read, context) 

                display: 指定 EGL 顯示設備 

                draw: 設定為 EGL_NO_SURFACE 表示無表面連結 

                read: 設定為 EGL_NO_SURFACE 表示無表面連結 

                context: 設定為 EGL_NO_CONTEXT 標示無上下文連結 

  1. 使用eglDestroyContext() API 銷毀上下文。 

        使用說明: 

            eglDestroyContext(display, context) 

                display: 指定 EGL 顯示設備 

                context: 指定 EGL 上下文 

  1. 使用 eglDestroySurface() API 銷毀表面。 

        使用說明: 

            eglDestroySurface(display, surface) 

                display: 指定 EGL 顯示設備 

                surface: 指定 EGL 表面 

  1. 使用 fbDestroyWindow() API 銷毀顯示視窗。 

        使用說明: 

            fbDestroyWindow(window) 

                window: 指定顯示視窗 

  1. 使用 eglTerminate() API 終止 EGL 顯示設備。 

        使用說明: 

            eglTerminate(display) 

                display: 指定 EGL 顯示設備 

  1. 使用 eglReleaseThread() API 釋放運作。 

        使用說明: 

            eglReleaseThread(void) 

依照上述步驟就可以完成 EGL 去初始化,參考代碼如下: 

eglMakeCurrent(device->display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); 

eglDestroyContext(device->display, device->context); 

device->context = (EGLContext)0; 

eglDestroySurface(device->display, device->surface); 

device->surface = (EGLSurface)0; 

fbDestroyWindow(device->window); 

device->window = (EGLNativeWindowType)0; 

eglTerminate(device->display); 

device->display = (EGLDisplay)0; 

eglReleaseThread(); 

 

四、 參考文獻 

  1. 1.《OpenGL ES 3.0 Programming Guide》2ndEdition 

 

 

★博文內容均由個人提供,與平台無關,如有違法或侵權,請與網站管理員聯繫。

★文明上網,請理性發言。內容一周內被舉報5次,發文人進小黑屋喔~

評論