美文网首页NDK
Android配置EGL环境

Android配置EGL环境

作者: 曾大稳丶 | 来源:发表于2018-08-14 20:14 被阅读0次

    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的环境配置,RendereronSurfaceCreated,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;
        }
    }
    
    
    

    相关文章

      网友评论

        本文标题:Android配置EGL环境

        本文链接:https://www.haomeiwen.com/subject/mzhbbftx.html