Android OpenGL ES 离屏幕渲染1——EGL环境的创建,以及基础概念的理解

news/2024/7/17 17:34:54 标签: android, EGL, 创建, EGLContext, EGLSurface

创建EGL上下文、配置EGL环境、创建EGL DISPLAY

什么是EGL

        由于OpenGL ES并不负责窗口管理以及上下文管理,该职责由各个平台自行完成;在Android平台下OpenGL ES的上下文环境是依赖EGL的API进行搭建的。

        对于EGL这个框架,谷歌已经提供了GLSurfaceView,是一个已经封装EGL相关处理的工具类,但是不够灵活;对于更加核心的OpengGL ES的用法(例如多线程共享纹理)则需要开发者自行搭建EGL开发环境。

        EGL是一套OpenGLES、OpenVG等渲染接口和它所运行的平台的底层原生窗口系统之间的桥接接口,也就是帮助OpenGLES或其他Khronos图形API渲染的内容投射到目标系统窗口的接口。它帮助处理图形上下文管理、表面/缓冲区绑定和渲染同步。并使用其他 Khronos API 实现高性能、加速、混合模式 2D 和 3D 渲染。EGL 还提供 Khronos旗下图形API 之间的互操作能力,以实现 API 之间的高效数据传输,例如在运行 OpenMAX AL 的视频子系统和运行 OpenGL ES 的 GPU 之间。

        EGL 提供创建渲染表面的机制,OpenGL ES 和 OpenVG 等客户端 API 可在该表面上进行绘制,为客户端 API 创建图形上下文,并同步客户端 API 和原生平台渲染 API 的绘制。这样便可使用 OpenGL ES 和 OpenVG 进行无缝渲染,从而实现高性能、加速、混合模式的 2D 和 3D 渲染。

        EGL 可以在多种操作系统(如 Android 和 Linux)和本机窗口系统(如 X 和 Microsoft Windows)上实现。实现还可以选择允许通过其他受支持的本机渲染 API(如 Xlib 或 GDI)渲染到特定类型的 EGL 表面。EGL 提供:

1、  用于创建客户端 API 可以在其上绘制和共享的渲染表面(窗口、pbuffers、pixmaps)的机制

2、  用于为客户端 API 创建和管理图形上下文的方法

3、  用于同步客户端 API 以及本机平台渲染 API 的绘制的方法。

        总结:为了创建和管理OpenGL ES的上下文、按照用户要求渲染图像到对应平台表面、渲染线程管理、生命周期、缓冲区等资源,以及把渲染的内容投射到目标容器(如某个surface),需要使用EGL接口进行简介操作。而安卓自带的GLSurfaceView只是把EGL创建以及和安卓系统Surface绑定的过程封装起来,让程序员方便一些而已。

示意图来自:

https://www.cnblogs.com/yongdaimi/p/11244950.html

创建EGL显示设备:

Display(EGLDisplay) 是对实际显示设备的抽象(这个设备不一定是物理存在,也可以是逻辑存在),也就是最终的画面输出终端。

        既然要进行渲染,那创建一个FrameBuffer容器是必须的,但这个容器根据自己的需要,可以通过绑定对应系统的窗口直接显示,也可以只是EGL内部一个不可见的容器——也就是所谓的离屏渲染

        在安卓中的创建也很简单,调用android.opengl.EGL14#eglGetDisplay(int)工具方法即可获得一个EGLDisplay对象,并使用android.opengl.EGL14#eglInitialize方法对其进行初始化。具体代码如下:

mEGLDisplay = EGL14.eglGetDisplay(EGL14.EGL_DEFAULT_DISPLAY)
val versions = IntArray(2)
EGL14.eglInitialize(mEGLDisplay, versions, 0, versions, 1)

