OpenGL ES 之EGL(6)
OpenGL ES 之EGL(6)
简述
EGL是OpenGL ES的封装,目的是跨设备跨平台,隔离不同平台对窗口不同的实现。上一节我们基本没有使用到EGL,因为GLSurfaceView帮助我们处理了相关的逻辑,我们这一节来看一下EGL的一些概念以及接口的使用。
同时我们会介绍GLSurfaceView做了什么,是怎么配置EGL等。
EGL接口
- 1.eglGetDisplay
用于获取EGLDisplay,这里会关联原生窗口,EGLDisplay是对设备的抽象。 - 2.eglInitialize(EGLDisplay display, EGLint *majorVersion, EGLint *minorVersion)
初始化函数,第一个参数是eglGetDisplay返回值。 - 3.eglChooseConfig
EGL会根据设备配置选择合适的Config - 4.eglCreateWindowSurface
通过前面EGLDisplay和EGLConfig创建EGLSurface - 5.eglCreateContext
创建EGLContext,创建渲染上下文 - 6.eglMakeCurrent
绑定EGLContext,EGLSurface,EGLDisplay,之后即可调用openGL ES的api做图像渲染了。 - 7.eglSwapBuffers
交换缓冲区,调用后就会将内存中的图像显示到屏幕上。
GLSurfaceView流程
setRenderer
配置了Renderer之后,GLSurfaceView启动了一个GLThread线程
public void setRenderer(Renderer renderer) {checkRenderThreadState();if (mEGLConfigChooser == null) {mEGLConfigChooser = new SimpleEGLConfigChooser(true);}if (mEGLContextFactory == null) {mEGLContextFactory = new DefaultContextFactory();}if (mEGLWindowSurfaceFactory == null) {mEGLWindowSurfaceFactory = new DefaultWindowSurfaceFactory();}// 构造并启动了一个GLThread线程mGLThread = new GLThread(renderer);mGLThread.start();
}
GLThread
调用了guardedRun。
guardedRun通过一个EglHelper来调用EGL的接口。
guardedRun在一个死循环中,死循环中还有一个死循环,这里会通过mEglHelper.start来初始化EGL。在EGLSurface创建好后,就会跳出这个死循环,在外层循环后面的逻辑,首次会通过createSurface创建EGLSurface,并且回调Renderer.onSurfaceCreated,也会检查sizeChanged,如果sizeChanged则会回调Renderer.onSurfaceChanged。
每次循环都会回调Renderer.onDrawFrame,在回调onDrawFrame之后会调用mEglHelper.swap来执行交换区。
这里EglHelper的start/createSurface/swap,我们接下来看看这几个方法。
private class GLThread extends Thread {// ...public void run() {setName("GLThread " + getId());if (LOG_THREADS) {DebugLog.i("GLThread", "starting tid=" + getId());}try {guardedRun();} catch (InterruptedException e) {// fall thru and exit normally} finally {sGLThreadManager.threadExiting(this);}}
}private void guardedRun() throws InterruptedException {mEglHelper = new EglHelper();// ...try {// ...while (true) {synchronized (sGLThreadManager) {while (true) {// ...if ((! mHasSurface) && (! mWaitingForSurface)) {if (LOG_SURFACE) {DebugLog.i("GLThread", "noticed surfaceView surface lost tid=" + getId());}if (mHaveEglSurface) {stopEglLocked();}mWaitingForSurface = true;sGLThreadManager.notifyAll();}// ...// Ready to draw?if ((!mPaused) && mHasSurface&& (mWidth > 0) && (mHeight > 0)&& (mRequestRender || (mRenderMode == RENDERMODE_CONTINUOUSLY))) {if (mHaveEglContext && !mHaveEglSurface) {// 检测EGL上下文if (!mEglHelper.verifyContext()) {mEglHelper.finish();mRenderer.onSurfaceLost();mHaveEglContext = false;}}if ((! mHaveEglContext) && sGLThreadManager.tryAcquireEglSurfaceLocked(this)) {mHaveEglContext = true;// 启动EGLHelper.start,这里会做EGL的初始化mEglHelper.start();sGLThreadManager.notifyAll();}// ...if (mHaveEglSurface) {// ... 配置宽高break;}}sGLThreadManager.wait();}} // end of synchronized(sGLThreadManager)if (event != null) {event.run();event = null;continue;}if (mHasFocus) {if (createEglSurface) {// 调用createSurface,初始化EGL上下文gl = (GL10) mEglHelper.createSurface(getHolder());// ...// 回调Renderer.onSurfaceCreatedmRenderer.onSurfaceCreated(gl, mEglHelper.mEglConfig);createEglSurface = false;framesSinceResetHack = 0;}if (sizeChanged) {// ...// 回调Renderer.onSurfaceChangedmRenderer.onSurfaceChanged(gl, w, h);sizeChanged = false;}// ...mWatchDog.reset();// 回调Renderer.onDrawFramemRenderer.onDrawFrame(gl);framesSinceResetHack++;// 调用eglSwapBuffers,交换缓冲区上屏显示if(!mEglHelper.swap()) {// ...stopEglLocked();}}if (wantRenderNotification) {doRenderNotification = true;}}} finally {// ... 释放EGL上下文}
}
EglHelper
EglHelper就是对EGL对接口进行封装,这些EGL的接口作用在前面都介绍过了。
public void start(){mEgl = (EGL10) EGLContext.getEGL();// 通过eglGetDisplay获取EglDisplaymEglDisplay = mEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);// ...int[] version = new int[2];// 调用eglInitialize进行初始化if(!mEgl.eglInitialize(mEglDisplay, version)) {throw new RuntimeException("eglInitialize failed");}// 调用eglChooseConfig获取EglConfigmEglConfig = mEGLConfigChooser.chooseConfig(mEgl, mEglDisplay);// 创建EglContextmEglContext = mEGLContextFactory.createContext(mEgl, mEglDisplay, mEglConfig);if (mEglContext == null || mEglContext == EGL10.EGL_NO_CONTEXT) {throwEglException("createContext");}mEglSurface = null;
}public GL createSurface(SurfaceHolder holder) {// 如果之前创建过EglSurface,直接调用eglMakeCurrent进行关联if (mEglSurface != null && mEglSurface != EGL10.EGL_NO_SURFACE) {mEgl.eglMakeCurrent(mEglDisplay, EGL10.EGL_NO_SURFACE,EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT);mEGLWindowSurfaceFactory.destroySurface(mEgl, mEglDisplay, mEglSurface);}// 调用createWindowSurface创建EglSurface mEglSurface = mEGLWindowSurfaceFactory.createWindowSurface(mEgl,mEglDisplay, mEglConfig, holder);if (mEglSurface == null || mEglSurface == EGL10.EGL_NO_SURFACE) {throwEglException("createWindowSurface");}// 调用eglMakeCurrent关联if (!mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) {throwEglException("eglMakeCurrent");}GL gl = mEglContext.getGL();if (mGLWrapper != null) {gl = mGLWrapper.wrap(gl);}// ... 配置debug相关flagreturn gl;
}public boolean swap() {// 调用eglSwapBuffers交换Buffer显示mEgl.eglSwapBuffers(mEglDisplay, mEglSurface);return mEgl.eglGetError() != EGL11.EGL_CONTEXT_LOST;
}
小结
EGL的接口比较简单,流程也基本是固定的,我们以GLSurfaceView为例介绍了它的使用流程,GLSurfaceView就是启动一个线程,除了处理固定的EGL上下文初始化,还控制了Renderer回调的几个生命周期。
介绍完EGL后,我们后面就可以专注于OpenGL ES的api使用了。
相关文章:
OpenGL ES 之EGL(6)
OpenGL ES 之EGL(6) 简述 EGL是OpenGL ES的封装,目的是跨设备跨平台,隔离不同平台对窗口不同的实现。上一节我们基本没有使用到EGL,因为GLSurfaceView帮助我们处理了相关的逻辑,我们这一节来看一下EGL的一些概念以及接口的使用。…...
kotlin 委托
一、类委托 interface DB{fun insert() } class SqliteDB : DB {override fun insert() {println(" SqliteDB insert")} }class MySql : DB{override fun insert() {println(" MySql insert")} }class OracleDB : DB{override fun insert() {println(&quo…...
Stream流的中间方法
一.Stream流的中间方法 注意1:中间方法,返回新的Stream流,原来的Stream流只能使用一次,建议使用链式编程 注意2:修改Stream流中的数据,不会影响原来集合或者数组中的数据 二.filter filter的主要用法是…...
【车载开发系列】ParaSoft单元测试环境配置(四)
【车载开发系列】ParaSoft单元测试环境配置(四) 【车载开发系列】ParaSoft单元测试环境配置(四) 【车载开发系列】ParaSoft单元测试环境配置(四)一. 如何设置过滤二. 如何设置静态扫描的规则三. 如何设置单…...
IDEA 设置自动定位文件
一、场景分析 IDEA 在使用的过程中,发现有时候,打开一个类,它并不能自动帮我们在左侧 Project 树中定位出文件,需要自己手动点击 瞄准 图标。很不方便。 二、解决方法 1、点击 瞄准 图标旁边的 竖三点 2、将 Alwasy Select Opene…...
Nature Machine Intelligence 基于强化学习的扑翼无人机机翼应变飞行控制
尽管无人机技术发展迅速,但复制生物飞行的动态控制和风力感应能力,仍然遥不可及。生物学研究表明,昆虫翅膀上有机械感受器,即钟形感受器campaniform sensilla,探测飞行敏捷性至关重要的复杂气动载荷。 近日࿰…...
[Web安全 网络安全]-XXE 外部实体注入攻击XML
文章目录: 一:前言 1.定义 1.1 XXE 1.2 XML可扩展标记语言 2.DDT文档类型定义 2.1 分类 2.2 元素element DTD元素 DTD属性 2.3 实体entity DTD实体类别 DTD实体声明引用 声明:内部 外部 参数实体 公共实体 引用:…...
8--苍穹外卖-SpringBoot项目中套餐管理 详解(二)
目录 删除套餐 需求分析和设计 代码开发 根据id查询套餐 mapper层 Service层 ServiceImpl层 Mapper层 批量删除套餐 mapper层 Service层 ServiceImpl层 Mapper层 SetmealMapper.xml 修改套餐 需求分析和设计 代码开发 起售停售套餐 需求分析和设计 代码开发…...
测试面试题:pytest断言时,数据是符点类型,如何断言?
在使用 Pytest 进行断言时,如果数据是浮点类型,可以使用以下方法进行断言: 一、使用pytest.approx pytest.approx可以用来比较两个浮点数是否近似相等。例如: import pytestdef test_float_assertion():result 3.14159expecte…...
Python与MongoDB交互
一、基本概念 MongoDB: 一个面向文档的数据库系统,使用BSON(Binary JSON)作为存储格式。集合(Collection): 类似于关系型数据库中的表,是文档的集合。文档(Document): MongoDB中的基…...
安卓AI虚拟女友项目开发的Android开发环境搭建
第五章:Android开发环境搭建与基础入门 5-1 项目讲解思路说明 本文是安卓AI数字虚拟人项目实战的第五章,开发安卓AI安卓版数字虚拟人的Android基础部分。 在本章中,我们将详细介绍如何搭建Android开发环境,包括Android Studio的…...
基于SpringBoot+Vue+MySQL的智能垃圾分类系统
系统展示 用户前台界面 管理员后台界面 系统背景 随着城市化进程的加速,垃圾问题日益凸显,不仅对环境造成污染,也给城市管理带来了巨大挑战。传统的垃圾分类方式不仅费时费力,而且手工操作容易出现错误,导致垃圾分类效…...
你的个人文件管理助手:AI驱动的本地文件整理工具
🌐 引言 在数字化时代,我们经常面临文件管理的挑战。电脑中的文件杂乱无章,寻找特定文件变得既费时又费力。幸运的是,现在有了一款名为本地文件整理器的神器,它利用AI技术帮助你快速、智能地整理文件,同时…...
【PyTorch】环境配置
框架介绍 Pytorch简介 2017年1月,FAIR(Facebook AI Research)发布了PyTorch。PyTorch是在Torch基础上用python语言重新打造的一款深度学习框架。Torch是采用Lua语言作为接口的机器学习框架,但因为Lua语言较为小众,导…...
枫叶MTS格式转换器- 强大、操作简单的MTS、M2TS视频转换工具供大家学习研究参考
一款功能强大、操作简单的MTS、M2TS视频转换工具,欢迎下载使用。 使用本MTS格式转换器可以帮助您将索尼和松下等摄像机录制的MTS、M2TS格式高清视频转换为其他流行的视频格式,如MP4、3GP、AVI、MPEG、WMV、ASF、MOV、RM、VCD、SVCD、DVD、MKV、FLV、SWF、MPG、MP3、WAV、WMA…...
Vscode把全部‘def‘都收起来的快捷键
在 VSCode 中,你可以使用以下快捷键来收起所有函数定义 (def): Windows/Linux: Ctrl K, Ctrl 0macOS: Cmd K, Cmd 0 这个快捷键组合会折叠当前文件中所有的代码块(包括所有函数和类定义)。你可以通过相同的快捷键再次展开这…...
Web和UE5像素流送、通信教程
一、web端配置 首先打开Github地址:https://github.com/EpicGamesExt/PixelStreamingInfrastructure 找到自己虚幻引擎对应版本的项目并下载下来,我这里用的是5.3。 打开项目找到PixelStreamingInfrastructure-master > Frontend > implementat…...
【YOLO目标检测电梯间电动车与人数据集】共4321张、已标注txt格式、有训练好的yolov5的模型
目录 说明图片示例 说明 数据集格式:YOLO格式 图片数量:4321 标注数量(txt文件个数):4321 标注类别数:2 标注类别名称:person、electricBicycle 数据集下载:电梯间电动车与人数据集 图片示例 数据…...
【网络安全】公钥基础设施
1. PKI 定义 1.1 公钥基础设施的概念 公钥基础设施(Public Key Infrastructure,简称PKI)是一种基于公钥密码学的系统,它提供了一套完整的解决方案,用于管理和保护通过互联网传输的信息。PKI的核心功能包括密钥管理、…...
云原生(四十一)| 阿里云ECS服务器介绍
文章目录 阿里云ECS服务器介绍 一、云计算概述 二、什么是公有云 三、公有云优缺点 1、优点 2、缺点 四、公有云品牌 五、市场占有率 六、阿里云ECS概述 七、阿里云ECS特点 阿里云ECS服务器介绍 一、云计算概述 云计算是一种按使用量付费的模式,这种模式…...
手把手教你为OpenBMC (AST2600平台) 正确配置PCA9545 I2C Switch的DTS节点
深入解析AST2600平台PCA9545 I2C Switch设备树配置实战指南 在嵌入式系统开发中,I2C总线扩展是连接多个外设的常见需求。NXP的PCA9545作为一款4通道I2C总线开关芯片,能够有效解决I2C地址冲突问题,但在实际应用中,设备树(DTS)配置…...
Vue3前端集成Gemma-3-12B-IT:构建智能聊天界面
Vue3前端集成Gemma-3-12B-IT:构建智能聊天界面 用最简单的方式,让你的Vue3项目拥有智能对话能力 1. 为什么要在Vue3中集成智能聊天功能 现在很多网站和应用都需要智能对话功能,不管是客服系统、学习助手还是内容创作工具。Gemma-3-12B-IT作为…...
小麦联合收割机的设计【说明书+SW三维+CAD图纸】
小麦联合收割机作为现代农业机械化的核心装备,其设计需兼顾效率、可靠性与适应性。该设备通过集成收割、脱粒、清选及集粮功能,实现小麦收获环节的连续作业,显著缩短田间作业周期,降低人工劳动强度。其核心作用体现在三方面&#…...
爱毕业aibiye等8款智能应用显著改善了论文撰写体验,编程与学术研究流程更加顺畅
文章总结表格(工具排名对比) 工具名称 核心优势 aibiye 精准降AIGC率检测,适配知网/维普等平台 aicheck 专注文本AI痕迹识别,优化人类表达风格 askpaper 快速降AI痕迹,保留学术规范 秒篇 高效处理混AIGC内容&…...
用Python的igraph和leidenalg搞定知识图谱布局:一个科研领域的可视化实战
科研知识图谱实战:用PythonLeiden算法揭示学科交叉规律 当你在文献海洋中寻找研究方向时,是否曾被复杂的学科交叉关系困扰?传统的关键词共现分析已经不能满足现代科研的需求。本文将带你用Python的igraph和leidenalg构建一个能自动识别学科社…...
QT6.5串口编程第一步:用CMakeLists.txt引入SerialPort模块的避坑指南
QT6.5串口编程避坑指南:CMakeLists.txt配置全解析 当你满怀期待地在QT6.5项目中引入串口通信功能,却在编译时遭遇"找不到QtSerialPort"的红色错误提示,这种挫败感我深有体会。作为一位经历过无数次类似"战斗"的开发者&am…...
Nanobot技能扩展开发:自定义OpenClaw功能模块教程
Nanobot技能扩展开发:自定义OpenClaw功能模块教程 1. 引言 想给你的Nanobot智能助手添加一些个性化功能吗?比如让它帮你查天气、管理待办事项,或者连接你常用的办公软件?今天就来手把手教你如何为Nanobot开发自定义技能模块。 …...
BH1750光照传感器避坑指南:STM32的I2C通信那些事儿(附STM32F407调试心得)
BH1750光照传感器实战避坑:STM32 I2C通信深度解析与调试技巧 第一次用STM32驱动BH1750光照传感器时,我盯着纹丝不动的数据寄存器发呆了半小时——I2C总线明明显示通信成功,但读回来的光照值永远是零。这种看似简单却暗藏玄机的外设调试经历&a…...
Z-Image-GGUF模型Java后端集成指南:SpringBoot微服务实战
Z-Image-GGUF模型Java后端集成指南:SpringBoot微服务实战 最近在做一个内容创作平台的后台重构,产品经理提了个需求,想给用户加个“AI一键生成文章配图”的功能。团队评估了几个方案,最终决定用Z-Image-GGUF这个模型,…...
工业质检实战:用Real-IAD D³的‘伪3D’光度立体数据,搞定MVTec搞不定的细微划痕
工业质检实战:用Real-IAD D的‘伪3D’光度立体数据,搞定MVTec搞不定的细微划痕 在精密制造领域,金属表面0.1mm级的发丝划痕往往成为质检工程师的噩梦。传统2D视觉系统受限于平面成像原理,对这类微观三维形变束手无策;而…...
