diff options
| author | Roberto Esteves <contact@robertoesteves.dev> | 2025-11-22 16:35:06 +0000 |
|---|---|---|
| committer | Roberto Esteves <contact@robertoesteves.dev> | 2025-11-22 16:35:06 +0000 |
| commit | e7c2ec9719349f7a20dd1d4854869c10d8836a11 (patch) | |
| tree | af5b34d8d21cabd4ec6d4206ce5a6fd4651de56c /core/surface/egl.c | |
| parent | d84537c52f537920369618028f84b48296811fd0 (diff) | |
Diffstat (limited to 'core/surface/egl.c')
| -rw-r--r-- | core/surface/egl.c | 147 |
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)); +} |