EGL

作者: xx_G | 来源:发表于2019-01-31 16:35 被阅读0次

    EGL 是什么?

    EGL 是 Khronos渲染 API(如OpenGL ES或OpenVG)与底层本机平台窗口系统之间的接口。
    在 Android 平台,一般是 OpenGL ES 和底层的 native window system 之间的接口,简单的说,就是 Android 应用层 和 底层window 渲染数据交互的媒介。

    EGL 的作用

    在 Android 平台上,一般是为 OpenGL ES 渲染 API 搭建使用环境

    EGL 在Java层的封装

    在Java层,EGL封装了两套框架,分别是:

        位于 javax.microedition.khronos.egl 包下的 EGL10
        位于 android.opengl 包下的 EGL14
    

    它们都是 OpenGL ES 和底层的 native window system 之间的接口,只是EGL的不同版本

        EGL10 对应于 EGL 1.0,它是在2003年
        EGL14 释放的规范对应于 EGL 1.4,其是在2014年
    

    其主要区别是:

        EGL14 是在 Android 4.2(API 17) 引入,换言之API 17以下的版本不支持 EGL14
        EGL10 不支持 OpenGL ES 2.x,因此在 EGL10 中某些相关常量参数只能用手写硬编码代替
        例如 EGL14.EGL_CONTEXT_CLIENT_VERSION 以及 EGL14.EGL_OPENGL_ES2_BIT 等等
    

    EGL 环境搭建流程

    参考 GLSurfaceView 内部的 EGL 环境搭建流程,只讨论 EGL10,EGL14基本同理

    1. 通过javax.microedition.khronos.egl.EGLContext获取EGL10对象
    2. 通过eglGetDisplay()获取EGLDisplay对象(EGLDisplay屏幕的抽象)
    3. 通过eglInitialize()初始化EGLDisplay对象
    4. 通过eglChooseConfig() 设置并筛选适合的EGL frame bufferEGLConfig配置
    5. 通过eglCreateContext()构建EGLContext对象(EGLContext是环境的抽象)
    6. 通过eglCreatePbufferSurface() or eglCreateWindowSurface() 构建EGLSurface对象 (我将它理解为屏幕画布的抽象)
    7. 通过eglMakeCurrent()EGLContextCurrent ThreadEGLSurface进行绑定
    8. 环境搭建成功,可以开始进行OpenGL ES的渲染操作
    9. 如果是eglCreateWindowSurface()渲染之后,可以调用SwapBuffer()进行双缓冲切换显示渲染画面
    10. 渲染结束eglDestroyXXX()资源

    <具体代码>

    @Override
    protected void start(int eglContextVersion, ComponentSizeChooser configChooser)
    {
        // first step: 获取 EGL 对象
        mEgl = (EGL10) EGLContext.getEGL();
    
        // second step: 获取 EGLDisplay 对象(屏幕的抽象)
        mEglDisplay = mEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
    
        // 检查 EGLDisplay 的可用性
        if (mEglDisplay == EGL10.EGL_NO_DISPLAY)
        {
            throw new RuntimeException("egl GetDisplay failed");
        }
    
        // 版本格式 xx.yy
        int[] version = new int[2];
        // third step: 初始化EGLDisplay连接, 成功返回具体版本
        if (!mEgl.eglInitialize(mEglDisplay, version))
        {
            throw new RuntimeException("egl Initialize failed");
        }
    
        // forth step: 获取 想要的 EGL framebuffer 配置, configChooser可参考 GLSurfaceView 内部实现
        mEglConfig = configChooser.chooseConfig(mEgl, mEglDisplay);
    
        int[] context_attribute_list = {EGL14.EGL_CONTEXT_CLIENT_VERSION, eglContextVersion,
                EGL10.EGL_NONE};
        // fifth step: 构建 EGLContext(环境的抽象)
        mEglContext = mEgl.eglCreateContext(mEglDisplay, mEglConfig, EGL10.EGL_NO_CONTEXT, context_attribute_list);
    
        // 检查 EGLContext 可用性
        if (mEglContext == null || mEglContext == EGL10.EGL_NO_CONTEXT)
        {
            mEglContext = null;
            throw new RuntimeException("egl create Context fail");
        }
    }
    
    @Override
    public boolean setUpEglBackgroundEnvironment(int eglContextVersion, ComponentSizeChooser configChooser, int width, int height)
    {
        start(eglContextVersion, configChooser);
    
        // 设置 EGLSurface 的宽高(唯一可以设置的属性)
        int[] surface_attribute_list = {EGL10.EGL_WIDTH, width,
                EGL10.EGL_HEIGHT, height,
                EGL10.EGL_NONE};
    
        // sixth step: 构建一个 Pbuffer 单缓冲区(无法直接显示) 的 EGLSurface(实际上 EGLSurface 是一个 FrameBuffer)
        mEglSurface = mEgl.eglCreatePbufferSurface(mEglDisplay, mEglConfig, surface_attribute_list);
    
        // 检查 EGLSurface 可用性
        if (mEglSurface == null || mEglSurface == EGL10.EGL_NO_SURFACE)
        {
            mEglSurface = null;
            Log.e(TAG, "egl create surface fail");
            return false;
        }
    
        // seventh step: 将 EGLContext 与当前线程、EGLSurface 进行绑定
        if (!mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext))
        {
            Log.e(TAG, "setUpEglPbufferSurfaceEnvironment:egl Make Current fail");
            return false;
        }
    
        return true;
    }
    
    @Override
    public void destroy()
    {
        mEgl.eglMakeCurrent(mEglDisplay, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT);
    
        mEgl.eglDestroySurface(mEglDisplay, mEglSurface);
    
        mEgl.eglDestroyContext(mEglDisplay, mEglContext);
    
        mEgl.eglTerminate(mEglDisplay);
    
        mEglSurface = EGL10.EGL_NO_SURFACE;
        mEglDisplay = EGL10.EGL_NO_DISPLAY;
        mEglContext = EGL10.EGL_NO_CONTEXT;
        mEgl = null;
    }

    相关文章

      网友评论

          本文标题:EGL

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