ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

EGL 作用及其使用

2020-04-04 23:07:27  阅读:733  来源: 互联网

标签:OpenGL 及其 EGL EGL10 EGL14 使用 ES EGLContext


大家好,接下来将为大家介绍EGL 作用及其使用。

1、什么是EGL

EGL 是 OpenGL ES 渲染 API 和本地窗口系统(native platform window system)之间的一个中间接口层,EGL作为OpenGL ES与显示设备的桥梁,让OpenGL ES绘制的内容能够在呈现当前设备上。它主要由系统制造商实现。

EGL具有如下作用:

a:与设备的原生窗口系统通信。

b:查询绘图表面的可用类型和配置。

c:创建绘图表面。

d:在OpenGL ES 和其他图形渲染API之间同步渲染。

e:管理纹理贴图等渲染资源。

2、EGL和OpenGL ES的关系

从上面的讲解我们基本上可以知道,EGL为OpenGL提供绘制表面。或者说EGL是OpenGl ES的渲染画布。EGL作为OpenGL ES与显示设备的桥梁,让OpenGL ES绘制的内容能够在呈现当前设备上。

 

3、EGL绘图的基本步骤

简单讲解下各部分的作用:

a:Display(EGLDisplay) 是对实际显示设备的抽象。

b:Surface(EGLSurface)是对用来存储图像的内存区域FrameBuffer 的抽象,包括 Color Buffer, Stencil Buffer ,Depth Buffer。

c:Context (EGLContext) 存储 OpenGL ES绘图的一些状态信息。

 

4.1、EGL的基本使用步骤:

a:获取 EGL Display 对象:通过eglGetDisplay()方法来返回EGLDisplay作为OpenGL ES的渲染目标。

 if ( (mEGLDisplay = EGL14.eglGetDisplay(EGL14.EGL_DEFAULT_DISPLAY)) == EGL14.EGL_NO_DISPLAY) {
                throw new RuntimeException("unable to get EGL14 display"); }

b:初始化与 EGLDisplay 之间的连接:eglInitialize()。第一参数代表Major版本,第二个代表Minor版本。如果不关心版本号,传0或者null就可以了。

 if (!EGL14.eglInitialize(mEGLDisplay, 0, 0)) {
     throw new RuntimeException("unable to initialize EGL14"); }

c:获取 EGLConfig 对象:eglChooseConfig()。

int[] attribList = {
                    EGL14.EGL_RED_SIZE, 8,
                    EGL14.EGL_GREEN_SIZE, 8,
                    EGL14.EGL_BLUE_SIZE, 8,
                    EGL14.EGL_ALPHA_SIZE, 8,
                    EGL14.EGL_RENDERABLE_TYPE, EGL14.EGL_OPENGL_ES3_BIT,
                    EGL_RECORDABLE_ANDROID, 1,
                    EGL14.EGL_NONE
            };
            EGLConfig[] configs = new EGLConfig[1];
            int[] numConfigs = new int[1];
            EGL14.eglChooseConfig(mEGLDisplay, attribList, 0, configs, 0, configs.length,
                    numConfigs, 0);

d:创建 EGLContext 实例:接下来我们需要创建OpenGL的上下文环境 EGLContext 实例,这里值得留意的是,OpenGL的任何一条指令都是必须在自己的OpenGL上下文环境中运行,我们可以通过eglCreateContext()方法来构建上下文环境:

    int[] attrib_list = {
                    EGL14.EGL_CONTEXT_CLIENT_VERSION, 2,
                    EGL14.EGL_NONE
            };
            mEGLContext = EGL14.eglCreateContext(mEGLDisplay, configs[0], EGL14.EGL_NO_CONTEXT,
                    attrib_list, 0);

e:创建 EGLSurface 实例:通过eglCreateWindowSurface()方法创建一个实际可以显示的EGLSurface。

     private EGLSurface mEGLSurface = EGL14.EGL_NO_SURFACE;
      int[] surfaceAttribs = {
                    EGL14.EGL_NONE
            };
            mEGLSurface = EGL14.eglCreateWindowSurface(mEGLDisplay, configs[0], mSurface,
                    surfaceAttribs, 0);

f:连接 EGLContext 和 EGLSurface:通过上面的步骤,EGL的准备工作做好了,一方面我们为OpenGL ES渲染提供了目标及上下文环境EGLContext,可以接收到OpenGl ES渲染出来的纹理;另一方面我们连接好了设备显示屏EGLSurface(这里指SurfaceView或者TextureView),接下来我们讲解如何在创建好的EGL环境下工作的。首先我们有一点必须要明确,OpenGL ES 的渲染必须新开一个线程,并为该线程绑定显示设备及上下文环境(EGLContext)。前面有说过OpenGL指令必须要在其上下文环境中才能执行。所以我们首先要通过 eglMakeCurrent()方法来绑定该线程的显示设备及上下文。

EGL14.eglMakeCurrent(mEGLDisplay, mEGLSurface, mEGLSurface, mEGLContext);

g:当我们绑定完成之后,我们就可以进行RenderLoop循环了,使用 OpenGL ES API 绘制图形:gl_*() 。

h:绘制好之后,切换 front buffer 和 back buffer 送显:eglSwapBuffer()。EGL的工作模式是双缓冲模式,其内部有两个FrameBuffer(帧缓冲区,可以理解为一个图像存储区域),当EGL将一个FrameBuffer显示到屏幕上的时候,另一个FrameBuffer就在后台等待OpenGl ES进行渲染输出。直到调用了eglSwapBuffer()这条指令的时候,才会把前台的FrameBuffers和后台的FrameBuffer进行交换,这时界面呈现的就是OpenGL ES刚刚渲染的内容了。