创建EGL配置信息表:

        有了渲染的FrameBuffer容器,还需要告诉EGL渲染时,像素的格式,例如红绿蓝透明度4通读占的bit数、深度信息记录的bit数等配置。详细各种配置的参数解释具体可参阅:https://registry.khronos.org/EGL/sdk/docs/man/html/eglChooseConfig.xhtml

 private val mEGLConfigAttrs = intArrayOf(
            EGL14.EGL_RED_SIZE, 8,
            EGL14.EGL_GREEN_SIZE, 8,
            EGL14.EGL_BLUE_SIZE, 8,
            EGL14.EGL_ALPHA_SIZE, 8,
            EGL14.EGL_DEPTH_SIZE, 8,
            EGL14.EGL_RENDERABLE_TYPE, 
            EGL14.EGL_OPENGL_ES2_BIT,
            EGL14.EGL_NONE
    )
    val configs: Array<EGLConfig?> = arrayOfNulls(1)
    val configNum = IntArray(1)
    EGL14.eglChooseConfig(mEGLDisplay, mEGLConfigAttrs, 0, configs, 0, 1, configNum, 0) //获取1个EGL配置,因为这个例子只需要一个

(安卓SDK自带的exoplayert2也自带了一些EGLConfig属性表的例子,可以参考com.google.android.exoplayer2.util.EGLSurfaceTexture#EGL_CONFIG_ATTRIBUTES、com.google.android.exoplayer2.util.GlUtil.Api17#getEglConfig

创建EGL渲染上下文:

使用刚刚创建EGLDisplay及其EGLConfig通过EGL创建EGLContext。

函数形式:

    public static native EGLContext eglCreateContext(
        EGLDisplay dpy,
        EGLConfig config,
        EGLContext share_context,
        int[] attrib_list,
        int offset
    );

具体代码:

mEGLContext = EGL14.eglCreateContext(mEGLDisplay, mEGLConfig, EGL14.EGL_NO_CONTEXT, mEGLContextAttrs, 0) 

        第三个参数如果有需要共享这个EGLContext,如实现多线程渲染,则可以传入一个已创建成功的上下文, 这样就可以得到一个共享的上下文(Shared Context)。例子可以参考:https://juejin.cn/post/6969580005151997989

        eglCreateContext 为当前渲染 API(使用 eglBindAPI 设置)创建 EGL 渲染上下文并返回上下文句柄。然后可以使用该上下文渲染到 EGL 绘图表面。如果 eglCreateContext 无法创建渲染上下文,则返回 EGL_NO_CONTEXT。

        如果传入的share_context不是EGL_NO_CONTEXT,而是像mEGLContext这种已经创建好的的eglContext,则这个上下文本身以及这个它所使用的其他上下文,所有已被它共享、且可共享的数据(由当前渲染 API 的客户端 API 规范定义),在这个新创建的上下文上也会共享得到。但是,所有共享数据的渲染上下文本身必须存在于同一地址空间中。如果两个渲染上下文都属于同一个进程,则它们共享一个地址空间。

        attrib_list 指定上下文的属性列表。该列表具有与 eglChooseConfig 中描述的相同的结构。可以指定的属性和属性值可参考:

https://registry.khronos.org/EGL/sdk/docs/man/html/eglCreateContext.xhtml

创建EGLSurface:

        Surface(EGLSurface)是对用来存储图像的内存区域。也就是实际存储数据的地方

        根据自己需要绘制内容的大小和需求,创建EGLSurface。例子使用的是PbufferSurface。

mEGLSurface = EGL14.eglCreatePbufferSurface(mEGLDisplay, mEGLConfig, eglSurfaceAttrs, 0)

        也可以根据需要创建其他类型的Surface,例如WindowSurface、PixmapSurface,android使用eglCreateWindowSurface可以创建一个SurfaceViewSurfaceHolderSurface捆绑EGLSurface,这样内容可以展示这些Window对象不过不是渲染

把刚刚创建的一系列EGL对象进行绑定:

        绑定EGLSurface和EGLContext到显示设备(EGLDisplay),但这个EGLDisplay的内容没有和View绑定,所以并不会直接显示

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

销毁EGL环境:

        当在渲染任务完成后,在使用完OpenGL ES后,要把EGL环境进行销毁,否则会浪费设备资源。销毁之前创建EGL上下文存储图像内容Surface以及投射内容显示设备EGLDisplay具体代码

        // 与显示设备解绑
        EGL14.eglMakeCurrent(mEGLDisplay, EGL14.EGL_NO_SURFACE, EGL14.EGL_NO_SURFACE, EGL14.EGL_NO_CONTEXT)
        // 销毁 EGLSurface
        EGL14.eglDestroySurface(mEGLDisplay, mEGLSurface)
        // 销毁EGLContext
        EGL14.eglDestroyContext(mEGLDisplay, mEGLContext)
        // 销毁EGLDisplay(显示设备)
        EGL14.eglTerminate(mEGLDisplay)

结尾:

        本文主要介绍EGL概念、作用,为后续的离屏渲染做铺垫。下一篇文章将开始介绍EGL环境创建如何进行OpenGL ES API调用结果进行提取

引用:

OpenGL ES:Android平台EGL环境 - 简书

Android OpenGL ES从白痴到入门(四):离屏渲染(Pbuffer)_pbuffers+pixmaps-CSDN博客

EGL Overview - The Khronos Group Inc

https://en.wikipedia.org/wiki/OpenVG

https://registry.khronos.org/EGL/sdk/docs/man/html/eglChooseConfig.xhtml

https://registry.khronos.org/EGL/sdk/docs/man/html/eglCreateContext.xhtml

OpenGL ES 共享上下文实现多线程渲染 - 掘金

https://www.cnblogs.com/yongdaimi/p/11244950.html


http://www.niftyadmin.cn/n/5543736.html

相关文章

Webpack安装以及快速入门

3 Webpack 1 什么是Webpack https://webpack.js.org/ (官网) webpack 是一个现代 javascript 应用程序的 静态模块打包器 (module bundler) 待会要学的 vue-cli 脚手架环境, 集成了 webpack, 所以才能对各类文件进行打包处理 webpack是一个 静态模块 打包器,可以做以下的这…

Bash ——shell

Bash作为用户与操作系统之间的接口&#xff0c;让用户通过命令行输入各种指令来控制和操作计算机系统。 shell的两种解释&#xff1a; 1.linux命令解释器 Terminal 终端 ——》shell命令 ——》 Linux kernel &#xff08;内核&#xff09; Linux内核的作用&#xff1a; 1.…

CSRF靶场通关合集

目录 前言 CSRF漏洞总结 1.PiKachu靶场 1.1CSRF(get) 1.2 CSRF(post)请求 1.3 CSRF Token 2.DVWA靶场 难度低 难度中 难度高 前言 最近系统的将从web渗透到内网渗透的知识点做一个回顾,同时结合一些实战的案例来演示,下面是对刚开始学习时对靶场的一个总结. CSRF漏洞…

【三维向量旋转】基于Matlab的三维坐标旋转

一、问题描述 若空间中存在三个点A,B,C&#xff0c;其中A点是不动点&#xff0c;B点是当前方向向量上的一个点&#xff0c;C是目标方向上的一个点。如果要让AB向量沿着BC方向进行旋转&#xff0c;使得AB最终旋转到AC。这个过程就是三维向量的旋转过程。我们关注的是这个过程&am…

阶段三:项目开发---大数据开发运行环境搭建:任务4:安装配置Spark集群

任务描述 知识点&#xff1a;安装配置Spark 重 点&#xff1a; 安装配置Spark 难 点&#xff1a;无 内 容&#xff1a; Apache Spark 是专为大规模数据处理而设计的快速通用的计算引擎。Spark是UC Berkeley AMP lab (加州大学伯克利分校的AMP实验室)所开源的类Hadoop …

合并pdf的方法,如何合并pdf文件到一个pdf,简单方法

在现代办公和学习中&#xff0c;pdf格式的文件因其跨平台兼容性和安全性得到了广泛应用。然而&#xff0c;有时我们需要将多个pdf文件合并成一个&#xff0c;以便于管理和分享。本文将详细介绍几种合并pdf的方法&#xff0c;帮助读者轻松完成pdf文件的合并工作。 方法一、使用p…

【YOLOv9教程】如何使用YOLOv9进行图像与视频检测

《博主简介》 小伙伴们好&#xff0c;我是阿旭。专注于人工智能、AIGC、python、计算机视觉相关分享研究。 ✌更多学习资源&#xff0c;可关注公-仲-hao:【阿旭算法与机器学习】&#xff0c;共同学习交流~ &#x1f44d;感谢小伙伴们点赞、关注&#xff01; 《------往期经典推…

【开放集目标检测】Grounding DINO

一、引言 论文&#xff1a; Grounding DINO: Grounding DINO: Marrying DINO with Grounded Pre-Training for Open-Set Object Detection 作者&#xff1a; IDEA 代码&#xff1a; Grounding DINO 注意&#xff1a; 该算法是在Swin Transformer、Deformable DETR、DINO基础上…