OpenGL ES EGL介绍

2023-10-27

前面已经在android平台上使用OpenGL ES的API了解了如何创建3D图形已经使用FBO渲染到纹理进行一些其他的操作,起初我学习OpenGL ES的目的就是为了研究Android平台上录制屏幕的方案。到目前为止,基础知识已经具备了,还差一点需要了解的是Embedded Graphics Library (EGL),EGL是连接OpenGL ES和本地窗口系统的接口,由于OpenGL ES是跨平台的,引入EGL就是为了屏蔽不同平台上的区别。本地窗口相关的API提供了访问本地窗口系统的接口,EGL提供了创建渲染表面,接下来OpenGL ES就可以在这个渲染表面上绘制,同时提供了图形上下文,用来进行状态管理。更详细的信息可以参考Khronos EGL Registry
OpenGL和EGL.pngOpenGL和EGL.png
下面这几篇文章有助于对EGL的理解

Using EGL to connect a native window and OpenGL ES
EGL use for Android native OpenGL ES applications
USING OPENGL ES ON WINDOWS DESKTOPS VIA EG

使用EGL一般为下面的顺序
1.使用EGL首先必须创建,建立本地窗口系统和OpenGL ES的连接。

EGLDisplay eglDisplay(EGLNativeDisplayType displayId)

EGL提供了平台无关类型EGLDisplay表示窗口。定义EGLNativeDisplayType是为了匹配原生窗口系统的显示类型,对于Windows,EGLNativeDisplayType被定义为HDC,对于Linux系统,被定义为Display*类型,对于Android系统,定义为ANativeWindow *类型,为了方便的将代码转移到不同的操作系统上,应该传入EGL_DEFAULT_DISPLAY,返回与默认原生窗口的连接。如果连接不可用,则返回EGL_NO_DISPLAY。

2.初始化EGL

创建与本地原生窗口的连接后需要初始化EGL,使用函数eglInitialize进行初始化操作。如果 EGL 不能初始化,它将返回EGL_FALSE,并将EGL错误码设置为EGL_BAD_DISPLAY表示制定了不合法的EGLDisplay,或者EGL_NOT_INITIALIZED表示EGL不能初始化。使用函数eglGetError用来获取最近一次调用EGL函数出错的错误代码

EGLBoolean eglInitialize(EGLDisplay display, // 创建的EGL连接
                         EGLint *majorVersion, // 返回EGL主板版本号
                         EGLint *minorVersion); // 返回EGL次版本号

初始化EGL示例

EGLint majorVersion;
EGLint minorVersion;
EGLDisplay display;
display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
if(display == EGL_NO_DISPLAY)
{
    // Unable to open connection to local windowing system
}
if(!eglInitialize(display, &majorVersion, &minorVersion))
{
    // Unable to initialize EGL. Handle and recover
}

3.确定可用的渲染表面(Surface)的配置。一旦初始化了EGL,就可以确定可用渲染表面的类型和配置了。

一种方式是使用eglGetConfigs函数获取底层窗口系统支持的所有EGL表面配置,然后再使用eglGetConfigAttrib依次查询每个EGLConfig相关的信息,EGLConfig包含了渲染表面的所有信息,包括可用颜色、缓冲区等其他特性。

EGLBoolean eglGetConfigs(EGLDisplay display, EGLConfig *configs, EGLint maxReturnConfigs,EGLint *numConfigs);

EGLBoolean eglGetConfigAttrib(EGLDisplay display, EGLConfig config, EGLint attribute, EGLint *value)

另一种方式是指定我们需要的渲染表面配置,让EGL自己选择一个符合条件的EGLConfig配置。eglChooseChofig调用成功返回EGL_TRUE,失败时返回EGL_FALSE,如果attribList包含了未定义的EGL属性,或者属性值不合法,EGL代码被设置为EGL_BAD_ATTRIBUTR

