implement hwc at pepper 14/263814/1
authorSooChan Lim <sc1.lim@samsung.com>
Fri, 10 Sep 2021 07:59:21 +0000 (16:59 +0900)
committerSooChan Lim <sc1.lim@samsung.com>
Fri, 10 Sep 2021 07:59:21 +0000 (16:59 +0900)
use pepper_hwc and pepper_hwc_entry

Change-Id: Iefa380828f58c62723a92e60abc1c0dba41d70eb

src/lib/pepper/Makefile.am
src/lib/pepper/compositor.c
src/lib/pepper/hwc.c [new file with mode: 0644]
src/lib/pepper/output.c
src/lib/pepper/pepper-internal.h
src/lib/pepper/pepper-output-backend.h
src/lib/pepper/view.c

index efae7c7..7556fd0 100644 (file)
@@ -17,6 +17,7 @@ libpepper_la_SOURCES = pepper.h                 \
                        pepper-internal.h        \
                        object.c                 \
                        compositor.c             \
+                       hwc.c                    \
                        output.c                 \
                        input.c                  \
                        pointer.c                \
index 8a0e968..345c07b 100644 (file)
@@ -312,13 +312,21 @@ pepper_compositor_destroy(pepper_compositor_t *compositor)
 {
        pepper_surface_t        *surface, *next_surface;
        pepper_wl_region_t      *region, *next_region;
-
+#if 0
+       pepper_output_t         *output, *next_output;
+#endif
        pepper_list_for_each_safe(surface, next_surface, &compositor->surface_list,
                                                          link)
-       pepper_surface_destroy(surface);
+               pepper_surface_destroy(surface);
 
        pepper_list_for_each_safe(region, next_region, &compositor->region_list, link)
-       pepper_wl_region_destroy(region);
+               pepper_wl_region_destroy(region);
+
+// TODO: this makes the block issue on libtdm thread. have to find out solution :()
+#if 0
+       pepper_list_for_each_safe(output, next_output, &compositor->output_list, link)
+               pepper_output_destroy(output);
+#endif
 
        if (compositor->subcomp)
                pepper_subcompositor_destroy(compositor->subcomp);
diff --git a/src/lib/pepper/hwc.c b/src/lib/pepper/hwc.c
new file mode 100644 (file)
index 0000000..b06693a
--- /dev/null
@@ -0,0 +1,211 @@
+/*
+* Copyright © 2021 Samsung Electronics co., Ltd. All Rights Reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice (including the next
+* paragraph) shall be included in all copies or substantial portions of the
+* Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*/
+
+#include "pepper-internal.h"
+
+void
+pepper_hwc_update(pepper_hwc_t *hwc, const pepper_list_t *view_list,
+                                       pepper_region_t *clip)
+{
+       int                 x = hwc->output->geometry.x;
+       int                 y = hwc->output->geometry.y;
+       int                 w = hwc->output->geometry.w;
+       int                 h = hwc->output->geometry.h;
+       pepper_region_t     hwc_clip;
+       pepper_view_t      *view;
+
+       pepper_region_init(&hwc_clip);
+       pepper_list_init(&hwc->entry_list);
+
+       pepper_list_for_each(view, view_list, link) {
+               pepper_hwc_entry_t *entry = &view->hwc_entries[hwc->output->id];
+
+               if (entry->hwc == hwc) {
+                       pepper_list_insert(hwc->entry_list.prev, &entry->link);
+
+                       if (entry->need_transform_update) {
+                               entry->base.transform = view->global_transform;
+                               pepper_transform_global_to_output(&entry->base.transform, hwc->output);
+                               entry->need_transform_update = PEPPER_FALSE;
+                               pepper_mat4_inverse(&entry->base.inverse, &entry->base.transform);
+                       }
+
+                       /* Calculate visible region (output space). */
+                       pepper_region_subtract(&entry->base.visible_region,
+                                                                        &view->bounding_region, &hwc_clip);
+                       pepper_region_intersect_rect(&entry->base.visible_region,
+                                                                                  &entry->base.visible_region, x, y, w, h);
+                       pepper_region_global_to_output(&entry->base.visible_region,
+                                                                                                 hwc->output);
+
+                       /* Accumulate opaque region of this view (global space). */
+                       pepper_region_union(&hwc_clip, &hwc_clip, &view->opaque_region);
+
+                       /* Add damage for the new visible region. */
+                       if (entry->need_damage) {
+                               pepper_hwc_add_damage_region(hwc, &entry->base.visible_region);
+                               entry->need_damage = PEPPER_FALSE;
+                       }
+
+                       /* Flush surface damage. (eg. texture upload) */
+                       if (view->surface)
+                               pepper_surface_flush_damage(view->surface);
+               }
+       }
+
+       /* Copy clip region of this hwc. */
+       pepper_region_copy(&hwc->clip_region, clip);
+
+       /* Accumulate clip region obsecured by this hwc. */
+       pepper_region_global_to_output(&hwc_clip, hwc->output);
+       pepper_region_union(clip, clip, &hwc_clip);
+       pepper_region_fini(&hwc_clip);
+}
+
+/**
+ * Create and add #pepper_hwc_t to the output.
+ *
+ * @param output        output to add the hwc
+ *
+ * @returns             #pepper_hwc_t
+ */
+PEPPER_API pepper_hwc_t *
+pepper_output_initialize_hwc(pepper_output_t *output)
+{
+       PEPPER_INFO("\n");
+
+       pepper_hwc_t *hwc;
+
+       PEPPER_CHECK(!output->hwc, return NULL, "Output already has hwc.\n");
+
+       hwc = (pepper_hwc_t *)pepper_object_alloc(PEPPER_OBJECT_HWC,
+                       sizeof(pepper_hwc_t));
+       PEPPER_CHECK(hwc, return NULL, "pepper_object_alloc() failed.\n");
+
+       hwc->output = output;
+       output->hwc = hwc;
+
+       pepper_list_init(&hwc->entry_list);
+       pepper_region_init(&hwc->damage_region);
+       pepper_region_init(&hwc->clip_region);
+
+       // TODO:
+       output->compositor->use_hwc = PEPPER_TRUE;
+
+       return hwc;
+}
+
+/**
+ * Destroy the hwc.
+ *
+ * @param hwc     hwc to destroy
+ */
+PEPPER_API void
+pepper_hwc_destroy(pepper_hwc_t *hwc)
+{
+       pepper_hwc_entry_t *entry;
+
+       PEPPER_INFO("\n");
+
+       pepper_object_fini(&hwc->base);
+
+       pepper_list_for_each(entry, &hwc->entry_list, link)
+               pepper_view_assign_hwc_entry(entry->base.view,
+                               hwc->output, PEPPER_FALSE);
+
+       pepper_region_fini(&hwc->damage_region);
+       pepper_region_fini(&hwc->clip_region);
+
+       free(hwc);
+}
+
+/**
+ * Get list of #pepper_render_item_t.
+ *
+ * @param hwc     hwc to get the list
+ *
+ * @returns         #pepper_list_t
+ */
+PEPPER_API const pepper_list_t *
+pepper_hwc_get_render_list(pepper_hwc_t *hwc)
+{
+       return &hwc->entry_list;
+}
+
+/**
+ * Get the region that has been changed. Not necessarily the damage region should be visible.
+ *
+ * @param hwc     hwc to get the damage region
+ *
+ * @returns         #pepper_region_t
+ */
+PEPPER_API pepper_region_t *
+pepper_hwc_get_damage_region(pepper_hwc_t *hwc)
+{
+       return &hwc->damage_region;
+}
+
+/**
+ * Add the damage_region to hwc.
+ *
+ * @param hwc        hwc to add the damage region
+ * @param damage     region to add
+ */
+void
+pepper_hwc_add_damage_region(pepper_hwc_t *hwc, pepper_region_t *damage)
+{
+       if (!damage) {
+               pepper_region_union_rect(&hwc->damage_region, &hwc->damage_region,
+                                                                  0, 0, hwc->output->geometry.w, hwc->output->geometry.h);
+               pepper_output_schedule_repaint(hwc->output);
+       } else if (pepper_region_not_empty(damage)) {
+               pepper_region_union(&hwc->damage_region, &hwc->damage_region, damage);
+               pepper_output_schedule_repaint(hwc->output);
+       }
+}
+
+/**
+ * Subtract given region from the damage region of a hwc. Called to partially update the
+ * damage region of a hwc.
+ *
+ * @param hwc     hwc
+ * @param damage    region to subtract
+ */
+PEPPER_API void
+pepper_hwc_subtract_damage_region(pepper_hwc_t *hwc,
+                                                                       pepper_region_t *damage)
+{
+       pepper_region_subtract(&hwc->damage_region, &hwc->damage_region, damage);
+}
+
+/**
+ * Clear the damage region of a hwc. Called when the output backend has processed the damage
+ * region. Or if you partially updated the damage region use pepper_hwc_subtract_damage_region.
+ *
+ * @param hwc     hwc to clear the damage region
+ */
+PEPPER_API void
+pepper_hwc_clear_damage_region(pepper_hwc_t *hwc)
+{
+       pepper_region_clear(&hwc->damage_region);
+}
index 5984733..6114962 100644 (file)
@@ -117,6 +117,18 @@ output_bind(struct wl_client *client, void *data, uint32_t version, uint32_t id)
 }
 
 static void
