美文网首页
OpenGL-ES 学习(3)---- EGL

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

作者: 特立独行的佩奇 | 来源:发表于2022-01-15 15:54 被阅读0次

EGL 介绍

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

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

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

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

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

EGL 的作用如下图所示:


EGL.png

EGL 类型和初始化

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

数据类型 说明
EGLBoolean EGL_TRUE =1,EGL_FALSE=0
EGLint windows上是int32类型
EGLDisplay Handle 概念 typedef void *EGLDisplay;
EGLConfig Handle 概念 typedef void *EGLConfig;
EGLSurface Handle 概念 typedef void *EGLSurface
EGLContext Handle 概念 typedef void *EGLContext; OpenGL-ES 图形上下文,它代表了OpenGL状态机)

EGL初始化方法

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


EGL 初始化流程.png
  • 获取display
    获得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结束的参数数组,通常以id,value依次存放,对于个别标识性的属性可以只有 id,没有value

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

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

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

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

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

EGL_HEIGHT EGL_WIDTH EGL_LARGEST_PBUFFER EGL_TEXTURE_FORMAT EGL_TEXTURE_TARGET EGL_MIPMAP_TEXTURE EGL_MIPMAP_LEVEL,
通过eglSurfaceAttrib()设置、eglQuerySurface()读取

  1. 构造 Context
    OpenGL ES的pipeline从程序的角度看就是一个状态机,有当前的颜色、纹理坐标、变换矩阵、绚染模式等一大堆状态,这些状态作用于OpenGL API程序提交的顶点坐标等图元从而形成帧缓冲内的像素;在OpenGL的编程接口中,Context就代表这个状态机,OpenGL API程序的主要工作就是向Context提供图元、设置状态,偶尔也从Context里获取一些信息。
    可以用
    EGLContext eglCreateContext(EGLDisplay dpy, EGLSurface write, EGLSurface read, EGLContext * share_list)来创建一个Context。
    EGL变量之间的绑定
    boolean eglMakeCurrent(EGLDisplay display, EGLSurface draw, EGLSurface read, EGLContext context)
    该接口将申请到的display,draw(surface)和 context进行了绑定。也就是说,在context下的OpenGLAPI指令将draw(surface)作为其渲染最终目的地。而display作为draw(surface)的前端显示。调用后,当前线程使用的EGLContex为context

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

Windows EGL demo 实例

#include "esUtil.h"

#define TDEBUG 1

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;
    }

    esContext->eglDisplay = eglGetDisplay(esContext->eglNativeDisplay);
    if (esContext->eglDisplay == EGL_NO_DISPLAY) {
        return GL_FALSE;
    }

    // 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;
        }

        if (numConfigs < 1)
        {
            return GL_FALSE;
        }
    }

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

    if (esContext->eglSurface == EGL_NO_SURFACE) {
        return GL_FALSE;
    }

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

    if (esContext->eglContext == EGL_NO_CONTEXT) {
        return GL_FALSE;
    }

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


    }

    return GL_TRUE;
}

static void Draw(ESContext *esContext)
{
    //glViewport(0, 0, esContext->width, esContext->height);
    glViewport(0, 0, 200, 200);
    glClear(GL_COLOR_BUFFER_BIT);
    glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
    glFlush();
}

int esMain01(ESContext *esContext)
{
    esCreateWindow(esContext, "gl_window demo", 500, 500, ES_WINDOW_RGB);
    esRegisterDrawFunc(esContext, Draw);
    return GL_TRUE;
}

相关文章

网友评论

      本文标题:OpenGL-ES 学习(3)---- EGL

      本文链接:https://www.haomeiwen.com/subject/feithrtx.html