天天看點

android egl 代碼,Android配置EGL環境

EGL

是OpenGL ES和本地視窗系統的接口,不同平台上EGL配置是不一樣的,而

OpenGL的調用方式是一緻的,就是說:OpenGL跨平台就是依賴于EGL接口。

我的得了解是:在一個平台上搭建OpenGL的環境。

為什麼要自己建立EGL環境?

有的人會想,在android裡面系統已經提供了GLSurfaceView

,已經有了EGL環境,我們為什麼還要自己搭建這個環境呢?

當我們需要把同一個場景渲染到不同的Surface上時,此時系統GLSurfaceView

就不能滿足需求了,是以我們需要自己建立EGL環境來實作渲染操作。

注意: OpenGL整體是一個狀态機,通過改變狀态就能改變後續的渲染方式,而

EGLContext(EgL上下文)就儲存有所有狀态,是以可以通過共享EGLContext

來實作同一場景渲染到不同的Surface上。

Android配置egl環境我們根據GLSurfaceView源碼來實作。在GLSurfaceView源碼裡面,當調用setRenderer的時候會開啟一個線程GLThread,GLThread調用start的時候會初始化EglHelper來配置egl環境,然後一個while(true)執行,根據不同的辨別判斷執行egl的環境配置,Renderer的onSurfaceCreated,onSurfaceChanged,onDrawFrame等函數。

從源碼得知我們配置egl環境主要根據GLSurfaceView.EglHelper來寫,主要分為已下幾步:

1、得到Egl執行個體

2、得到預設的顯示裝置(就是視窗)

3、初始化預設顯示裝置

4、設定顯示裝置的屬性

5、從系統中擷取對應屬性的配置

6、建立EglContext

7、建立渲染的Surface

8、綁定EglContext和Surface到顯示裝置中

9、重新整理資料,顯示渲染場景

最終代碼如下:

EglHelper.java

package com.zzw.glsurfaceviewdemo;

import android.view.Surface;

import javax.microedition.khronos.egl.EGL10;

import javax.microedition.khronos.egl.EGLConfig;

import javax.microedition.khronos.egl.EGLContext;

import javax.microedition.khronos.egl.EGLDisplay;

import javax.microedition.khronos.egl.EGLSurface;

public class EglHelper {

private static final String TAG = "EglHelper";

private EGL10 mEgl;

private EGLDisplay mEglDisplay;

private EGLContext mEglContext;

private EGLSurface mEglSurface;

public void initEgl(Surface surface, EGLContext eglContext) {

//1. 得到Egl執行個體

mEgl = (EGL10) EGLContext.getEGL();

//2. 得到預設的顯示裝置(就是視窗)

mEglDisplay = mEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);

if (mEglDisplay == EGL10.EGL_NO_DISPLAY) {

throw new RuntimeException("eglGetDisplay failed");

}

//3. 初始化預設顯示裝置

int[] version = new int[2];

if (!mEgl.eglInitialize(mEglDisplay, version)) {

throw new RuntimeException("eglInitialize failed");

}

//4. 設定顯示裝置的屬性

int[] attrib_list = new int[]{

EGL10.EGL_RED_SIZE, mRedSize,

EGL10.EGL_GREEN_SIZE, mGreenSize,

EGL10.EGL_BLUE_SIZE, mBlueSize,

EGL10.EGL_ALPHA_SIZE, mAlphaSize,

EGL10.EGL_DEPTH_SIZE, mDepthSize,

EGL10.EGL_STENCIL_SIZE, mStencilSize,

EGL10.EGL_RENDERABLE_TYPE, mRenderType,//egl版本 2.0

EGL10.EGL_NONE};

int[] num_config = new int[1];

if (!mEgl.eglChooseConfig(mEglDisplay, attrib_list, null, 1,

num_config)) {

throw new IllegalArgumentException("eglChooseConfig failed");

}

int numConfigs = num_config[0];

if (numConfigs <= 0) {

throw new IllegalArgumentException(

"No configs match configSpec");

}

//5. 從系統中擷取對應屬性的配置

EGLConfig[] configs = new EGLConfig[numConfigs];

if (!mEgl.eglChooseConfig(mEglDisplay, attrib_list, configs, numConfigs,

num_config)) {

throw new IllegalArgumentException("eglChooseConfig#2 failed");

}

EGLConfig eglConfig = chooseConfig(mEgl, mEglDisplay, configs);

if (eglConfig == null) {

eglConfig = configs[0];

}

//6. 建立EglContext

int[] contextAttr = new int[]{

EGL14.EGL_CONTEXT_CLIENT_VERSION, 2,

EGL10.EGL_NONE

};

if (eglContext == null) {

mEglContext = mEgl.eglCreateContext(mEglDisplay, eglConfig, EGL10.EGL_NO_CONTEXT, contextAttr);

} else {

mEglContext = mEgl.eglCreateContext(mEglDisplay, eglConfig, eglContext, contextAttr);

}

//7. 建立渲染的Surface

mEglSurface = mEgl.eglCreateWindowSurface(mEglDisplay, eglConfig, surface, null);

//8. 綁定EglContext和Surface到顯示裝置中

if (!mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) {

throw new RuntimeException("eglMakeCurrent fail");

}

}

