OpenGL-ES 学习(11) ---- EGL

EGL 介绍

OpenGL-ES 是一个操作GPU的图像API标准,它通过驱动向 GPU 发送相关图形指令,控制图形渲染管线状态机的运行状态,但OpenGL需要本地视窗系统进行交互,这就需要一个中间控制层,最好与平台无关

EGL ---- 因此被独立的设计出来,它作为 OpenGL-ES和本地窗口的桥梁

EGLOpenGL ES和底层 Native 平台视窗系统之间的接口层,EGL API 是独立于OpenGL ES各版本标准的独立 APIEGL 提供下面的机制:

  • 和设备的原生窗口系统进行通信
  • 查询绘图表面的可用类型和配置
  • 创建绘图表面
  • OpenGL-ES 和其他渲染API之间同步渲染
  • 管理纹理贴图等绘图资源

比如 egl 可以和 opencl 进行同步,主要通过下面几种方式:

  • 通过 eglCreateContext 创建共享的上下文
  • 通过 eglCreateImageKHR 创建可以被 OpenGL ESOpenCL0 共同访问的图像资源
  • eglCreateSyncKHR/eglDestroySyncKHR 等函数可以创建跨 API 的同步点

总结:对接窗口系统,保存绘图状态,管理绘图资源,提供绘图表面配置,和其他 API 进行同步

OpenGL-ES指令创建 Context 、绘制目标Surface 、配置Framebuffer属性、Swap提交绘制结果等都是EGL实现的功能

EGL 的作用如下图所示:
EGL.png

EGL 类型和初始化

EGL 包含了自己的一组数据类型,同时也提供了对一组平台相关的本地数据类型的支持,这些 Native 数据类型定义在 EGL 系统的头文件中
下面表格中列举了常见的几种 EGL类型:

数据类型说明
EGLBooleanEGL_TRUE =1,EGL_FALSE=0
EGLintwindows上是int32类型
EGLDisplayHandle 概念 typedef void *EGLDisplay;
EGLConfigHandle 概念 typedef void *EGLConfig;
EGLSurfaceHandle 概念 typedef void *EGLSurface
EGLContextHandle 概念 typedef void *EGLContext; OpenGL-ES 图形上下文,它代表了OpenGL状态机)
EGL初始化方法

EGL 初始化流程如下图所示:
EGL 初始化流程.png

获取 eglDisplay

获得 Display 要调用 EGLboolean eglGetDisplay(NativeDisplay dpy) 参数一般为 EGL_DEFAULT_DISPLAY

初始化 EGL

调用 EGLboolean eglInitialize**(EGLDisplay dpy, EGLint *major, EGLint *minor),该函数会进行一些内部初始化工作,并传回 EGL版本号(major,minor)

选择 Config

一般用EGLboolean eglChooseConfig**(EGLDisplay dpy, const EGLint * attr_list, EGLConfig * config, EGLint config_size, EGLint *num_config)

其中 attr_list 是以 EGL_NONE 结束的参数数组,通常以idvalue依次存放,对于个别标识性的属性可以只有 id,没有value

另一个办法是用 EGLboolean eglGetConfigs(EGLDisplay dpy, EGLConfig * config, EGLint config_size, EGLint *num_config) 来获得所有config,这两个函数都会返回不多于 config_sizeconfig ,结果保存在 config[]中,系统的总 Config 个数保存 在num_config

可以利用 eglGetConfig() 中间两个参数为0来查询系统支持的 Config总个数,Config有众多的Attribute,这些Attribute决定FrameBuffer的格式和能力,通过 eglGetConfigAttrib来读取,但不能修改

构造 Surface

通过 EGLSurface eglCreateWindowSurface**(EGLDisplay dpy, EGLConfig confg, NativeWindow win, EGLint *cfg_attr)
来创建一个可实际显示的 Surface

系统通常还支持另外两种 SurfacePixmapSurface和PBufferSurface,这两种都不是可显示的Surface,PixmapSurface 是保存在系统内存中的位图,PBuffer 则是保存在显存中的帧

对于这两种 SurfaceAndroid 系统中,支持 PBufferSurface
Surface 也有一些 attribute,基本上都可以顾名思义

EGL_HEIGHT   
EGL_WIDTH   
EGL_LARGEST_PBUFFER   
EGL_TEXTURE_FORMAT   
EGL_TEXTURE_TARGET  
EGL_MIPMAP_TEXTURE   
EGL_MIPMAP_LEVEL

