EGL 是什么?
EGL 是 Khronos渲染 API(如OpenGL ES或OpenVG)与底层本机平台窗口系统之间的接口。
在 Android 平台,一般是 OpenGL ES 和底层的 native window system 之间的接口,简单的说,就是 Android 应用层 和 底层window 渲染数据交互的媒介。
EGL 的作用
在 Android 平台上,一般是为 OpenGL ES 渲染 API 搭建使用环境
EGL 在Java层的封装
在Java层,EGL封装了两套框架,分别是:
位于 javax.microedition.khronos.egl 包下的 EGL10
位于 android.opengl 包下的 EGL14
它们都是 OpenGL ES 和底层的 native window system 之间的接口,只是EGL的不同版本
EGL10 对应于 EGL 1.0,它是在2003年
EGL14 释放的规范对应于 EGL 1.4,其是在2014年
其主要区别是:
EGL14 是在 Android 4.2(API 17) 引入,换言之API 17以下的版本不支持 EGL14
EGL10 不支持 OpenGL ES 2.x,因此在 EGL10 中某些相关常量参数只能用手写硬编码代替
例如 EGL14.EGL_CONTEXT_CLIENT_VERSION 以及 EGL14.EGL_OPENGL_ES2_BIT 等等
EGL 环境搭建流程
参考 GLSurfaceView 内部的 EGL 环境搭建流程,只讨论 EGL10,EGL14基本同理
- 通过
javax.microedition.khronos.egl.EGLContext
获取EGL10
对象 - 通过
eglGetDisplay()
获取EGLDisplay
对象(EGLDisplay
屏幕的抽象) - 通过
eglInitialize()
初始化EGLDisplay
对象 - 通过
eglChooseConfig()
设置并筛选适合的EGL frame buffer
的EGLConfig
配置 - 通过
eglCreateContext()
构建EGLContext
对象(EGLContext
是环境的抽象) - 通过
eglCreatePbufferSurface() or eglCreateWindowSurface()
构建EGLSurface
对象 (我将它理解为屏幕画布的抽象
) - 通过
eglMakeCurrent()
将EGLContext
与Current Thread
、EGLSurface
进行绑定 - 环境搭建成功,可以开始进行
OpenGL ES
的渲染操作 - 如果是
eglCreateWindowSurface()
渲染之后,可以调用SwapBuffer()
进行双缓冲切换显示渲染画面 - 渲染结束
eglDestroyXXX()
资源
<具体代码>
@Override
protected void start(int eglContextVersion, ComponentSizeChooser configChooser)
{
// first step: 获取 EGL 对象
mEgl = (EGL10) EGLContext.getEGL();
// second step: 获取 EGLDisplay 对象(屏幕的抽象)
mEglDisplay = mEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
// 检查 EGLDisplay 的可用性
if (mEglDisplay == EGL10.EGL_NO_DISPLAY)
{
throw new RuntimeException("egl GetDisplay failed");
}
// 版本格式 xx.yy
int[] version = new int[2];
// third step: 初始化EGLDisplay连接, 成功返回具体版本
if (!mEgl.eglInitialize(mEglDisplay, version))
{
throw new RuntimeException("egl Initialize failed");
}
// forth step: 获取 想要的 EGL framebuffer 配置, configChooser可参考 GLSurfaceView 内部实现
mEglConfig = configChooser.chooseConfig(mEgl, mEglDisplay);
int[] context_attribute_list = {EGL14.EGL_CONTEXT_CLIENT_VERSION, eglContextVersion,
EGL10.EGL_NONE};
// fifth step: 构建 EGLContext(环境的抽象)
mEglContext = mEgl.eglCreateContext(mEglDisplay, mEglConfig, EGL10.EGL_NO_CONTEXT, context_attribute_list);
// 检查 EGLContext 可用性
if (mEglContext == null || mEglContext == EGL10.EGL_NO_CONTEXT)
{
mEglContext = null;
throw new RuntimeException("egl create Context fail");
}
}
@Override
public boolean setUpEglBackgroundEnvironment(int eglContextVersion, ComponentSizeChooser configChooser, int width, int height)
{
start(eglContextVersion, configChooser);
// 设置 EGLSurface 的宽高(唯一可以设置的属性)
int[] surface_attribute_list = {EGL10.EGL_WIDTH, width,
EGL10.EGL_HEIGHT, height,
EGL10.EGL_NONE};
// sixth step: 构建一个 Pbuffer 单缓冲区(无法直接显示) 的 EGLSurface(实际上 EGLSurface 是一个 FrameBuffer)
mEglSurface = mEgl.eglCreatePbufferSurface(mEglDisplay, mEglConfig, surface_attribute_list);
// 检查 EGLSurface 可用性
if (mEglSurface == null || mEglSurface == EGL10.EGL_NO_SURFACE)
{
mEglSurface = null;
Log.e(TAG, "egl create surface fail");
return false;
}
// seventh step: 将 EGLContext 与当前线程、EGLSurface 进行绑定
if (!mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext))
{
Log.e(TAG, "setUpEglPbufferSurfaceEnvironment:egl Make Current fail");
return false;
}
return true;
}
@Override
public void destroy()
{
mEgl.eglMakeCurrent(mEglDisplay, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT);
mEgl.eglDestroySurface(mEglDisplay, mEglSurface);
mEgl.eglDestroyContext(mEglDisplay, mEglContext);
mEgl.eglTerminate(mEglDisplay);
mEglSurface = EGL10.EGL_NO_SURFACE;
mEglDisplay = EGL10.EGL_NO_DISPLAY;
mEglContext = EGL10.EGL_NO_CONTEXT;
mEgl = null;
}
网友评论