pepper: view damage processing and repaint scheduling
authorTaekyun Kim <tkq.kim@samsung.com>
Tue, 21 Jul 2015 12:16:38 +0000 (21:16 +0900)
committerTaekyun Kim <tkq.kim@samsung.com>
Wed, 22 Jul 2015 00:52:05 +0000 (09:52 +0900)
1. Schedule repaint on all outputs when a view is modified.

2. Each output update views in the compositor's view list.
   Updating the views will inflict damage on their belonging plane.

3. Each output gathers views visible on it.

4. Assign planes for the visible views.

5. Do repaint.

Change-Id: Ie3e05107a6b31908866eb90e4d4b3d37d5872fe8

src/lib/pepper/compositor.c
src/lib/pepper/output.c
src/lib/pepper/pepper-internal.h
src/lib/pepper/plane.c
src/lib/pepper/region.c
src/lib/pepper/surface.c
src/lib/pepper/view.c

index 834c52a..a5a6512 100644 (file)
@@ -46,6 +46,15 @@ compositor_bind(struct wl_client *client,
     wl_resource_set_implementation(resource, &compositor_interface, compositor, NULL);
 }
 
+void
+pepper_compositor_schedule_repaint(pepper_compositor_t *compositor)
+{
+    pepper_list_t   *l;
+
+    PEPPER_LIST_FOR_EACH(&compositor->output_list, l)
+        pepper_output_schedule_repaint((pepper_output_t *)l->item);
+}
+
 PEPPER_API pepper_compositor_t *
 pepper_compositor_create(const char *socket_name)
 {
index 808c28c..c66e83f 100644 (file)
@@ -151,7 +151,7 @@ output_repaint(pepper_output_t *output)
     pepper_list_t          *l;
 
     PEPPER_LIST_FOR_EACH(&output->compositor->view_list, l)
-        pepper_view_update_geometry((pepper_view_t *)l->item);
+        pepper_view_update((pepper_view_t *)l->item);
 
     pepper_list_init(&output->view_list);
 
@@ -160,7 +160,7 @@ output_repaint(pepper_output_t *output)
     {
         pepper_view_t *view = l->item;
 
-        if (!view->visibility || !(view->output_overlap & (1 << output->id)))
+        if (!view->visible || !(view->output_overlap & (1 << output->id)))
         {
             /* Detach from the previously assigned plane. */
             pepper_view_assign_plane(view, output, NULL);
index fae6383..7073b46 100644 (file)
@@ -42,6 +42,8 @@ struct pepper_compositor
     pepper_list_t       output_list;
     uint32_t            output_id_allocator;
     struct wl_list      event_hook_chain;
+
+    pepper_bool_t       update_scheduled;
     pepper_list_t       view_list;
 };
 
@@ -180,6 +182,9 @@ pepper_region_create(pepper_compositor_t *compositor,
 void
 pepper_region_destroy(pepper_region_t *region);
 
+void
+pepper_transform_pixman_region(pixman_region32_t *region, const pepper_mat4_t *matrix);
+
 /* Input */
 struct pepper_seat
 {
@@ -265,19 +270,27 @@ struct pepper_plane_entry
     pepper_list_t           link;
 };
 
+enum
+{
+    PEPPER_VIEW_VISIBILITY_DIRTY    = 0x00000001,
+    PEPPER_VIEW_GEOMETRY_DIRTY      = 0x00000002,
+    PEPPER_VIEW_Z_ORDER_DIRTY       = 0x00000004,
+};
+
 struct pepper_view
 {
     pepper_object_t         base;
     pepper_compositor_t    *compositor;
     pepper_list_t           compositor_link;
 
+    uint32_t                dirty;
+
     /* Hierarchy. */
     pepper_view_t          *parent;
     pepper_list_t           parent_link;
     pepper_list_t           children_list;
 
     /* Geometry. */
-    pepper_bool_t           geometry_dirty;
     double                  x, y;
     int                     w, h;
     pepper_mat4_t           transform;
@@ -287,7 +300,8 @@ struct pepper_view
     pixman_region32_t       opaque_region;
 
     /* Visibility. */
-    pepper_bool_t           visibility;
+    pepper_bool_t           visible;
+    pepper_bool_t           prev_visible;
     pepper_bool_t           mapped;
 
     /* Content. */
@@ -304,10 +318,10 @@ struct pepper_view
 };
 
 void
-pepper_view_damage_below(pepper_view_t *view);
+pepper_view_update(pepper_view_t *view);
 
 void
-pepper_view_update_geometry(pepper_view_t *view);
+pepper_view_surface_damage(pepper_view_t *view);
 
 struct pepper_plane
 {
index f2d7e4f..be01006 100644 (file)
@@ -51,7 +51,7 @@ pepper_plane_accumulate_damage(pepper_plane_t *plane, pixman_region32_t *clip)
 
         if (entry->need_damage)
         {
-            pepper_view_damage_below(view);
+            pepper_plane_add_damage_region(plane, &entry->base.visible_region);
             entry->need_damage = PEPPER_FALSE;
         }
     }
index 62458c9..fca1f10 100644 (file)
@@ -80,3 +80,56 @@ pepper_region_destroy(pepper_region_t *region)
     pixman_region32_fini(&region->pixman_region);
     pepper_free(region);
 }
+
+static inline void
+add_bbox_point(double *box, int x, int y, const pepper_mat4_t *matrix)
+{
+    pepper_vec2_t v = { x, y };
+
+    pepper_mat4_transform_vec2(matrix, &v);
+
+    box[0] = PEPPER_MIN(box[0], v.x);
+    box[1] = PEPPER_MIN(box[1], v.y);
+    box[2] = PEPPER_MAX(box[2], v.x);
+    box[3] = PEPPER_MAX(box[3], v.y);
+}
+
+static inline void
+transform_bounding_box(pixman_box32_t *box, const pepper_mat4_t *matrix)
+{
+    double          b[4] = { HUGE_VAL, HUGE_VAL, -HUGE_VAL, -HUGE_VAL };
+
+    add_bbox_point(b, box->x1, box->y1, matrix);
+    add_bbox_point(b, box->x2, box->y1, matrix);
+    add_bbox_point(b, box->x2, box->y2, matrix);
+    add_bbox_point(b, box->x1, box->y2, matrix);
+
+    box->x1 = floor(b[0]);
+    box->y1 = floor(b[1]);
+    box->x2 = ceil(b[2]);
+    box->y2 = ceil(b[3]);
+}
+
+void
+pepper_transform_pixman_region(pixman_region32_t *region, const pepper_mat4_t *matrix)
+
+{
+    pixman_region32_t   result;
+    pixman_box32_t     *rects;
+    int                 i, num_rects;
+
+    pixman_region32_init(&result);
+    rects = pixman_region32_rectangles(region, &num_rects);
+
+    for (i = 0; i < num_rects; i++)
+    {
+        pixman_box32_t box = rects[i];
+
+        transform_bounding_box(&box, matrix);
+        pixman_region32_union_rect(&result, &result,
+                                   box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1);
+    }
+
+    pixman_region32_copy(region, &result);
+    pixman_region32_fini(&result);
+}
index d123133..f31bb4b 100644 (file)
@@ -391,7 +391,7 @@ pepper_surface_commit(pepper_surface_t *surface)
     pixman_region32_copy(&surface->opaque_region, &surface->pending.opaque_region);
     pixman_region32_copy(&surface->input_region, &surface->pending.input_region);
 
-    pepper_surface_schedule_repaint(surface);
+    pepper_surface_flush_damage(surface);
 }
 
 void
@@ -474,5 +474,13 @@ pepper_surface_get_input_region(pepper_surface_t *surface)
 void
 pepper_surface_flush_damage(pepper_surface_t *surface)
 {
-    /* TODO: */
+    pepper_list_t *l;
+
+    if (!pixman_region32_not_empty(&surface->damage_region))
+        return;
+
+    PEPPER_LIST_FOR_EACH(&surface->view_list, l)
+        pepper_view_surface_damage((pepper_view_t *)l->item);
+
+    /* TODO: Call backend.urface_flush(). */
 }
index 32163f8..26214c5 100644 (file)
 #include <string.h>
 
 static void
-view_mark_plane_entries_damaged(pepper_view_t *view)
-{
-    int i;
-
-    for (i = 0; i < PEPPER_MAX_OUTPUT_COUNT; i++)
-        view->plane_entries[i].need_damage = PEPPER_TRUE;
-}
-
-static void
-view_handle_surface_destroy(struct wl_listener *listener, void *data)
-{
-    pepper_view_t *view = pepper_container_of(listener, pepper_view_t, surface_destroy_listener);
-    PEPPER_ASSERT(view->surface != NULL);
-    pepper_view_destroy(view);
-}
-
-static void
-view_geometry_dirty(pepper_view_t *view)
+view_mark_dirty(pepper_view_t *view, uint32_t flag)
 {
     pepper_list_t *l;
 
-    if (view->geometry_dirty)
+    if (view->dirty & flag)
         return;
 
-    view->geometry_dirty = PEPPER_TRUE;
-    pepper_view_damage_below(view);
-
-    PEPPER_LIST_FOR_EACH(&view->children_list, l)
-        view_geometry_dirty((pepper_view_t *)l->item);
-}
-
-static void
-view_update_visibility(pepper_view_t *view)
-{
-    pepper_bool_t visibility;
+    view->dirty |= flag;
 
-    if (view->parent)
-        visibility = view->parent->visibility && view->mapped;
-    else
-        visibility = view->mapped;
-
-    if (visibility != view->visibility)
+    if ((flag & PEPPER_VIEW_VISIBILITY_DIRTY) ||
+        (flag & PEPPER_VIEW_GEOMETRY_DIRTY))
     {
-        pepper_list_t *l;
-
-        view->visibility = visibility;
-
-        /* We simply treat a visibility change as a geometry change. */
-        view_geometry_dirty(view);
-
         PEPPER_LIST_FOR_EACH(&view->children_list, l)
-            view_update_visibility((pepper_view_t *)l->item);
+            view_mark_dirty((pepper_view_t *)l->item, flag);
     }
-}
 
-static void
-view_map(pepper_view_t *view)
-{
-    if (view->mapped)
-        return;
-
-    view->mapped = PEPPER_TRUE;
-    view_update_visibility(view);
+    pepper_compositor_schedule_repaint(view->compositor);
 }
 
 static void
-view_unmap(pepper_view_t *view)
-{
-    if (!view->mapped)
-        return;
-
-    view->mapped = PEPPER_FALSE;
-    view_update_visibility(view);
-}
-
-static inline void
-add_bbox_point(double *box, int x, int y, const pepper_mat4_t *matrix)
+view_mark_damaged(pepper_view_t *view)
 {
-    pepper_vec2_t v = { x, y };
-
-    pepper_mat4_transform_vec2(matrix, &v);
+    int i;
 
-    box[0] = PEPPER_MIN(box[0], v.x);
-    box[1] = PEPPER_MIN(box[1], v.y);
-    box[2] = PEPPER_MAX(box[2], v.x);
-    box[3] = PEPPER_MAX(box[3], v.y);
+    for (i = 0; i < PEPPER_MAX_OUTPUT_COUNT; i++)
+        view->plane_entries[i].need_damage = PEPPER_TRUE;
 }
 
-static inline void
-transform_bounding_box(pixman_box32_t *box, const pepper_mat4_t *matrix)
+static void
+view_damage_below(pepper_view_t *view)
 {
-    double          b[4] = { HUGE_VAL, HUGE_VAL, -HUGE_VAL, -HUGE_VAL };
+    int i;
 
-    add_bbox_point(b, box->x1, box->y1, matrix);
-    add_bbox_point(b, box->x2, box->y1, matrix);
-    add_bbox_point(b, box->x2, box->y2, matrix);
-    add_bbox_point(b, box->x1, box->y2, matrix);
+    for (i = 0; i < PEPPER_MAX_OUTPUT_COUNT; i++)
+    {
+        pepper_plane_entry_t *entry = &view->plane_entries[i];
 
-    box->x1 = floor(b[0]);
-    box->y1 = floor(b[1]);
-    box->x2 = ceil(b[2]);
-    box->y2 = ceil(b[3]);
+        if (entry->plane)
+            pepper_plane_add_damage_region(entry->plane, &entry->base.visible_region);
+    }
 }
 
-static inline void
-transform_region_bounding(pixman_region32_t *region, const pepper_mat4_t *matrix)
+void
+pepper_view_surface_damage(pepper_view_t *view)
 {
-    pixman_region32_t   result;
-    pixman_box32_t     *rects;
-    int                 i, num_rects;
-
-    pixman_region32_init(&result);
-    rects = pixman_region32_rectangles(region, &num_rects);
+    int i;
 
-    for (i = 0; i < num_rects; i++)
+    for (i = 0; i < PEPPER_MAX_OUTPUT_COUNT; i++)
     {
-        pixman_box32_t box = rects[i];
+        pepper_plane_entry_t *entry = &view->plane_entries[i];
 
-        transform_bounding_box(&box, matrix);
-        pixman_region32_union_rect(&result, &result,
-                                   box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1);
+        if (entry->plane)
+        {
+            pixman_region32_t damage;
+
+            pixman_region32_init(&damage);
+            pixman_region32_copy(&damage, &view->surface->damage_region);
+            pepper_transform_pixman_region(&damage, &view->global_transform);
+            pixman_region32_translate(&damage,
+                                      -entry->plane->output->geometry.x,
+                                      -entry->plane->output->geometry.y);
+            pixman_region32_intersect(&damage, &damage, &entry->base.visible_region);
+            pepper_plane_add_damage_region(entry->plane, &damage);
+        }
     }
-
-    pixman_region32_copy(region, &result);
-    pixman_region32_fini(&result);
 }
 
 static void
-view_update_output_overlap(pepper_view_t *view)
+view_handle_surface_destroy(struct wl_listener *listener, void *data)
 {
-    pepper_list_t *l;
-
-    view->output_overlap = 0;
-
-    PEPPER_LIST_FOR_EACH(&view->compositor->output_list, l)
-    {
-        pepper_output_t *output = l->item;
-        pixman_box32_t   box =
-        {
-            output->geometry.x,
-            output->geometry.y,
-            output->geometry.x + output->geometry.w,
-            output->geometry.y + output->geometry.h
-        };
-
-        if (pixman_region32_contains_rectangle(&view->bounding_region, &box) != PIXMAN_REGION_OUT)
-            view->output_overlap |= (1 << output->id);
-    }
+    pepper_view_t *view = pepper_container_of(listener, pepper_view_t, surface_destroy_listener);
+    PEPPER_ASSERT(view->surface != NULL);
+    pepper_view_destroy(view);
 }
 
 static pepper_list_t *
@@ -159,12 +84,7 @@ view_insert(pepper_view_t *view, pepper_list_t *pos, pepper_bool_t subtree)
     {
         pepper_list_remove(&view->compositor_link, NULL);
         pepper_list_insert(pos, &view->compositor_link);
-
-        if (view->visibility)
-        {
-            pepper_view_damage_below(view);
-            view_mark_plane_entries_damaged(view);
-        }
+        view_mark_dirty(view, PEPPER_VIEW_Z_ORDER_DIRTY);
     }
 
     pos = &view->compositor_link;
@@ -179,6 +99,7 @@ view_insert(pepper_view_t *view, pepper_list_t *pos, pepper_bool_t subtree)
 
     return pos;
 }
