diff options
Diffstat (limited to 'backend/egl.c')
-rw-r--r-- | backend/egl.c | 94 |
1 files changed, 87 insertions, 7 deletions
diff --git a/backend/egl.c b/backend/egl.c index a547523c..15a2c58e 100644 --- a/backend/egl.c +++ b/backend/egl.c @@ -1,10 +1,17 @@ #include <EGL/egl.h> #include <EGL/eglext.h> -#include <GLES3/gl3.h> +#include <GLES2/gl2.h> #include <gbm.h> // GBM_FORMAT_XRGB8888 +#include <stdlib.h> #include <wlr/util/log.h> #include "backend/egl.h" +// Extension documentation +// https://www.khronos.org/registry/EGL/extensions/KHR/EGL_KHR_image_base.txt. +// https://cgit.freedesktop.org/mesa/mesa/tree/docs/specs/WL_bind_wayland_display.spec + +struct wlr_egl *egl_global; + const char *egl_error(void) { switch (eglGetError()) { case EGL_SUCCESS: @@ -46,6 +53,12 @@ const char *egl_error(void) { PFNEGLGETPLATFORMDISPLAYEXTPROC get_platform_display; PFNEGLCREATEPLATFORMWINDOWSURFACEEXTPROC create_platform_window_surface; +PFNEGLCREATEIMAGEKHRPROC eglCreateImageKHR; +PFNEGLDESTROYIMAGEKHRPROC eglDestroyImageKHR; +PFNEGLQUERYWAYLANDBUFFERWL eglQueryWaylandBufferWL; +PFNEGLBINDWAYLANDDISPLAYWL eglBindWaylandDisplayWL; +PFNEGLUNBINDWAYLANDDISPLAYWL eglUnbindWaylandDisplayWL; + static bool egl_exts() { get_platform_display = (PFNEGLGETPLATFORMDISPLAYEXTPROC) eglGetProcAddress("eglGetPlatformDisplayEXT"); @@ -109,7 +122,8 @@ static bool egl_get_config(EGLDisplay disp, EGLConfig *out, EGLenum platform) { return false; } -bool wlr_egl_init(struct wlr_egl *egl, EGLenum platform, void *display) { +bool wlr_egl_init(struct wlr_egl *egl, EGLenum platform, + void *remote_display) { if (!egl_exts()) { return false; } @@ -119,7 +133,7 @@ bool wlr_egl_init(struct wlr_egl *egl, EGLenum platform, void *display) { goto error; } - egl->display = get_platform_display(platform, display, NULL); + egl->display = get_platform_display(platform, remote_display, NULL); if (egl->display == EGL_NO_DISPLAY) { wlr_log(L_ERROR, "Failed to create EGL display: %s", egl_error()); goto error; @@ -147,11 +161,31 @@ bool wlr_egl_init(struct wlr_egl *egl, EGLenum platform, void *display) { } eglMakeCurrent(egl->display, EGL_NO_SURFACE, EGL_NO_SURFACE, egl->context); + egl->egl_exts = eglQueryString(egl->display, EGL_EXTENSIONS); + if (strstr(egl->egl_exts, "EGL_WL_bind_wayland_display") == NULL || + strstr(egl->egl_exts, "EGL_KHR_image_base") == NULL) { + wlr_log(L_ERROR, "Required egl extensions not supported"); + goto error; + } + + eglCreateImageKHR = (PFNEGLCREATEIMAGEKHRPROC) + eglGetProcAddress("eglCreateImageKHR"); + eglDestroyImageKHR = (PFNEGLDESTROYIMAGEKHRPROC) + eglGetProcAddress("eglDestroyImageKHR"); + eglQueryWaylandBufferWL = (PFNEGLQUERYWAYLANDBUFFERWL) + (void*) eglGetProcAddress("eglQueryWaylandBufferWL"); + eglBindWaylandDisplayWL = (PFNEGLBINDWAYLANDDISPLAYWL) + (void*) eglGetProcAddress("eglBindWaylandDisplayWL"); + eglUnbindWaylandDisplayWL = (PFNEGLUNBINDWAYLANDDISPLAYWL) + (void*) eglGetProcAddress("eglUnbindWaylandDisplayWL"); + + egl_global = egl; + + egl->gl_exts = (const char*) glGetString(GL_EXTENSIONS); wlr_log(L_INFO, "Using EGL %d.%d", (int)major, (int)minor); - wlr_log(L_INFO, "Supported EGL extensions: %s", eglQueryString(egl->display, - EGL_EXTENSIONS)); + wlr_log(L_INFO, "Supported EGL extensions: %s", egl->egl_exts); wlr_log(L_INFO, "Using %s", glGetString(GL_VERSION)); - wlr_log(L_INFO, "Supported OpenGL ES extensions: %s", glGetString(GL_EXTENSIONS)); + wlr_log(L_INFO, "Supported OpenGL ES extensions: %s", egl->gl_exts); return true; error: @@ -162,11 +196,57 @@ error: } void wlr_egl_free(struct wlr_egl *egl) { - eglMakeCurrent(egl->display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + if (egl->wl_display && eglUnbindWaylandDisplayWL) { + eglUnbindWaylandDisplayWL(egl->display, egl->wl_display); + } + eglDestroyContext(egl->display, egl->context); eglTerminate(egl->display); eglReleaseThread(); eglMakeCurrent(EGL_NO_DISPLAY, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + + if (egl_global == egl) + egl_global = NULL; +} + +bool wlr_egl_bind_display(struct wlr_egl *egl, struct wl_display *local_display) { + if (!eglBindWaylandDisplayWL) { + return false; + } + + if (eglBindWaylandDisplayWL(egl->display, local_display)) { + egl->wl_display = local_display; + return true; + } + + return false; +} + +bool wlr_egl_query_buffer(struct wl_resource *buf, int attrib, int *value) { + if (!egl_global || !eglQueryWaylandBufferWL) { + return false; + } + + return eglQueryWaylandBufferWL(egl_global->display, buf, attrib, value); +} + +EGLImage wlr_egl_create_image(EGLenum target, + EGLClientBuffer buffer, const EGLint *attribs) { + if (!egl_global || !eglCreateImageKHR) { + return false; + } + + return eglCreateImageKHR(egl_global->display, egl_global->context, target, + buffer, attribs); +} + +bool wlr_egl_destroy_image(EGLImage image) { + if (!egl_global || !eglDestroyImageKHR) { + return false; + } + + eglDestroyImageKHR(egl_global->display, image); + return true; } EGLSurface wlr_egl_create_surface(struct wlr_egl *egl, void *window) { |