#include #include #include static char* eglGetErrorText(int code) { switch(eglGetError()) { #define E(code, desc) case code: return (char*) desc; break; case EGL_SUCCESS: return nullptr; // "No error" E(EGL_NOT_INITIALIZED, "EGL not initialized or failed to initialize"); E(EGL_BAD_ACCESS, "Resource inaccessible"); E(EGL_BAD_ALLOC, "Cannot allocate resources"); E(EGL_BAD_ATTRIBUTE, "Unrecognized attribute or attribute value"); E(EGL_BAD_CONTEXT, "Invalid EGL context"); E(EGL_BAD_CONFIG, "Invalid EGL frame buffer configuration"); E(EGL_BAD_CURRENT_SURFACE, "Current surface is no longer valid"); E(EGL_BAD_DISPLAY, "Invalid EGL display"); E(EGL_BAD_SURFACE, "Invalid surface"); E(EGL_BAD_MATCH, "Inconsistent arguments"); E(EGL_BAD_PARAMETER, "Invalid argument"); E(EGL_BAD_NATIVE_PIXMAP, "Invalid native pixmap"); E(EGL_BAD_NATIVE_WINDOW, "Invalid native window"); E(EGL_CONTEXT_LOST, "Context lost"); #undef E default: return (char*) "Unknown error"; } } #undef checkEGLError void checkEGLError(int line) { char *error = eglGetErrorText(eglGetError()); if (error != nullptr) LOGE("EGL: %s after %d", error, line); } #define checkEGLError() checkEGLError(__LINE__) bool LorieEGLHelper::init(EGLNativeDisplayType display) { EGLint majorVersion, minorVersion; LOGV("Initializing EGL"); dpy = eglGetDisplay(display); checkEGLError(); if (dpy == EGL_NO_DISPLAY) { LOGE("LorieEGLHelper::init : eglGetDisplay failed: %s", eglGetErrorText(eglGetError())); return false; } if (eglInitialize(dpy, &majorVersion, &minorVersion) != EGL_TRUE) { LOGE("LorieEGLHelper::init : eglInitialize failed: %s", eglGetErrorText(eglGetError())); return false; } const EGLint configAttribs[] = { EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_BLUE_SIZE, 8, EGL_ALPHA_SIZE, 8, EGL_NONE }; EGLint numConfigs; if (eglChooseConfig(dpy, configAttribs, &cfg, 1, &numConfigs) != EGL_TRUE) { LOGE("LorieEGLHelper::init : eglChooseConfig failed: %s", eglGetErrorText(eglGetError())); return false; } eglBindAPI(EGL_OPENGL_ES_API); const EGLint ctxattribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, // Request opengl ES2.0 EGL_NONE }; ctx = eglCreateContext(dpy, cfg, NULL, ctxattribs); if (ctx == EGL_NO_CONTEXT) { LOGE("LorieEGLHelper::init : eglCreateContext failed: %s", eglGetErrorText(eglGetError())); return false; } if (eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONFIG_KHR) != EGL_TRUE) { LOGE("LorieEGLHelper::init : eglMakeCurrent failed: %s", eglGetErrorText(eglGetError())); return false; } return true; } bool LorieEGLHelper::setWindow(EGLNativeWindowType window) { LOGV("Trying to use window %p", window); if (sfc != EGL_NO_SURFACE) { if (eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT) != EGL_TRUE) { LOGE("LorieEGLHelper::setWindow : eglMakeCurrent (EGL_NO_SURFACE) failed: %s", eglGetErrorText(eglGetError())); return false; } if (eglDestroySurface(dpy, sfc) != EGL_TRUE) { LOGE("LorieEGLHelper::setWindow : eglDestoySurface failed: %s", eglGetErrorText(eglGetError())); return false; } }; sfc = EGL_NO_SURFACE; win = window; if (win == EGL_NO_WINDOW) { if (onUninit != nullptr) onUninit(); return true; } sfc = eglCreateWindowSurface(dpy, cfg, win, NULL); if (sfc == EGL_NO_SURFACE) { LOGE("LorieEGLHelper::setWindow : eglCreateWindowSurface failed: %s", eglGetErrorText(eglGetError())); if (onUninit != nullptr) onUninit(); return false; } if (eglMakeCurrent(dpy, sfc, sfc, ctx) != EGL_TRUE) { LOGE("LorieEGLHelper::setWindow : eglMakeCurrent failed: %s", eglGetErrorText(eglGetError())); if (onUninit != nullptr) onUninit(); return false; } glClearColor(0.f, 0.f, 0.f, 0.f); glClear(GL_COLOR_BUFFER_BIT); swap(); if (onInit != nullptr) onInit(); return true; } void LorieEGLHelper::swap() { EGLint b = eglSwapBuffers(dpy, sfc); if (b != EGL_TRUE) { EGLint err = eglGetError(); if (err == EGL_BAD_SURFACE) { LOGE("eglSwapBuffers failed because of invalid surface. Regenerating surface."); setWindow(win); } else if (err == EGL_BAD_CONTEXT || err == EGL_CONTEXT_LOST) { LOGE("eglSwapBuffers failed because of invalid context. Regenerating context."); const EGLint ctxattribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, // Request opengl ES2.0 EGL_NONE }; ctx = eglCreateContext(dpy, cfg, NULL, ctxattribs); if (ctx == EGL_NO_CONTEXT) { LOGE("LorieEGLHelper::init : eglCreateContext failed: %s", eglGetErrorText(eglGetError())); return; } } } } void LorieEGLHelper::uninit() { if (eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT) != EGL_TRUE) { LOGE("LorieEGLHelper::uninit : eglMakeCurrent failed: %s", eglGetErrorText(eglGetError())); return; } if (eglDestroyContext(dpy, ctx) != EGL_TRUE) { LOGE("LorieEGLHelper::uninit : eglDestroyContext failed: %s", eglGetErrorText(eglGetError())); return; } ctx = EGL_NO_CONTEXT; if (eglDestroySurface(dpy, sfc) != EGL_TRUE) { LOGE("LorieEGLHelper::uninit : eglDestroySurface failed: %s", eglGetErrorText(eglGetError())); return; } sfc = EGL_NO_SURFACE; if (eglTerminate(dpy) != EGL_TRUE) { LOGE("LorieEGLHelper::uninit : eglTerminate failed: %s", eglGetErrorText(eglGetError())); return; } dpy = EGL_NO_DISPLAY; }