美文网首页Android学习
Android EGL 接口使用方法

Android EGL 接口使用方法

作者: 1999c1b720cd | 来源:发表于2018-08-19 00:14 被阅读0次

背景

这段时间经常跟 OpenGL ES 和 EGL 打交道。在这整理记录 EGL 接口的使用方法,方便后续理解

问题

  • EGL 是一层接口,上层跟 OpenGL 对接,下层跟本地窗口系统对接,负责隔离 OpenGL 与本地窗口的依赖
  • OpenGL 本身只专注于渲染流程,核心就是 Pipeline 的处理
  • 如果没有 EGL 提供的渲染上下文,则 OpenGL 无法执行


    EGL 与 OpenGL ES 的关系

使用方法

由于 OpenGL ES 依赖于 EGL,故需要先建立 EGL,再使用 OpenGL ES。下面以 Android SDK 的源码为例说明经典用法。

  • 以下源码出自 android.hardware.camera2.legacy.SurfaceTextureRenderer 类
  • 初始化 EGLContext 对象
private void configureEGLContext() {
        // 查询默认显示屏对象 EGLDisplay。Android 支持多个显示屏。
        mEGLDisplay = EGL14.eglGetDisplay(EGL14.EGL_DEFAULT_DISPLAY);
        if (mEGLDisplay == EGL14.EGL_NO_DISPLAY) {
            throw new IllegalStateException("No EGL14 display");
        }
        int[] version = new int[2];
        // 初始化 EGL
        if (!EGL14.eglInitialize(mEGLDisplay, version, /*offset*/ 0, version, /*offset*/ 1)) {
            throw new IllegalStateException("Cannot initialize EGL14");
        }

        int[] attribList = {
                EGL14.EGL_RED_SIZE, EGL_COLOR_BITLENGTH,
                EGL14.EGL_GREEN_SIZE, EGL_COLOR_BITLENGTH,
                EGL14.EGL_BLUE_SIZE, EGL_COLOR_BITLENGTH,
                EGL14.EGL_RENDERABLE_TYPE, EGL14.EGL_OPENGL_ES2_BIT,
                EGL_RECORDABLE_ANDROID, 1,
                EGL14.EGL_SURFACE_TYPE, EGL14.EGL_PBUFFER_BIT | EGL14.EGL_WINDOW_BIT,
                EGL14.EGL_NONE
        };
        EGLConfig[] configs = new EGLConfig[1];
        int[] numConfigs = new int[1];
        // 选择最佳的 Surface 配置
        EGL14.eglChooseConfig(mEGLDisplay, attribList, /*offset*/ 0, configs, /*offset*/ 0,
                configs.length, numConfigs, /*offset*/ 0);
        checkEglError("eglCreateContext RGB888+recordable ES2");
        mConfigs = configs[0];
        int[] attrib_list = {
                EGL14.EGL_CONTEXT_CLIENT_VERSION, GLES_VERSION,
                EGL14.EGL_NONE
        };
        // 创建记录 OpenGL ES 状态机信息的对象 EGLContext
        mEGLContext = EGL14.eglCreateContext(mEGLDisplay, configs[0], EGL14.EGL_NO_CONTEXT,
                attrib_list, /*offset*/ 0);
        checkEglError("eglCreateContext");
        if(mEGLContext == EGL14.EGL_NO_CONTEXT) {
            throw new IllegalStateException("No EGLContext could be made");
        }
    }
  • 指定当前线程操作的 EGLContext 对象。可以创建多个不同的 EGLContext 对象
    private void makeCurrent(EGLSurface surface) {
        EGL14.eglMakeCurrent(mEGLDisplay, surface, surface, mEGLContext);
        checkEglError("makeCurrent");
    }
  • 交换渲染好的 Buffer 去显示出来
private boolean swapBuffers(EGLSurface surface)
            throws LegacyExceptionUtils.BufferQueueAbandonedException {
        boolean result = EGL14.eglSwapBuffers(mEGLDisplay, surface);

        int error = EGL14.eglGetError();
        ...
    }
  • 销毁上下文资源
private void releaseEGLContext() {
        if (mEGLDisplay != EGL14.EGL_NO_DISPLAY) {
            // 让当前线程操作的 EGLContext 指向默认的 EGL_NO_CONTEXT 对象。解绑
            EGL14.eglMakeCurrent(mEGLDisplay, EGL14.EGL_NO_SURFACE, EGL14.EGL_NO_SURFACE,
                    EGL14.EGL_NO_CONTEXT);
            dumpGlTiming();
            if (mSurfaces != null) {
                for (EGLSurfaceHolder holder : mSurfaces) {
                    if (holder.eglSurface != null) {
                        // 销毁 Surface 对象
                        EGL14.eglDestroySurface(mEGLDisplay, holder.eglSurface);
                    }
                }
            }
            if (mConversionSurfaces != null) {
                for (EGLSurfaceHolder holder : mConversionSurfaces) {
                    if (holder.eglSurface != null) {
                        EGL14.eglDestroySurface(mEGLDisplay, holder.eglSurface);
                    }
                }
            }
            // 销毁 EGLContext 对象
            EGL14.eglDestroyContext(mEGLDisplay, mEGLContext);
            // 释放线程?
            EGL14.eglReleaseThread();
            // 终止 Display 对象
            EGL14.eglTerminate(mEGLDisplay);
        }

        mConfigs = null;
        mEGLDisplay = EGL14.EGL_NO_DISPLAY;
        mEGLContext = EGL14.EGL_NO_CONTEXT;
        clearState();
    }
  • 离屏渲染
android.opengl.EGL14#eglCreatePbufferSurface
采用该方法创建的 EGLSurface 对象不需要 swapBuffer 进行一帧数据的显示。

相关文章

  • Android EGL 接口使用方法

    背景 这段时间经常跟 OpenGL ES 和 EGL 打交道。在这整理记录 EGL 接口的使用方法,方便后续理解 ...

  • Android EGL环境的搭建

    Android EGL环境的搭建 1.概述 1.1 EGL是什么? 想要了解EGL是什么,我觉得我们首先就必须要了...

  • Android GUI系统-SurfaceFlinger基础

    一、OpenGL ES与EGL Android的GUI系统是基于OpenGL/EGL来实现的。 由于OpenGL是...

  • Android中的OpenGL ES使用基础

    一、OpenGL/EGL 因为Android的GUI系统是基于OpenGL/EGL实现的,所以先介绍相关基础知识。...

  • GUI:egl

    《android内核设计框架》读书笔记 1.EGL 和 OpenGL ES EGL是图形渲染API(如OpenGL...

  • Android EGL

    部分内容摘自其他博客,请见最下[参考资料] 首先来看看Android官方对EGL的解释: OpenGL ES 定义...

  • Android配置EGL环境

    EGL 是OpenGL ES和本地窗口系统的接口,不同平台上EGL配置是不一样的,而OpenGL的调用方式是一致的...

  • Android:egl例子

    egl的最基本流程代码,记录一下。 因为这个点比较大后续会更新: 基本概念: 一.离屏(offscreen)渲染 ...

  • Android接口回调

    Android接口回调,见的最多的就是系统的点击事件的回调方法:OnClick,使用方法如下。 OnClickLi...

  • EGL接口解析与理解

    EGL 介绍 通俗上讲,OpenGL是一个操作GPU的API,它通过驱动向GPU发送相关指令,控制图形渲染管线状态...

网友评论

    本文标题:Android EGL 接口使用方法

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