+output_update_hwc(pepper_output_t *output)
+{
+       pepper_region_t   clip;
+
+       pepper_region_init(&clip);
+
+       pepper_hwc_update(output->hwc, &output->view_list, &clip);
+
+       pepper_region_fini(&clip);
+}
+
+static void
 output_update_planes(pepper_output_t *output)
 {
        pepper_plane_t     *plane;
@@ -153,7 +165,11 @@ output_repaint(pepper_output_t *output)
        }
 
        output->backend->assign_planes(output->data, &output->view_list);
-       output_update_planes(output);
+       if (output->compositor->use_hwc)
+               output_update_hwc(output);
+       else
+               output_update_planes(output);
+
        output->backend->repaint(output->data, &output->plane_list);
 
        output->frame.pending = PEPPER_TRUE;
index 479636d..8187b15 100644 (file)
@@ -605,6 +605,15 @@ struct pepper_hwc {
        pepper_region_t   clip_region;
 };
 
+pepper_object_t *
+pepper_hwc_create(pepper_object_t *output);
+
+void
+pepper_hwc_add_damage_region(pepper_hwc_t *hwc, pepper_region_t *damage);
+
+void
+pepper_hwc_update(pepper_hwc_t *hwc, const pepper_list_t *view_list,
+                                 pepper_region_t *clip);
 
 void
 pepper_surface_flush_damage(pepper_surface_t *surface);
