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

创建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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/781417.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

WAWA鱼曲折的大学四年回忆录

声明&#xff1a;本文内容纯属个人主观臆断&#xff0c;如与事实不符&#xff0c;请参考事实 前言&#xff1a; 早想写一下大学四年的总结了&#xff0c;但总是感觉无从下手&#xff0c;不知道从哪里开始写&#xff0c;通过这篇文章主要想做一个记录&#xff0c;并从现在的认…

那些年背过的面试题——MySQL篇

本文是技术人面试系列 MySQL 篇&#xff0c;面试中关于 MySQL 都需要了解哪些基础&#xff1f;一文带你详细了解&#xff0c;欢迎收藏&#xff01; WhyMysql&#xff1f; NoSQL 数据库四大家族 列存储 Hbase K-V 存储 Redis 图像存储 Neo4j 文档存储 MongoDB 云存储 OSS …

【Gin】项目搭建 一

环境准备 首先确保自己电脑安装了Golang 开始项目 1、初始化项目 mkdir gin-hello; # 创建文件夹 cd gin-hello; # 需要到刚创建的文件夹里操作 go mod init goserver; # 初始化项目&#xff0c;项目名称&#xff1a;goserver go get -u github.com/gin-gonic/gin; # 下载…

C++入门7——string类详解

目录 1.什么是string类&#xff1f; 2.string类对象的常见构造 2.1 string(); 2.2 string (const char* s); 2.3 string (const string& str); 2.4 string (const string& str, size_t pos, size_t len npos); 2.5 string (const char* s, size_t n); 2.7 验证…

模块一SpringBoot(一)

maven记得配置本地路径和镜像 IJ搭建 SpringIntiallizer--》将https://start.spring.io改成https://start.aliyun.com/ 项目结构 Spring有默认配置&#xff0c; application.properties会覆盖默认信息&#xff1a; 如覆盖端口号server.port8888

一个最简单的comsol斜坡稳定性分析例子——详细步骤

一个最简单的comsol斜坡稳定性分析例子——详细步骤 标准模型例子—详细步骤 线弹性模型下的地应力平衡预应力与预应变、土壤塑性和安全系数求解的辅助扫描

【深入理解JVM】关于Object o = new Object()

1. 解释一下对象的创建过程 “半初始化”状态通常指的是对象在内存分配后、但在完全初始化之前的一种状态。在Java中&#xff0c;虽然JVM的规范和设计努力避免对象处于这种不稳定的状态&#xff0c;但在多线程环境下&#xff0c;由于指令重排序等并发问题&#xff0c;仍有可能…

通义千问 2,大模型应用开发时的新选择

我在进行 AI 相关的开发中&#xff0c;最常用的模型是通义千问。本地开发的时候&#xff0c;使用 Ollama 来运行 qwen 模型。集成测试和线上环境&#xff0c;使用阿里云模型服务灵积上的通义千问模型。使用阿里云的好处是&#xff1a;模型服务的获取方便&#xff0c;稳定性好&a…

无人机5公里WiFi低延迟图传模组,抗干扰、长距离、低延迟,飞睿智能无线通信新标杆

在科技日新月异的今天&#xff0c;我们见证了无数通信技术的飞跃。从开始的电报、电话&#xff0c;到如今的4G、5G网络&#xff0c;再到WiFi的广泛应用&#xff0c;每一次技术的革新都极大地改变了人们的生活方式。飞睿智能5公里WiFi低延迟图传模组&#xff0c;它以其独特的优势…

GD32实战篇-双向数控BUCK-BOOST-BUCK降压理论基础

本文章基于兆易创新GD32 MCU所提供的2.2.4版本库函数开发 向上代码兼容GD32F450ZGT6中使用 后续项目主要在下面该专栏中发布&#xff1a; https://blog.csdn.net/qq_62316532/category_12608431.html?spm1001.2014.3001.5482 感兴趣的点个关注收藏一下吧! 电机驱动开发可以跳转…

