summaryrefslogtreecommitdiff
path: root/core/surface
diff options
context:
space:
mode:
Diffstat (limited to 'core/surface')
-rw-r--r--core/surface/egl.c147
1 files changed, 147 insertions, 0 deletions
diff --git a/core/surface/egl.c b/core/surface/egl.c
new file mode 100644
index 0000000..f0370ce
--- /dev/null
+++ b/core/surface/egl.c
@@ -0,0 +1,147 @@
+#include "core/event.h"
+#include "core/renderer.h"
+#include "core/window.h"
+#include "internal/utils.h"
+
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+/* Get human-readable EGL error string */
+const char *egl_error_string(EGLint error) {
+ switch (error) {
+ case EGL_SUCCESS:
+ return "EGL_SUCCESS";
+ case EGL_NOT_INITIALIZED:
+ return "EGL_NOT_INITIALIZED";
+ case EGL_BAD_ACCESS:
+ return "EGL_BAD_ACCESS";
+ case EGL_BAD_ALLOC:
+ return "EGL_BAD_ALLOC";
+ case EGL_BAD_ATTRIBUTE:
+ return "EGL_BAD_ATTRIBUTE";
+ case EGL_BAD_CONFIG:
+ return "EGL_BAD_CONFIG";
+ case EGL_BAD_CONTEXT:
+ return "EGL_BAD_CONTEXT";
+ case EGL_BAD_CURRENT_SURFACE:
+ return "EGL_BAD_CURRENT_SURFACE";
+ case EGL_BAD_DISPLAY:
+ return "EGL_BAD_DISPLAY";
+ case EGL_BAD_MATCH:
+ return "EGL_BAD_MATCH";
+ case EGL_BAD_NATIVE_PIXMAP:
+ return "EGL_BAD_NATIVE_PIXMAP";
+ case EGL_BAD_NATIVE_WINDOW:
+ return "EGL_BAD_NATIVE_WINDOW";
+ case EGL_BAD_PARAMETER:
+ return "EGL_BAD_PARAMETER";
+ case EGL_BAD_SURFACE:
+ return "EGL_BAD_SURFACE";
+ case EGL_CONTEXT_LOST:
+ return "EGL_CONTEXT_LOST";
+ default:
+ return "UNKNOWN_EGL_ERROR";
+ }
+}
+
+/* Crash with EGL error information
+ * */
+void crash_egl(const char *expr, const char *file, int line) {
+ EGLint error = eglGetError();
+ fprintf(stderr, "EGL Error at %s:%d\n", file, line);
+ fprintf(stderr, "Expression: %s\n", expr);
+ fprintf(stderr, "Error code: 0x%x (%s)\n", error, egl_error_string(error));
+ abort();
+}
+
+/* Macro for checking EGL boolean returns (EGL_TRUE/EGL_FALSE) */
+#define assert_egl(expr) \
+ do { \
+ if (!(expr)) \
+ crash_egl(#expr, __FILE__, __LINE__); \
+ } while (0)
+
+void RuimInitEGL(RuimToplevel *toplevel) {
+ RuimSurfaceEGL ruimSurface;
+ EGLint version_major, version_minor;
+ EGLConfig config;
+ EGLint num_config;
+ struct toplevel_x11 *x11_toplevel = (struct toplevel_x11 *)toplevel->data;
+ struct backend_x11 *x11_backend =
+ (struct backend_x11 *)toplevel->backend->data;
+ EGLint constraints[] = {
+ EGL_SURFACE_TYPE,
+ EGL_WINDOW_BIT,
+ EGL_RENDERABLE_TYPE,
+ EGL_OPENGL_ES3_BIT,
+ EGL_RED_SIZE,
+ 8,
+ EGL_GREEN_SIZE,
+ 8,
+ EGL_BLUE_SIZE,
+ 8,
+ EGL_ALPHA_SIZE,
+ 8,
+ EGL_DEPTH_SIZE,
+ 24,
+ EGL_NONE,
+ };
+
+ /* egl-contexts collect all state descriptions needed required for operation
+ */
+ EGLint ctxattr[] = {EGL_CONTEXT_MAJOR_VERSION, 3, EGL_CONTEXT_MINOR_VERSION,
+ 0, EGL_NONE};
+
+ const char *client_extensions =
+ eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS);
+
+ if (!client_extensions) {
+ abort();
+ }
+ if (!strstr(client_extensions, "EGL_EXT_platform_xcb")) {
+ abort();
+ }
+
+ ruimSurface.display = eglGetPlatformDisplay(EGL_PLATFORM_XCB_EXT,
+ x11_backend->connection, NULL);
+
+ assert_egl(ruimSurface.display);
+
+ assert_egl(
+ eglInitialize(ruimSurface.display, &version_major, &version_minor));
+ ;
+ assert_egl(eglChooseConfig(ruimSurface.display, constraints, &config, 1,
+ &num_config));
+ assert_egl(eglBindAPI(EGL_OPENGL_ES_API));
+
+ ruimSurface.surface = eglCreatePlatformWindowSurface(
+ ruimSurface.display, config, &x11_toplevel->window, NULL);
+ assert_egl(ruimSurface.surface);
+
+ ruimSurface.context =
+ eglCreateContext(ruimSurface.display, config, EGL_NO_CONTEXT, ctxattr);
+ assert_egl(ruimSurface.context);
+
+ assert_egl(eglMakeCurrent(ruimSurface.display, ruimSurface.surface,
+ ruimSurface.surface, ruimSurface.context));
+ assert_egl(eglSwapInterval(ruimSurface.display, 1));
+
+ x11_backend->surface = ruimSurface;
+}
+
+EGLBoolean RuimSwapEGL(RuimToplevel *toplevel) {
+ struct backend_x11 *x11_backend =
+ (struct backend_x11 *)toplevel->backend->data;
+
+ return eglSwapBuffers(x11_backend->surface.display,
+ x11_backend->surface.surface);
+}
+
+void RuimDeinitEGL(RuimSurfaceEGL *eglCtx) {
+ assert_egl(eglMakeCurrent(eglCtx->display, EGL_NO_SURFACE, EGL_NO_SURFACE,
+ EGL_NO_CONTEXT));
+ assert_egl(eglDestroyContext(eglCtx->display, eglCtx->context));
+ assert_egl(eglDestroySurface(eglCtx->display, eglCtx->surface));
+ assert_egl(eglTerminate(eglCtx->display));
+}