//9. 重新整理資料,顯示渲染場景

public boolean swapBuffers() {

if (mEgl != null) {

return mEgl.eglSwapBuffers(mEglDisplay, mEglSurface);

} else {

throw new RuntimeException("egl is null");

}

}

public void destoryEgl() {

if (mEgl != null) {

if (mEglSurface != null && mEglSurface != EGL10.EGL_NO_SURFACE) {

mEgl.eglMakeCurrent(mEglDisplay, EGL10.EGL_NO_SURFACE,

EGL10.EGL_NO_SURFACE,

EGL10.EGL_NO_CONTEXT);

mEgl.eglDestroySurface(mEglDisplay, mEglSurface);

mEglSurface = null;

}

if (mEglContext != null) {

mEgl.eglDestroyContext(mEglDisplay, mEglContext);

mEglContext = null;

}

if (mEglDisplay != null) {

mEgl.eglTerminate(mEglDisplay);

mEglDisplay = null;

}

mEgl = null;

}

}

public EGLContext getEglContext() {

return mEglContext;

}

private final int mRedSize = 8;

private final int mGreenSize = 8;

private final int mBlueSize = 8;

private final int mAlphaSize = 8;

private final int mDepthSize = 8;

private final int mStencilSize = 8;

private final int mRenderType = 4;

private EGLConfig chooseConfig(EGL10 egl, EGLDisplay display,

EGLConfig[] configs) {

for (EGLConfig config : configs) {

int d = findConfigAttrib(egl, display, config,

EGL10.EGL_DEPTH_SIZE, 0);

int s = findConfigAttrib(egl, display, config,

EGL10.EGL_STENCIL_SIZE, 0);

if ((d >= mDepthSize) && (s >= mStencilSize)) {

int r = findConfigAttrib(egl, display, config,

EGL10.EGL_RED_SIZE, 0);

int g = findConfigAttrib(egl, display, config,

EGL10.EGL_GREEN_SIZE, 0);

int b = findConfigAttrib(egl, display, config,

EGL10.EGL_BLUE_SIZE, 0);

int a = findConfigAttrib(egl, display, config,

EGL10.EGL_ALPHA_SIZE, 0);

if ((r == mRedSize) && (g == mGreenSize)

&& (b == mBlueSize) && (a == mAlphaSize)) {

return config;

}

}

}

return null;

}

private int findConfigAttrib(EGL10 egl, EGLDisplay display,

EGLConfig config, int attribute, int defaultValue) {

int[] value = new int[1];

if (egl.eglGetConfigAttrib(display, config, attribute, value)) {

return value[0];

}

return defaultValue;

}

}