Java多线程不会?一文解决——

方法一 新建类如MyThread继承Thread类重写run()方法再通过new MyThread类来新建线程通过start方法启动新线程 案例&#xff1a; class MyThread extends Thread {public MyThread(String name) {super(name);}Overridepublic void run() {for(int i0;i<10;i){System.out.…

kafka-3

Kafka 消费组 consumer-offsets-N 稀疏索引 Kafka集群 集群搭建 集群启动和验证 Topic的意义 Topic和Partition 分区 副本 集群操作指令 多分区&多副本 多分区消费组 Rebalance机制 Rebalance机制处理流程 Rebalance机制-Range Rebalance机制-RoudRobin Rebalance机制-St…

【Linux】在线求助命令--help,man page , info page

我们知道Linux有很多的命令&#xff0c;那LInux要不要背命令&#xff1f; 答案是背最常用的那些就行了 那有的时候我们想查询一些命令的详细用法该怎么办呢&#xff1f; 这里我给出3种方法 1.--help --help的使用方法很简单啊 要查询的命令 --help 我们看个例子 这里我只…

一览 Anoma 上的有趣应用概念

撰文&#xff1a;Tia&#xff0c;Techub News 本文来源香港Web3媒体&#xff1a;Techub News Anoma 的目标是为应用提供通用的意图机器接口&#xff0c;这意味着使用 Anoma&#xff0c;开发人员可以根据意图和分布式意图机编写应用&#xff0c;而不是根据事务和特定状态机进行…

java原子类

在Java中&#xff0c;原子类&#xff08;Atomic Classes&#xff09; 是位于java.util.concurrent.atomic包中的一组类&#xff0c;这些类提供了一些原子操作&#xff0c;用于在多线程环境下进行安全的并发编程。原子类利用了底层的硬件支持&#xff0c;确保操作的原子性和线程…

初阶数据结构 二叉树常用函数(二)

函数一 求二叉树第K层的节点个数 还是一样 我们假设 K就是等于一 如果说是一个空数的话就返回0 如果说有值的话就返回一个1就可以 假设这个这层既不为空 又不是第K层的话 那么就说明第K层肯定是子树下面 那么就说明是左右子树的第&#xff08;K-1&#xff09;层 那么只将…

谷哥剪映助手使用教程-剪映自动化批量视频剪辑软件-批量混剪素材替换

谷哥剪映助手是一款提高视频剪辑效率的软件&#xff0c;很多人问具体怎么使用&#xff0c;我会抽点时间把各个功能拆分开来&#xff0c;一个个介绍。 一、按组精准替换素材 该功能可以按组精确替换图片或视频素材&#xff0c;如果你草稿里只有一个素材需要替换&#xff0c;请…

【算法笔记自学】第 8 章 提高篇(2)——搜索专题

8.1深度优先搜索&#xff08;DFS&#xff09; #include <cstdio>const int MAXN 5; int n, m, maze[MAXN][MAXN]; bool visited[MAXN][MAXN] {false}; int counter 0;const int MAXD 4; int dx[MAXD] {0, 0, 1, -1}; int dy[MAXD] {1, -1, 0, 0};bool isValid(int …

docker中实现多机redis主从集群

redis主从集群是每个使用redis的小伙伴都必需知道的&#xff0c;那如何在docker中快速配置呢&#xff1f;这篇来教你快速上手&#xff0c;跟着复制完全就能用&#xff01;&#xff01; 1. 前置准备 1.1 docker安装 以防有小伙伴没预先安装docker&#xff0c;这里提供安装步骤…

驾校管理系统设计

驾校管理系统设计旨在提高驾校运营效率、学员管理、教练安排、考试预约、财务结算等方面的能力。以下是一个基本的设计框架&#xff0c;包括关键模块和数据表设计&#xff1a; 1. 系统架构设计 前端界面&#xff1a;提供给学员、教练和管理员使用的Web界面或移动应用&#xf…