From 6143f7dfbd2383eab2462d76d77018a20bfee827 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Sat, 14 Jul 2012 00:31:32 -0400 Subject: [PATCH] compositor-drm: Assign primary framebuffer in assign_planes callout Determining whether it was possible to use a surface buffer as the primary framebuffer was always a bit of a hack. Just before rendering, we look at the second top-most surface to see if it's the right size and position and then use it if it is. If we have a hw cursor and a drm plane on top, it's no longer the second top-most and it wouldn't be picked even if it could work. With this change, we inspect surfaces in drm_assign_planes and try to find a candidate for the primary fb there. We track the overlap like for overlays and if there is a surface that's not overlapped and fills the output we pick it. This commit also consolidate the logic to track damage as we move a surface in and out of the primary plane, which was missing in the drm plane case. --- src/compositor-drm.c | 124 ++++++++++++++----------------------------- 1 file changed, 40 insertions(+), 84 deletions(-) diff --git a/src/compositor-drm.c b/src/compositor-drm.c index fad8977b..6a365730 100644 --- a/src/compositor-drm.c +++ b/src/compositor-drm.c @@ -46,7 +46,9 @@ static int option_current_mode = 0; enum { - WESTON_PLANE_DRM_CURSOR = 0x100 + WESTON_PLANE_DRM_CURSOR = 0x100, + WESTON_PLANE_DRM_PLANE = 0x101, + WESTON_PLANE_DRM_FB = 0x102 }; struct drm_compositor { @@ -143,18 +145,6 @@ struct drm_sprite { uint32_t formats[]; }; -static int -surface_is_primary(struct weston_compositor *ec, struct weston_surface *es) -{ - struct weston_surface *primary; - - primary = container_of(ec->surface_list.next, struct weston_surface, - link); - if (es == primary) - return -1; - return 0; -} - static int drm_sprite_crtc_supported(struct weston_output *output_base, uint32_t supported) { @@ -242,16 +232,14 @@ fb_handle_buffer_destroy(struct wl_listener *listener, void *data) } static int -drm_output_prepare_scanout_surface(struct drm_output *output) +drm_output_prepare_scanout_surface(struct weston_output *_output, + struct weston_surface *es) { + struct drm_output *output = (struct drm_output *) _output; struct drm_compositor *c = (struct drm_compositor *) output->base.compositor; - struct weston_surface *es; struct gbm_bo *bo; - es = container_of(c->base.surface_list.next, - struct weston_surface, link); - if (es->geometry.x != output->base.x || es->geometry.y != output->base.y || es->geometry.width != output->base.current->width || @@ -285,8 +273,7 @@ drm_output_prepare_scanout_surface(struct drm_output *output) wl_signal_add(&output->next->buffer->resource.destroy_signal, &output->next->buffer_destroy_listener); - pixman_region32_fini(&es->damage); - pixman_region32_init(&es->damage); + es->plane = WESTON_PLANE_DRM_FB; return 0; } @@ -307,7 +294,8 @@ drm_output_render(struct drm_output *output, pixman_region32_t *damage) } wl_list_for_each_reverse(surface, &compositor->base.surface_list, link) - weston_surface_draw(surface, &output->base, damage); + if (surface->plane == WESTON_PLANE_PRIMARY) + weston_surface_draw(surface, &output->base, damage); wl_signal_emit(&output->base.frame_signal, output); @@ -337,7 +325,6 @@ drm_output_repaint(struct weston_output *output_base, struct drm_mode *mode; int ret = 0; - drm_output_prepare_scanout_surface(output); if (!output->next) drm_output_render(output, damage); if (!output->next) @@ -509,18 +496,6 @@ drm_surface_transform_supported(struct weston_surface *es) return 1; } -static int -drm_surface_overlap_supported(struct weston_output *output_base, - pixman_region32_t *overlap) -{ - /* We could potentially use a color key here if the surface left - * to display has rectangular regions - */ - if (pixman_region32_not_empty(overlap)) - return 0; - return 1; -} - static void drm_disable_unused_sprites(struct weston_output *output_base) { @@ -560,8 +535,7 @@ drm_disable_unused_sprites(struct weston_output *output_base) */ static int drm_output_prepare_overlay_surface(struct weston_output *output_base, - struct weston_surface *es, - pixman_region32_t *overlap) + struct weston_surface *es) { struct weston_compositor *ec = output_base->compositor; struct drm_compositor *c =(struct drm_compositor *) ec; @@ -583,18 +557,12 @@ drm_output_prepare_overlay_surface(struct weston_output *output_base, if (es->output_mask != (1u << output_base->id)) return -1; - if (surface_is_primary(ec, es)) - return -1; - if (es->buffer == NULL) return -1; if (!drm_surface_transform_supported(es)) return -1; - if (!drm_surface_overlap_supported(output_base, overlap)) - return -1; - wl_list_for_each(s, &c->sprite_list, link) { if (!drm_sprite_crtc_supported(output_base, s->possible_crtcs)) continue; @@ -639,14 +607,6 @@ drm_output_prepare_overlay_surface(struct weston_output *output_base, return -1; } - if (s->surface && s->surface != es) { - struct weston_surface *old_surf = s->surface; - pixman_region32_fini(&old_surf->damage); - pixman_region32_init_rect(&old_surf->damage, - old_surf->geometry.x, old_surf->geometry.y, - old_surf->geometry.width, old_surf->geometry.height); - } - s->pending_fb_id = fb_id; s->pending_surface = es; es->buffer->busy_count++; @@ -696,6 +656,8 @@ drm_output_prepare_overlay_surface(struct weston_output *output_base, s->src_h = (sy2 - sy1) << 8; pixman_region32_fini(&src_rect); + es->plane = WESTON_PLANE_DRM_PLANE; + wl_signal_add(&es->buffer->resource.destroy_signal, &s->pending_destroy_listener); @@ -708,8 +670,7 @@ drm_output_set_cursor(struct weston_output *output_base, static void weston_output_set_cursor(struct weston_output *output, - struct weston_seat *seat, - pixman_region32_t *overlap) + struct weston_seat *seat) { pixman_region32_t cursor_region; @@ -721,26 +682,10 @@ weston_output_set_cursor(struct weston_output *output, &seat->sprite->transform.boundingbox, &output->region); - if (!pixman_region32_not_empty(&cursor_region)) { - drm_output_set_cursor(output, NULL); - goto out; - } - - if (pixman_region32_not_empty(overlap) || - drm_output_set_cursor(output, seat) < 0) { - if (seat->sprite->plane == WESTON_PLANE_DRM_CURSOR) { - weston_surface_damage(seat->sprite); - drm_output_set_cursor(output, NULL); - } - seat->sprite->plane = WESTON_PLANE_PRIMARY; - } else { - if (seat->sprite->plane == WESTON_PLANE_PRIMARY) - weston_surface_damage_below(seat->sprite); - wl_list_remove(&seat->sprite->link); + if (pixman_region32_not_empty(&cursor_region) && + drm_output_set_cursor(output, seat) == 0) seat->sprite->plane = WESTON_PLANE_DRM_CURSOR; - } -out: pixman_region32_fini(&cursor_region); } @@ -751,6 +696,7 @@ drm_assign_planes(struct weston_output *output) struct weston_surface *es, *next; pixman_region32_t overlap, surface_overlap; struct weston_seat *seat; + int prev_plane; /* * Find a surface for each sprite in the output using some heuristics: @@ -776,26 +722,36 @@ drm_assign_planes(struct weston_output *output) pixman_region32_intersect(&surface_overlap, &overlap, &es->transform.boundingbox); - if (es == seat->sprite) { - weston_output_set_cursor(output, seat, - &surface_overlap); - - if (seat->sprite->plane == WESTON_PLANE_PRIMARY) - pixman_region32_union(&overlap, &overlap, - &es->transform.boundingbox); - } else if (!drm_output_prepare_overlay_surface(output, es, - &surface_overlap)) { - pixman_region32_fini(&es->damage); - pixman_region32_init(&es->damage); - } else { + prev_plane = es->plane; + es->plane = WESTON_PLANE_PRIMARY; + if (pixman_region32_not_empty(&surface_overlap)) + goto bail; + + if (es == seat->sprite) + weston_output_set_cursor(output, seat); + + if (es->plane == WESTON_PLANE_PRIMARY) + drm_output_prepare_scanout_surface(output, es); + if (es->plane == WESTON_PLANE_PRIMARY) + drm_output_prepare_overlay_surface(output, es); + + bail: + if (es->plane == WESTON_PLANE_PRIMARY) pixman_region32_union(&overlap, &overlap, &es->transform.boundingbox); - } + + if (prev_plane != WESTON_PLANE_PRIMARY && + es->plane == WESTON_PLANE_PRIMARY) + weston_surface_damage(es); + else if (prev_plane == WESTON_PLANE_PRIMARY && + es->plane != WESTON_PLANE_PRIMARY) + weston_surface_damage_below(es); + pixman_region32_fini(&surface_overlap); } pixman_region32_fini(&overlap); - if (!seat->sprite || !weston_surface_is_mapped(seat->sprite)) + if (!seat->sprite || seat->sprite->plane == WESTON_PLANE_PRIMARY) drm_output_set_cursor(output, NULL); drm_disable_unused_sprites(output);