前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Android配置EGL环境

Android配置EGL环境

作者头像
曾大稳
发布2018-09-11 10:28:08
1.4K0
发布2018-09-11 10:28:08
举报
文章被收录于专栏:曾大稳的博客

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

代码语言:javascript
复制

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;
    }
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2018-08-14,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档