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服务器介绍 一、云计算概述 云计算是一种按使用量付费的模式,这种模式…...
计算机网络:计算机网络体系结构 —— OSI 模型 与 TCP/IP 模型
文章目录 计算机网络体系结构OSI 参考模型TCP/IP 参考模型分层的必要性物理层的主要问题数据链路层的主要问题网络层的主要问题运输层的主要问题应用层的主要问题 分层思想的处理方法发送请求路由器转发接受请求发送响应接收响应 计算机网络体系结构 计算机网络体系结构是指将…...
【openwrt-21.02】T750 openwrt switch划分VLAN之后网口插拔状态异常问题分析及解决方案
Openwrt版本 NAME="OpenWrt" VERSION="21.02-SNAPSHOT" ID="openwrt" ID_LIKE="lede openwrt" PRETTY_NAME="OpenWrt 21.02-SNAPSHOT" VERSION_ID="21.02-snapshot" HOME_URL="https://openwrt.org/" …...
C++随心记
C随心记 C中的 CONST C中的const是表示不可修改 int main() {/* 对于变量而言 */// 不可修改的常量const int A 10;// 不可修改的指针指向const int* pointer_0 nullptr;int const* poniter_1 nullptr;// 不可修改指针指向的内容int* const poniter_2 nullptr; }const也…...
【微服务即时通讯系统】——brpc远程过程调用、百度开源的RPC框架、brpc的介绍、brpc的安装、brpc使用和功能测试
文章目录 brpc1. brpc的介绍1.1 rpc的介绍1.2 rpc的原理1.3 grpc和brpc 2. brpc的安装3. brpc使用3.1 brpc接口介绍 4. brpc使用测试4.1 brpc同步和异步调用 brpc 1. brpc的介绍 1.1 rpc的介绍 RPC(Remote Procedure Call)远程过程调用,是一…...
鸿蒙开发(NEXT/API 12)【状态查询与订阅】手机侧应用开发
注意 该接口的调用需要在开发者联盟申请设备基础信息权限与穿戴用户状态权限,穿戴用户状态权限还需获得用户授权。 实时查询穿戴设备可用空间、电量状态。订阅穿戴设备连接状态、低电量告警、用户心率告警。查询和订阅穿戴设备充电状态、佩戴状态、设备模式。 使…...
vite中sass警告JS API过期
1.问题 在Vite创建项目中引入Sass弹出The legacy JS API is deprecated and will be removed in Dart Sass 2.0.0 - vite中sass警告JS API过期 The legacy JS API is deprecated and will be removed in Dart Sass 2.0.0警告提示表明你当前正在使用的 Dart Sass 版本中&#…...
睢宁自闭症寄宿学校:培养特殊孩子的未来
在自闭症儿童的教育与康复领域,每一所学校的努力都是对孩子们未来无限可能的一次深刻诠释。从江苏睢宁到广东广州,自闭症寄宿学校正以不同的方式,为这些特殊的孩子铺设一条通往未来的希望之路。其中,广州的星贝育园自闭症儿童寄宿…...
【Canvas与徽章】金圈蓝底国庆75周年徽章
【成图】 【代码】 <!DOCTYPE html> <html lang"utf-8"> <meta http-equiv"Content-Type" content"text/html; charsetutf-8"/> <head><title>金边黑盾75周年</title><style type"text/css"&g…...
Java Servlet 详解
Java Servlet 是 Java 企业级应用 中的一个核心组件,特别是在 Web 应用开发中,它为服务器端处理请求提供了基础。每次用户发出请求时,Servlet 都会动态生成响应,这在构建复杂、交互式的 Web 应用时尤为重要。 什么是 Servlet&am…...
yolov8/9/10模型在安全帽、安全衣检测中的应用【代码+数据集+python环境+GUI系统】
yolov8910模型安全帽、安全衣检测中的应用【代码数据集python环境GUI系统】 yolov8/9/10模型在安全帽、安全衣检测中的应用【代码数据集python环境GUI系统】 背景意义 安全帽和安全衣在工业生产、建筑施工等高风险作业环境中是保护工人免受意外伤害的重要装备。然而࿰…...
做网站加载速度有什么方法/西安seo优化推广
最近再写页面的时候,感觉页面之间的切换有点生硬,所以查了一下文档看见了transition这个组建,很实用,故此在这里跟大家分享一下----------------------------------------------------------------------------------------------…...
蓝色网站特点/湖南seo优化推荐
resize2fsresize2fs命令被用来增大或者收缩未加载的“ext2/ext3”文件系统的大小。如果文件系统是处于mount状态下,那么它只能做到扩容,前提条件是内核支持在线resize。linux kernel 2.6支持在mount状态下扩容但仅限于ext3文件系统。语法resize2fs(选项)…...
俱乐部网站模板/产品推广平台有哪些
刚刚偶然之间在书上看到了关于如何进行raid配置的内容,就顺便给大家截取下来了,大家有兴趣的可以看看...
深圳物流公司网站/小红书推广方式
链接静态C库和C 代码时出现“未定义的引用”错误我有一个测试文件(仅用于链接测试),其中我使用我自己的/ 库调用来重载new/ delete运算符。但是在链接静态库时,我一直得到“未定义的引用”错误,即使我改变了和的顺序。但是一切都适用于连接这…...
做算法题的 网站/公司软文推广
早就听说需求分析这个环节是重中之重,看看他人之前做过的一些产品实践案例,这样学起来更快。以一款APP为例,阐述了需求痛点及其解决方案,我们姑且叫这个App为TT吧。TT是一个面向食品供应商的、以试吃为特色的社会化食品电商导购平…...
wordpress虚拟币主题/怎么弄一个自己的网址
【摘要】2019年3月全国计算机等级考试即将开启,为了方便广大考生及时获取考试相关的信息,下面为您精心整理了2019年3月西北工业大学计算机等级考试准考证打印须知,希望广大考生及时关注,更多计算机等级考试的相关资讯,…...