pepper-internal.h \
object.c \
compositor.c \
+ hwc.c \
output.c \
input.c \
pointer.c \
{
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);
--- /dev/null
+/*
+* 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);
+}
}
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;
}
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;
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);
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);
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. */
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);
+ }
}
}
}
}
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)
* 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. */
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;
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];
+ }
}
}
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);