index c38e269..c28896a 100644 (file)
@@ -172,6 +172,29 @@ PEPPER_API void
 pepper_view_assign_plane(pepper_view_t *view, pepper_output_t *output,
                                                 pepper_plane_t *plane);
 
+PEPPER_API pepper_hwc_t *
+pepper_output_initialize_hwc(pepper_output_t *output);
+
+PEPPER_API void
+pepper_hwc_destroy(pepper_hwc_t *hwc);
+
+PEPPER_API const pepper_list_t *
+pepper_hwc_get_render_list(pepper_hwc_t *hwc);
+
+PEPPER_API pepper_region_t *
+pepper_hwc_get_damage_region(pepper_hwc_t *hwc);
+
+PEPPER_API void
+pepper_hwc_subtract_damage_region(pepper_hwc_t *hwc,
+                                                                       pepper_region_t *damage);
+
+PEPPER_API void
+pepper_hwc_clear_damage_region(pepper_hwc_t *hwc);
+
+PEPPER_API void
+pepper_view_assign_hwc_entry(pepper_view_t *view, pepper_output_t *output,
+                                               pepper_bool_t active);
+
 PEPPER_API void
 pepper_output_add_damage_region(pepper_output_t *output,
                                                                pepper_region_t *region);
index 0d8899c..0de6ef8 100644 (file)
@@ -48,7 +48,10 @@ pepper_view_mark_dirty(pepper_view_t *view, uint32_t flag)
                        pepper_view_mark_dirty(child, PEPPER_VIEW_GEOMETRY_DIRTY);
 
                for (i = 0; i < PEPPER_MAX_OUTPUT_COUNT; i++)
