compositor: Track opaque region of a surface
diff --git a/compositor/compositor.c b/compositor/compositor.c
index a6dc025..e6dba98 100644
--- a/compositor/compositor.c
+++ b/compositor/compositor.c
@@ -255,6 +255,7 @@
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_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 @@
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 @@
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 @@
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 @@
{
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 @@
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 e2cf9ef..5c5e40c 100644
--- a/compositor/compositor.h
+++ b/compositor/compositor.h
@@ -238,6 +238,7 @@
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;
@@ -320,6 +321,10 @@
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);
void
diff --git a/compositor/shell.c b/compositor/shell.c
index b1e780c..91af256 100644
--- a/compositor/shell.c
+++ b/compositor/shell.c
@@ -46,11 +46,8 @@
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