summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKristian Høgsberg <krh@bitplanet.net>2011-05-16 09:37:15 -0400
committerKristian Høgsberg <krh@bitplanet.net>2011-05-16 09:37:15 -0400
commit81006c69a479e65eee1e89c9a5d8cc8ec67fd531 (patch)
tree547b981ba6cd73e803dc30f2f8c99c59164b7d53
parent8f386ce1621247a3dfa8829a3c180f7a37aa0e8d (diff)
compositor: Clip out damage obscured by opaque surfacessurface-damage
-rw-r--r--compositor/compositor.c153
-rw-r--r--compositor/compositor.h6
2 files changed, 98 insertions, 61 deletions
diff --git a/compositor/compositor.c b/compositor/compositor.c
index 00ffc91b..398de5ed 100644
--- a/compositor/compositor.c
+++ b/compositor/compositor.c
@@ -181,6 +181,9 @@ wlsc_surface_create(struct wlsc_compositor *compositor,
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ pixman_region32_init(&surface->damage);
+ pixman_region32_init(&surface->lower_damage);
+
surface->compositor = compositor;
surface->visual = NULL;
surface->image = EGL_NO_IMAGE_KHR;
@@ -202,8 +205,8 @@ wlsc_surface_damage_rectangle(struct wlsc_surface *surface,
{
struct wlsc_compositor *compositor = surface->compositor;
- pixman_region32_union_rect(&compositor->damage_region,
- &compositor->damage_region,
+ pixman_region32_union_rect(&surface->damage,
+ &surface->damage,
surface->x + x, surface->y + y,
width, height);
wlsc_compositor_schedule_repaint(compositor);
@@ -216,6 +219,15 @@ wlsc_surface_damage(struct wlsc_surface *surface)
surface->width, surface->height);
}
+WL_EXPORT void
+wlsc_surface_damage_below(struct wlsc_surface *surface)
+{
+ pixman_region32_union_rect(&surface->lower_damage,
+ &surface->lower_damage,
+ 0, 0, surface->width, surface->height);
+ wlsc_compositor_schedule_repaint(surface->compositor);
+}
+
WL_EXPORT uint32_t
wlsc_compositor_get_time(void)
{
@@ -233,7 +245,7 @@ destroy_surface(struct wl_resource *resource, struct wl_client *client)
container_of(resource, struct wlsc_surface, surface.resource);
struct wlsc_compositor *compositor = surface->compositor;
- wlsc_surface_damage(surface);
+ wlsc_surface_damage_below(surface);
wl_list_remove(&surface->link);
if (surface->saved_texture == 0)
@@ -433,6 +445,13 @@ texture_region(struct wlsc_surface *es, pixman_region32_t *region)
inv_height = 1.0 / es->height;
for (i = 0; i < n; i++, v += 16, p += 6) {
+ fprintf(stderr, "texture rect: %d,%d-%d,%d (%dx%d)\n",
+ rectangles[i].x1, rectangles[i].y1,
+ rectangles[i].x2, rectangles[i].y2,
+
+ rectangles[i].x2 - rectangles[i].x1,
+ rectangles[i].y2 - rectangles[i].y1);
+
v[ 0] = rectangles[i].x1;
v[ 1] = rectangles[i].y1;
v[ 2] = (GLfloat) (rectangles[i].x1 - es->x) * inv_width;
@@ -514,15 +533,21 @@ wlsc_surface_draw(struct wlsc_surface *es,
struct wlsc_output *output, pixman_region32_t *clip)
{
struct wlsc_compositor *ec = es->compositor;
- GLfloat *v;
pixman_region32_t repaint;
+ GLfloat *v;
int n;
pixman_region32_init_rect(&repaint,
es->x, es->y, es->width, es->height);
pixman_region32_intersect(&repaint, &repaint, clip);
- if (!pixman_region32_not_empty(&repaint))
+ pixman_region32_intersect(&repaint, &repaint, &output->region);
+
+ if (!pixman_region32_not_empty(&repaint)) {
+ pixman_region32_fini(&repaint);
return;
+ }
+
+ fprintf(stderr, "draw surface %p\n", es);
if (es->visual == &ec->compositor.argb_visual) {
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
@@ -549,6 +574,7 @@ wlsc_surface_draw(struct wlsc_surface *es,
ec->vertices.size = 0;
ec->indices.size = 0;
+
pixman_region32_fini(&repaint);
}
@@ -599,8 +625,8 @@ wlsc_output_damage(struct wlsc_output *output)
{
struct wlsc_compositor *compositor = output->compositor;
- pixman_region32_union_rect(&compositor->damage_region,
- &compositor->damage_region,
+ pixman_region32_union_rect(&compositor->pending_damage,
+ &compositor->pending_damage,
output->x, output->y,
output->width, output->height);
wlsc_compositor_schedule_repaint(compositor);
@@ -659,12 +685,50 @@ fade_output(struct wlsc_output *output,
}
static void
+push_down_damage(struct wlsc_compositor *ec)
+{
+ struct wlsc_surface *es;
+
+ wl_list_for_each(es, &ec->surface_list, link) {
+ pixman_region32_union(&es->damage, &es->damage,
+ &ec->pending_damage);
+ pixman_region32_union(&ec->pending_damage,
+ &ec->pending_damage,
+ &es->lower_damage);
+ pixman_region32_fini(&es->lower_damage);
+ pixman_region32_init(&es->lower_damage);
+ }
+ pixman_region32_fini(&ec->pending_damage);
+ pixman_region32_init(&ec->pending_damage);
+}
+
+static void
+clip_surface_damage(struct wlsc_compositor *ec)
+{
+ struct wlsc_surface *es;
+ pixman_region32_t opaque, visible;
+
+ pixman_region32_init(&opaque);
+ wl_list_for_each(es, &ec->surface_list, link) {
+ pixman_region32_init_rect(&visible,
+ es->x, es->y, es->width, es->height);
+ pixman_region32_subtract(&visible, &visible, &opaque);
+ pixman_region32_intersect(&es->damage, &es->damage, &visible);
+
+ if (es->visual == &ec->compositor.rgb_visual)
+ pixman_region32_union(&opaque, &opaque, &visible);
+ pixman_region32_fini(&visible);
+ }
+ pixman_region32_fini(&opaque);
+}
+
+static void
wlsc_output_repaint(struct wlsc_output *output)
{
struct wlsc_compositor *ec = output->compositor;
struct wlsc_surface *es;
struct wlsc_input_device *eid, *hw_cursor;
- pixman_region32_t new_damage, total_damage;
+ pixman_region32_t damage;
output->prepare_render(output);
@@ -675,18 +739,6 @@ wlsc_output_repaint(struct wlsc_output *output)
1, GL_FALSE, output->matrix.d);
glUniform1i(ec->texture_shader.tex_uniform, 0);
- pixman_region32_init(&new_damage);
- pixman_region32_init(&total_damage);
- pixman_region32_intersect_rect(&new_damage,
- &ec->damage_region,
- output->x, output->y,
- output->width, output->height);
- pixman_region32_subtract(&ec->damage_region,
- &ec->damage_region, &new_damage);
- pixman_region32_union(&total_damage, &new_damage,
- &output->previous_damage_region);
- pixman_region32_copy(&output->previous_damage_region, &new_damage);
-
hw_cursor = NULL;
if (ec->focus && ec->fade.spring.current < 0.001) {
hw_cursor = (struct wlsc_input_device *) ec->input_device;
@@ -699,50 +751,31 @@ wlsc_output_repaint(struct wlsc_output *output)
es = container_of(ec->surface_list.next, struct wlsc_surface, link);
if (es->visual == &ec->compositor.rgb_visual && hw_cursor) {
- if (output->prepare_scanout_surface(output, es) == 0) {
- /* We're drawing nothing now,
- * draw the damaged regions later. */
- pixman_region32_union(&ec->damage_region,
- &ec->damage_region,
- &total_damage);
+ if (output->prepare_scanout_surface(output, es) == 0)
return;
- }
}
- if (es->fullscreen_output == output) {
- if (es->width < output->width ||
- es->height < output->height)
- glClear(GL_COLOR_BUFFER_BIT);
- wlsc_surface_draw(es, output, &total_damage);
- } else {
- if (output->background)
- wlsc_surface_draw(output->background,
- output, &total_damage);
- else
- fade_output(output, 1.0, &total_damage);
-
- glUseProgram(ec->texture_shader.program);
- wl_list_for_each_reverse(es, &ec->surface_list, link) {
- if (ec->overlay == es)
- continue;
+ glUseProgram(ec->texture_shader.program);
+ pixman_region32_init(&damage);
+ wl_list_for_each_reverse(es, &ec->surface_list, link) {
+ pixman_region32_union(&damage, &damage, &es->damage);
+ pixman_region32_subtract(&es->damage,
+ &es->damage, &output->region);
- wlsc_surface_draw(es, output, &total_damage);
- }
+ wlsc_surface_draw(es, output, &damage);
}
-
- if (ec->overlay)
- wlsc_surface_draw(ec->overlay, output, &total_damage);
+ pixman_region32_fini(&damage);
if (ec->focus)
wl_list_for_each(eid, &ec->input_device_list, link) {
if (&eid->input_device != ec->input_device ||
eid != hw_cursor)
wlsc_surface_draw(eid->sprite, output,
- &total_damage);
+ &output->region);
}
if (ec->fade.spring.current > 0.001)
- fade_output(output, ec->fade.spring.current, &total_damage);
+ fade_output(output, ec->fade.spring.current, &damage);
}
static int
@@ -751,6 +784,9 @@ repaint(void *data)
struct wlsc_compositor *ec = data;
struct wlsc_output *output;
int repainted_all_outputs = 1;
+
+ push_down_damage(ec);
+ clip_surface_damage(ec);
wl_list_for_each(output, &ec->output_list, link) {
if (!output->repaint_needed)
@@ -858,7 +894,7 @@ surface_attach(struct wl_client *client,
* 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. */
- wlsc_surface_damage(es);
+ wlsc_surface_damage_below(es);
switch (es->map_type) {
case WLSC_SURFACE_MAP_FULLSCREEN:
@@ -996,7 +1032,7 @@ static void
wlsc_input_device_attach(struct wlsc_input_device *device,
int x, int y, int width, int height)
{
- wlsc_surface_damage(device->sprite);
+ wlsc_surface_damage_below(device->sprite);
device->hotspot_x = x;
device->hotspot_y = y;
@@ -1235,7 +1271,7 @@ notify_motion(struct wl_input_device *device, uint32_t time, int x, int y)
time, x, y, sx, sy);
}
- wlsc_surface_damage(wd->sprite);
+ wlsc_surface_damage_below(wd->sprite);
wd->sprite->x = device->x - wd->hotspot_x;
wd->sprite->y = device->y - wd->hotspot_y;
@@ -1695,8 +1731,6 @@ wlsc_output_move(struct wlsc_output *output, int x, int y)
output->background->y = y;
}
- pixman_region32_init(&output->previous_damage_region);
-
wlsc_matrix_init(&output->matrix);
wlsc_matrix_translate(&output->matrix,
-output->x - output->width / 2.0,
@@ -1707,9 +1741,10 @@ wlsc_output_move(struct wlsc_output *output, int x, int y)
2.0 / output->width,
flip * 2.0 / output->height, 1);
- pixman_region32_union_rect(&c->damage_region,
- &c->damage_region,
- x, y, output->width, output->height);
+ pixman_region32_init_rect(&output->region,
+ x, y, output->width, output->height);
+ pixman_region32_union(&c->pending_damage,
+ &c->pending_damage, &output->region);
}
WL_EXPORT void
@@ -1859,7 +1894,7 @@ wlsc_compositor_init(struct wlsc_compositor *ec, struct wl_display *display)
wl_event_source_timer_update(ec->idle_source, option_idle_time * 1000);
ec->timer_source = wl_event_loop_add_timer(loop, repaint, ec);
- pixman_region32_init(&ec->damage_region);
+ pixman_region32_init(&ec->pending_damage);
wlsc_compositor_schedule_repaint(ec);
return 0;
diff --git a/compositor/compositor.h b/compositor/compositor.h
index 2546d58f..61ece260 100644
--- a/compositor/compositor.h
+++ b/compositor/compositor.h
@@ -59,8 +59,8 @@ struct wlsc_output {
struct wlsc_compositor *compositor;
struct wlsc_surface *background;
struct wlsc_matrix matrix;
+ pixman_region32_t region;
int32_t x, y, width, height;
- pixman_region32_t previous_damage_region;
uint32_t flags;
int repaint_needed;
int finished;
@@ -178,7 +178,7 @@ struct wlsc_compositor {
struct wl_event_source *timer_source;
int repaint_on_timeout;
struct timespec previous_swap;
- pixman_region32_t damage_region;
+ pixman_region32_t pending_damage;
struct wl_array vertices, indices;
struct wlsc_surface *overlay;
@@ -223,6 +223,8 @@ struct wlsc_surface {
struct wl_surface surface;
struct wlsc_compositor *compositor;
GLuint texture, saved_texture;
+ pixman_region32_t damage;
+ pixman_region32_t lower_damage;
int32_t x, y, width, height;
int32_t pitch;
int32_t saved_x, saved_y;