-                       view->plane_entries[i].need_transform_update = PEPPER_TRUE;
+                       if (view->compositor->use_hwc)
+                               view->hwc_entries[i].need_transform_update = PEPPER_TRUE;
+                       else
+                               view->plane_entries[i].need_transform_update = PEPPER_TRUE;
        }
 
        /* Mark entire subtree's active as dirty. */
@@ -64,23 +67,39 @@ void
 pepper_view_surface_damage(pepper_view_t *view)
 {
        int i;
+       pepper_region_t damage;
 
        for (i = 0; i < PEPPER_MAX_OUTPUT_COUNT; i++) {
-               pepper_plane_entry_t *entry = &view->plane_entries[i];
-
-               if (entry->plane) {
-                       pepper_region_t damage;
-
-                       pepper_region_init(&damage);
-                       pepper_region_copy(&damage, &view->surface->damage_region);
-                       pepper_region_intersect_rect(&damage, &damage, 0, 0, view->w, view->h);
-
-                       pepper_transform_region(&damage, &view->global_transform);
-                       pepper_region_translate(&damage,
-                                                                         -entry->plane->output->geometry.x,
-                                                                         -entry->plane->output->geometry.y);
-                       pepper_region_intersect(&damage, &damage, &entry->base.visible_region);
-                       pepper_plane_add_damage_region(entry->plane, &damage);
+               if (view->compositor->use_hwc) {
+                       pepper_hwc_entry_t *entry = &view->hwc_entries[i];
+
+                       if (entry->hwc) {
+                               pepper_region_init(&damage);
+                               pepper_region_copy(&damage, &view->surface->damage_region);
+                               pepper_region_intersect_rect(&damage, &damage, 0, 0, view->w, view->h);
+
+                               pepper_transform_region(&damage, &view->global_transform);
+                               pepper_region_translate(&damage,
+                                                                                       -entry->hwc->output->geometry.x,
+                                                                                       -entry->hwc->output->geometry.y);
+                               pepper_region_intersect(&damage, &damage, &entry->base.visible_region);
+                               pepper_hwc_add_damage_region(entry->hwc, &damage);
+                       }
+               } else {
+                       pepper_plane_entry_t *entry = &view->plane_entries[i];
+
+                       if (entry->plane) {
+                               pepper_region_init(&damage);
+                               pepper_region_copy(&damage, &view->surface->damage_region);
+                               pepper_region_intersect_rect(&damage, &damage, 0, 0, view->w, view->h);
+
+                               pepper_transform_region(&damage, &view->global_transform);
+                               pepper_region_translate(&damage,
+                                                                                       -entry->plane->output->geometry.x,
+                                                                                       -entry->plane->output->geometry.y);
+                               pepper_region_intersect(&damage, &damage, &entry->base.visible_region);
+                               pepper_plane_add_damage_region(entry->plane, &damage);
+                       }
                }
        }
 }
@@ -108,6 +127,44 @@ view_insert(pepper_view_t *view, pepper_list_t *pos, pepper_bool_t subtree)
 }
 
 static void
