compositor: Track opaque region of a surface

dev
Kristian Høgsberg 13 years ago
parent aee7f84347
commit a691aeefd7
  1. 58
      compositor/compositor.c
  2. 5
      compositor/compositor.h
  3. 7
      compositor/shell.c

@ -255,6 +255,7 @@ wlsc_surface_create(struct wlsc_compositor *compositor,
surface->buffer = NULL; surface->buffer = NULL;
pixman_region32_init(&surface->damage); pixman_region32_init(&surface->damage);
pixman_region32_init(&surface->opaque);
surface->buffer_destroy_listener.func = surface_handle_buffer_destroy; surface->buffer_destroy_listener.func = surface_handle_buffer_destroy;
wl_list_init(&surface->buffer_destroy_listener.link); 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); 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 WL_EXPORT uint32_t
wlsc_compositor_get_time(void) wlsc_compositor_get_time(void)
{ {
@ -751,7 +777,7 @@ wlsc_output_repaint(struct wlsc_output *output)
struct wlsc_compositor *ec = output->compositor; struct wlsc_compositor *ec = output->compositor;
struct wlsc_surface *es; struct wlsc_surface *es;
struct wlsc_input_device *device; 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); output->prepare_render(output);
@ -769,11 +795,7 @@ wlsc_output_repaint(struct wlsc_output *output)
wl_list_for_each(es, &ec->surface_list, link) { wl_list_for_each(es, &ec->surface_list, link) {
pixman_region32_intersect(&es->damage, &es->damage, &clip); pixman_region32_intersect(&es->damage, &es->damage, &clip);
pixman_region32_union(&new_damage, &new_damage, &es->damage); pixman_region32_union(&new_damage, &new_damage, &es->damage);
if (es->visual == &ec->compositor.rgb_visual) { pixman_region32_subtract(&clip, &clip, &es->opaque);
pixman_region32_init_rect(&region, es->x, es->y, es->width, es->height);
pixman_region32_subtract(&clip, &clip, &region);
pixman_region32_fini(&region);
}
} }
pixman_region32_subtract(&ec->damage, &ec->damage, &output->region); 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); glClear(GL_COLOR_BUFFER_BIT);
wlsc_surface_draw(es, output, &total_damage); wlsc_surface_draw(es, output, &total_damage);
} else { } else {
pixman_region32_init(&opaque);
wl_list_for_each(es, &ec->surface_list, link) { wl_list_for_each(es, &ec->surface_list, link) {
pixman_region32_subtract(&es->damage, &total_damage, &opaque); pixman_region32_copy(&es->damage, &total_damage);
if (es->visual == &ec->compositor.rgb_visual) pixman_region32_subtract(&total_damage, &total_damage, &es->opaque);
pixman_region32_union_rect(&opaque, &opaque,
es->x, es->y, es->width, es->height);
} }
pixman_region32_fini(&opaque);
wl_list_for_each_reverse(es, &ec->surface_list, link) { wl_list_for_each_reverse(es, &ec->surface_list, link) {
wlsc_surface_draw(es, output, &es->damage); 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; 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++; buffer->busy_count++;
wlsc_buffer_post_release(es->buffer); 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, wl_list_insert(es->buffer->resource.destroy_listener_list.prev,
&es->buffer_destroy_listener.link); &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) if (es->visual == NULL)
wl_list_insert(&es->compositor->surface_list, &es->link); 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); wlsc_buffer_attach(buffer, surface);
es->compositor->shell->attach(es->compositor->shell, es); es->compositor->shell->attach(es->compositor->shell, es);

@ -238,6 +238,7 @@ struct wlsc_surface {
struct wlsc_compositor *compositor; struct wlsc_compositor *compositor;
GLuint texture, saved_texture; GLuint texture, saved_texture;
pixman_region32_t damage; pixman_region32_t damage;
pixman_region32_t opaque;
int32_t x, y, width, height; int32_t x, y, width, height;
int32_t pitch; int32_t pitch;
int32_t saved_x, saved_y; int32_t saved_x, saved_y;
@ -319,6 +320,10 @@ struct wlsc_surface *
wlsc_surface_create(struct wlsc_compositor *compositor, wlsc_surface_create(struct wlsc_compositor *compositor,
int32_t x, int32_t y, int32_t width, int32_t height); 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 void
wlsc_surface_assign_output(struct wlsc_surface *surface); wlsc_surface_assign_output(struct wlsc_surface *surface);

@ -46,11 +46,8 @@ move_grab_motion(struct wl_grab *grab,
struct wlsc_move_grab *move = (struct wlsc_move_grab *) grab; struct wlsc_move_grab *move = (struct wlsc_move_grab *) grab;
struct wlsc_surface *es = move->surface; struct wlsc_surface *es = move->surface;
wlsc_surface_damage_below(es); wlsc_surface_configure(es, x + move->dx, y + move->dy,
es->x = x + move->dx; es->width, es->height);
es->y = y + move->dy;
wlsc_surface_assign_output(es);
wlsc_surface_damage(es);
} }
static void static void

Loading…
Cancel
Save