OpenGL ES学习系列文章:
上一篇:OpenGL ES (一)EGL介绍和使用
下一篇:OpenGL ES (三)着色器和程序

EGL介绍和使用

  • 一、EGL简介
  • 二、EGL的功能
  • 三、EGL使用
    • 1、创建OpenGL ES与原生窗口系统的连接
    • 2、初始化EGL连接
    • 3.选择Surface配置
    • 4. 创建渲染区域Surface
      • 4.1 创建屏幕上的渲染区域:EGL窗口
      • 4.2 其他操作surface方法
    • 5. 创建渲染上下文

一、EGL简介

与OpenGl ES一样,EGL同样是由Khronos Group所提供的一个与平台无关的API。

OpenGL作为一个图形化API,允许我们操作GPU以绘制图形,但是当涉及到本地的窗口时,就需要一个与平台无关的API来与之进行交互,EGL应运而生,承担起OpenGl和原生窗口系统之间桥梁的作用。

二、EGL的功能

EGL API作为一套与OpenGL ES各个版本相互独立的API,其作用主要是管理绘图表面。EGL提供以下机制:

  1. 与设备的原生窗口系统通信
  2. 查询绘图表面的可用类型和配置
  3. 创建绘图表面
  4. 在OpenGL ES3.0或其他渲染API之间同步渲染
  5. 管理纹理贴图等渲染资源

三、EGL使用

1、创建OpenGL ES与原生窗口系统的连接

EGLDisplay eglGetDisplay(EGLNativeDisplayType displayId);
eglGetDisplay为原生窗口系统displayId获取一个EGL display连接,
在OpenGL ES与本地窗口系统之间架起了一座沟通的桥梁

2、初始化EGL连接

与窗口系统的连接建立以后,随后要进行EGL的初始化

