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 834c52abbd5c46cf3863efd7bfcaec5e0ceb9d8c..a5a6512918d8777e8a5544e2ef54530a9595e2be 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 808c28c87575bc2a69298596b8254241a594dc22..c66e83f9bfadb70478fef29b262e95b906309344 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 fae63836a732b89c0107959181f011c1d3c2ec9d..7073b46697b7337adda39d726a3c45bf7084f522 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 f2d7e4fff3e45a33dd047e58a146fdd373687c13..be01006b0d2b4766e364702de6d706bd35ebd734 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 62458c9ab1086efb2d7411b2762809cb470e0a1a..fca1f10bd5f8d533f465359b6ed86392fb18c734 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 d1231338cb186fb88d521487d56c649bdddaafca..f31bb4be84bbd12b3885cd5dc80ef0ad8f6adf50 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 32163f8c999f876ca368207fa359e02a1367e2be..26214c5ea2f9091e6a965fcc6352e68cc826f4c8 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;
 }