From 65796816b951f11541311c2624e28f0881fec61d Mon Sep 17 00:00:00 2001 From: Ander Conselvan de Oliveira Date: Tue, 19 Nov 2013 15:22:04 +0200 Subject: [PATCH] compositor-drm: Add key binding to switch from pixman to GL renderer When running with the pixman renderer, the debug binding 'W' (mod-shift-space W) will cause the compositor to load gl-renderer.so and start using it instead of the pixman renderer. --- src/compositor-drm.c | 83 +++++++++++++++++++++++++++++++++++++++++++++++----- src/gl-renderer.c | 6 ++++ 2 files changed, 81 insertions(+), 8 deletions(-) diff --git a/src/compositor-drm.c b/src/compositor-drm.c index d4fc871..5cb0fab 100644 --- a/src/compositor-drm.c +++ b/src/compositor-drm.c @@ -596,7 +596,8 @@ drm_output_repaint(struct weston_output *output_base, return -1; mode = container_of(output->base.current_mode, struct drm_mode, base); - if (!output->current) { + if (!output->current || + output->current->stride != output->next->stride) { ret = drmModeSetCrtc(compositor->drm.fd, output->crtc_id, output->next->fb_id, 0, 0, &output->connector_id, 1, @@ -1286,15 +1287,15 @@ init_drm(struct drm_compositor *ec, struct udev_device *device) return 0; } -static int -init_egl(struct drm_compositor *ec) +static struct gbm_device * +create_gbm_device(int fd) { - EGLint format; + struct gbm_device *gbm; gl_renderer = weston_load_module("gl-renderer.so", "gl_renderer_interface"); if (!gl_renderer) - return -1; + return NULL; /* GBM will load a dri driver, but even though they need symbols from * libglapi, in some version of Mesa they are not linked to it. Since @@ -1303,14 +1304,34 @@ init_egl(struct drm_compositor *ec) * Workaround this by dlopen()'ing libglapi with RTLD_GLOBAL. */ dlopen("libglapi.so.0", RTLD_LAZY | RTLD_GLOBAL); - ec->gbm = gbm_create_device(ec->drm.fd); + gbm = gbm_create_device(fd); - if (!ec->gbm) - return -1; + return gbm; +} + +static int +drm_compositor_create_gl_renderer(struct drm_compositor *ec) +{ + EGLint format; format = ec->format; if (gl_renderer->create(&ec->base, ec->gbm, gl_renderer->opaque_attribs, &format) < 0) { + return -1; + } + + return 0; +} + +static int +init_egl(struct drm_compositor *ec) +{ + ec->gbm = create_gbm_device(ec->drm.fd); + + if (!ec->gbm) + return -1; + + if (drm_compositor_create_gl_renderer(ec) < 0) { gbm_device_destroy(ec->gbm); return -1; } @@ -2585,6 +2606,50 @@ recorder_binding(struct weston_seat *seat, uint32_t time, uint32_t key, } #endif +static void +switch_to_gl_renderer(struct drm_compositor *c) +{ + struct drm_output *output; + + if (!c->use_pixman) + return; + + weston_log("Switching to GL renderer\n"); + + c->gbm = create_gbm_device(c->drm.fd); + if (!c->gbm) { + weston_log("Failed to create gbm device. " + "Aborting renderer switch\n"); + return; + } + + wl_list_for_each(output, &c->base.output_list, base.link) + pixman_renderer_output_destroy(&output->base); + + c->base.renderer->destroy(&c->base); + + if (drm_compositor_create_gl_renderer(c) < 0) { + gbm_device_destroy(c->gbm); + weston_log("Failed to create GL renderer. Quitting.\n"); + /* FIXME: we need a function to shutdown cleanly */ + assert(0); + } + + wl_list_for_each(output, &c->base.output_list, base.link) + drm_output_init_egl(output, c); + + c->use_pixman = 0; +} + +static void +renderer_switch_binding(struct weston_seat *seat, uint32_t time, uint32_t key, + void *data) +{ + struct drm_compositor *c = (struct drm_compositor *) seat->compositor; + + switch_to_gl_renderer(c); +} + static struct weston_compositor * drm_compositor_create(struct wl_display *display, struct drm_parameters *param, @@ -2734,6 +2799,8 @@ drm_compositor_create(struct wl_display *display, planes_binding, ec); weston_compositor_add_debug_binding(&ec->base, KEY_Q, recorder_binding, ec); + weston_compositor_add_debug_binding(&ec->base, KEY_W, + renderer_switch_binding, ec); return &ec->base; diff --git a/src/gl-renderer.c b/src/gl-renderer.c index 7a535c7..5e1b396 100644 --- a/src/gl-renderer.c +++ b/src/gl-renderer.c @@ -511,6 +511,12 @@ draw_view(struct weston_view *ev, struct weston_output *output, GLint filter; int i; + /* In case of a runtime switch of renderers, we may not have received + * an attach for this surface since the switch. In that case we don't + * have a valid buffer or a proper shader set up so skip rendering. */ + if (!gs->shader) + return; + pixman_region32_init(&repaint); pixman_region32_intersect(&repaint, &ev->transform.boundingbox, damage); -- 2.7.4