EGLBoolean eglInitialize(EGLDisplay display,   // 要进行初始化的EGL连接,即上一部中的返回值EGLint *majorVersion, // 主版本号EGLint *minorVersion) // 次版本号
  1. display默认为EGL_DEFAULT_DISPLAY,即返回与默认原生窗口的连接
  2. majorVersion 和minorVersion 会在调用后返回版本号,例如EGL1.0, majorVersion返回1, minorVersion返回0

注:eglInitialize会初始化EGL内部数据,比如分配显存等;如果初始化失败,可以用eglGetError()
函数获取具体的错误类型,其他EGL相关的函数,也都可以使用eglGetError()来获取错误的类型。

EGL中大部分函数执行成功时返回EGL_TRUE,失败时返回EGL_FALSE。eglGetError()函数可以指示故障原因

常见错误返回值(使用eglGetError获取):

  • EGL_BAD_DISPLAY :表示参数display不是一个EGL diaplay 连接
  • EGL_NOT_INITIALIZED :表示传入的display不可以被初始化

创建连接与初始化实例:

EGLint majorVersion;
EGLint minorVersion;
EGLDisplay display;
display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
if (display == EGL_NO_DISPLAY) {// 与本地窗口系统创建连接失败
}
if (!eglInitialize(display, &majorVersion, &minorVersion)) {// 初始化EGL连接失败
}

3.选择Surface配置

EGL初始化成功之后,就需要确定可用渲染表面的类型和配置。
一般来说,选择配置的方法有两种:

  • 方法一:查询所有可行的配置(eglGetConfigs),再让EGL从中找出最优选择(eglGetConfigAttrib

  • 方法二:指定一组需求,然后再让EGL推荐(eglChooseChofig)最佳配置。

下面分写介绍这两种方法的使用。

方法一:从所有可行配置中找到最优配置

EGLBoolean eglGetConfigs(EGLDisplay display,         //指定EGL显示连接EGLConfig * configs,     //指定一组configEGLint config_size,         //指定配置列表的大小EGLint * num_config);        //实际匹配的配置总数

参数configs将包含在你平台上所有有效的EGLframebuffer配置列表。支持的总数通过num_config返回,而实际返回的 configs 的配置个数依赖于程序传入的 config_size,如果 config_size < num_config,则不是所有可行的config都会被返回。如果想要获取系统支持的所有配置信息,最好的方法就是先给eglGetConfigs传一个null的configs参数,这样执行后就会得到系统支持的配置总数num_config,然后使用num_config来给configs分配合适的内存大小,再用得到的configs来调用eglGetConfig。

示例:


EGLConfig *configs_list;
EGLint num_configs;
m_eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
if( m_eglDisplay == EGL_NO_DISPLAY || eglGetError() != EGL_SUCCESS ){return FALSE;
}if( eglInitialize( m_eglDisplay, NULL, NULL ) == EGL_FALSE || eglGetError() != EGL_SUCCESS ){return FALSE;
}// find out how many configurations are supported
if(eglGetConfigs(m_eglDisplay, NULL, 0, &num_configs)== EGL_FALSE || eglGetError() != EGL_SUCCESS){return FALSE;
}configs_list = malloc(num_configs * sizeof(EGLConfig));
if (configs_list == (EGLConfig *)0){return FALSE;
}// Get Configurations
if( eglGetConfigs( m_eglDisplay, configs_list, num_configs, &num_configs)== EGL_FALSE || eglGetError() != EGL_SUCCESS ){return FALSE;
}

由于当前平台的限制,通常只有很少的配置可用。系统支持的配置通常是利用系统硬件提供最好的性能。当你移植游戏到多个平台,它们的EGL 配置可能会有细微的差别,我们希望作为通用的移植问题来直接处理这些问题。

方法二:指定一组需求,让EGL推荐最佳配置

EGLBoolean eglChooseConfig(EGLDisplay display,       // 指定EGL显示连接 const EGLint *attribList,  // 指定configs匹配的属性列表EGLConfig *configs,     // 指定配置列表EGLint maxReturnConfigs,   // 指定配置的大小EGLint *numConfigs)        // 指定返回的配置大小

glChooseConfig()函数将适配一个你所期望的配置,并且尽可能接近一个有效的系统配置。参数 attribList 指定了选择配置时需要参照的属性。参数 configs 将返回一个按照 attribList 排序的平台有效的所有 EGL framebuffer 配置列表。参数 config_size 指定了可以返回到 configs 的总配置个数。参数 num_config 返回了实际匹配的配置总数。

示例:

EGLint attrs[3] = { EGL_DEPTH_SIZE, 16, EGL_NONE };
EGLint num_configs;
EGLConfigs *configs_list;
// Get the display device
if ((eglDisplay = eglGetDisplay(EGL_NO_DISPLAY)) == EGL_NO_DISPLAY) {return eglGetError();
}
// Initialize the display
if (eglInitialize(eglDisplay, NULL, NULL) == EGL_FALSE) {return eglGetError();
}
// Obtain the total number of configurations that match
if (eglChooseConfig(eglDisplay, attrs, NULL, 0, &num_configs) == EGL_FALSE) {return eglGetError();
}
configs_list = malloc(num_configs * sizeof(EGLConfig));
if (configs_list == (EGLConfig *)0){return eglGetError();
}
// Obtain the first configuration with a depth buffer of 16 bits
if (!eglChooseConfig(eglDisplay, attrs, &configs_list, num_configs, &num_configs)) {return eglGetError();
}

如果找到了多个配置,则基于属性的优先级进行排序,下表显示了基于属性值的用来选择和排序的顺序(不需过多关注),也包括了 EGL 规范中所有 EGL 配置属性及其默认值。

属性 数据类型 默认值 排序优先级 选择排序
EGL_BUFFER_SIZE int 0 3 Smaller value
EGL_RED_SIZE int 0 2 Larger value
EGL_GREEN_SIZE int 0 2 Larger value
EGL_BLUE_SIZE int 0 2 Larger value
EGL_ALPHA_SIZE int 0 2 Larger value
EGL_CONFIG_CAVET enum EGL_DONT_CARE 1(first) Exact value
EGL_CONFIG_ID int EGL_DONT_CARE 9 Exact value
EGL_DEPTH_SIZE int 0 6 Smaller value
EGL_LEVEL int 0 - Equal value
EGL_NATIVE_RENDERABLE Boolean EGL_DONT_CARE - Exact value
EGL_NATIVE_VISUAL_TYPE int EGL_DONT_CARE 8 Exact value
EGL_SAMPLE_BUFFERS int 0 4 Smaller value
EGL_SAMPLES int 0 5 Smaller value
EGL_STENCIL_SIZE int 0 7 Smaller value
EGL_SURFACE_TYPE bitmask EGL_WINDOW_BIT - Mask value
EGL_TRANSPARENT_TYPE enum EGL_NONE - Exact value
EGL_TRANSPARENT_RED_VALUE int EGL_DONT_CARE - Exact value
EGL_TRANSPARENT_GREEN_VALUE int EGL_DONT_CARE - Exact value
EGL_TRANSPARENT_BLUE_VALUE int EGL_DONT_CARE - Exact value

4. 创建渲染区域Surface

当有了符合条件的 EGLConfig 后,就可以通过 eglCreateWindowSurface 函数创建渲染区域。

4.1 创建屏幕上的渲染区域:EGL窗口

创建surface

EGLSurface eglCreateWindowSurface(   EGLDisplay display,             //对应的EGL display连接EGLConfig config,             //EGL frame buffer配置,定义了可用于Surface的frame buffer资源NativeWindowType native_window, //原生窗口EGLint const * attrib_list);  // attrib_list为Window Surface属性列表,可以为NULL,成功时返回新创建的EGLSurface,失败时返回EGL_NO_SURFACE.// 可能出现的错误:
// EGL_BAD_DISPLAY: 连接不是一个EGL display连接
//EGL_NOT_INITIALIZED: EGL没有初始化
//EGL_BAD_CONFIG: EGL frame buffer配置无效
//EGL_BAD_NATIVE_WINDOW: native window不是与display相同平台的有效Native Window
//EGL_BAD_ATTRIBUTE: attrib_list包含无效参数,或者参数未被识别,或者参数越界
//EGL_BAD_ALLOC:已经有一个与native window关联的Surface,或者无法为新的EGL窗口分配资源,
//EGL_BAD_MATCH:本机窗口的像素格式与配置所需的颜色缓冲区的格式、类型和大小不一致

4.2 其他操作surface方法

  • 销毁surface:
EGLAPI EGLBoolean EGLAPIENTRY eglDestroySurface(EGLDisplay display, EGLSurface surface);

与eglCreateWindowSurface对应的,还有一个eglDestroySurface,用来销毁surface,display为对应的Display,surface为将要销毁的Surface, 如果任何其它线程都没有使用这个Surface时,Surface将被立即销毁,否则要等到这个Surface不被任何线程使用时才销毁,另外,对于一个PBuffer Surface来说,其资源要等到绑定到纹理对象的颜色缓冲区释放后才被销毁。成功时返回EGL_TRUE,失败时返回EGL_FALSE,可能的错误为EGL_BAD_DISPLAY、EGL_NOT_INITIALIZED、EGL_BAD_SURFACE。

  • 获取surface信息
EGLAPI EGLBoolean EGLAPIENTRY eglQuerySurface(EGLDisplay display, EGLSurface surface,EGLint attribute, EGLint *value);

eglQuerySurface用于获取Surface信息,display为对应的Display,surface待查询的Surface,attribute为待查询的Surface属性,value用于返回Surface属性值,成功时返回EGL_TRUE,失败时返回EGL_FALSE,可能的错误为EGL_BAD_DISPLAY、EGL_NOT_INITIALIZED、EGL_BAD_SURFACE、EGL_BAD_ATTRIBUTE。attribute取值可以是:

EGL_CONFIG_ID
EGL_HEIGHT
EGL_HORIZONTAL_RESOLUTION
EGL_LARGEST_PBUFFER
EGL_MIPMAP_LEVEL
EGL_MIPMAP_TEXTURE
EGL_MULTISAMPLE_RESOLVE
EGL_PIXEL_ASPECT_RATIO
EGL_RENDER_BUFFER
EGL_SWAP_BEHAVIOR
EGL_TEXTURE_FORMAT
EGL_TEXTURE_TARGET
EGL_VERTICAL_RESOLUTION
EGL_WIDTH
  • 设置surface属性
EGLAPI EGLBoolean EGLAPIENTRY eglSurfaceAttrib(EGLDisplay display, EGLSurface surface,EGLint attribute, EGLint value);

eglSurfaceAttrib用于设置Surface属性,display为对应的Display,surface为要设置的Surface,attribute为要设置的Surface属性,value为要设置的Surface属性值,成功时返回EGL_TRUE,失败时返回EGL_FALSE,可能的错误为EGL_BAD_DISPLAY、EGL_BAD_MATCH、EGL_NOT_INITIALIZED、EGL_BAD_SURFACE、EGL_BAD_ATTRIBUTE。attribute取值可以是:

EGL_MIPMAP_LEVEL:默认值为0。
EGL_MULTISAMPLE_RESOLVE:EGL_MULTISAMPLE_RESOLVE_DEFAULT或>EGL_MULTISAMPLE_RESOLVE_BOX,默认值为前者。
EGL_SWAP_BEHAVIOR:EGL_BUFFER_PRESERVED或EGL_BUFFER_DESTROYED,默认值由实现而定。
  • 创建屏幕外的渲染区域
EGLSurface eglCreatePbufferSurface(EGLDisplay display,       // 指定EGL显示连接EGLConfig config,           // 指定配置const EGLint *attribList)   // 指定像素缓冲区属性

OpenGL ES 3.0不仅可以在屏幕上的窗口渲染,还可以渲染称作pbuffer的不可见屏幕外表面。PBuffer Surface是不同于Window Surface的另一种EGLSurface,eglCreatePbufferSurface用于创建off-screen的pixel buffer Surface,display为对应的Display,config为frame buffer配置,attribList为PBuffer属性列表,可以为NULL,成功时返回新创建的EGLSurface,失败时返回EGL_NO_SURFACE,可能的错误为EGL_BAD_DISPLAY、EGL_NOT_INITIALIZED、EGL_BAD_CONFIG、EGL_BAD_ATTRIBUTE、EGL_BAD_ALLOC、EGL_BAD_MATCH。attribList的属性可以是:

EGL_HEIGHT:默认值为0。
EGL_LARGEST_PBUFFER:默认值为EGL_FALSE。
EGL_MIPMAP_TEXTURE:默认值为EGL_FALSE。
EGL_TEXTURE_FORMAT:默认值为EGL_NO_TEXTURE,还可以选择EGL_TEXTURE_RGB或>EGL_TEXTURE_RGBA。
EGL_TEXTURE_TARGET:默认值为EGL_NO_TEXTURE,还可以选择EGL_TEXTURE_2D。
EGL_VG_ALPHA_FORMAT:只适用于OpenVG,默认值为EGL_VG_ALPHA_FORMAT_NONPRE,>还可以选择EGL_VG_ALPHA_FORMAT_PRE。
EGL_VG_COLORSPACE:只适用于OpenVG,默认值为EGL_VG_COLORSPACE_sRGB,还可以选>择EGL_VG_COLORSPACE_LINEAR。
EGL_WIDTH:默认值为0。

PBuffer Surface与Window Surface

除了可以用OpenGL ES 3.0在屏幕上的窗口渲染之外,还可以渲染称作PBuffer(像素缓冲区Pixel Buffer的缩写)的不可见屏幕外表面,和窗口一样,PBuffer可以利用OpenGL ES 3.0中的任何硬件加速,PBuffer最常用于生成纹理贴图,如果想要做的是渲染到一个纹理,那么建议使用帧缓冲区对象(FBO)代替PBuffer,因为帧缓冲区更高效,不过在某些FBO无法使用的情况下,PBuffer仍然有用,例如用OpenGL ES在屏幕外表面上渲染,然后将其作为其它API(如OpenVG)中的纹理。另外,EGLSurface还有个Pixmap Surface,简单总结一下三者的特点。window是on-screen的,pbuffer和pixmap是off-screen的,window绑定到了NativeWindow,pixmap绑定到了NativePixmap,pbuffer没有任何本地绑定,window是双缓冲区的,pbuffer和pixmap是单缓冲区的,window默认在back buffer渲染,通过eglSwapBuffers交换到屏幕上显示,pbuffer在显存中分配,由EGL_HEIGHT和EGL_WIDTH指定大小,常用作纹理数据,pixmap绑定到本地的像素缓冲区,这个缓冲区可以被其它API使用。创建不同的EGLSurface时,需要在EGLConfig中配置EGL_SURFACE_TYPE,window、pbuffer、pixmap分别对应于EGL_WINDOW_BIT、EGL_PBUFFER_BIT、EGL_PIXMAP_BUFFER。

5. 创建渲染上下文

创建渲染上下文

EGLAPI EGLContext EGLAPIENTRY eglCreateContext(EGLDisplay display, EGLConfig config,EGLContext share_context,const EGLint *attribList);

eglCreateContext用于创建EGL渲染Context,display为对应的Display,config为frame buffer配置,share_context为其它的共享Context,可以设置为EGL_NO_CONTEXT,attribList为Context属性列表,成功时返回新创建的EGLContext,失败时返回EGL_NO_CONTEXT,可能的错误为EGL_BAD_MATCH、EGL_BAD_DISPLAY、EGL_NOT_INITIALIZED、EGL_BAD_CONFIG、EGL_BAD_CONTEXT、EGL_BAD_ATTRIBUTE、EGL_BAD_ALLOC。attrib_list属性目前只有EGL_CONTEXT_CLIENT_VERSION,整数值,指定OpenGL ES版本,默认值为1,还可以是2、3等其它版本值,创建OpenGL ES Context时设置这个属性,也就是说渲染API为EGL_OPENGL_ES_API时才设置这个属性,为此还要设置或查询渲染API,使用如下两个函数。

销毁渲染上下文

EGLAPI EGLBoolean EGLAPIENTRY eglDestroyContext(EGLDisplay display, EGLContext context);

eglDestroyContext用于销毁渲染Context,dpy为对应的Display,ctx为要销毁的Context,如果有其它线程使用这个Context时就要等到不使用时再销毁,否则立即销毁,成功时返回EGL_TRUE,失败时返回EGL_FALSE,可能的错误为EGL_BAD_DISPLAY、EGL_NOT_INITIALIZED、EGL_BAD_CONTEXT。

获取Context信息

EGLAPI EGLBoolean EGLAPIENTRY eglQueryContext(EGLDisplay display, EGLContext context,EGLint attribute, EGLint *value);

eglQueryContext用于获取Context信息,dpy为对应的Display,ctx为要查询的Context,attribute为要查询的Context属性,value返回查询的Context属性值,成功时返回EGL_TRUE,失败时返回EGL_FALSE,可能的错误为EGL_BAD_DISPLAY、EGL_NOT_INITIALIZED、EGL_BAD_CONTEXT、EGL_BAD_ATTRIBUTE。attribute取值可以是:

EGL_CONFIG_ID
EGL_CONTEXT_CLIENT_TYPE
EGL_CONTEXT_CLIENT_VERSION
EGL_RENDER_BUFFER

eglMakeCurrent

EGLAPI EGLBoolean EGLAPIENTRY eglMakeCurrent(EGLDisplay display, EGLSurface draw,EGLSurface read, EGLContext context);

创建了Surface和Context之后,因为可能有多个Surface和Context,所以需要通过eglMakeCurrent绑定Context到Surface,display为对应的Display,draw用于绘制,read用于读,ctx为要绑定的Context,成功是返回EGL_TRUE,失败时返回EGL_FALSE,可能的错误为EGL_BAD_DISPLAY、EGL_NOT_INITIALIZED、EGL_BAD_SURFACE、EGL_BAD_CONTEXT、EGL_BAD_MATCH、EGL_BAD_ACCESS 、EGL_BAD_NATIVE_PIXMAP、EGL_BAD_NATIVE_WINDOW、EGL_BAD_CURRENT_SURFACE、EGL_BAD_ALLOC、EGL_CONTEXT_LOST。因为EGL规范要求eglMakeCurrent实现进行一次刷新,所以这一调用对于基于图块的架构代价很高。

OpenGL ES (二)EGL介绍和使用相关推荐

  1. 【Android OpenGL开发】OpenGL ES与EGL介绍

    什么是OpenGL ES OpenGL(Open Graphics Library)是一个跨编程语言.跨平台的编程图形程序接口,主要用于图像的渲染. Android提供了简化版的OpenGL接口,即O ...

  2. Adreno OpenGL ES 2.0 介绍(3)

    Adreno OpenGL ES 2.0 介绍(3) 1. 应用程序示例 1.2 在Android上创建ES 2.0 上下文/环境 1.3 Adreno GPU检测 1.4 检查支持的ES拓展 1. ...

  3. Adreno OpenGL ES 3.1 介绍(3)

    Adreno OpenGL ES 3.1 介绍(3) 4.1.7单独的着色器对象 4.1.8着色器存储缓冲区对象 4.1.7单独的着色器对象 OpenGL ES中的关键对象类型之一是程序对象. 他们需 ...

  4. OpenGL ES和EGL关系(二十五)

    什么是 EGL EGL 是 OpenGL ES 和本地窗口系统(Native Window System)之间的通信接口,它的主要作用: 与设备的原生窗口系统通信: 查询绘图表面的可用类型和配置: 创 ...

  5. OpenGL ES与EGL的关系(二十一)

    什么是OpenGL? Open Graphics Library (OpenGL) is a cross-language, cross-platform application programmin ...

  6. opengl,opengl es,egl,glfw,glew

    OpenGL ES之GLFW窗口搭建 - Plato - 博客园概述 本章节主要总结如何使用GLFW来创建Opengl窗口.主要包括如下内容: OpenGl窗口创建介绍 GLFW Window版编译 ...

  7. 与context的关系_你还不知道 OpenGL ES 和 EGL 的关系?

    什么是 EGL EGL 是 OpenGL ES 和本地窗口系统(Native Window System)之间的通信接口,它的主要作用: 与设备的原生窗口系统通信: 查询绘图表面的可用类型和配置: 创 ...

  8. opengl、opengl es、webgl介绍与opengl开发入门

    1.OpenGL OpenGL(英语:Open Graphics Library,译名:开放图形库或者"开放式图形库")常用于CAD.虚拟现实.科学可视化程序和电子游戏开发.Ope ...

  9. OpenGL ES: (3) EGL、EGL绘图的基本步骤、EGLSurface、ANativeWindow

    1. EGL概述 EGL 是 OpenGL ES 渲染 API 和本地窗口系统(native platform window system)之间的一个中间接口层,它主要由系统制造商实现. EGL提供如 ...

  10. OpenGL ES基本概念介绍

    最近不太忙,打算这周开始学习下OpenGL,网上也已经有好多关于OpenGL的书籍和资料了.至于为什么还要写,是为了养成一个良好的学习习惯,也算给自己的学习过程做一个总结. 基本概念 OpenGL定义 ...

最新文章

  1. 文件时间信息在测试中的应用
  2. python综合学习一之多线程
  3. Java常用设计模式————建造者模式
  4. 嘘!你与谷歌语音助手的对话,可能已经泄露……
  5. IOS-程序员和设计师必备的20个CSS工具
  6. sudo chown r mysql_Linux 文件基本属性: chown修改所属组 和 chmod修改文件属性命令
  7. jest (让人愉悦的测试框架)
  8. Maxwell简单使用
  9. Python怎么安装PHP,php中ThinkPHP的下载和安装
  10. catia 桥接曲面圆角_CATIA建模教程(二)——圆角及桥接在空间曲线中的应用.pdf...
  11. Java多线程案例-单例模式【饿汉模式,懒汉模式】
  12. linux df -h显示空间信息不正确
  13. 修改docker镜像提高下载速度
  14. Wopus问答第一期
  15. 学习博客:关键字package包的使用
  16. mt4 python神经网络_用Python写MT4自动交易策略来炒外汇
  17. linux kernel build
  18. 人生新的开始,组建大数据公司
  19. VISTA无人驾驶模拟器;FinRL量化金融深度强化学习库;『深度神经网络应用』电子书;CUDA/TensorRT案例集锦;前沿论文 | ShowMeAI资讯日报
  20. 中文版PyCharm改为英文版PyCharm

热门文章

  1. java scavenge_Java垃圾收集器之Parallel Scavenge收集器
  2. obs噪音抑制调多少合适_(3)阿里国际站OBS申请设置使用教程,OBS音频没有声音怎么办?国际站直播回放如何下载?...
  3. 程序员转行一般是因为什么,会去哪些行业?
  4. php mocking,php – Mocking Static Eloquent Models方法包括find()
  5. pancake-frontend(薄饼)二次开发
  6. [NOIp 2014]解方程
  7. 郑轻oj1000-从今天开始入坑C语言
  8. opengl绘制太阳、地球、月亮,贴上纹理,设置光照,符合自转和公转规律
  9. 作业中关于H5中动画的实现——animation
  10. 折下我的翅膀,送你飞翔