EGLBoolean eglChooseChofig(EGLDispay display, // 创建的和本地窗口系统的连接
                           const EGLint *attribList, // 指定渲染表面的参数列表,可以为null
                           EGLConfig *config,   // 调用成功,返会符合条件的EGLConfig列表
                           EGLint maxReturnConfigs, //最多返回的符合条件的EGLConfig个数
                           ELGint *numConfigs );  // 实际返回的符合条件的EGLConfig个数

attribList参数在EGL函数中可以为null或者指向一组以EGL_NONE结尾的键对值

// we need this config
EGLint attribList[] ={
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
EGL_RED_SIZE, 5,
EGL_GREEN_SIZE, 6,
EGL_BLUE_SIZE, 5,
EGL_DEPTH_SIZE, 1,
EGL_NONE
};
const EGLint MaxConfigs = 10;
EGLConfig configs[MaxConfigs]; // We'll only accept 10 configs
EGLint numConfigs;
if(!eglChooseConfig(dpy, attribList, configs, MaxConfigs,
&numConfigs))
{
// Something didn't work … handle error situation
}
else
{
// Everything's okay. Continue to create a rendering surface
}

4.创建渲染表面

有了符合条件的EGLConfig后,就可以通过eglCreateWindowSurface函数创建渲染表面。使用这个函数的前提是要使用原生窗口系统提供的API创建一个窗口。eglCreateWindowSurface中attribList一般可以使用null即可。函数调用失败会返回EGL_NO_SURFACE,并设置对应的错误码。

EGLSurface eglCreateWindowSurface(EGLDisplay display,
                                  EGLConfig config, // 前面选好的可用EGLConfig
                                  EGLNatvieWindowType window, // 指定原生窗口
                                  const EGLint *attribList) // 指定窗口属性列表,可以为null,一般指定渲染所用的缓冲区使用但缓冲或者后台缓冲,默认为后者。

创建EGL渲染表面示例

EGLRenderSurface window;
EGLint attribList[] =
{
  EGL_RENDER_BUFFER, EGL_BACK_BUFFER,
  EGL_NONE
);
window = eglCreateWindowSurface(dpy, config, window, attribList);
if(window == EGL_NO_SURFACE)
{
switch(eglGetError())
{
  case EGL_BAD_MATCH:
    // Check window and EGLConfig attributes to determine
    // compatibility, or verify that the EGLConfig
    // supports rendering to a window,
  break;
  case EGL_BAD_CONFIG:
      // Verify that provided EGLConfig is valid
  break;
  case EGL_BAD_NATIVE_WINDOW:
      // Verify that provided EGLNativeWindow is valid
  break;
  case EGL_BAD_ALLOC:
      // Not enough resources available. Handle and recover
  break;
}
}

使用eglCreateWindowSurface函数创建在窗口上的渲染表面,此外还可以使用eglCreatePbufferSurface创建屏幕外渲染表面(Pixel Buffer 像素缓冲区)。使用Pbuffer一般用于生成纹理贴图,不过该功能已经被FrameBuffer替代了,使用帧缓冲对象的好处是所有的操作都由OpenGL ES来控制。使用Pbuffer的方法和前面创建窗口渲染表面一样,需要改动的地方是在选取EGLConfig时,增加EGL_SURFACE_TYPE参数使其值包含EGL_PBUFFER_BIT。而该参数默认值为EGL_WINDOW_BIT。

EGLSurface eglCreatePbufferSurface( EGLDisplay display,
                                   EGLConfig config,
                                   EGLint const * attrib_list // 指定像素缓冲区属性列表
                                  );

5.创建渲染上下文

使用eglCreateContext为当前的渲染API创建EGL渲染上下文,返回一个上下文,当前的渲染API是由函数eglBindAPI设置的。OpenGL ES是一个状态机,用一系列变量描述OpenGL ES当前的状态如何运行,我们通常使用如下途径去更改OpenGL状态:设置选项,操作缓冲。最后,我们使用当前OpenGL上下文来渲染。比如我想告诉OpenGL ES接下来要绘制三角形,可以通过一些上下文变量来改变OpenGL ES的状态,一旦改变了OpenGL ES的状态为绘制三角形,下一个命令就会画出三角形。通过这些状态设置函数就会改变上下文,接下来的操作总会根据当前上下文的状态来执行,除非再次重新改变状态。