+
 static void
 view_handle_plane_destroy(struct wl_listener *listener, void *data);
 
@@ -190,7 +111,7 @@ plane_entry_set_plane(pepper_plane_entry_t *entry, pepper_plane_t *plane)
 
     if (entry->plane)
     {
-        pepper_view_damage_below((pepper_view_t *)entry->base.view);
+        view_damage_below((pepper_view_t *)entry->base.view);
         entry->plane = NULL;
         wl_list_remove(&entry->plane_destroy_listener.link);
         pixman_region32_fini(&entry->base.visible_region);
@@ -230,44 +151,28 @@ pepper_view_assign_plane(pepper_view_t *view, pepper_output_t *output, pepper_pl
 }
 
 void
-pepper_view_damage_below(pepper_view_t *view)
+view_update_geometry(pepper_view_t *view)
 {
-    int i;
+    pepper_list_t *l;
 
-    for (i = 0; i < PEPPER_MAX_OUTPUT_COUNT; i++)
+    if (view->surface)
     {
-        pepper_plane_entry_t *entry = &view->plane_entries[i];
-
-        if (entry->plane)
-            pepper_plane_add_damage_region(entry->plane, &entry->base.visible_region);
+        view->w = view->surface->w;
+        view->h = view->surface->h;
     }
-}
-
-void
-pepper_view_update_geometry(pepper_view_t *view)
-{
-    if (!view->geometry_dirty)
-        return;
 
     pepper_mat4_init_translate(&view->global_transform, view->x, view->y, 0.0);
     pepper_mat4_multiply(&view->global_transform, &view->transform, &view->global_transform);
 
     if (view->parent)
     {
-        pepper_view_update_geometry(view->parent);
         pepper_mat4_multiply(&view->global_transform,
                              &view->parent->global_transform, &view->global_transform);
     }
 
-    if (view->surface)
-    {
-        view->w = view->surface->w;
-        view->h = view->surface->h;
-    }
-
     /* Bounding region. */
     pixman_region32_init_rect(&view->bounding_region, 0, 0, view->w, view->h);
-    transform_region_bounding(&view->bounding_region, &view->global_transform);
+    pepper_transform_pixman_region(&view->bounding_region, &view->global_transform);
 
     /* Opaque region. */
     pixman_region32_init(&view->opaque_region);
@@ -279,9 +184,73 @@ pepper_view_update_geometry(pepper_view_t *view)
                                   view->global_transform.m[3], view->global_transform.m[7]);
     }
 
