From 6129a6f93e97680dfe7e983db2ee7671edb5ffbe Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Mon, 6 Apr 2020 13:27:05 +0200 Subject: [PATCH] backend/headless: add wlr_headless_backend_create_with_renderer This allows one to create a headless backend with an existing renderer. --- backend/headless/backend.c | 105 +++++++++++++++++++++------------ backend/headless/output.c | 10 ++-- include/backend/headless.h | 3 +- include/wlr/backend/headless.h | 5 ++ 4 files changed, 80 insertions(+), 43 deletions(-) diff --git a/backend/headless/backend.c b/backend/headless/backend.c index 73ec9ebd..8eadd3b7 100644 --- a/backend/headless/backend.c +++ b/backend/headless/backend.c @@ -62,7 +62,9 @@ static void backend_destroy(struct wlr_backend *wlr_backend) { wlr_signal_emit_safe(&wlr_backend->events.destroy, backend); wlr_renderer_destroy(backend->renderer); - wlr_egl_finish(&backend->egl); + if (backend->egl == &backend->priv_egl) { + wlr_egl_finish(&backend->priv_egl); + } free(backend); } @@ -85,41 +87,15 @@ static void handle_display_destroy(struct wl_listener *listener, void *data) { backend_destroy(&backend->backend); } -struct wlr_backend *wlr_headless_backend_create(struct wl_display *display, - wlr_renderer_create_func_t create_renderer_func) { - wlr_log(WLR_INFO, "Creating headless backend"); - - struct wlr_headless_backend *backend = - calloc(1, sizeof(struct wlr_headless_backend)); - if (!backend) { - wlr_log(WLR_ERROR, "Failed to allocate wlr_headless_backend"); - return NULL; - } +static bool backend_init(struct wlr_headless_backend *backend, + struct wl_display *display, struct wlr_renderer *renderer) { wlr_backend_init(&backend->backend, &backend_impl); backend->display = display; wl_list_init(&backend->outputs); wl_list_init(&backend->input_devices); - static const EGLint config_attribs[] = { - EGL_SURFACE_TYPE, 0, - EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, - EGL_BLUE_SIZE, 1, - EGL_GREEN_SIZE, 1, - EGL_RED_SIZE, 1, - EGL_NONE, - }; - - if (!create_renderer_func) { - create_renderer_func = wlr_renderer_autocreate; - } - - backend->renderer = create_renderer_func(&backend->egl, - EGL_PLATFORM_SURFACELESS_MESA, EGL_DEFAULT_DISPLAY, - (EGLint*)config_attribs, 0); - if (!backend->renderer) { - wlr_log(WLR_ERROR, "Failed to create renderer"); - goto error_backend; - } + backend->renderer = renderer; + backend->egl = wlr_gles2_renderer_get_egl(renderer); if (wlr_gles2_renderer_check_ext(backend->renderer, "GL_OES_rgb8_rgba8") || wlr_gles2_renderer_check_ext(backend->renderer, @@ -136,13 +112,68 @@ struct wlr_backend *wlr_headless_backend_create(struct wl_display *display, backend->display_destroy.notify = handle_display_destroy; wl_display_add_destroy_listener(display, &backend->display_destroy); - return &backend->backend; + return true; +} -error_renderer: - wlr_renderer_destroy(backend->renderer); -error_backend: - free(backend); - return NULL; +struct wlr_backend *wlr_headless_backend_create(struct wl_display *display, + wlr_renderer_create_func_t create_renderer_func) { + wlr_log(WLR_INFO, "Creating headless backend"); + + struct wlr_headless_backend *backend = + calloc(1, sizeof(struct wlr_headless_backend)); + if (!backend) { + wlr_log(WLR_ERROR, "Failed to allocate wlr_headless_backend"); + return NULL; + } + + static const EGLint config_attribs[] = { + EGL_SURFACE_TYPE, 0, + EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, + EGL_BLUE_SIZE, 1, + EGL_GREEN_SIZE, 1, + EGL_RED_SIZE, 1, + EGL_NONE, + }; + + if (!create_renderer_func) { + create_renderer_func = wlr_renderer_autocreate; + } + + struct wlr_renderer *renderer = create_renderer_func(&backend->priv_egl, + EGL_PLATFORM_SURFACELESS_MESA, EGL_DEFAULT_DISPLAY, + (EGLint*)config_attribs, 0); + if (!renderer) { + wlr_log(WLR_ERROR, "Failed to create renderer"); + free(backend); + return NULL; + } + + if (!backend_init(backend, display, renderer)) { + wlr_renderer_destroy(backend->renderer); + free(backend); + return NULL; + } + + return &backend->backend; +} + +struct wlr_backend *wlr_headless_backend_create_with_renderer( + struct wl_display *display, struct wlr_renderer *renderer) { + wlr_log(WLR_INFO, "Creating headless backend"); + + struct wlr_headless_backend *backend = + calloc(1, sizeof(struct wlr_headless_backend)); + if (!backend) { + wlr_log(WLR_ERROR, "Failed to allocate wlr_headless_backend"); + return NULL; + } + + if (!backend_init(backend, display, renderer)) { + free(backend); + return NULL; + } + + return &backend->backend; } bool wlr_backend_is_headless(struct wlr_backend *backend) { diff --git a/backend/headless/output.c b/backend/headless/output.c index 0f6a1549..dc0a1478 100644 --- a/backend/headless/output.c +++ b/backend/headless/output.c @@ -16,7 +16,7 @@ static struct wlr_headless_output *headless_output_from_output( static bool create_fbo(struct wlr_headless_output *output, unsigned int width, unsigned int height) { - if (!wlr_egl_make_current(&output->backend->egl, EGL_NO_SURFACE, NULL)) { + if (!wlr_egl_make_current(output->backend->egl, EGL_NO_SURFACE, NULL)) { return false; } @@ -46,7 +46,7 @@ static bool create_fbo(struct wlr_headless_output *output, } static void destroy_fbo(struct wlr_headless_output *output) { - if (!wlr_egl_make_current(&output->backend->egl, EGL_NO_SURFACE, NULL)) { + if (!wlr_egl_make_current(output->backend->egl, EGL_NO_SURFACE, NULL)) { return; } @@ -82,7 +82,7 @@ static bool output_attach_render(struct wlr_output *wlr_output, struct wlr_headless_output *output = headless_output_from_output(wlr_output); - if (!wlr_egl_make_current(&output->backend->egl, EGL_NO_SURFACE, NULL)) { + if (!wlr_egl_make_current(output->backend->egl, EGL_NO_SURFACE, NULL)) { return false; } @@ -129,7 +129,7 @@ static bool output_commit(struct wlr_output *wlr_output) { wlr_output_send_present(wlr_output, NULL); } - wlr_egl_make_current(&output->backend->egl, EGL_NO_SURFACE, NULL); + wlr_egl_make_current(output->backend->egl, EGL_NO_SURFACE, NULL); glBindFramebuffer(GL_FRAMEBUFFER, 0); return true; @@ -138,7 +138,7 @@ static bool output_commit(struct wlr_output *wlr_output) { static void output_rollback(struct wlr_output *wlr_output) { struct wlr_headless_output *output = headless_output_from_output(wlr_output); - wlr_egl_make_current(&output->backend->egl, EGL_NO_SURFACE, NULL); + wlr_egl_make_current(output->backend->egl, EGL_NO_SURFACE, NULL); glBindFramebuffer(GL_FRAMEBUFFER, 0); } diff --git a/include/backend/headless.h b/include/backend/headless.h index d8cb4dc2..564cb154 100644 --- a/include/backend/headless.h +++ b/include/backend/headless.h @@ -9,7 +9,8 @@ struct wlr_headless_backend { struct wlr_backend backend; - struct wlr_egl egl; + struct wlr_egl priv_egl; // may be uninitialized + struct wlr_egl *egl; struct wlr_renderer *renderer; struct wl_display *display; struct wl_list outputs; diff --git a/include/wlr/backend/headless.h b/include/wlr/backend/headless.h index eab102e2..f9481228 100644 --- a/include/wlr/backend/headless.h +++ b/include/wlr/backend/headless.h @@ -19,6 +19,11 @@ */ struct wlr_backend *wlr_headless_backend_create(struct wl_display *display, wlr_renderer_create_func_t create_renderer_func); +/** + * Creates a headless backend with an existing renderer. + */ +struct wlr_backend *wlr_headless_backend_create_with_renderer( + struct wl_display *display, struct wlr_renderer *renderer); /** * Create a new headless output backed by an in-memory EGL framebuffer. You can * read pixels from this framebuffer via wlr_renderer_read_pixels but it is