OpenGL ES: (3) EGL、EGL繪圖的基本步驟、EGLSurface、ANativeWindow


1. EGL概述

EGL 是 OpenGL ES 渲染 API 和本地窗口系統(native platform window system)之間的一個中間接口層,它主要由系統制造商實現。

EGL提供如下機制:

  • 與設備的原生窗口系統通信
  • 查詢繪圖表面的可用類型和配置
  • 創建繪圖表面
  • 在OpenGL ES 和其他圖形渲染API之間同步渲染
  • 管理紋理貼圖等渲染資源
  • 為了讓OpenGL ES能夠繪制在當前設備上,我們需要EGL作為OpenGL ES與設備的橋梁。

2. 使用EGL繪圖的基本步驟

Display(EGLDisplay) 是對實際顯示設備的抽象。

Surface(EGLSurface)是對用來存儲圖像的內存區域。

FrameBuffer 的抽象,包括 Color Buffer, Stencil Buffer ,Depth Buffer。Context (EGLContext) 存儲 OpenGL ES繪圖的一些狀態信息。

使用EGL的繪圖的一般步驟:

1、獲取 EGL Display 對象:eglGetDisplay()
2、初始化與 EGLDisplay 之間的連接:eglInitialize()
3、獲取 EGLConfig 對象:eglChooseConfig()
4、創建 EGLContext 實例:eglCreateContext()
5、創建 EGLSurface 實例:eglCreateWindowSurface()
6、連接 EGLContext 和 EGLSurface:eglMakeCurrent()
7、使用 OpenGL ES API 繪制圖形:gl_*()
8、切換 front buffer 和 back buffer 送顯:eglSwapBuffer()
9、斷開並釋放與 EGLSurface 關聯的 EGLContext 對象:eglRelease()
10、刪除 EGLSurface 對象
11、刪除 EGLContext 對象
12、終止與 EGLDisplay 之間的連接

標准 EGL 數據類型如下所示:

EGLBoolean —— EGL_TRUE =1, EGL_FALSE=0
EGLint —— int 數據類型
EGLDisplay —— 系統顯示 ID 或句柄,可以理解為一個前端的顯示窗口
EGLConfig —— Surface的EGL配置,可以理解為繪制目標framebuffer的配置屬性
EGLSurface —— 系統窗口或 frame buffer 句柄 ,可以理解為一個后端的渲染目標窗口。
EGLContext —— OpenGL ES 圖形上下文,它代表了OpenGL狀態機;如果沒有它,OpenGL指令就沒有執行的環境。

下面幾個類型比較復雜,通過例子可以更深入的理解。這里要說明的是這幾個類型在不同平台其實現是不同的,EGL只提供抽象標准。

NativeDisplayType—— Native 系統顯示類型,標識你所開發設備的物理屏幕

NativeWindowType —— Native 系統窗口緩存類型,標識系統窗口

NativePixmapType —— Native 系統 frame buffer,可以作為 Framebuffer 的系統圖像(內存)數據類型,該類型只用於離屏渲染。

3. EGLSurface

EGLSurface 可以是由 EGL 分配的離屏緩沖區(稱為“pbuffer”),或由操作系統分配的窗口。EGL 窗口 Surface 通過 eglCreateWindowSurface() 調用被創建。該調用將“窗口對象”作為參數,在 Android 上,該對象可以是 SurfaceView、SurfaceTexture、SurfaceHolder 或 Surface,所有這些對象下面都有一個 BufferQueue。當您進行此調用時,EGL 將創建一個新的 EGLSurface 對象,並將其連接到窗口對象的 BufferQueue 的生產方接口。此后,渲染到該 EGLSurface 會導致一個緩沖區離開隊列、進行渲染,然后排隊等待消耗方使用。(術語“窗口”表示預期用途,但請注意,輸出內容不一定會顯示在顯示屏上。)

EGL 不提供鎖定/解鎖調用,而是由您發出繪制命令,然后調用 eglSwapBuffers() 來提交當前幀。方法名稱來自傳統的前后緩沖區交換,但實際實現可能會有很大的不同。

一個 Surface 一次只能與一個 EGLSurface 關聯(您只能將一個生產方連接到一個 BufferQueue),但是如果您銷毀該 EGLSurface,它將與該 BufferQueue 斷開連接,並允許其他內容連接到該 BufferQueue。

通過更改“當前”EGLSurface,指定線程可在多個 EGLSurface 之間進行切換。一個 EGLSurface 一次只能在一個線程上處於當前狀態。

關於 EGLSurface 最常見的一個錯誤理解就是假設它只是 Surface 的另一方面(如 SurfaceHolder)。它是一個相關但獨立的概念。您可以在沒有 Surface 作為支持的 EGLSurface 上繪制,也可以在沒有 EGL 的情況下使用 Surface。EGLSurface 僅為 GLES 提供一個繪制的地方。

4. ANativeWindow

公開的 Surface 類以 Java 編程語言實現。C/C++ 中的同等項是 ANativeWindow 類,由 Android NDK 半公開。您可以使用 ANativeWindow_fromSurface() 調用從 Surface 獲取 ANativeWindow。就像它的 Java 語言同等項一樣,您可以對 ANativeWindow 進行鎖定、在軟件中進行渲染,以及解鎖並發布。

要從原生代碼創建 EGL 窗口 Surface,可將 EGLNativeWindowType 的實例傳遞到 eglCreateWindowSurface()。EGLNativeWindowType 是 ANativeWindow 的同義詞,您可以自由地在它們之間轉換。

基本的“原生窗口”類型只是封裝 BufferQueue 的生產方,這一點並不足為奇。

5. EGLSurface與ANativeWindow之間的關系

OpenGL ES 定義了一個渲染圖形的 API,但沒有定義窗口系統。為了讓 GLES 能夠適合各種平台,GLES 將與知道如何通過操作系統創建和訪問窗口的庫結合使用。用於 Android 的庫稱為 EGL。如果要繪制紋理多邊形,應使用 GLES 調用;如果要在屏幕上進行渲染,應使用 EGL 調用。

在使用 GLES 進行任何操作之前,需要創建一個 GL 上下文。在 EGL 中,這意味着要創建一個 EGLContext 和一個 EGLSurface。GLES 操作適用於當前上下文,該上下文通過線程局部存儲訪問,而不是作為參數進行傳遞。這意味着您必須注意渲染代碼在哪個線程上執行,以及該線程上的當前上下文。

 

參考鏈接:

1. Android Display System(2)

2. OpenGL ES 2.0 知識串講

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM