diff options
author | nyorain <nyorain@gmail.com> | 2017-08-09 21:25:34 +0200 |
---|---|---|
committer | nyorain <nyorain@gmail.com> | 2017-08-10 10:59:58 +0200 |
commit | 67369173aaafd763a6369a84917ae457c7095a72 (patch) | |
tree | c42bbcebd5b1e972c422386ce46f353c2f3a31ca /backend | |
parent | 750d0ad4583732ee24c998f46a62fc684f86bc48 (diff) |
Implement drm (egl) buffer attaching
Diffstat (limited to 'backend')
-rw-r--r-- | backend/drm/backend.c | 4 | ||||
-rw-r--r-- | backend/drm/drm.c | 2 | ||||
-rw-r--r-- | backend/egl.c | 96 | ||||
-rw-r--r-- | backend/wayland/backend.c | 2 |
4 files changed, 96 insertions, 8 deletions
diff --git a/backend/drm/backend.c b/backend/drm/backend.c index e361358e..bcc81624 100644 --- a/backend/drm/backend.c +++ b/backend/drm/backend.c @@ -149,6 +149,10 @@ struct wlr_backend *wlr_drm_backend_create(struct wl_display *display, goto error_event; } + if (!wlr_egl_bind_display(&drm->renderer.egl, display)) { + wlr_log(L_INFO, "Failed to bind egl/wl display: %s", egl_error()); + } + return backend; error_event: diff --git a/backend/drm/drm.c b/backend/drm/drm.c index 1c83af3e..e11751e2 100644 --- a/backend/drm/drm.c +++ b/backend/drm/drm.c @@ -579,7 +579,7 @@ static bool wlr_drm_output_set_cursor(struct wlr_output_state *output, wlr_matrix_texture(plane->matrix, plane->width, plane->height, output->base->transform ^ WL_OUTPUT_TRANSFORM_FLIPPED_180); - plane->wlr_rend = wlr_gles2_renderer_init(); + plane->wlr_rend = wlr_gles2_renderer_init(&output->renderer->egl); if (!plane->wlr_rend) { return false; } 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) { diff --git a/backend/wayland/backend.c b/backend/wayland/backend.c index ef480c18..a0fb0be6 100644 --- a/backend/wayland/backend.c +++ b/backend/wayland/backend.c @@ -52,6 +52,8 @@ static bool wlr_wl_backend_init(struct wlr_backend_state* state) { } wlr_egl_init(&state->egl, EGL_PLATFORM_WAYLAND_EXT, state->remote_display); + wlr_egl_bind_display(&state->egl, state->local_display); + for (size_t i = 0; i < state->requested_outputs; ++i) { wlr_wl_output_create(state->backend); } |