+hwc_entry_set_active(pepper_hwc_entry_t *entry, pepper_hwc_t *hwc,
+                                                               pepper_bool_t active)
+{
+       if (entry->active == active)
+               return;
+
+       if (entry->active) {
+               pepper_hwc_add_damage_region(entry->hwc, &entry->base.visible_region);
+               pepper_region_fini(&entry->base.visible_region);
+               entry->active = PEPPER_FALSE;
+               entry->hwc = NULL;
+       }
+
+       entry->active = active;
+       entry->hwc = hwc;
+
+       if (entry->active) {
+               pepper_region_init(&entry->base.visible_region);
+               entry->need_damage = PEPPER_TRUE;
+       }
+}
+
+/**
+ * Assign a view to a hwc.
+ *
+ * @param view          view to assign
+ * @param output        output of the hwc
+ * @param active        active on render target
+ */
+PEPPER_API void
+pepper_view_assign_hwc_entry(pepper_view_t *view, pepper_output_t *output,
+                                               pepper_bool_t active)
+{
+       PEPPER_CHECK(output && output->hwc, return, "No output and output->hwc.\n");
+       hwc_entry_set_active(&view->hwc_entries[output->id], output->hwc, active);
+}
+
+static void
 plane_entry_set_plane(pepper_plane_entry_t *entry, pepper_plane_t *plane)
 {
        if (entry->plane == plane)
@@ -193,10 +250,15 @@ pepper_view_update(pepper_view_t *view)
         * each output when the visible region is calculated on output repaint.
         */
        for (i = 0; i < PEPPER_MAX_OUTPUT_COUNT; i++) {
-               pepper_plane_entry_t *entry = &view->plane_entries[i];
-
-               if (entry->plane)
-                       pepper_plane_add_damage_region(entry->plane, &entry->base.visible_region);
+               if (view->compositor->use_hwc) {
+                       pepper_hwc_entry_t *entry = &view->hwc_entries[i];
+                       if (entry->active)
+                               pepper_hwc_add_damage_region(entry->hwc, &entry->base.visible_region);
+               } else {
+                       pepper_plane_entry_t *entry = &view->plane_entries[i];
+                       if (entry->plane)
+                               pepper_plane_add_damage_region(entry->plane, &entry->base.visible_region);
+               }
        }
 
        /* Update geometry. */
@@ -258,8 +320,12 @@ pepper_view_update(pepper_view_t *view)
        PEPPER_DEBUG("view:%p output_overlap:%d\n", view, view->output_overlap);
 
        /* Mark the plane entries as damaged. */
-       for (i = 0; i < PEPPER_MAX_OUTPUT_COUNT; i++)
-               view->plane_entries[i].need_damage = PEPPER_TRUE;
+       for (i = 0; i < PEPPER_MAX_OUTPUT_COUNT; i++) {
+               if (view->compositor->use_hwc)
+                       view->hwc_entries[i].need_damage = PEPPER_TRUE;
+               else
+                       view->plane_entries[i].need_damage = PEPPER_TRUE;
+       }
 
        view->active = active;
        view->dirty = 0;
@@ -286,8 +352,13 @@ view_init(pepper_view_t *view, pepper_compositor_t *compositor)
        pepper_region_init(&view->opaque_region);
 
        for (i = 0; i < PEPPER_MAX_OUTPUT_COUNT; i++) {
-               view->plane_entries[i].base.view = view;
-               view->plane_entries[i].link.item = &view->plane_entries[i];
+               if (view->compositor->use_hwc) {
+                       view->hwc_entries[i].base.view = view;
+                       view->hwc_entries[i].link.item = &view->hwc_entries[i];
+               } else {
+                       view->plane_entries[i].base.view = view;
+                       view->plane_entries[i].link.item = &view->plane_entries[i];
+               }
        }
 }
 
@@ -377,12 +448,19 @@ pepper_view_destroy(pepper_view_t *view)
        int             i;
        pepper_view_t  *child, *tmp;
 
+       // schedule to repaint when a view destroys.
+       pepper_compositor_schedule_repaint(view->compositor);
+
        pepper_object_emit_event(&view->compositor->base,
                                                         PEPPER_EVENT_COMPOSITOR_VIEW_REMOVE, view);
        pepper_object_fini(&view->base);
 
-       for (i = 0; i < PEPPER_MAX_OUTPUT_COUNT; i++)
-               plane_entry_set_plane(&view->plane_entries[i], NULL);
+       for (i = 0; i < PEPPER_MAX_OUTPUT_COUNT; i++) {
+               if (view->compositor->use_hwc)
+                       hwc_entry_set_active(&view->hwc_entries[i], NULL, PEPPER_FALSE);
+               else
+                       plane_entry_set_plane(&view->plane_entries[i], NULL);
+       }
 
        pepper_list_for_each_safe(child, tmp, &view->children_list, parent_link)
                pepper_view_destroy(child);