aboutsummaryrefslogtreecommitdiff
path: root/backend/egl.c
diff options
context:
space:
mode:
authornyorain <nyorain@gmail.com>2017-08-09 21:25:34 +0200
committernyorain <nyorain@gmail.com>2017-08-10 10:59:58 +0200
commit67369173aaafd763a6369a84917ae457c7095a72 (patch)
treec42bbcebd5b1e972c422386ce46f353c2f3a31ca /backend/egl.c
parent750d0ad4583732ee24c998f46a62fc684f86bc48 (diff)
Implement drm (egl) buffer attaching
Diffstat (limited to 'backend/egl.c')
-rw-r--r--backend/egl.c96
1 files changed, 89 insertions, 7 deletions
diff --git a/backend/egl.c b/backend/egl.c
index a547523c..591dfe40 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,59 @@ 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) {