-    view->geometry_dirty = PEPPER_FALSE;
-    view_update_output_overlap(view);
-    view_mark_plane_entries_damaged(view);
+    view->output_overlap = 0;
+
+    PEPPER_LIST_FOR_EACH(&view->compositor->output_list, l)
+    {
+        pepper_output_t *output = l->item;
+        pixman_box32_t   box =
+        {
+            output->geometry.x,
+            output->geometry.y,
+            output->geometry.x + output->geometry.w,
+            output->geometry.y + output->geometry.h
+        };
+
+        if (pixman_region32_contains_rectangle(&view->bounding_region, &box) != PIXMAN_REGION_OUT)
+            view->output_overlap |= (1 << output->id);
+    }
+
+}
+
+static void
+view_update_visibility(pepper_view_t *view)
+{
+    pepper_bool_t visible;
+
+    if (!(view->dirty & PEPPER_VIEW_VISIBILITY_DIRTY))
+        return;
+
+    if (view->parent)
+        view_update_visibility(view->parent);
+
+    view->visible = view->parent->visible && view->mapped;
+    view->dirty &= ~PEPPER_VIEW_VISIBILITY_DIRTY;
+}
+
+void
+pepper_view_update(pepper_view_t *view)
+{
+    if (!view->dirty)
+        return;
+
+    if (view->parent)
+    {
+        pepper_view_update(view->parent);
+        view->visible = view->parent->visible && view->mapped;
+    }
+    else
+    {
+        view->visible = view->mapped;
+    }
+
+    if (view->visible == view->prev_visible)
+        view->dirty &= ~PEPPER_VIEW_VISIBILITY_DIRTY;
+
+    if (!view->dirty)
+        return;
+
+    if (view->prev_visible)
+        view_damage_below(view);
+
+    if ((view->dirty & PEPPER_VIEW_GEOMETRY_DIRTY) || (!view->prev_visible && view->visible))
+        view_update_geometry(view);
+
+    if (view->visible)
+        view_mark_damaged(view);
+
+    view->dirty = 0;
+    view->prev_visible = view->visible;
 }
 
 static void
