openg es egl筆記
opengl es: java端開發
// 導入類
import android.opengl.GLES20;
//函數調用加上GLES20.glxxx(), 類的靜态函數形式調用
//GLSurfaceView內建了EGL部分,兩個重要的接口setEGLContextClientVersion和setRenderer
//setEGLContextClientVersion用來設定OpenGL ES的版本, 如:OpenGL ES 2.0
GLES20.glClearColor()
GLES20.glCreateProgram()
opengl es: jni端開發
// 包含相關頭檔案
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
#include <EGL/egl.h> // EGL 頭檔案
//函數調用, C語言風格使用, 與java端使用整體差别不大
//jni需增加EGL操作部分,搭建opengl es本地運作環境
glClearColor()
glCreateProgram()
OpenGL
OpenGL是和程式設計語言、平台無關的一套interface ,主要是為了rendering 2D 和 3D圖形等。一般這套接口是用來和GPU進行互動的,使用GPU進行rendering硬體加速
(一個操作GPU的API,它通過驅動向GPU發送相關指令,控制圖形渲染管線狀态機的運作狀态)
本地代碼:
framework/base/opengl/libagl //Android提供的OpenGL軟體庫, 編譯生成libGLES_android.so:
是一個由系統提供的純軟體3D加速庫,可以相容各種環境。包含一個EGL架構的實作和OpenGL各種API的實作。OpenGL的API底層是通過libpixelflinger.so庫實作
libGLES_android.so提供了兩種API:一種是egl實作API,另一種是OpenGL标準API。
Pixelflinger: 是Android系統中為OpenGL ES引擎提供的一套軟體渲染器(renderer)
Pixelflinger作為軟體渲染器,為OpenGL ES引擎提供了一系列基礎繪圖功能。這些功能包括定義各種顔色格式像素位置、畫點畫線、繪制矩形及三角形、填充紋理等等。
由于OpenGL ES相當于一個狀态機,配置OpenGL ES狀态的函數也均由Pixelflinger提供。
Pixelflinger的源代碼:
system/core/libpixelflinger。
system/core/include/libpixelflinger
system/core/include/private/pixelflinger
JNI代碼:
framework/base/core/jni/com_google_android_gles_jni_GLImpl.cpp
framework/base/core/jni/android_opengl_GLESXXX.cpp
Java代碼:
framework/base/opengl/java/javax/microedition/khronos/opengles
framework/base/opengl/java/com/google/android/gles_jni/
framework/base/opengl/android/opengl
OpenGL支援Java層、JNI層開發,使用opengl函數時,首先利用egl的函數去建構本地環境,然後再使用opengl繪圖
opengl在android中主要有2個用途:上層使用opengl render,即繪圖, 下層surfaceflinger中使用opengl去做layer的合成
OpenGL的各種資料類型: 類似與GL***, 即以GL作字首;
GLenum: 用于GL枚舉的無符号整型。
GLboolean: 用于單布爾值。GL_TRUE和GL_FALSE
GLbyte: 有符号單位元組整型,包含數值從-128 到 127
GLshort: 有符号雙位元組整型,包含數值從−32,768 到 32,767
GLint: 有符号四位元組整型,包含數值從−2,147,483,648 到 2,147,483,647
GLsizei: 有符号四位元組整型,用于代表資料的尺寸(位元組),類似于C中的size_t
GLubyte: 無符号單位元組整型,包含數值從0 到 255。
GLushort: 無符号雙位元組整型,包含數值從0 到 65,535
GLuint: 無符号四位元組整型,包含數值從0 到 4,294,967,295
GLfloat: 四位元組精度IEEE 754-1985 浮點數
GLclampf: 這也是四位元組精度浮點數,但OpenGL使用GLclampf特别表示數值為0.0 到 1.0
GLvoid: void值用于訓示一個函數沒有傳回值,或沒有參數
GLfixed: 定點數 使用整型數存儲實數。
EGL:
OpenGL ES和底層Native平台視窗系統之間的接口,是OpenGL ES和本地視窗的橋梁。
EGL API獨立于OpenGL ES各版本标準的獨立API,其主要作用是為OpenGL指令建立Context 、繪制目标Surface 、配置Framebuffer屬性、Swap送出繪制結果等
它被用于處理圖形管理、表面/緩沖捆綁、渲染同步及支援使用其他Khronos API進行的高效、加速、混合模式2D和3D渲染.
EGL主要用來管理繪圖表面(Drawing surfaces),并提供如下的功能:
1、與本地視窗系統進行通信
2、查找繪圖表面可用的類型和配置資訊
3、建立繪圖表面
4、同步OpenGL ES 2.0和其他的渲染API(Open VG、本地視窗系統的繪圖指令等)
5、管理渲染資源,比如材質
OpenGL ES圖形管線的狀态被存儲于EGL管理的一個Context中, 而Frame Buffers和其他繪制Surfaces通過 EGL API進行建立、管理和銷毀。同時EGL也控制和提供了對裝置顯示和可能的裝置渲染配置的通路
本地代碼:
framework/base/opengl/libs/egl
Android EGL架構,負責加載OpenGL函數庫和EGL本地實作, 編譯生成libEGL.so
JNI代碼:
framework/base/core/jni/com_google_android_gles_jni_EGLImpl.cpp //EGL本地代碼的JNI調用接口
Java代碼:
framework/base/opengl/java/javax/microedition/khronos/egl
Android OpenGL庫加載和調用過程:
http://blog.sina.com.cn/s/blog_7213e0310102wzbn.html
EGL支援Java層、JNI層開發, EGL10、EGL11、EGL14幾個版本,
Android 4.2(API 17)後使用的是EGL14, 可通過eglQueryString(display, EGL10.EGL_VERSION)進行查詢:
EGL14設定EGL渲染類型API的參數: EGL_OPENGL_ES2_BIT // 支援opengl es 2.0
EGL10、EGL11隻能手寫的寫死類型來指定: EGL_RENDERABLE_TYPE = 4; // 支援opengl es 2.0
EGL 資料類型
資料類型 值
EGLBoolean — EGL_TRUE =1, EGL_FALSE=0
EGLint/ — int 資料類型
EGLDisplay —系統顯示 ID 或句柄
EGLConfig —Surface 的 EGL 配置
EGLSurface —系統視窗或 frame buffer 句柄
EGLContext —OpenGL ES 圖形上下文
NativeDisplayType—Native 系統顯示類型
NativeWindowType—Native 系統視窗緩存類型
NativePixmapType—Native 系統 frame buffer
OpenGL ES/EGL的初始化過程:
Application –>OpenGL Command–>EGLContext(Context)
EGLSurface<– EGLConfig <–EGLDisplay
平台編譯後可使用的庫:
//android中的egl庫,可加載具體的平台(廠商)實作
system\lib\libEGL.so //用來加載具體的egl和opengl實作的,起到橋梁作用,需要和EGL實作的庫區分開
//opengl具體實作的wrapper, 可加載具體的平台(廠商)實作
system\lib\libGLESv1_CM.so
system\lib\libGLESv2.so
//opengl軟體實作,即agl, 包括egl、opengl es實作(硬體需求低,無gpu,無overlay,隻能通過agl去合成layer的應用場景)
system\lib\egl\libGLES_android.so
//以下針對具體平台(廠商)egl、opengl es實作庫:
//egl的實作
system\vendor\lib\egl\libEGL_adreno.so
//opengl硬體實作
system\vendor\lib\egl\libGLESv1_CM_adreno.so
system\vendor\lib\egl\libGLESv2_adreno.so
EGL主要資料結構
egl_object_t結構用來描述沒一個elg對象。
egl_display_t結構用來存儲get_display函數擷取的實體顯示裝置。
egl_surface_t結構用來存儲surface對象,系統可以同時擁有多個surface對象。
egl_context_t結構用用來存儲OpenGL狀态機資訊。
egl_image_t結構用來存儲EGLImage對象。
EGL操作流程
init流程:
ANativeWindow *mWin = ANativeWindow_fromSurface(env, jsurface);
EGLDisplay mEglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY); // 1、擷取顯示裝置
//EGLDisplay eglGetDisplay (NativeDisplayType display); //display 參數是native系統的視窗顯示ID值
eglInitialize(mEglDisplay, &major, &minor); // 2、初始化顯示裝置、擷取EGL版本号
EGLint config_attribs[] = {
EGL_BLUE_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_RED_SIZE, 8,
EGL_RENDERABLE_TYPE, //指定渲染api類别, 這裡或者是寫死的4
EGL_OPENGL_ES2_BIT, //或者是EGL14.EGL_OPENGL_ES2_BIT
EGL_SURFACE_TYPE,
EGL_WINDOW_BIT,
EGL_NONE
};
int num_configs = 0;
EGLConfig eglConfig;
//3、擷取滿足attributes的所有config, EGLConfig---描述EGLSurface配置資訊的資料類型(繪制目标framebuffer的配置屬性)
eglChooseConfig(mEglDisplay, config_attribs, &eglConfig, 1, &num_configs))
/*
eglChooseConfig(display, attributes, configs, num, configNum);
功能:用于擷取滿足attributes的所有config
參數1目前顯示裝置
參數2需滿足的attributes
參數3用于存放輸出的configs,
參數4指定最多輸出多少個config,
參數5由EGL系統寫入,表明滿足attributes的config一共有多少個。
如用eglChooseConfig(display, attributes, null, 0, configNum)形式調用,則會在configNum中輸出所有滿足條件的config個數。
*/
//通過ANativeWindow 建立本地surface---EGLSurface,它是系統視窗或frame buffer句柄,可以了解為一個後端的渲染目标視窗
EGLSurface mEglSurface = eglCreateWindowSurface(mEglDisplay, eglConfig, mWin, NULL); // 4、将Surface轉換為本地視窗
eglQuerySurface(mEglDisplay, mEglSurface, EGL_WIDTH, &mSurfaceWidth); // 5、查詢高寬
eglQuerySurface(mEglDisplay, mEglSurface, EGL_HEIGHT, &mSurfaceHeight);
EGLint context_attrib[] = {
EGL_CONTEXT_CLIENT_VERSION, 2,
EGL_NONE
};
//建立EGL環境, EGLContext: OpenGL ES圖形上下文,它代表了OpenGL狀态機
EGLContext mEglContext = eglCreateContext(mEglDisplay, eglConfig, EGL_NO_CONTEXT, context_attrib); // 6、根據EGLConfig、context_attrib建立EGLContext
//7、将EGLDisplay、EGLSurface和EGLContext進行綁定(渲染上下文綁定到渲染面,指定目前的環境為繪制環境 EGLContext->context)
//eglMakeCurrent後生成的surface就可以利用opengl畫圖了
eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext);
render:
//雙緩沖重新整理 front buffer 和 back buffer
//eglSwapBuffers會去觸發queuebuffer,dequeuebuffer,
//queuebuffer将畫好的buffer(back->front)交給surfaceflinger處理,
//dequeuebuffer新建立一個buffer用來畫圖
eglSwapBuffers(mEglDisplay, mEglSurface);
release流程:
eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); //1、
eglDestroyContext(mEglDisplay, mEglContext); // 2、
eglDestroySurface(mEglDisplay, mEglSurface); // 3、
eglTerminate(mEglDisplay); // 4、
mEglDisplay = EGL_NO_DISPLAY; // 5、
mEglContext = EGL_NO_CONTEXT;
mEglSurface = EGL_NO_SURFACE;
opengl es 大緻程式開發流程:
(opengl es繪制流程:讀取頂點資料――執行頂點着色器――組裝圖元――光栅化圖元――執行片段着色器――寫入幀緩沖區――顯示到螢幕上)
1、使用GLSL編寫頂點着色器、片元着色器腳本
2、讀取頂點着色器、片元着色器,建立着色器程式
glCreateShader(shaderType);
glShaderSource(shader, 1, &pSource, NULL);
glCompileShader(shader);
glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
…
GLuint gProgram = glCreateProgram();
glAttachShader(program, vertexShader);
glAttachShader(program, pixelShader);
glLinkProgram(program);
glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
3、擷取着色器程式中的相關變量的引用
_phandle = glGetAttribLocation(gProgram, “vPosition”);
…
4、清屏、深度緩存等,傳入頂點位置、紋理坐标、紋理單元等所需資料到着色器,由着色器程式完成繪制
glClearColor(0, 0, 0, 1.0f); //設定顔色,黑色
glClear( GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); //清除顔色緩沖、深度緩沖
glUseProgram(gProgram); // 使用着色器程式
glVertexAttribPointer(_phandle, 2, GL_FLOAT, GL_FALSE, 0, gTriangleVertices);
// 将頂點位置資料傳入渲染管線
glEnableVertexAttribArray(_phandle); //啟用頂點位置資料
glDrawArrays(GL_TRIANGLES, 0, 3); //繪制