// 设置当前的渲染API
EGLBoolean eglBindAPI(
  EGLenum api //可选 EGL_OPENGL_API, EGL_OPENGL_ES_API, or EGL_OPENVG_API
);

EGLContext eglCreateContext(EGLDisplay display, 
                            EGLConfig config, // 前面选好的可用EGLConfig
                            EGLContext shareContext, // 允许多个EGLContext共享特定类型的数据,传递EGL_NO_CONTEXT表示不与其他上下文共享资源
                            const EGLint* attribList // 指定操作的属性列表,只能接受一个属性EGL_CONTEXT_CLIENT_VERSION用来表示使用的OpenGL ES版本
                           );

创建上下文示例

const ELGint attribList[] = {
EGL_CONTEXT_CLIENT_VERSION, 2,
    EGL_NONE
};
EGLContext context;
context = eglCreateContext(dpy, config, EGL_NO_CONTEXT, attribList);
if(context == EGL_NO_CONTEXT)
{
  EGLError error = eglGetError();
  if(error == EGL_BAD_CONFIG)
  {
    // Handle error and recover
  }
}

6.指定某个EGLContext为当前上下文。使用eglMakeCurrent函数进行当前上下文的绑定。一个程序可能创建多个EGLContext,所以需要关联特定的EGLContext和渲染表面,一般情况下两个EGLSurface参数设置成一样的。

EGLBoolean eglMakeCurrent(EGLDisplay display,
                          EGLSurface draw, // EGL绘图表面
                          EGLSurface read, // EGL读取表面
                          EGLContext context // 指定连接到该表面的渲染上下文
                         );

7.使用OpenGL相关的API进行绘制操作。
8.交换EGL的Surface的内部缓冲和EGL创建的和平台无关的窗口diaplay。EGL实际上维护了两个buffer,前台buffer显示的时候,绘制操作会在后台buffer上进行。

EGLBoolean eglSwapBuffers(EGLDisplay display, // 指定的EGL和本地窗口的连接
                          EGLSurface surface  // 指定要交换缓冲的EGL绘制表面
                         );

At the first time I learned this function, I was thinking that its purpose is swapping the display and the surface :)) very silly.
Actually, the only thing that you need to focus here is the surface. If the surface is a pixel buffer surface, then nothing to do, the function returns without any error.
If the surface is a double-buffer surface (you often use this), the function will swap the front-buffer and the back-buffer inside the surface. The back-buffer is used to store output of rendering, while front-buffer is used by the native window to show color on your monitors.

如果surface是一个window surface,那么该函数执行的结果将是将数据给本地窗口,即显示在屏幕上。如果surface是一个屏幕外渲染surface(pixel buffer),执行该函数没有效果。

可以看到想要使用OpenGL是比较麻烦的,而这些操作又是固定的,如果把大量的代码用在做这些重复的操作上,对于学习OpenGL来说是不必要的,因此就有了一些框架,封装好了创建EGL环境以及处理事件部分,只需要将重点放在OpenGL的学习上即可。比如C语言库GLFW,还有OpenGL ES3.0编程指南的作者封装的库https://github.com/danginsburg/opengles3-book/,esMain函数作为入口,其他的处消息循环,创建窗口等操作不需要我们去处理,只需要关注OpenGL代码的编写即可。在Android系统中提供的GLSurfaceView可以很方便的用来使用OpenGL ES进行编码,其实也是因为Android的GUI系统将创建EGL环境等部分封装好了。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

