在OpenGL系列(一)三角形 中用到了EGL的接口,本文主要介绍这部分内容。
EGL是OpenGL ES 和本地窗口系统(Native Window System)之间的通信接口。OpenGL ES的平台无关性正是借助 EGL 实现的,EGL屏蔽了不同平台的差异。
- eglGetDisplay:获取EGLDisplay对象,这一步会确定当前所使用的平台。
- eglInitialize:初始化驱动。
- eglChooseConfig:选择配置。
- eglCreateContext:创建EGLContext对象,把OpenGL ES看做上下文,这一步会创建一个上下文对象,只有创建了上下文对象,调用OpemGL的API才起作用。
- eglCreateWindowSurface:根据本地窗口创建上下文可识别的EGLSurface。在Android系统中,本地窗口使用ANativeWindow表示。
- eglMakeCurrent:把EGLSurface和EGLContext关联在一起,调用该接口的线程可以使用OpenGL ES的接口绘制图形。
- eglSwapBuffers:把前台缓冲与后台缓冲交换,后台缓冲变成前台缓冲后,可以从前台缓冲中得到绘制的图形内容。
在三角形示例中,以上的接口都封装到了EglManager中,初始化过程如下
void EglManager::initialize(ANativeWindow *nativeWindow) {
mEglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
if(mEglDisplay == EGL_NO_DISPLAY){
return;
}
EGLint major, minor;
if(eglInitialize(mEglDisplay, &major, &minor) == EGL_FALSE){
LOGI( "Failed to initialize display %p! err=%s", mEglDisplay, eglErrorString());
return;
}
const EGLint attribs[] = {
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT_KHR,
EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
EGL_RED_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_BLUE_SIZE, 8,
EGL_ALPHA_SIZE, 8,
EGL_DEPTH_SIZE, 16,
EGL_STENCIL_SIZE, 8,
EGL_NONE
};
if (!eglChooseConfig(mEglDisplay, attribs, &config, 1, &numConfigs)) {
LOGE("eglChooseConfig() returned error %d", eglGetError());
destroy();
return;
}
const EGLint ctxAttr[] = {
EGL_CONTEXT_CLIENT_VERSION, 3,
EGL_NONE
};
if (!(mEglContext = eglCreateContext(mEglDisplay, config, 0, ctxAttr))) {
LOGE("eglCreateContext() returned error %d", eglGetError());
destroy();
return;
}
ANativeWindow_setBuffersGeometry(nativeWindow, 0, 0, format);
if (!(mEglSurface = eglCreateWindowSurface(mEglDisplay, config, nativeWindow, 0))) {
LOGE("eglCreateWindowSurface() returned error %d", eglGetError());
destroy();
return;
}
if (!eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) {
LOGE("eglMakeCurrent() returned error %d", eglGetError());
destroy();
return;
}
EGLint width;
EGLint height;
if (!eglQuerySurface(mEglDisplay, mEglSurface, EGL_WIDTH, &width) ||
!eglQuerySurface(mEglDisplay, mEglSurface, EGL_HEIGHT, &height)) {
LOGE("eglQuerySurface() returned error %d", eglGetError());
destroy();
return;
}
glViewport(0, 0, width, height);
mIsInited = true;
}
初始化完成后,即可调用OpenGL的API了,如glViewport设置视口的大小。
绘制完成后,调用swapBuffer交换图形缓冲,绘制的内容才能显示出来。
void EglManager::swapBuffer() {
if(!mIsInited) return;
if (!eglSwapBuffers(mEglDisplay, mEglSurface)) {
LOGE("eglSwapBuffers() returned error %d", eglGetError());
}
}