EGL14.eglSwapBuffer();

i:断开并释放与 EGLSurface 关联的 EGLContext 对象:eglRelease()。

j:删除 EGLSurface 对象,eglDestroySurface()。

EGL14.eglDestroySurface(display, surface);

k:删除 EGLContext 对象,

EGL14.eglDestroyContext(display, context);

l:终止与 EGLDisplay 之间的连接,

EGL14.eglTerminate(display);

 

5、EGL 环境搭建示例


import android.icu.text.UFormat;
import android.util.Log;
import android.view.Surface;
import android.view.SurfaceView;

import javax.microedition.khronos.egl.EGL;
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;

import static javax.microedition.khronos.egl.EGL10.EGL_NO_CONTEXT;


public class EGLHelper {
    private EGL10 mEgl;
    private EGLDisplay mEglDisplay;
    private EGLContext mEglContext;
    private EGLSurface eglSurface;

    public void init(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.初始化默认显示设备(初始化EGL)
        //主版本号和次版本号
       int[] version=new int[2];
        boolean initialize = mEgl.eglInitialize(mEglDisplay, version);
        if (!initialize){
            throw new RuntimeException("eglInitialize failed");
        }
        Log.e("ike","version:"+version[0]);
        Log.e("ike","version:"+version[1]);

        //4.设置显示设备的属性
        int[] attribute=new int[] {
                EGL10.EGL_RED_SIZE, 8,
                EGL10.EGL_GREEN_SIZE, 8,
                EGL10.EGL_BLUE_SIZE, 8,
                EGL10.EGL_ALPHA_SIZE, 8,
                EGL10.EGL_DEPTH_SIZE, 8,
                EGL10.EGL_STENCIL_SIZE, 4,
                EGL10.EGL_NONE};
        //根据属性信息从系统的所有的配置信息中,获取支持该属性列表的配置信息的个数。一般来说就选取一个就好了
        int[] num_config = new int[1];
        boolean chooseConfig = mEgl.eglChooseConfig(mEglDisplay, attribute, null, 1, num_config);
        if (!chooseConfig){
            throw new RuntimeException("eglChooseConfig failed");

        }
        //判断是否选择到符合传入参数的配置信息
        if (num_config[0]<=0){
            throw new IllegalArgumentException(
                    "No configs match configSpec");
        }
        //5.从系统中获取对应属性的配置
        EGLConfig[] eglConfigs=new EGLConfig[num_config[0]];
        boolean eglChooseConfig = mEgl.eglChooseConfig(mEglDisplay, attribute, eglConfigs, num_config[0], num_config);
        if (!eglChooseConfig){
            throw new RuntimeException("eglChooseConfig$2 failed");
        }
        //6. 创建EglContext
        //如果eglContext==null则创建新的egl上下文
        int[] attrib_list = {EGL_CONTEXT_CLIENT_VERSION, 3,
            EGL10.EGL_NONE };
        if (eglContext==null){
            mEglContext = mEgl.eglCreateContext(mEglDisplay, eglConfigs[0], EGL_NO_CONTEXT, null);

        }else {
            //根据传入eglContext创建可以共享的egl上下文
            mEglContext = mEgl.eglCreateContext(mEglDisplay, eglConfigs[0], eglContext, null);
        }
        if (mEglContext==null||mEglContext== EGL_NO_CONTEXT){
            mEglContext=null;
            throw new RuntimeException("eglCreateContext failed");
        }
        //7.创建surface
        eglSurface = mEgl.eglCreateWindowSurface(mEglDisplay, eglConfigs[0], surface, null);
        if (eglSurface==null||eglSurface==EGL10.EGL_NO_SURFACE){
            eglSurface=null;
            throw new RuntimeException("eglCreateWindowSurface failed");
        }
        //8.绑定EGLContext和surface到显示设备
        boolean makeCurrent = mEgl.eglMakeCurrent(mEglDisplay, eglSurface, eglSurface, mEglContext);
        if (!makeCurrent){
            Log.e("ike","eglMakeCurrent failed");
        }
    }

    /**
     * 刷新数据
     */
    public void swapBuffers(){
        if (mEgl!=null){
            boolean eglSwapBuffers = mEgl.eglSwapBuffers(mEglDisplay, eglSurface);
            if (!eglSwapBuffers){
                Log.e("ike","eglSwapBuffers failed");

            }
        }
    }

    /**
     * 获取EGL上下文
     * @return
     */
    public EGLContext getEGLCOntext(){
        return mEglContext;
    }
    public void destoryEgl(){
       if (mEgl!=null){
           //与显示设备解绑,销毁eglsurface
           mEgl.eglMakeCurrent(mEglDisplay,EGL10.EGL_NO_SURFACE,EGL10.EGL_NO_SURFACE,EGL_NO_CONTEXT);
           mEgl.eglDestroySurface(mEglDisplay,eglSurface);
           eglSurface=null;
           //销毁上下文
           mEgl.eglDestroyContext(mEglDisplay,mEglContext);
           mEglContext=null;
           //销毁显示设备
           mEgl.eglTerminate(mEglDisplay);
           mEglDisplay=null;
           mEgl=null;
       }
    }
}

 

最后,欢迎大家一起交流学习:微信:liaosy666 ; QQ:2209115372 。

标签:OpenGL,及其,EGL,EGL10,EGL14,使用,ES,EGLContext
来源: https://blog.csdn.net/u010281924/article/details/105296617

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有