OpenGL ES EGL介绍 的相关文章

  • Visual Studio 不允许我在 Android 物理设备上进行调试

    我正在使用 Xamarin 和 Visual Studio 2013 开发 Android 应用程序 我已将 Android 小程序连接到计算机 Sansung Kies 识别了该设备 Adb 也能识别它 因为当我输入 adb device
  • Android 主机意图过滤器通配符

    是否可以在 android host 属性上使用通配符 就像是 android host site com android pathPattern android pathPrefix m android scheme http gt Or
  • 单击 RecyclerView 内的 ImageView 时更改图像资源

    每当我单击它时 单击图像 而不是项目 我都会尝试更改回收器视图内特定位置的设备图像资源 我尝试将 setOnClickListener 放入 onBindViewHolder 方法中 但只有最后一个项目受到影响 这是我的回收者视图 http
  • Android中如何使用洪水填充算法?

    我是Android编程新手 最近尝试编写一个简单的应用程序 仅供练习 在这个中 我想在用户点击时为图像着色 但我不知道如何开始 我读过不同的主题 其中提到使用 洪水填充 算法 我在网上找到了它 但我不知道如何将它放入我的简单应用程序中 我找
  • 按回键隐藏软键盘

    我有一个EditText in an Activity我希望当我打开它时它处于活动状态并且软键盘处于打开状态Activity 这是我的xml for EditText
  • 如何在出现“无法解析放置符号”错误时向哈希图添加键和值

    我正在与安卓工作室 https en wikipedia org wiki Android Studio1 4 1 我刚刚创建了一个 Hashmap 并正在遵循有关如何填充和操作它的教程 Java 语言 但是 我收到 无法解析符号放置 错误
  • 使用 APDU 命令的有效 NFC 读取比特率是多少?

    我目前正在使用 Android IsoDep trancieve 函数发送和接收累计 1628 字节的数据 该函数分布在 35 个 APDU 命令 选择应用程序 身份验证 读取 中 字节计数包括返回的 MAC 校验和以及由 transcie
  • 按钮未显示在屏幕上

    我创建了一个应用程序 其中显示带有图像和文本的列表视图 我在页面末尾添加按钮 但这没有显示在屏幕上 我是 Android 新手 我该如何解决这个问题 这是我的 UI XML 代码
  • Android - 当不在栏顶部时推送通知空白

    我在使用 Android 推送通知时遇到一个小问题 如果有 3 个通知 并且只有其中一个显示标题和消息 位于酒吧顶部的那个 如果有人知道可能是什么问题 请告诉我 请参阅此链接上的图像 这就是我接收通知的方式http postimg org
  • Android-工具栏中的SearchView

    我只想在我的应用程序中添加 searchview 但我不想搜索任何东西 只是我想要用户输入的查询 到目前为止 我尝试了这段代码 但是当我运行我的应用程序时它崩溃了 Update 我尝试了这个 但即使我的应用程序崩溃了 main menu x
  • android 确定设备是否采用从右到左的语言/布局

    有没有办法确定设备是否使用从右到左的语言 例如阿拉伯语 而不是从左到右的语言 英语 与较旧的 API 级别 低至 10 兼容的东西是必要的 SOLUTION 我最终在接受的答案中使用了 xml 方法 接下来 我还添加了此处指示的代码 以应对
  • 如何在 iOS 应用程序中通过其他应用程序共享内容/数据,就像我们在 Android 应用程序中使用 Intent.ACTION_SEND 所做的那样?

    在Android中 我们可以通过Intent ACTION SEND startactivity api轻松共享内容 文本 图像 视频等 我已经有一个应用程序可以完美地做到这一点 并且有一个并行的 iOS 应用程序 我希望它能够实现相同的功
  • window.onbeforeunload 在 Android Chrome 上不会触发 [alt.解决方案?]

    我开发了一个简单的聊天应用程序 我正在使用 window onbeforeunload当有人关闭选项卡 浏览器时 基本上是当用户离开房间时 通知其他用户 这是我的代码 scope onExit function scope chatstat
  • 如何在android中的操作栏中创建Edittext?

    我们可以在操作栏中使用编辑文本吗 在阅读了 Google 中的大量资源后 我找不到如何在操作栏中创建编辑文本 谁能告诉我该怎么做 您可以设置自定义View为了ActionBar像这样 getActionBar setCustomView R
  • 在 AppAuth-Android 中注销

    我有一个用JAVA开发的Android应用程序 对于这个应用程序 我使用的是身份服务器4 https github com IdentityServer IdentityServer4作为我的 STS 一切正常 但我找不到任何注销的实现Ap
  • android 中camera.setParameters 失败

    我已将相机功能包含在我的应用程序中 我还在市场上推出了该应用程序 我从一位用户那里收到一条错误消息 称他在打开相机时遇到错误 我已经在 2 1 的设备上测试了该应用程序 我从用户那里得到的错误是使用 Nexus One 它主要运行 2 2
  • 检测 ListView(或 ScrollView)内的滚动位置

    我正在构建一个聊天室应用程序 其中每 X 秒就会轮询一次新事件 每次发生这种情况时 此代码都会使用新数据更新 RoomAdapter ArrayAdapter 的自定义子类 并将其滚动到底部 RoomAdapter adapter Room
  • Android:确定 2.2 及更高版本上的摄像头数量

    我的应用程序需要在 Android 2 2 及更高版本上运行 我需要一种方法来确定可用摄像机的数量 有很多帖子解决了这个问题 但我找不到一个有效的 一种解决方案是简单地检测操作系统版本 任何 2 2 版本的设备都仅限于 1 个摄像头 即使该
  • 更改Android菜单的背景颜色[重复]

    这个问题在这里已经有答案了 我正在尝试将标准浅灰色更改为浅绿色 似乎没有一个简单的方法可以做到这一点 例如 通过 Android 主题 但我找到了一个解决方法 如本页所述 http tinyurl com 342dgn3 http tiny
  • putFragment() - 片段 x 当前不在 FragmentManager 中

    上面的标题被问了很多次 但答案似乎与FragmentStatePagerAdapter这与我的问题无关 我正在使用该方法putFragment Bundle String Fragment 直接地 The 安卓文档 http develop

