182 lines
5.4 KiB
C++
182 lines
5.4 KiB
C++
#include <log.h>
|
|
#include <lorie-egl-helper.hpp>
|
|
#include <GLES2/gl2.h>
|
|
|
|
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;
|
|
}
|