OpenGL 4.4 和 Android
手機硬件的更新是如此迅速以至于我們開始進入一個手機與高端PC功能無異的時代。它們的區(qū)別將只是芯片的功耗不同而已。
我不想讓自己聽起來像是在推廣我們自己的芯片,但我相信Tegra K1是未來即將發(fā)生的事物的前瞻。不僅僅發(fā)生在我們身上,我希望其他行業(yè)也能加入進來,從而使開發(fā)者可以為從PC到手機安全地假設一個相對統(tǒng)一的功能集。K1只是***示例,因為它的GPU核心是Kepler 。而且它不是什么營銷手段,它實際上是與運轉(zhuǎn)像GTX780這種神奇事物相同的微架構。幾年的血汗與淚水使其成為了可能。并且限于尺寸,功率和熱限制,它 只有192個核心(而不是2304個),但它仍具有較強的性能競爭力。更重要的是在功能上它處于一個完全不同的陣營中,因為它支持完整的桌面級 OpenGL4.4,包括幾何著色器,鑲嵌,計算等,還有像bindless這樣的支持其他事物的擴展。
但是Android只支持OpenGL ES,對嗎?實際上不是這樣的。雖然現(xiàn)在在Android平臺上,***的官方支持的圖形API是OpenGL ES,你仍然可以使用EGL在平臺上創(chuàng)建一個"大"OpenGL 上下文,前提是你的設備支持它。這使得在不同的操作系統(tǒng)上傳輸數(shù)據(jù)很實用,Windows/Linux/Mac/streamOS 都有OpenGL的后臺程序,可以快速啟動并模擬裁剪平面(clip planes),alpha測試,或者spec中的少數(shù)差異。它同樣可以作為一個不錯的引用渲染后端程序,在ES渲染路徑啟動和運行之前驗證你的端口。
不要擔心,你可以在你的app中同時使用GLES和BigGL。實際上,這很簡單。最重要的事情在EGL中,它是Android為創(chuàng)建OpenGL上下文而公開的API。Java或C/C++同樣可以這樣做,但是要注意需要EGL_SPEC.1.4以上版本。
首先,在創(chuàng)建上下文(或者調(diào)用任何一個EGL函數(shù))之前,要知道哪個版本的GL最支持當前設備。可以通過簡單地調(diào)用eglBindAPI(EGL_OPENGL_API)來完成。該API會將EGL切換到桌面OpenGL模式,如果當前設備不支持,則返回EGL_TRUE或者留下未改變的狀態(tài)并返回EGL_FALSE。鑒于該函數(shù)可以切換全局狀態(tài),所以最安全的做法是讓EGL首先調(diào)用它,之后不再調(diào)用。
創(chuàng)建完上下文之后,如果eglBindAPI()函數(shù)沒有切換BigGL模式,你就要和你之前那樣創(chuàng)建你的ES上下文。如果切換成功,你可選擇性地 創(chuàng)建BigGL上下文。幸運的是,EGL讓它簡單化。因為我們已經(jīng)調(diào)用了eglBindAPI(EGL_OPENGL_API),EGL已經(jīng)設置為 BigGL模式,所以我們只需要在配置文件和上下文中調(diào)整一些屬性即可。
首先,在傳遞給eglChooseConfig()的配置屬性中,我們需要確保 EGL_RENDERABLE_TYPE 設置為 EGL_OPENGL_BIT ,而不是EGL_OPENGL_ES2_BIT.
其次, 傳遞給函數(shù) eglCreateContext() 的屬性也需要稍微調(diào)整。對于 ES上下文,通常把 EGL_CONTEXT_CLIENT_VERSION 設為 1, 2 或3, 這取決于你想搭建哪個版本的OpenGL ES.對于BigGL上下文,我們不使用這個屬性,所以不要設置。事實上,你可以直接把BigGL的屬性列表置空。
粗略地講,這比較像下面的樣本 (為簡潔起見,忽視錯誤檢查):
- if(eglBindAPI(EGL_OPENGL_API))
- {
- // Create a BigGL context...
- EGLDisplay display = eglGetDisplay(...);
- eglInitialize(display, ...);
- const EGLint configAttrs[] =
- {
- EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
- EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
- // backbuffer attributes here...
- EGL_NONE
- };
- EGLConfig config;
- EGLint numConfigs = 0;
- eglChooseConfig(display, configAttrs, &config, 1, &numConfigs);
- EGLint ctxAttrs[] =
- {
- EGL_NONE
- };
- eglCreateContext(display, config, EGL_NO_CONTEXT, ctxAttrs);
- }
- else
- {
- // TODO: Fallback to old ES context creation...
- }
***一點問題,也是我對于使用OpenGL或者OpenGL ES的開發(fā)人員的一些建議,不論他們基于怎樣的平臺進行開發(fā)。尤其重要的一點是像上面提到的那樣在API之間進行切換。并且,不要隱式地鏈接到GL符號!就算是再多的功能,你都應當使用eglGetProcAddress(), 并且當心不要在上下文中共享函數(shù)指針。如果你做了一下比較瘋狂的事情,比如在同一個應用中創(chuàng)建了一個BigGL上下文和一個ES上下文,或者創(chuàng)建了像 glDrawElement()這樣的函數(shù),在兩者的API中都存在,但是可能指向了完全不同的實現(xiàn)方法。這就意味著你應當僅鏈接到libEGL,所以需 要通過qglGetProcAddress()函數(shù)查詢所有的符號。
編輯:應當指出的是,從技術的角度講,通過eglGetProcAddress()可獲得的“EGL_KHR_get_all_proc_addresses”應當是目前的核心功能,但是我堅信,既然目前它在Android通用EGL接口上進行了實現(xiàn),也就意味著它可以單獨驅(qū)動,這可能在舊版本的Android上無法正常工作。但是如果你正在考慮支持BigGL,你可能不希望舊設備成為你道路上的絆腳石。
特別強調(diào):我強烈建議如果可能的話,任何正在開發(fā)的應用程序應該也有GLES渲染路徑。BigGL對于開發(fā)是實用的,對于一些邊緣特性,甚至會更實用,但是有GLES后端同樣會幫助Android避免分段存儲,并且?guī)椭愕膽酶嗟钠毓庠诒M可能多的用戶面前。
英文原文:OpenGL 4.4 and beyond on Android
譯文鏈接:http://www.oschina.net/translate/opengl-44-and-beyond-on-android