From b852fb9a2b3842dc6d122a2483c11322beb7a489 Mon Sep 17 00:00:00 2001 From: emersion Date: Sun, 17 Dec 2017 13:35:07 +0100 Subject: [PATCH] Minimal working headless output --- backend/headless/backend.c | 10 ++++++++ backend/headless/output.c | 48 +++++++++++++++++++++++++++++++------- include/backend/headless.h | 1 + 3 files changed, 51 insertions(+), 8 deletions(-) diff --git a/backend/headless/backend.c b/backend/headless/backend.c index c60eb7e5..bc2de2f2 100644 --- a/backend/headless/backend.c +++ b/backend/headless/backend.c @@ -26,6 +26,9 @@ static void backend_destroy(struct wlr_backend *wlr_backend) { } wl_list_remove(&backend->display_destroy.link); + + // TODO: destroy outputs + wlr_egl_finish(&backend->egl); free(backend); } @@ -61,6 +64,12 @@ static bool egl_get_config(EGLDisplay disp, EGLConfig *out) { static const EGLint attribs[] = { EGL_SURFACE_TYPE, EGL_PBUFFER_BIT, + EGL_BUFFER_SIZE, 32, + EGL_ALPHA_SIZE, 0, + EGL_BLUE_SIZE, 8, + EGL_GREEN_SIZE, 8, + EGL_RED_SIZE, 8, + EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, EGL_NONE, }; @@ -146,6 +155,7 @@ struct wlr_backend *wlr_headless_backend_create(struct wl_display *display) { } wlr_backend_init(&backend->backend, &backend_impl); backend->display = display; + wl_list_init(&backend->outputs); egl_init(&backend->egl); diff --git a/backend/headless/output.c b/backend/headless/output.c index 194f542f..d4a46978 100644 --- a/backend/headless/output.c +++ b/backend/headless/output.c @@ -6,6 +6,27 @@ #include #include "backend/headless.h" +static void output_transform(struct wlr_output *wlr_output, + enum wl_output_transform transform) { + struct wlr_headless_backend_output *output = + (struct wlr_headless_backend_output *)wlr_output; + output->wlr_output.transform = transform; +} + +static void output_make_current(struct wlr_output *wlr_output) { + struct wlr_headless_backend_output *output = + (struct wlr_headless_backend_output *)wlr_output; + if (!eglMakeCurrent(output->backend->egl.display, + output->egl_surface, output->egl_surface, + output->backend->egl.context)) { + wlr_log(L_ERROR, "eglMakeCurrent failed: %s", egl_error()); + } +} + +static void output_swap_buffers(struct wlr_output *wlr_output) { + // No-op +} + static void output_destroy(struct wlr_output *wlr_output) { struct wlr_headless_backend_output *output = (struct wlr_headless_backend_output *)wlr_output; @@ -19,13 +40,20 @@ static void output_destroy(struct wlr_output *wlr_output) { } static const struct wlr_output_impl output_impl = { - //.set_custom_mode = wlr_wl_output_set_custom_mode, - //.transform = wlr_wl_output_transform, + //.set_custom_mode = output_set_custom_mode, + .transform = output_transform, .destroy = output_destroy, - //.make_current = wlr_wl_output_make_current, - //.swap_buffers = wlr_wl_output_swap_buffers, + .make_current = output_make_current, + .swap_buffers = output_swap_buffers, }; +static int signal_frame(void *data) { + struct wlr_headless_backend_output *output = data; + wl_signal_emit(&output->wlr_output.events.frame, &output->wlr_output); + wl_event_source_timer_update(output->frame_timer, 16); + return 0; +} + static EGLSurface egl_create_surface(struct wlr_egl *egl, unsigned int width, unsigned int height) { EGLint attribs[] = {EGL_WIDTH, width, EGL_HEIGHT, height, EGL_NONE}; @@ -49,10 +77,15 @@ struct wlr_output *wlr_headless_add_output(struct wlr_backend *wlr_backend, wlr_log(L_ERROR, "Failed to allocate wlr_headless_backend_output"); return NULL; } + output->backend = backend; wlr_output_init(&output->wlr_output, &backend->backend, &output_impl); struct wlr_output *wlr_output = &output->wlr_output; output->egl_surface = egl_create_surface(&backend->egl, width, height); + if (output->egl_surface == EGL_NO_SURFACE) { + // TODO: cleanup + return NULL; + } wlr_output_update_size(wlr_output, width, height); @@ -67,14 +100,13 @@ struct wlr_output *wlr_headless_add_output(struct wlr_backend *wlr_backend, glClearColor(1.0, 1.0, 1.0, 1.0); glClear(GL_COLOR_BUFFER_BIT); - if (!eglSwapBuffers(output->backend->egl.display, output->egl_surface)) { - wlr_log(L_ERROR, "eglSwapBuffers failed: %s", egl_error()); - goto error; - } + struct wl_event_loop *ev = wl_display_get_event_loop(backend->display); + output->frame_timer = wl_event_loop_add_timer(ev, signal_frame, output); wl_list_insert(&backend->outputs, &output->link); wlr_output_create_global(wlr_output, backend->display); wl_signal_emit(&backend->backend.events.output_add, wlr_output); + wl_event_source_timer_update(output->frame_timer, 16); return wlr_output; error: diff --git a/include/backend/headless.h b/include/backend/headless.h index 56ae626a..e4cc85e4 100644 --- a/include/backend/headless.h +++ b/include/backend/headless.h @@ -20,6 +20,7 @@ struct wlr_headless_backend_output { struct wl_list link; void *egl_surface; + struct wl_event_source *frame_timer; }; #endif