From 5df8ecac5d31467122a9d8bda6241d5957ae6848 Mon Sep 17 00:00:00 2001 From: Ander Conselvan de Oliveira Date: Tue, 30 Oct 2012 17:44:01 +0200 Subject: [PATCH] compositor: Fix partial repaints Partial repaints have been broken since the introduction of the atomic surface updates. The problem was that surface_commit would set the geometry dirty flag unconditionally, causing transform updates on every frame which would in turn cause weston_surface_damage_below() to damage the whole surface area. This patch changes this so that flag is only set if the pending buffer has a different size, the location of the surface changed or the opaque region changed. Note that changing the opaque region will cause a full repaint of the affected surface, because of the transform update. https://bugs.freedesktop.org/show_bug.cgi?id=56538 --- src/compositor.c | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/src/compositor.c b/src/compositor.c index 3597cf7b..56474a5e 100644 --- a/src/compositor.c +++ b/src/compositor.c @@ -1234,6 +1234,13 @@ static void surface_commit(struct wl_client *client, struct wl_resource *resource) { struct weston_surface *surface = resource->data; + pixman_region32_t opaque; + + if (surface->pending.sx || surface->pending.sy || + (surface->pending.buffer && + (surface->pending.buffer->width != surface->geometry.width || + surface->pending.buffer->height != surface->geometry.height))) + surface->geometry.dirty = 1; /* wl_surface.attach */ if (surface->pending.buffer || surface->pending.remove_contents) @@ -1249,13 +1256,18 @@ surface_commit(struct wl_client *client, struct wl_resource *resource) empty_region(&surface->pending.damage); /* wl_surface.set_opaque_region */ - pixman_region32_fini(&surface->opaque); - pixman_region32_init_rect(&surface->opaque, 0, 0, + pixman_region32_init_rect(&opaque, 0, 0, surface->geometry.width, surface->geometry.height); - pixman_region32_intersect(&surface->opaque, - &surface->opaque, &surface->pending.opaque); - surface->geometry.dirty = 1; + pixman_region32_intersect(&opaque, + &opaque, &surface->pending.opaque); + + if (!pixman_region32_equal(&opaque, &surface->opaque)) { + pixman_region32_copy(&surface->opaque, &opaque); + surface->geometry.dirty = 1; + } + + pixman_region32_fini(&opaque); /* wl_surface.set_input_region */ pixman_region32_fini(&surface->input);