Agenda:
EGL? is an interface between Khronos rendering APIs such as OpenGL ES or OpenVG and the underlying native platform window system.  
It handles graphics context management, surface/buffer binding, and rendering synchronization and enables high-performance, accelerated, mixed-mode 2D and 3D rendering using other Khronos APIs. 
 
那么什么是EGL?EGL是OpenGL ES和底层的native window system之间的接口,承上启下。
在Android上,EGL完善了OpenGL ES。利用类似eglCreateWindowSurface的EGL函数可以创建surface 用来render ,有了这个surface你就能往这个surface中利用OpenGL ES函数去画图了。OpenGL ES 本质上是一个图形渲染管线的状态机,而 EGL 则是用于监控这些状态以及维护 Frame buffer 和其他渲染 Surface 的外部层。下图是一个3d游戏典型的 EGL 系统布局图。 
| 数据类型 | 值 | 
|---|---|
| EGLBoolean | EGL_TRUE =1, EGL_FALSE=0 | 
| EGLint | int 数据类型 | 
| EGLDisplay | 系统显示 ID 或句柄 | 
| EGLConfig | Surface 的 EGL 配置 | 
| EGLSurface | 系统窗口或 frame buffer 句柄 | 
| EGLContext | OpenGL ES 图形上下文 | 
| NativeDisplayType | Native 系统显示类型 | 
| NativeWindowType | Native 系统窗口缓存类型 | 
| NativePixmapType | Native 系统 frame buffer | 
下面是开机动画BootAnimation中的实现,首先是创建本地环境,
status_t BootAnimation::readyToRun() {
    // 创建SurfaceControl
    // create the native surface
    sp<SurfaceControl> control = session()->createSurface(String8("BootAnimation"),
            dinfo.w, dinfo.h, PIXEL_FORMAT_RGB_565);
    SurfaceComposerClient::openGlobalTransaction();
    // 设置layerstack
    control->setLayer(0x40000000);
    SurfaceComposerClient::closeGlobalTransaction();
    //获取Surface
    sp<Surface> s = control->getSurface();
    // initialize opengl and egl
    const EGLint attribs[] = {
            EGL_RED_SIZE,   8,
            EGL_GREEN_SIZE, 8,
            EGL_BLUE_SIZE,  8,
            EGL_DEPTH_SIZE, 0,
            EGL_NONE
    };
    EGLint w, h, dummy;
    EGLint numConfigs;
    EGLConfig config;
    EGLSurface surface;
    EGLContext context;
    //调用eglGetDisplay
    EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY); // 第一步
    eglInitialize(display, 0, 0); // 第二步
    eglChooseConfig(display, attribs, &config, 1, &numConfigs); // 第三步
    //调用eglCreateWindowSurface将Surface s转换为本地窗口,
    surface = eglCreateWindowSurface(display, config, s.get(), NULL); // 第四步
    context = eglCreateContext(display, config, NULL, NULL); // 第五步
    eglQuerySurface(display, surface, EGL_WIDTH, &w);
    eglQuerySurface(display, surface, EGL_HEIGHT, &h);
    //eglMakeCurrent后生成的surface就可以利用opengl画图了
    if (eglMakeCurrent(display, surface, surface, context) == EGL_FALSE)
        return NO_INIT;
    return NO_ERROR;
}egl创建好后,调用gl相关命令去画图,注意eglSwapBuffers(mDisplay, mSurface) 函数是非常重要的一个函数,会去触发queueBuffer和dequeueBuffer,图画就一帧一帧的画出来了。
bool BootAnimation::android()
{
    initTexture(&mAndroid[0], mAssets, "images/android-logo-mask.png");
    initTexture(&mAndroid[1], mAssets, "images/android-logo-shine.png");
    // clear screen
    glShadeModel(GL_FLAT);
    glDisable(GL_DITHER);
    glDisable(GL_SCISSOR_TEST);
    glClearColor(0,0,0,1);
    glClear(GL_COLOR_BUFFER_BIT);
    //调用eglSwapBuffers会去触发queuebuffer,dequeuebuffer,
    //queuebuffer将画好的buffer交给surfaceflinger处理,
    //dequeuebuffer新创建一个buffer用来画图
    eglSwapBuffers(mDisplay, mSurface); // 第六步
    glEnable(GL_TEXTURE_2D);
    glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
    const GLint xc = (mWidth  - mAndroid[0].w) / 2;
    const GLint yc = (mHeight - mAndroid[0].h) / 2;
    const Rect updateRect(xc, yc, xc + mAndroid[0].w, yc + mAndroid[0].h);
    glScissor(updateRect.left, mHeight - updateRect.bottom, updateRect.width(),
            updateRect.height());
    // Blend state
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
    const nsecs_t startTime = systemTime();
    do {
        nsecs_t now = systemTime();
        double time = now - startTime;
        float t = 4.0f * float(time / us2ns(16667)) / mAndroid[1].w;
        GLint offset = (1 - (t - floorf(t))) * mAndroid[1].w;
        GLint x = xc - offset;
        glDisable(GL_SCISSOR_TEST);
        glClear(GL_COLOR_BUFFER_BIT);
        glEnable(GL_SCISSOR_TEST);
        glDisable(GL_BLEND);
        glBindTexture(GL_TEXTURE_2D, mAndroid[1].name);
        glDrawTexiOES(x,                 yc, 0, mAndroid[1].w, mAndroid[1].h);
        glDrawTexiOES(x + mAndroid[1].w, yc, 0, mAndroid[1].w, mAndroid[1].h);
        glEnable(GL_BLEND);
        glBindTexture(GL_TEXTURE_2D, mAndroid[0].name);
        glDrawTexiOES(xc, yc, 0, mAndroid[0].w, mAndroid[0].h);
        EGLBoolean res = eglSwapBuffers(mDisplay, mSurface);
        if (res == EGL_FALSE)
            break;
        // 12fps: don‘t animate too fast to preserve CPU
        const nsecs_t sleepTime = 83333 - ns2us(systemTime() - now);
        if (sleepTime > 0)
            usleep(sleepTime);
        checkExit();
    } while (!exitPending());
    glDeleteTextures(1, &mAndroid[0].name);
    glDeleteTextures(1, &mAndroid[1].name);
    return false;
}以上开机动画,可分如下几个阶段:
1、 获取Display。 
Display代表显示。获得Display要调用EGLboolean eglGetDisplay(NativeDisplay dpy),参数一般为 EGL_DEFAULT_DISPLAY 。对应开机动画就是如下代码:
//调用eglGetDisplay
EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);2、 初始化egl。 
调用 EGLboolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor),该函数会进行一些内部初始化工作,并传回EGL版本号(major.minor)。对应开机动画就是如下代码:
eglInitialize(display, 0, 0); 3、 选择Config。 
所为Config实际指的是FrameBuffer的参数。一般用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 ()来读取,但不能修改。对应开机动画就是如下代码:
eglChooseConfig(display, attribs, &config, 1, &numConfigs);4、 构造Surface。 
Surface实际上就是一个FrameBuffer,通过 EGLSurface eglCreateWindowSurface(EGLDisplay dpy, EGLConfig confg, NativeWindow win, EGLint *cfg_attr) 来创建一个可实际显示的Surface。系统通常还支持另外两种Surface:PixmapSurface和PBufferSurface,这两种都不是可显示的Surface,PixmapSurface是保存在系统内存中的位图,PBuffer则是保存在显存中的帧。 
Surface也有一些attribute,基本上都可以故名思意, EGL_HEIGHT EGL_WIDTH EGL_LARGEST_PBUFFER EGL_TEXTURE_FORMAT EGL_TEXTURE_TARGET EGL_MIPMAP_TEXTURE EGL_MIPMAP_LEVEL,通过eglSurfaceAttrib()设置、eglQuerySurface()读取。对应开机动画就是如下代码:
surface = eglCreateWindowSurface(display, config, s.get(), NULL);5、 创建Context。 
OpenGL的pipeline从程序的角度看就是一个状态机,有当前的颜色、纹理坐标、变换矩阵、绚染模式等一大堆状态,这些状态作用于程序提交的顶点 坐标等图元从而形成帧缓冲内的像素。在OpenGL的编程接口中,Context就代表这个状态机,程序的主要工作就是向Context提供图元、设置状态,偶尔也从Context里获取一些信息。 
用EGLContext eglCreateContext(EGLDisplay dpy, EGLSurface write, EGLSurface read, EGLContext * share_list)来创建一个Context。对应开机动画就是如下代码:
context = eglCreateContext(display, config, NULL, NULL);6、 绘制。 
应用程序通过OpenGL API进行绘制,一帧完成之后,调用eglSwapBuffers(EGLDisplay dpy, EGLContext ctx)来显示。对应开机动画就是如下代码:
eglSwapBuffers(mDisplay, mSurface); /EGL 官网详细讲述了Surface、Display、Context 概念。对应链接:
简单地说 
(1)Display 是图形显示设备(显示屏)的抽象表示。大部分EGL函数都要带一个 Display 作为参数 
(2)Context 是 OpenGL 状态机。Context 与 Surface 可以是一对一、多对一、一对多的关系 
(3)Surface 是绘图缓冲,可以是 window、pbuffer、pixmap 三种类型之一 
EGL 工作流程为: 
(1)初始化 
(2)配置 
(3)创建Surface(绑定到平台Windowing系统) 
(4)绑定Surface与Context 
(5)Main Loop:渲染(OpenGL),交换离线缓冲(offline buffer)与显示缓冲 
(6)释放资源
简单Demo:
原文:http://blog.csdn.net/hejjunlin/article/details/65935584