From a25d1be9f9b6c2a4a9373cf6a2c747d507206a18 Mon Sep 17 00:00:00 2001 From: Taekyun Kim Date: Tue, 23 Jun 2015 14:35:58 +0900 Subject: [PATCH] pepper: Accumulate output damage and automatically schedule repaint. Damage is maintained per output and is passed to the repaint function. Damage region is in output local coordinate space so an output backend should be careful not to translate it to global compositor space. No damage, we have nothing to repaint. So, we can safely schedule repaint whenever damage is generated. Essentially, we don't have to expose repaint scheduling APIs. Change-Id: Iebff5fec5f93d764a8ea8894b7f84c8ded9c59c3 --- pepper/src/compositor.c | 21 +++++++++++-- pepper/src/output.c | 70 +++++++++++++++++++++++++++++++++++++------- pepper/src/pepper-internal.h | 12 +++++++- pepper/src/pepper.h | 9 +++++- pepper/src/surface.c | 2 +- x11/src/x11-common.c | 6 +++- 6 files changed, 104 insertions(+), 16 deletions(-) diff --git a/pepper/src/compositor.c b/pepper/src/compositor.c index f1a6358..6c7750a 100644 --- a/pepper/src/compositor.c +++ b/pepper/src/compositor.c @@ -137,8 +137,25 @@ pepper_compositor_get_display(pepper_object_t *cmp) } void -pepper_compositor_add_damage(pepper_compositor_t *compositor, pixman_region32_t *region) +pepper_compositor_add_damage(pepper_compositor_t *compositor, const pixman_region32_t *region) { + pepper_output_t *output; + CHECK_MAGIC_AND_NON_NULL(&compositor->base, PEPPER_COMPOSITOR); - pixman_region32_union(&compositor->damage_region, &compositor->damage_region, region); + + wl_list_for_each(output, &compositor->output_list, link) + { + pepper_output_add_damage(&output->base, region, output->geometry.x, output->geometry.y); + } +} + +void +pepper_compositor_add_damage_rect(pepper_compositor_t *compositor, + int x, int y, unsigned int w, unsigned int h) +{ + pixman_region32_t region; + + pixman_region32_init_rect(®ion, x, y, w, h); + pepper_compositor_add_damage(compositor, ®ion); + pixman_region32_fini(®ion); } diff --git a/pepper/src/output.c b/pepper/src/output.c index 80daa5e..c4e942c 100644 --- a/pepper/src/output.c +++ b/pepper/src/output.c @@ -148,13 +148,10 @@ idle_repaint(void *data) } } -PEPPER_API void -pepper_output_schedule_repaint(pepper_object_t *out) +void +pepper_output_schedule_repaint(pepper_output_t *output) { struct wl_event_loop *loop; - pepper_output_t *output = (pepper_output_t *)out; - - CHECK_MAGIC_AND_NON_NULL(out, PEPPER_OUTPUT); if (output->frame.scheduled) return; @@ -235,8 +232,7 @@ pepper_compositor_add_output(pepper_object_t *cmp, output->frame.frame_listener.notify = handle_output_frame; interface->add_frame_listener(data, &output->frame.frame_listener); - pepper_output_schedule_repaint(&output->base); - + pepper_output_add_damage_whole(&output->base); return &output->base; } @@ -281,8 +277,7 @@ pepper_output_move(pepper_object_t *out, int32_t x, int32_t y) output->geometry.x = x; output->geometry.y = y; - /* TODO: Repaint. */ - + pepper_output_add_damage_whole(out); output_send_geometry(output); } } @@ -332,5 +327,60 @@ pepper_output_set_mode(pepper_object_t *out, const pepper_output_mode_t *mode) if (output->current_mode == mode) return PEPPER_TRUE; - return output->interface->set_mode(output->data, mode); + if (output->interface->set_mode(output->data, mode)) + { + pepper_output_add_damage_whole(out); + return PEPPER_TRUE; + } + + return PEPPER_FALSE; +} + +PEPPER_API void +pepper_output_add_damage(pepper_object_t *out, + const pixman_region32_t *region, int x, int y) +{ + pepper_output_t *output = (pepper_output_t *)out; + pixman_region32_t damage; + + CHECK_MAGIC_AND_NON_NULL(out, PEPPER_OUTPUT); + + pixman_region32_init(&damage); + pixman_region32_copy(&damage, (pixman_region32_t *)region); + pixman_region32_translate(&damage, x, y); + pixman_region32_intersect_rect(&damage, &damage, 0, 0, output->geometry.w, output->geometry.h); + + if (pixman_region32_not_empty(&damage)) + pixman_region32_union(&output->damage_region, &output->damage_region, &damage); + + pixman_region32_fini(&damage); + pepper_output_schedule_repaint(output); +} + +PEPPER_API void +pepper_output_add_damage_rect(pepper_object_t *out, int x, int y, unsigned int w, unsigned int h) +{ + pepper_output_t *output = (pepper_output_t *)out; + pixman_region32_t damage; + + CHECK_MAGIC_AND_NON_NULL(out, PEPPER_OUTPUT); + + pixman_region32_init_rect(&damage, x, y, w, h); + pixman_region32_intersect_rect(&damage, &damage, 0, 0, output->geometry.w, output->geometry.h); + + if (pixman_region32_not_empty(&damage)) + pixman_region32_union(&output->damage_region, &output->damage_region, &damage); + + pixman_region32_fini(&damage); + pepper_output_schedule_repaint(output); +} + +PEPPER_API void +pepper_output_add_damage_whole(pepper_object_t *out) +{ + pepper_output_t *output = (pepper_output_t *)out; + + CHECK_MAGIC_AND_NON_NULL(out, PEPPER_OUTPUT); + pixman_region32_init_rect(&output->damage_region, 0, 0, output->geometry.w, output->geometry.h); + pepper_output_schedule_repaint(output); } diff --git a/pepper/src/pepper-internal.h b/pepper/src/pepper-internal.h index c546cac..71e39ec 100644 --- a/pepper/src/pepper-internal.h +++ b/pepper/src/pepper-internal.h @@ -128,9 +128,15 @@ struct pepper_output pepper_bool_t pending; struct wl_listener frame_listener; } frame; + + /* Region damaged but not repainted. */ + pixman_region32_t damage_region; }; void +pepper_output_schedule_repaint(pepper_output_t *output); + +void pepper_output_repaint(pepper_output_t *output); struct pepper_buffer @@ -369,7 +375,11 @@ pepper_compositor_event_handler(pepper_object_t *seat, void *data); void -pepper_compositor_add_damage(pepper_compositor_t *compositor, pixman_region32_t *region); +pepper_compositor_add_damage(pepper_compositor_t *compositor, const pixman_region32_t *region); + +void +pepper_compositor_add_damage_rect(pepper_compositor_t *compositor, + int x, int y, unsigned int w, unsigned int h); void pepper_surface_flush_damage(pepper_surface_t *surface); diff --git a/pepper/src/pepper.h b/pepper/src/pepper.h index 8395b3c..30a0662 100644 --- a/pepper/src/pepper.h +++ b/pepper/src/pepper.h @@ -156,7 +156,14 @@ PEPPER_API pepper_bool_t pepper_output_set_mode(pepper_object_t *output, const pepper_output_mode_t *mode); PEPPER_API void -pepper_output_schedule_repaint(pepper_object_t *output); +pepper_output_add_damage(pepper_object_t *output, + const pixman_region32_t *region, int x, int y); + +PEPPER_API void +pepper_output_add_damage_rect(pepper_object_t *output, int x, int y, unsigned int w, unsigned int h); + +PEPPER_API void +pepper_output_add_damage_whole(pepper_object_t *output); /* Input. */ struct pepper_seat_interface diff --git a/pepper/src/surface.c b/pepper/src/surface.c index f6c1f03..a02f13c 100644 --- a/pepper/src/surface.c +++ b/pepper/src/surface.c @@ -299,7 +299,7 @@ pepper_surface_schedule_repaint(pepper_surface_t *surface) /* FIXME: Find outputs to be repainted */ pepper_output_t *output; wl_list_for_each(output, &surface->compositor->output_list, link) - pepper_output_schedule_repaint(&output->base); + pepper_output_schedule_repaint(output); } static void diff --git a/x11/src/x11-common.c b/x11/src/x11-common.c index 7234836..1ac64ca 100644 --- a/x11/src/x11-common.c +++ b/x11/src/x11-common.c @@ -72,8 +72,12 @@ x11_handle_event(int fd, uint32_t mask, void *data) { xcb_expose_event_t *expose = (xcb_expose_event_t *)event; x11_output_t *output = x11_find_output_by_window(connection, expose->window); + if (output) - pepper_output_schedule_repaint(output->base); + { + /* TODO: Damage only newly exposed area. */ + pepper_output_add_damage_whole(output->base); + } } break; case XCB_FOCUS_IN: -- 2.7.4