通过 eglSurfaceAttrib 设置、eglQuerySurface读取

构造 Context

OpenGL ESPipeline 从程序的角度看就是一个状态机,有当前的颜色、纹理坐标、变换矩阵、绚染模式等一大堆状态,这些状态作用于 OpenGL API 程序提交的顶点坐标等图元从而形成帧缓冲内的像素;在 OpenGL 的编程接口中,Context就代表这个状态机,OpenGL API程序的主要工作就是向 Context 提供图元、设置状态,偶尔也从 Context 里获取一些信息。
可以用

EGLContext eglCreateContext(EGLDisplay dpy, EGLSurface write, EGLSurface read, EGLContext * share_list)

EGL变量之间的绑定

boolean eglMakeCurrent(EGLDisplay display, EGLSurface draw, EGLSurface read, EGLContext context)
//该接口将申请到的display,draw(surface)和 context进行了绑定。也就是说,在context下的 OpenGLAPI 指令将draw
//(surface)作为其渲染最终目的地。而display作为draw(surface)的前端显示。调用后,当前线程使用的EGLContex为context
开始绘制

应用程序通过 OpenGL API 进行绘制,一帧完成之后,调用 eglSwapBuffers(EGLDisplay dpy, EGLContext ctx) 来显示

EGL Demo

#include "esUtil.h"

static GLboolean ESUTIL_API esCreateWindow(ESContext *esContext, \
	      const char *title, GLint width, GLint height, GLuint flags) {
	EGLConfig config;
	EGLint majorVersion;
	EGLint minorVersion;
	EGLint contextAttribs[] = { EGL_CONTEXT_CLIENT_VERSION, 3, EGL_NONE };

	if (esContext == NULL) {
		return GL_FALSE;
	}

	esContext->width = width;
	esContext->height = height;

	if (!WinCreate(esContext, title)) {
		return GL_FALSE;
	}
    
    // 获取 eglDisplay
	esContext->eglDisplay = eglGetDisplay(esContext->eglNativeDisplay);

	// Initialize EGL
	if (!eglInitialize(esContext->eglDisplay, &majorVersion, &minorVersion)) {
		return GL_FALSE;
	}

#if (TDEBUG == 1)
	printf("opengl version major:%d minor:%d\n", majorVersion, minorVersion);

	EGLint numsConfig = 0;
	eglGetConfigs(esContext->eglDisplay, NULL, 0, &numsConfig);
	printf("get numsConfig: %d \n", numsConfig);
#endif

	{
		EGLint numConfigs = 0;
		EGLint attribList[] =
		{
			EGL_RED_SIZE,       5,
			EGL_GREEN_SIZE,     6,
			EGL_BLUE_SIZE,      5,
			EGL_ALPHA_SIZE,     (flags & ES_WINDOW_ALPHA) ? 8 : EGL_DONT_CARE,
			EGL_DEPTH_SIZE,     (flags & ES_WINDOW_DEPTH) ? 8 : EGL_DONT_CARE,
			EGL_STENCIL_SIZE,   (flags & ES_WINDOW_STENCIL) ? 8 : EGL_DONT_CARE,
			EGL_SAMPLE_BUFFERS, (flags & ES_WINDOW_MULTISAMPLE) ? 1 : 0,
			// if EGL_KHR_create_context extension is supported, then we will use
			// EGL_OPENGL_ES3_BIT_KHR instead of EGL_OPENGL_ES2_BIT in the attribute list
			EGL_RENDERABLE_TYPE, GetContextRenderableType(esContext->eglDisplay),
			EGL_NONE
		};

		// Choose config
		if (!eglChooseConfig(esContext->eglDisplay, attribList, &config, 1, &numConfigs)) {
			return GL_FALSE;
		}

	}

	// Create a surface
	esContext->eglSurface = eglCreateWindowSurface(esContext->eglDisplay, config,
		esContext->eglNativeWindow, NULL);

	// Create a GL context contextAttribs 指定openGL ES 版本
	esContext->eglContext = eglCreateContext(esContext->eglDisplay, config,
		EGL_NO_CONTEXT, contextAttribs);

	// Make the context current
	if (!eglMakeCurrent(esContext->eglDisplay, esContext->eglSurface,
		esContext->eglSurface, esContext->eglContext)) {
		return GL_FALSE;
	}

	return GL_TRUE;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值