backend/headless: add wlr_headless_backend_create_with_renderer
This allows one to create a headless backend with an existing renderer.
This commit is contained in:
parent
40513f1a0e
commit
6129a6f93e
|
@ -62,7 +62,9 @@ static void backend_destroy(struct wlr_backend *wlr_backend) {
|
||||||
wlr_signal_emit_safe(&wlr_backend->events.destroy, backend);
|
wlr_signal_emit_safe(&wlr_backend->events.destroy, backend);
|
||||||
|
|
||||||
wlr_renderer_destroy(backend->renderer);
|
wlr_renderer_destroy(backend->renderer);
|
||||||
wlr_egl_finish(&backend->egl);
|
if (backend->egl == &backend->priv_egl) {
|
||||||
|
wlr_egl_finish(&backend->priv_egl);
|
||||||
|
}
|
||||||
free(backend);
|
free(backend);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,41 +87,15 @@ static void handle_display_destroy(struct wl_listener *listener, void *data) {
|
||||||
backend_destroy(&backend->backend);
|
backend_destroy(&backend->backend);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct wlr_backend *wlr_headless_backend_create(struct wl_display *display,
|
static bool backend_init(struct wlr_headless_backend *backend,
|
||||||
wlr_renderer_create_func_t create_renderer_func) {
|
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;
|
|
||||||
}
|
|
||||||
wlr_backend_init(&backend->backend, &backend_impl);
|
wlr_backend_init(&backend->backend, &backend_impl);
|
||||||
backend->display = display;
|
backend->display = display;
|
||||||
wl_list_init(&backend->outputs);
|
wl_list_init(&backend->outputs);
|
||||||
wl_list_init(&backend->input_devices);
|
wl_list_init(&backend->input_devices);
|
||||||
|
|
||||||
static const EGLint config_attribs[] = {
|
backend->renderer = renderer;
|
||||||
EGL_SURFACE_TYPE, 0,
|
backend->egl = wlr_gles2_renderer_get_egl(renderer);
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (wlr_gles2_renderer_check_ext(backend->renderer, "GL_OES_rgb8_rgba8") ||
|
if (wlr_gles2_renderer_check_ext(backend->renderer, "GL_OES_rgb8_rgba8") ||
|
||||||
wlr_gles2_renderer_check_ext(backend->renderer,
|
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;
|
backend->display_destroy.notify = handle_display_destroy;
|
||||||
wl_display_add_destroy_listener(display, &backend->display_destroy);
|
wl_display_add_destroy_listener(display, &backend->display_destroy);
|
||||||
|
|
||||||
return &backend->backend;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
error_renderer:
|
struct wlr_backend *wlr_headless_backend_create(struct wl_display *display,
|
||||||
wlr_renderer_destroy(backend->renderer);
|
wlr_renderer_create_func_t create_renderer_func) {
|
||||||
error_backend:
|
wlr_log(WLR_INFO, "Creating headless backend");
|
||||||
free(backend);
|
|
||||||
return NULL;
|
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) {
|
bool wlr_backend_is_headless(struct wlr_backend *backend) {
|
||||||
|
|
|
@ -16,7 +16,7 @@ static struct wlr_headless_output *headless_output_from_output(
|
||||||
|
|
||||||
static bool create_fbo(struct wlr_headless_output *output,
|
static bool create_fbo(struct wlr_headless_output *output,
|
||||||
unsigned int width, unsigned int height) {
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,7 +46,7 @@ static bool create_fbo(struct wlr_headless_output *output,
|
||||||
}
|
}
|
||||||
|
|
||||||
static void destroy_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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,7 +82,7 @@ static bool output_attach_render(struct wlr_output *wlr_output,
|
||||||
struct wlr_headless_output *output =
|
struct wlr_headless_output *output =
|
||||||
headless_output_from_output(wlr_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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,7 +129,7 @@ static bool output_commit(struct wlr_output *wlr_output) {
|
||||||
wlr_output_send_present(wlr_output, NULL);
|
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);
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -138,7 +138,7 @@ static bool output_commit(struct wlr_output *wlr_output) {
|
||||||
static void output_rollback(struct wlr_output *wlr_output) {
|
static void output_rollback(struct wlr_output *wlr_output) {
|
||||||
struct wlr_headless_output *output =
|
struct wlr_headless_output *output =
|
||||||
headless_output_from_output(wlr_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);
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,8 @@
|
||||||
|
|
||||||
struct wlr_headless_backend {
|
struct wlr_headless_backend {
|
||||||
struct wlr_backend 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 wlr_renderer *renderer;
|
||||||
struct wl_display *display;
|
struct wl_display *display;
|
||||||
struct wl_list outputs;
|
struct wl_list outputs;
|
||||||
|
|
|
@ -19,6 +19,11 @@
|
||||||
*/
|
*/
|
||||||
struct wlr_backend *wlr_headless_backend_create(struct wl_display *display,
|
struct wlr_backend *wlr_headless_backend_create(struct wl_display *display,
|
||||||
wlr_renderer_create_func_t create_renderer_func);
|
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
|
* 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
|
* read pixels from this framebuffer via wlr_renderer_read_pixels but it is
|
||||||
|
|
Loading…
Reference in New Issue