@@ -325,8 +294,6 @@ pepper_compositor_add_surface_view(pepper_compositor_t *compositor, pepper_surfa
     view->w = surface->w;
     view->h = surface->h;
 
-    view->geometry_dirty = PEPPER_TRUE;
-
     view->surface = surface;
     view->surface_link.item = view;
     pepper_list_insert(&surface->view_list, &view->surface_link);
@@ -346,7 +313,6 @@ pepper_view_destroy(pepper_view_t *view)
      * destruction can detach from their parent.
      */
     pepper_object_fini(&view->base);
-    view_unmap(view);
 
     for (i = 0; i < PEPPER_MAX_OUTPUT_COUNT; i++)
         plane_entry_set_plane(&view->plane_entries[i], NULL);
@@ -391,13 +357,15 @@ pepper_view_set_parent(pepper_view_t *view, pepper_view_t *parent)
     if (view->parent == parent)
         return;
 
+    if (view->parent)
+        pepper_list_remove(&view->parent_link, NULL);
+
     view->parent = parent;
-    pepper_list_remove(&view->parent_link, NULL);
 
     if (view->parent)
         pepper_list_insert(view->parent->children_list.prev, &view->parent_link);
 
-    view_geometry_dirty(view);
+    view_mark_dirty(view, PEPPER_VIEW_VISIBILITY_DIRTY | PEPPER_VIEW_GEOMETRY_DIRTY);
 }
 
 PEPPER_API pepper_view_t *
