EGL简介
1.EGLDisplay
获取
使用EGL的入口点,获取EGLDisplay
1 | EGLDisplay eglGetDisplay(EGLNativeDisplayType display_id); |
EGL_DEFAULT_DISPLAY
:是display_id的默认值,通常是当前显示
- X11平台示例
1 | Display* x11_display = XOpenDisplay(NULL); // 打开默认 X11 显示 |
- wayland
1 | struct wl_display* wayland_display = wl_display_connect(NULL); // 连接到默认 Wayland 显示 |
- windows平台
1 | HDC hdc = GetDC(hwnd); // 获取窗口设备上下文 |
- 扩展
1 | // egl1.5 core函数 |
初始化EGLDisplay
获取EGLDisplay后需要初始化,初始化接口,指向具体的EGL主副版本;
1 | EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor); |
查询EGLDisplay信息
查询EGLDisplay信息
1 | EGLint numConfigs; |
销毁EGLDisplay
终止连接
1 | eglTerminate(display); |
2.EGLSurface
关键对象之一,用于表示一个绘制表面,可以与窗口、屏幕缓冲区(Pbuffer Surface)、或屏幕(Pixmap Surface)关联,是图形渲染的目标。可以将渲染内容输出到屏幕或者离屏缓冲区中。
有三种类型的EGLSurface:
- Window Surface:渲染到屏幕上的窗口;
- Pbuffer Surface:离屏渲染表面,渲染到内存缓冲区,适合需要生成纹理或图像的应用;
- Pixmap Surface:渲染内容输出到像素对象(Pixmap),较少使用;
创建
创建windowSurface
1 | EGLSurface eglCreateWindowSurface( |
创建PbufferSurface
1 | EGLint pbuffer_attribs[] = { |
创建到本地像素对象
1 | EGLSurface eglCreatePixmapSurface( |
绑定和渲染
在使用EGLSuface之前,需要与EGLContext绑定;
1 | EGLBoolean eglMakeCurrent( |
对于WindowSurface需要调用eglSwapBuffer来提交绘制结果到屏幕;
1 | eglSwapBuffers(display, surface); |
销毁
不在使用时需要释放资源
1 | EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface surface); |
查询
可以使用eglQuerySurface
获取EGLSurface的信息
1 | EGLBoolean eglQuerySurface( |
3.EGLConext
渲染上下文,是图形API的运行环境,管理状态、资源和命令的执行,只有通过有效的EGLConext,命令才会被正确的发送到GPU执行。在多线程渲染中,可以使用多个EGLConext,同一个EGLContext也可以被多个线程共享。
创建
1 | EGLContext eglCreateContext( |
绑定
创建EGLSurface和EGLContext后,需要绑定才能发出渲染命令。
1 | EGLBoolean eglMakeCurrent( |
解除绑定
1 | eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); |
销毁
不再需要时,释放资源
1 | EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx); |
共享
可以共享纹理、帧缓冲,上下文之间的状态是独立的。另外共享的上下文必须基于相同的EGLConfig创建;
注意事项
每个线程只能绑定一个EGLConext,但同一个EGLConext可以在不同线程中绑定和解绑;应该避免频繁的上下文绑定解绑操作,合理利用共享上下文机制来管理纹理和缓冲区;在销毁EGLConext前,确保所有资源已释放;
4.EGLSurface渲染到纹理对象
绑定PbufferSurface和纹理
通过EGL,可以将EGLSurface(PbufferSurface或者PixmapSurface)直接渲染到GLES的纹理对象,可以实现高效的数据共享和后续的纹理操作;常用于离屏渲染(offscreen rendering),渲染内容不会直接显示在屏幕上,而是作为纹理使用,也可以用作后续处理,锐化、模糊的等。
1 | EGLBoolean eglBindTexImage( |
主要步骤:
1.创建Surface支持纹理绑定
绑定的Surface在创建时,必须支持纹理绑定,EGL_TETURE_2D;
1 | // 1. 创建 PbufferSurface |
2.创建GLES纹理
1 | // 2. 创建 OpenGL ES 纹理 |
3.绑定PbufferSurface到纹理
1 | // 3. 绑定 PbufferSurface 到纹理 |
4.使用纹理绘制
1 | // 4. 使用纹理进行渲染 |
5.解除绑定
1 | eglReleaseTexImage(display, pbufferSurface, EGL_BACK_BUFFER); |
6.清理资源
1 | // 清理资源 |
解除绑定
1 | EGLBoolean eglReleaseTexImage( |
- buffer:通常未EGL_BACK_BUFFER
5.EGLImage
EGL允许相同API的上下文之间共享大量状态(包括纹理对象),但是某些情况下需要在不同api之间(GLES、VK、EGL)共享状态,比如OpenVG图像作为OGLES纹理对象。那么EGLImages对象就是可以实现不同客户端api的相互共享的资源对象;
EGLImageKHR:EGLImage的实际类型,表示共享的图形数据,作为桥梁,在不同API之间访问,可以减少数据拷贝,提供性能。
创建
从一个资源创建EGLImage,比如纹理或者缓冲区
1 | EGLImage eglCreateImage(EGLDisplay dpy, |
target:资源的目标类型,
EGL_GL_TEXTURE_2D_KHR
:OpenGL ES 2D 纹理。EGL_GL_RENDERBUFFER_KHR
:OpenGL ES 渲染缓冲区。EGL_NATIVE_PIXMAP_KHR
:本地 pixmap。EGL_LINUX_DMA_BUF_EXT
:扩展目标类型,使用该类型是,buffer参数为null,dma
buffer:客户端缓冲区资源句柄,比如:OGLES的纹理对象ID。
绑定
将一个EGLImage绑定到GLES的纹理
1 | void glEGLImageTargetTexture2DOES(GLenum target, GLeglImageOES image); |
target:纹理目标类型,通常未GL_TEXTURE_2D
image:要绑定的EGLImage对象
手动触发
显式通知EGL同步对象触发,用于与其他线程或客户端同步,确保资源在同步对象的状态改变后安全使用;
1 | const char* extensions = eglQueryString(display, EGL_EXTENSIONS); |
销毁
销毁一个EGLImage对象,释放资源。
1 | EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR image); |
示例
1 | #include <EGL/egl.h> |
6.EGLSync
该对象提供一种同步机制,处理不同图形操作或者多个图形任务之间的顺序,在多线程或者多进程之间尤其重要。同步需求主要在等待GPU渲染任务的完成,确保后续任务可以在正确的时间执行,多线程之间同步渲染命令的执行,实现多步渲染操作的顺序控制。
创建
创建EGLSync对象
1 | EGLSyncKHR eglCreateSyncKHR( |
type:同步对象类型
EGL_SYNC_FENCE_KHR
:这是一种基于 GPU 的同步对象,通常用于等待 GPU 完成某些操作,如渲染。EGL_SYNC_NATIVE_FENCE_FD_KHR
:这个同步对象与底层操作系统的同步机制兼容,通常用于与 Linux 上的 fence 或 sync 文件描述符配合使用。
attrib_list:同步对象属性的整数数组,取决type类型
EGL_SYNC_FENCE_KHR
类型的同步对象可能不需要任何附加属性;EGL_SYNC_NATIVE_FENCE_FD_KHR
类型的同步对象则可能需要指定某些操作系统特定的属性。如果没有附加的属性,传入NULL
即可。
等待
等待特定的同步对象达到某种状态
1 | EGLint eglClientWaitSync( |
常用于CPU在等待GPU的任务完成后再继续CPU上的计算操作,避免后续操作错误依赖未完成的GPU任务。
销毁
销毁同步对象,在销毁前确保没有其他地方依赖等待使用,如果提前销毁会有意想不到的情况。
1 | EGLBoolean eglDestroySyncKHR( |
7.eglSwapBuffers
交换前后台缓冲区的函数,在双缓冲或多缓冲的图形系统用于将渲染结果从后台缓冲区显示到前台缓冲区。
1 | EGLBoolean eglSwapBuffers( |
eglSwapInterval
控制V-sync间隔,控制缓冲区交换的频率,控制每秒交换的次数
1 | EGLBoolean eglSwapInterval( |
interval:
0:禁用垂直同步
1:启用垂直同步,每个垂直同步周期交换一次,即和显示器的刷新率保持一致,一般是60Hz或者120Hz
2:每两个垂直同步周期交换一次,降低GPU负载
eglCopyBuffers
用于把EGLSurface上的图像数据复制到一个外部的缓冲区,一般用于把图像渲染结果保存到外部图像缓冲区,或者把图像数据传输到GPU之外的存储空间。
1 | EGLBoolean eglCopyBuffers( |
将EGLSurface上的图像数据直接复制到原生平台的缓冲区或纹理中,然后用于后续的处理,或者保存为图像文件。主要应用场景:截图、跨平台渲染、后处理等;
8.Others
1.eglBindAPI
指定客户端使用哪种API,OpenGL、OpenGLES、OpenVG