From a691aeefd7f4bed97e60543723fa9b76888fbce3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Thu, 23 Jun 2011 21:43:50 -0400 Subject: [PATCH] compositor: Track opaque region of a surface --- compositor/compositor.c | 58 +++++++++++++++++++++++------------------ compositor/compositor.h | 5 ++++ compositor/shell.c | 7 ++--- 3 files changed, 40 insertions(+), 30 deletions(-) diff --git a/compositor/compositor.c b/compositor/compositor.c index a6dc025d..e6dba982 100644 --- a/compositor/compositor.c +++ b/compositor/compositor.c @@ -255,6 +255,7 @@ wlsc_surface_create(struct wlsc_compositor *compositor, surface->buffer = NULL; pixman_region32_init(&surface->damage); + pixman_region32_init(&surface->opaque); surface->buffer_destroy_listener.func = surface_handle_buffer_destroy; wl_list_init(&surface->buffer_destroy_listener.link); @@ -302,6 +303,31 @@ wlsc_surface_damage_below(struct wlsc_surface *surface) wlsc_compositor_schedule_repaint(surface->compositor); } +WL_EXPORT void +wlsc_surface_configure(struct wlsc_surface *surface, + int x, int y, int width, int height) +{ + struct wlsc_compositor *compositor = surface->compositor; + + wlsc_surface_damage_below(surface); + + surface->x = x; + surface->y = y; + surface->width = width; + surface->height = height; + + wlsc_surface_assign_output(surface); + wlsc_surface_damage(surface); + + pixman_region32_fini(&surface->opaque); + if (surface->visual == &compositor->compositor.rgb_visual) + pixman_region32_init_rect(&surface->opaque, + surface->x, surface->y, + surface->width, surface->height); + else + pixman_region32_init(&surface->opaque); +} + WL_EXPORT uint32_t wlsc_compositor_get_time(void) { @@ -751,7 +777,7 @@ wlsc_output_repaint(struct wlsc_output *output) struct wlsc_compositor *ec = output->compositor; struct wlsc_surface *es; struct wlsc_input_device *device; - pixman_region32_t clip, new_damage, total_damage, region, opaque; + pixman_region32_t clip, new_damage, total_damage; output->prepare_render(output); @@ -769,11 +795,7 @@ wlsc_output_repaint(struct wlsc_output *output) wl_list_for_each(es, &ec->surface_list, link) { pixman_region32_intersect(&es->damage, &es->damage, &clip); pixman_region32_union(&new_damage, &new_damage, &es->damage); - if (es->visual == &ec->compositor.rgb_visual) { - pixman_region32_init_rect(®ion, es->x, es->y, es->width, es->height); - pixman_region32_subtract(&clip, &clip, ®ion); - pixman_region32_fini(®ion); - } + pixman_region32_subtract(&clip, &clip, &es->opaque); } pixman_region32_subtract(&ec->damage, &ec->damage, &output->region); @@ -825,14 +847,10 @@ wlsc_output_repaint(struct wlsc_output *output) glClear(GL_COLOR_BUFFER_BIT); wlsc_surface_draw(es, output, &total_damage); } else { - pixman_region32_init(&opaque); wl_list_for_each(es, &ec->surface_list, link) { - pixman_region32_subtract(&es->damage, &total_damage, &opaque); - if (es->visual == &ec->compositor.rgb_visual) - pixman_region32_union_rect(&opaque, &opaque, - es->x, es->y, es->width, es->height); + pixman_region32_copy(&es->damage, &total_damage); + pixman_region32_subtract(&total_damage, &total_damage, &es->opaque); } - pixman_region32_fini(&opaque); wl_list_for_each_reverse(es, &ec->surface_list, link) { wlsc_surface_draw(es, output, &es->damage); @@ -969,13 +987,6 @@ surface_attach(struct wl_client *client, { struct wlsc_surface *es = (struct wlsc_surface *) surface; - /* FIXME: This damages the entire old surface, but we should - * really just damage the part that's no longer covered by the - * surface. Anything covered by the new surface will be - * damaged by the client. */ - if (es->buffer) - wlsc_surface_damage_below(es); - buffer->busy_count++; wlsc_buffer_post_release(es->buffer); @@ -984,15 +995,12 @@ surface_attach(struct wl_client *client, wl_list_insert(es->buffer->resource.destroy_listener_list.prev, &es->buffer_destroy_listener.link); - es->x += x; - es->y += y; - es->width = buffer->width; - es->height = buffer->height; - if (x != 0 || y != 0) - wlsc_surface_assign_output(es); if (es->visual == NULL) wl_list_insert(&es->compositor->surface_list, &es->link); + wlsc_surface_configure(es, es->x + x, es->y + y, + buffer->width, buffer->height); + wlsc_buffer_attach(buffer, surface); es->compositor->shell->attach(es->compositor->shell, es); diff --git a/compositor/compositor.h b/compositor/compositor.h index e2cf9efc..5c5e40cd 100644 --- a/compositor/compositor.h +++ b/compositor/compositor.h @@ -238,6 +238,7 @@ struct wlsc_surface { struct wlsc_compositor *compositor; GLuint texture, saved_texture; pixman_region32_t damage; + pixman_region32_t opaque; int32_t x, y, width, height; int32_t pitch; int32_t saved_x, saved_y; @@ -319,6 +320,10 @@ struct wlsc_surface * wlsc_surface_create(struct wlsc_compositor *compositor, int32_t x, int32_t y, int32_t width, int32_t height); +void +wlsc_surface_configure(struct wlsc_surface *surface, + int x, int y, int width, int height); + void wlsc_surface_assign_output(struct wlsc_surface *surface); diff --git a/compositor/shell.c b/compositor/shell.c index b1e780cd..91af2568 100644 --- a/compositor/shell.c +++ b/compositor/shell.c @@ -46,11 +46,8 @@ move_grab_motion(struct wl_grab *grab, struct wlsc_move_grab *move = (struct wlsc_move_grab *) grab; struct wlsc_surface *es = move->surface; - wlsc_surface_damage_below(es); - es->x = x + move->dx; - es->y = y + move->dy; - wlsc_surface_assign_output(es); - wlsc_surface_damage(es); + wlsc_surface_configure(es, x + move->dx, y + move->dy, + es->width, es->height); } static void