随机推荐

  • 接口测试之测试原则、测试用例、测试流程......

    一 接口的介绍 软件测试中 常说的接口有两种 图形用户接口 GUI 人与程序的接口 应用程序编程接口 API 接口 API 是系统与系统之间 模块与模块之间或者服务与服务之间相互调用的入口 它的本质 其实就是一种约定 在开发前期 我们约定接
  • BERT: Pre-training of Deep Bidirectional Transformer for Language Understanding 阅读笔记(部分翻译)

    BERT Pre training of Deep Bidirectional Transformers for Language Understanding Author Unit Google AI Language Authors J
  • elementUI_el-radio踩坑_设置点击事件会触发两次

    el radio设置点击事件会触发两次 问题描述 代码实现 问题 原因 解决 问题描述 使用了elementUI的单选按钮 点击按钮时对数据进行校验 1 若校验成功 则打开弹框 2 若是校验失败 则给出提示 代码实现
  • UE4 VR官方教程学习总结-项目设置

    这是我在学习官方VR项目教程中的笔记和总结 以及一些思考 如果有不对的地方也谢谢指出 教程链接 https docs unrealengine com 4 26 zh CN SharingAndReleasing XRDevelopment
  • java对象转jsonarray,并运用stream流各实例(jsonArray循环、分组、强转、某个字段集合值、集合用条件筛选对象)

    持续更新 获取集合某个字段的值 set接收 list集合根据字段分组 list筛选返回对象 没有返回null 集合筛选对象 如果有返回对象 没有返回null parallelStream 多线程 异步任务 流 使用lambda表达式的Map
  • UNIX网络编程卷一 学习笔记 第二十二章 高级UDP套接字编程

    TCP是一个字节流协议 又使用滑动窗口 因此没有记录边界或发送者数据发送能力超过接收者接收能力之类的事情 但对于UDP 每个输入操作对应一个UDP数据报 一个记录 因此当收取的数据报大于引用的输入缓冲区时就有问题 UDP是不可靠协议 但有些
  • 4-5非连续内存分配:页表-方向页表

    页表的大小和逻辑地址的空间大小 是有一个对应关系的 l逻辑空间越大 寻址空间也就越大 其实意味者对应的页表也越多 那有没有办法使得页表项不和l逻辑地址空间有直接的关系 尽量和物理地址空间建立关系 这其实就是所谓的方向页表的想法 方法一 页寄
  • Linux——IP协议

    IP协议是网络层一个协议 IP协议主要来实现报文段在网络环境中的转发 特点 无连接 不可靠 无状态 指通信双方不同步传输数据的状态信息 因此所有 IP 数据报的发送 传输和接收都是相互独立 没有上下文关系的 路由器实现就是到网络层 所以每台
  • 【疑点】js中的break,continue和return到底怎么用?

    为什么要说个 好像很简单 但是我也会迷糊 不懂有时候为什么要用return 然而break和continue也经常和他放在一起 所以就一起来说一说 这三个看起来很简单 却常常会出错的关键词的具体用法 主要从以下几个方面来详细论述 1 3个关
  • Python 计算机视觉(十五)—— 图像特效处理

    参考的一些文章以及论文我都会给大家分享出来 链接就贴在原文 论文我上传到资源中去 大家可以免费下载学习 如果当天资源区找不到论文 那就等等 可能正在审核 审核完后就可以下载了 大家一起学习 一起进步 加油 目录 前言 1 毛玻璃特效 2 浮
  • 【CV】第 16 章:结合计算机视觉和强化学习

    大家好 我是Sonhhxg 柒 希望你看完之后 能对你有所帮助 不足请指正 共同学习交流 个人主页 Sonhhxg 柒的博客 CSDN博客 欢迎各位 点赞 收藏 留言 系列专栏 机器学习 ML 自然语言处理 NLP 深度学习 DL fore
  • sharding-jdbc异步执行bug UnsupportedOperationException

    Cause java lang UnsupportedOperationException Cannot support database type MySQL 注册时异步bug 优先注册即可NewInstanceServiceLoader
  • C++智能指针weak_ptr详解

    一 介绍 std weak ptr 是一种智能指针 通常不单独使用 只能和 shared ptr 类型指针搭配使用 可以视为 shared ptr 指针的一种辅助工具 借助 weak ptr 类型指针可以获取 shared ptr 指针的一
  • 川教版计算机三年级下册教案,川教版小学三年级下册信息技术教案(全册)

    川教版小学三年级下册信息技术教案 全册 小学学年度第二学期 信息技术 教学工作计划 一 学情分析 孩子们经过了三年级上期的学习 大部分孩子已经养成了良好的学习习惯 本学期教师要继续保护并且激发学生的学习热情 培养孩子的自信心 教给孩子科学的
  • 音视频开发二:音视频知识总结

    文章目录 简介 简单理解 音视频原理 音视频理论基础 音频 声音介绍 为什么要存在数字音频 什么是数字音频 从 模拟信号 到 数字化 的过程 1 采样 2 量化 3 编码 音频存储空间 音频编码 音频解码 视频 颜色模型 光和颜色 YUV
  • idea单元测试时,@Test爆红解决方案

    如果出现以下单元测试 Test爆红 第一种解决方案 选中 alt enter 点Add Maven dependency 选中下图第一个选项 之后再选中注解 Test 同时按alt enter 便可解决 第二种解决方案 点击pom xml文
  • java url加密_Java实现url加密处理的方法示例

    本文实例讲述了Java实现url加密处理的方法 分享给大家供大家参考 具体如下 package test import java security Key import java security SecureRandom import j
  • jsp实现简易计算器

    一 案例演示 输入两个数实现加减乘除 结果输出到页面上 二 实现步骤 1 addall jsp 简易的jsp代码 有两个输入框 四个提交按钮
  • 设计一个学生类 Student 包含姓名、成绩两个属性。定义一个无参的构造方法和一个接收两个参数的构造方法。

    请按照以下要求设计一个学生类 Student 并进行测试 要求如下 Student 类中包含姓名 成绩两个属性 分别给这两个属性定义两个方法 一个方法用于设置值 另一个方法用于获取值 Student 类中定义一个无参的构造方法和一个接收两个
  • OpenGL ES EGL介绍

    前面已经在android平台上使用OpenGL ES的API了解了如何创建3D图形已经使用FBO渲染到纹理进行一些其他的操作 起初我学习OpenGL ES的目的就是为了研究Android平台上录制屏幕的方案 到目前为止 基础知识已经具备了