@@ -458,7 +426,7 @@ pepper_view_resize(pepper_view_t *view, int w, int h)
 
     view->w = w;
     view->h = h;
-    view_geometry_dirty(view);
+    view_mark_dirty(view, PEPPER_VIEW_GEOMETRY_DIRTY);
 }
 
 PEPPER_API void
@@ -479,7 +447,7 @@ pepper_view_set_position(pepper_view_t *view, double x, double y)
 
     view->x = x;
     view->y = y;
-    view_geometry_dirty(view);
+    view_mark_dirty(view, PEPPER_VIEW_GEOMETRY_DIRTY);
 }
 
 PEPPER_API void
@@ -496,7 +464,7 @@ PEPPER_API void
 pepper_view_set_transform(pepper_view_t *view, const pepper_mat4_t *matrix)
 {
     pepper_mat4_copy(&view->transform, matrix);
-    view_geometry_dirty(view);
+    view_mark_dirty(view, PEPPER_VIEW_GEOMETRY_DIRTY);
 }
 
 PEPPER_API const pepper_mat4_t *
@@ -508,13 +476,21 @@ pepper_view_get_transform(pepper_view_t *view)
 PEPPER_API void
 pepper_view_map(pepper_view_t *view)
 {
-    view_map(view);
+    if (view->mapped)
+        return;
+
+    view->mapped = PEPPER_TRUE;
+    view_mark_dirty(view, PEPPER_VIEW_VISIBILITY_DIRTY);
 }
 
 PEPPER_API void
 pepper_view_unmap(pepper_view_t *view)
 {
-    view_unmap(view);
+    if (!view->mapped)
+        return;
+
+    view->mapped = PEPPER_FALSE;
+    view_mark_dirty(view, PEPPER_VIEW_VISIBILITY_DIRTY);
 }
 
 PEPPER_API pepper_bool_t
@@ -526,5 +502,5 @@ pepper_view_is_mapped(pepper_view_t *view)
 PEPPER_API pepper_bool_t
 pepper_view_is_visible(pepper_view_t *view)
 {
-    return view->visibility;
+    return view->visible;
 }