天天看點

openg es egl筆記

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); //繪制