From: SooChan Lim Date: Fri, 10 Sep 2021 07:59:21 +0000 (+0900) Subject: implement hwc at pepper X-Git-Tag: submit/tizen_6.5/20210604.093338~27 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=628bd379e808550ff8e0bb021bd6c1607fb3031c;p=platform%2Fcore%2Fuifw%2Fpepper.git implement hwc at pepper use pepper_hwc and pepper_hwc_entry Change-Id: Iefa380828f58c62723a92e60abc1c0dba41d70eb --- diff --git a/src/lib/pepper/Makefile.am b/src/lib/pepper/Makefile.am index efae7c7..7556fd0 100644 --- a/src/lib/pepper/Makefile.am +++ b/src/lib/pepper/Makefile.am @@ -17,6 +17,7 @@ libpepper_la_SOURCES = pepper.h \ pepper-internal.h \ object.c \ compositor.c \ + hwc.c \ output.c \ input.c \ pointer.c \ diff --git a/src/lib/pepper/compositor.c b/src/lib/pepper/compositor.c index 8a0e968..345c07b 100644 --- a/src/lib/pepper/compositor.c +++ b/src/lib/pepper/compositor.c @@ -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 index 0000000..b06693a --- /dev/null +++ b/src/lib/pepper/hwc.c @@ -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); +} diff --git a/src/lib/pepper/output.c b/src/lib/pepper/output.c index 5984733..6114962 100644 --- a/src/lib/pepper/output.c +++ b/src/lib/pepper/output.c @@ -116,6 +116,18 @@ output_bind(struct wl_client *client, void *data, uint32_t version, uint32_t id) output_send_modes(output, resource); } +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) { @@ -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; diff --git a/src/lib/pepper/pepper-internal.h b/src/lib/pepper/pepper-internal.h index 479636d..8187b15 100644 --- a/src/lib/pepper/pepper-internal.h +++ b/src/lib/pepper/pepper-internal.h @@ -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); diff --git a/src/lib/pepper/pepper-output-backend.h b/src/lib/pepper/pepper-output-backend.h index c38e269..c28896a 100644 --- a/src/lib/pepper/pepper-output-backend.h +++ b/src/lib/pepper/pepper-output-backend.h @@ -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); diff --git a/src/lib/pepper/view.c b/src/lib/pepper/view.c index 0d8899c..0de6ef8 100644 --- a/src/lib/pepper/view.c +++ b/src/lib/pepper/view.c @@ -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); + } } } } @@ -107,6 +126,44 @@ view_insert(pepper_view_t *view, pepper_list_t *pos, pepper_bool_t subtree) return pos; } +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) { @@ -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);