pepper: Accumulate output damage and automatically schedule repaint.
authorTaekyun Kim <tkq.kim@samsung.com>
Tue, 23 Jun 2015 05:35:58 +0000 (14:35 +0900)
committerTaekyun Kim <tkq.kim@samsung.com>
Tue, 7 Jul 2015 06:56:51 +0000 (15:56 +0900)
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
pepper/src/output.c
pepper/src/pepper-internal.h
pepper/src/pepper.h
pepper/src/surface.c
x11/src/x11-common.c

index f1a6358..6c7750a 100644 (file)
@@ -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(&region, x, y, w, h);
+    pepper_compositor_add_damage(compositor, &region);
+    pixman_region32_fini(&region);
 }
index 80daa5e..c4e942c 100644 (file)
@@ -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);
 }
index c546cac..71e39ec 100644 (file)
@@ -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);
index 8395b3c..30a0662 100644 (file)
@@ -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
index f6c1f03..a02f13c 100644 (file)
@@ -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
index 7234836..1ac64ca 100644 (file)
@@ -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: