From 91ae7143b46d7d9bdfc8dbb0bf796479f1cffa6c Mon Sep 17 00:00:00 2001 From: SooChan Lim Date: Fri, 10 Sep 2021 17:07:04 +0900 Subject: [PATCH] add pepper_tdm_hwc functions Change-Id: Idff22254f676132d1bf28d9e2760da2800db4d92 --- src/lib/tdm/Makefile.am | 3 +- src/lib/tdm/tdm-hwc.c | 851 +++++++++++++++++++++++++++++++++++++ src/lib/tdm/tdm-internal.h | 9 + src/lib/tdm/tdm-output.c | 18 +- 4 files changed, 875 insertions(+), 6 deletions(-) create mode 100644 src/lib/tdm/tdm-hwc.c diff --git a/src/lib/tdm/Makefile.am b/src/lib/tdm/Makefile.am index c3e5e64..e52cac1 100644 --- a/src/lib/tdm/Makefile.am +++ b/src/lib/tdm/Makefile.am @@ -10,4 +10,5 @@ libpepper_tdm_la_LIBADD = $(PEPPER_TDM_LIBS) libpepper_tdm_la_SOURCES = tdm-internal.h \ tdm-common.c \ - tdm-output.c + tdm-output.c \ + tdm-hwc.c diff --git a/src/lib/tdm/tdm-hwc.c b/src/lib/tdm/tdm-hwc.c new file mode 100644 index 0000000..d2f6a2a --- /dev/null +++ b/src/lib/tdm/tdm-hwc.c @@ -0,0 +1,851 @@ +/* +* 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 "tdm-internal.h" + +#define C(b, m) (((b) >> (m)) & 0xFF) +#define B(c, s) ((((unsigned int)(c)) & 0xff) << (s)) +#define FOURCC(a, b, c, d) (B(d, 24) | B(c, 16) | B(b, 8) | B(a, 0)) +#define FOURCC_STR(id) C(id, 0), C(id, 8), C(id, 16), C(id, 24) +#define CLEAR(x) memset(&(x), 0, sizeof (x)) + +enum buffer_type { + BUFFER_TYPE_NONE, + BUFFER_TYPE_SHM, + BUFFER_TYPE_EGL, + BUFFER_TYPE_TBM +}; + +static pepper_bool_t +__hwc_window_attach_shm(pepper_tdm_hwc_window_t *hwc_window, pepper_buffer_t *buffer) +{ + struct wl_shm_buffer *shm_buffer = wl_shm_buffer_get( + pepper_buffer_get_resource(buffer)); + + if (!shm_buffer) + return PEPPER_FALSE; + + hwc_window->shm_buffer = shm_buffer; + hwc_window->buffer_width = wl_shm_buffer_get_width(shm_buffer); + hwc_window->buffer_height = wl_shm_buffer_get_height(shm_buffer); + hwc_window->buffer_type = BUFFER_TYPE_TBM; + + //TODO: make a tbm_surface_h with shm_buffer + // and tdm_hwc_window_set_buffer(); + + return PEPPER_TRUE; +} + +#ifdef HAVE_TBM +static pepper_bool_t +__hwc_window_attach_tbm(pepper_tdm_hwc_window_t *hwc_window, pepper_buffer_t *buffer) +{ + tbm_surface_h tbm_surface = wayland_tbm_server_get_surface(NULL, + pepper_buffer_get_resource(buffer)); + tdm_error terror = TDM_ERROR_NONE; + + if (!tbm_surface) + return PEPPER_FALSE; + + hwc_window->tbm_surface = tbm_surface; + hwc_window->buffer_width = tbm_surface_get_width(tbm_surface); + hwc_window->buffer_height = tbm_surface_get_height(tbm_surface); + hwc_window->buffer_type = BUFFER_TYPE_TBM; + + terror = tdm_hwc_window_set_buffer(hwc_window->thwc_window, tbm_surface); + PEPPER_CHECK(terror == TDM_ERROR_NONE, return PEPPER_FALSE, "tdm_hwc_window_set_buffer() failed.\n"); + + return PEPPER_TRUE;; +} +#endif + +static pepper_bool_t +__hwc_window_attach_egl(pepper_tdm_hwc_window_t *hwc_window, pepper_buffer_t *buffer) +{ +#if 0 //TODO: deal with gbm_bo associated with wl_buffer resource??? + gl_renderer_t *gr = state->renderer; + EGLDisplay display = gr->display; + struct wl_resource *resource = pepper_buffer_get_resource(buffer); + + gr->query_buffer(display, resource, EGL_WIDTH, &state->buffer_width); + gr->query_buffer(display, resource, EGL_HEIGHT, &state->buffer_height); + if (!gr->query_buffer(display, resource, EGL_WAYLAND_Y_INVERTED_WL, + &state->y_inverted)) + state->y_inverted = 1; + + state->buffer_type = BUFFER_TYPE_EGL; + return PEPPER_TRUE +#else + PEPPER_ERROR("__hwc_window_attach_egl() is not supported\n"); + return PEPPER_FALSE; +#endif +} + +static void +__hwc_window_release_buffer(pepper_tdm_hwc_window_t *hwc_window) +{ + if (hwc_window->buffer) { + pepper_event_listener_remove(hwc_window->buffer_destroy_listener); + hwc_window->buffer = NULL; + } +} + +static void +__hwc_window_handle_buffer_destroy(pepper_event_listener_t *listener, + pepper_object_t *object, + uint32_t id, + void *info, + void *data) +{ + pepper_tdm_hwc_window_t *hwc_window = data; + __hwc_window_release_buffer(hwc_window); +} + +static void +__hwc_window_handle_surface_destroy(pepper_event_listener_t *listener, + pepper_object_t *object, + uint32_t id, + void *info, + void *data) +{ + pepper_tdm_hwc_window_t *hwc_window = data; + + PEPPER_INFO("hwc_window:%p thwc_window:%p.\n", hwc_window, hwc_window->thwc_window); + + __hwc_window_release_buffer(hwc_window); + pepper_event_listener_remove(hwc_window->surface_destroy_listener); + pepper_object_set_user_data((pepper_object_t *)hwc_window->surface, hwc_window->hwc, + NULL, NULL); + + tdm_hwc_window_destroy(hwc_window->thwc_window); + + pepper_list_remove(&hwc_window->link); + free(hwc_window); +} + +static pepper_tdm_hwc_window_t * +__get_hwc_window(pepper_tdm_hwc_t *hwc, pepper_surface_t *surface) +{ + pepper_tdm_hwc_window_t *hwc_window = pepper_object_get_user_data(( + pepper_object_t *)surface, hwc); + + if (!hwc_window) { + tdm_error terror; + + hwc_window = (pepper_tdm_hwc_window_t *)calloc(1, sizeof(pepper_tdm_hwc_window_t)); + if (!hwc_window) { + PEPPER_ERROR("pepper_tdm_hwc_window_t allocation failed.\n"); + return NULL; + } + + hwc_window->thwc_window = tdm_hwc_create_window(hwc->thwc, &terror); + if (!hwc_window->thwc_window) { + PEPPER_ERROR("tdm_hwc_create_window() failed.\n"); + free(hwc_window); + return NULL; + } + hwc_window->tcomposition_type = TDM_HWC_WIN_COMPOSITION_NONE; + + PEPPER_INFO("surface:%p hwc_window:%p thwc_window:%p.\n", + surface, hwc_window, hwc_window->thwc_window); + + hwc_window->hwc = (pepper_tdm_hwc_t *)hwc; + hwc_window->surface = surface; + hwc_window->surface_destroy_listener = + pepper_object_add_event_listener((pepper_object_t *)surface, + PEPPER_EVENT_OBJECT_DESTROY, 0, + __hwc_window_handle_surface_destroy, hwc_window); + + pepper_list_init(&hwc_window->prop_list); + pepper_object_set_user_data((pepper_object_t *)surface, hwc, hwc_window, NULL); + + pepper_list_insert(&hwc->window_list, &hwc_window->link); + } + + return hwc_window; +} + +pepper_bool_t +pepper_tdm_hwc_attach_surface(pepper_tdm_hwc_t *hwc, pepper_surface_t *surface) +{ + pepper_tdm_hwc_window_t *hwc_window = __get_hwc_window(hwc, surface); + pepper_buffer_t *buffer = pepper_surface_get_buffer(surface); + + __hwc_window_release_buffer(hwc_window); + + if (!buffer) { + hwc_window->buffer_width = 0; + hwc_window->buffer_height = 0; + goto done; + } + + if (__hwc_window_attach_shm(hwc_window, buffer)) + goto done; + +#ifdef HAVE_TBM + if (__hwc_window_attach_tbm(hwc_window, buffer)) + goto done; +#endif + + if (__hwc_window_attach_egl(hwc_window, buffer)) + goto done; + + PEPPER_ERROR("Not supported buffer type.\n"); + return PEPPER_FALSE; + +done: + hwc_window->buffer = buffer; + + if (hwc_window->buffer) { + hwc_window->buffer_destroy_listener = + pepper_object_add_event_listener((pepper_object_t *)buffer, + PEPPER_EVENT_OBJECT_DESTROY, 0, + __hwc_window_handle_buffer_destroy, hwc_window); + } + + return PEPPER_TRUE; +} + +// check the changes of the visible_window_list on hwc +// check chagnes below +// - number of visible windows +// - windows stack +// - add a window on the list +// - remove a window on the list +// - change the order of windows : window stack +static pepper_bool_t +__hwc_check_changes_visible_window_list(pepper_tdm_hwc_t *hwc, + pepper_list_t *visible_window_list, + unsigned int num_visible_wins) +{ + pepper_list_t *prev_list; + pepper_list_t *curr_list; + pepper_tdm_hwc_window_t *hwc_window1, *hwc_window2, *tmp; + unsigned int i, cnt; + + // first time + if (!hwc->visible_window_list) + return PEPPER_TRUE; + + prev_list = hwc->visible_window_list; + curr_list = visible_window_list; + + if (hwc->num_visible_wins != num_visible_wins) + return PEPPER_TRUE; + + for (i = 0; i < num_visible_wins; i++) { + cnt = 0; + pepper_list_for_each_safe(hwc_window1, tmp, prev_list, link) + if (i == cnt++) break; + cnt = 0; + pepper_list_for_each_safe(hwc_window2, tmp, curr_list, link) + if (i == cnt++) break; + + if (hwc_window1 != hwc_window2) return PEPPER_TRUE; + } + + return PEPPER_FALSE; +} + +static void +__hwc_visible_window_list_destory(pepper_list_t *visible_window_list) +{ + pepper_tdm_hwc_window_t *hwc_window, *tmp; + + if (!visible_window_list) + return; + + pepper_list_for_each_safe(hwc_window, tmp, visible_window_list, visible_window_link) + pepper_list_remove(&hwc_window->visible_window_link); + + free(visible_window_list); +} + +// create a visible window list with a view list +static pepper_list_t * +__hwc_create_visible_window_list(pepper_tdm_hwc_t *hwc, + const pepper_list_t *view_list, + unsigned int *num_visible_wins) +{ + pepper_list_t *visible_window_list, *l; + pepper_view_t *view; + pepper_surface_t *surface; + pepper_tdm_hwc_window_t *hwc_window, *hwc_window2; + + visible_window_list = calloc(1, sizeof(pepper_list_t)); + if (!visible_window_list) + return NULL; + + pepper_list_init(visible_window_list); + + // make a visible_window_list + // TODO: CHECK Point.. + // does not add hwc_window to the visible window list + // when a pepper_view does not have a pepper_surface because + // a hwc_window is only associated with a pepper_surface + pepper_list_for_each_list(l, view_list) { + view = l->item; + surface = pepper_view_get_surface(view); + if (!surface) + continue; + + hwc_window = pepper_object_get_user_data((pepper_object_t *)surface, hwc); + if (!hwc_window) + continue; + + hwc_window2 = pepper_object_get_user_data((pepper_object_t *)view, hwc); + if (!hwc_window2) + pepper_object_set_user_data((pepper_object_t *)view, hwc, hwc_window, NULL); + + PEPPER_INFO("surface:%p view:%p hwc_window:%p thwc_window:%p.\n", + surface, view, hwc_window, hwc_window->thwc_window); + + pepper_list_insert(visible_window_list, &hwc_window->visible_window_link); + ++(*num_visible_wins); + } + + PEPPER_INFO("num_visible_wins curr:%d, necxt:%d\n", hwc->num_visible_wins, num_visible_wins); + + return visible_window_list; +} + +// change the visible window list on hwc with the given visible window list +static void +__hwc_change_visible_window_list(pepper_tdm_hwc_t *hwc, pepper_list_t *visible_window_list, + unsigned int num_visible_wins) +{ + __hwc_visible_window_list_destory(hwc->visible_window_list); + + hwc->num_visible_wins = num_visible_wins; + hwc->visible_window_list = visible_window_list; +} + +// update the visible window list on hwc with the given visible view list +static pepper_bool_t +__hwc_update_visible_window_list(pepper_tdm_hwc_t *hwc, const pepper_list_t *view_list) +{ + pepper_list_t *visible_window_list; + unsigned int num_visible_wins = 0; + + // get a visible hwc window list from view list + visible_window_list = __hwc_create_visible_window_list(hwc, view_list, &num_visible_wins); + if (!visible_window_list) + return PEPPER_FALSE; + + // check the changes of the visible windows + if (!__hwc_check_changes_visible_window_list(hwc, visible_window_list, num_visible_wins)) { + __hwc_visible_window_list_destory(visible_window_list); + return PEPPER_FALSE; + } + + __hwc_change_visible_window_list(hwc, visible_window_list, num_visible_wins); + + return PEPPER_TRUE; +} + +static void +__hwc_window_update_composition_type(pepper_tdm_hwc_window_t *hwc_window, + tdm_hwc_window_composition tcomposition_type) +{ + tdm_error terror; + + if (hwc_window->tcomposition_type == tcomposition_type) + return; + + terror = tdm_hwc_window_set_composition_type(hwc_window->thwc_window, + tcomposition_type); + if (terror != TDM_ERROR_NONE) + PEPPER_ERROR("tdm_hwc_window_set_composition failed. hwc_window:%p\n", hwc_window); + else + hwc_window->tcomposition_type = tcomposition_type; +} + +static pepper_bool_t +__hwc_window_update_buffer(pepper_tdm_hwc_window_t *hwc_window) +{ + tdm_error terror; + + terror = tdm_hwc_window_set_buffer(hwc_window->thwc_window, + hwc_window->tbm_surface); + PEPPER_CHECK(terror == TDM_ERROR_NONE, return PEPPER_FALSE, + "tdm_hwc_window_set_buffer() failed.\n"); + + return PEPPER_TRUE; +} + +//TODO: move this function to util file. +static unsigned int +__hwc_window_tbm_get_aligned_width_get(tbm_surface_h tsurface) +{ + unsigned int aligned_width = 0; + tbm_surface_info_s surf_info; + + tbm_surface_get_info(tsurface, &surf_info); + + switch (surf_info.format) + { + case TBM_FORMAT_YUV420: + case TBM_FORMAT_YVU420: + case TBM_FORMAT_YUV422: + case TBM_FORMAT_YVU422: + case TBM_FORMAT_NV12: + case TBM_FORMAT_NV21: + aligned_width = surf_info.planes[0].stride; + break; + case TBM_FORMAT_YUYV: + case TBM_FORMAT_UYVY: + aligned_width = surf_info.planes[0].stride >> 1; + break; + case TBM_FORMAT_XRGB8888: + case TBM_FORMAT_XBGR8888: + case TBM_FORMAT_RGBX8888: + case TBM_FORMAT_BGRX8888: + case TBM_FORMAT_ARGB8888: + case TBM_FORMAT_ABGR8888: + case TBM_FORMAT_RGBA8888: + case TBM_FORMAT_BGRA8888: + case TBM_FORMAT_XRGB2101010: + case TBM_FORMAT_XBGR2101010: + case TBM_FORMAT_RGBX1010102: + case TBM_FORMAT_BGRX1010102: + case TBM_FORMAT_ARGB2101010: + case TBM_FORMAT_ABGR2101010: + case TBM_FORMAT_RGBA1010102: + case TBM_FORMAT_BGRA1010102: + aligned_width = surf_info.planes[0].stride >> 2; + break; + default: + PEPPER_ERROR("not supported format: %c%c%c%c", FOURCC_STR(surf_info.format)); + } + + return aligned_width; +} + +static pepper_bool_t +__hwc_window_info_get(pepper_tdm_hwc_window_t *hwc_window, tdm_hwc_window_info *hwc_win_info) +{ + tbm_surface_h tsurface = NULL; + tbm_surface_info_s surf_info = {0}; + int x, y, w, h; + + tsurface = hwc_window->tbm_surface; + if (!tsurface) + return PEPPER_FALSE; + + tbm_surface_get_info(tsurface, &surf_info); + + // make the source infomation + hwc_win_info->src_config.format = surf_info.format; + hwc_win_info->src_config.pos.x = 0; + hwc_win_info->src_config.pos.y = 0; + hwc_win_info->src_config.pos.w = surf_info.width; + hwc_win_info->src_config.pos.h = surf_info.height; + + hwc_win_info->src_config.size.h = __hwc_window_tbm_get_aligned_width_get(tsurface); + PEPPER_CHECK(hwc_win_info->src_config.size.h == 0, return PEPPER_FALSE, + "hwc_win_info->src_config.size.h is 0.\n"); + hwc_win_info->src_config.size.v = surf_info.height; + + // make the destination information + // TODO: calculate the result of the tranformation which + // is the final dest information from + // (buffer_to_surface * surface_to_global * global_to_output). + x = 0; + y = 0; + w = hwc_win_info->src_config.size.h; + h = hwc_win_info->src_config.size.v; + + hwc_win_info->dst_pos.x = x; + hwc_win_info->dst_pos.y = y; + hwc_win_info->dst_pos.w = w; + hwc_win_info->dst_pos.h = h; + + hwc_win_info->transform = TDM_TRANSFORM_NORMAL; + + return PEPPER_TRUE; +} + +static pepper_bool_t +__hwc_window_update_info(pepper_tdm_hwc_window_t *hwc_window) +{ + tdm_error terror; + tdm_hwc_window_info hwc_win_info; + + // get the hwc information to be updated + if (!__hwc_window_info_get(hwc_window, &hwc_win_info)) + return PEPPER_FALSE; + + // compare the hwc information with current hwc information on hwc_window + if (!memcmp(&hwc_window->current.info, &hwc_win_info, sizeof(tdm_hwc_window_info))) + return PEPPER_FALSE; + + terror = tdm_hwc_window_set_info(hwc_window->thwc_window, &hwc_window->current.info); + PEPPER_CHECK(terror == TDM_ERROR_NONE, return PEPPER_FALSE, + "tdm_hwc_window_set_info() failed.\n"); + + // change the current hwc information with the hwc inf + memcpy(&hwc_window->current.info, &hwc_win_info, sizeof(tdm_hwc_window_info)); + + return PEPPER_TRUE; +} + +static pepper_bool_t +__hwc_window_update_prop(pepper_tdm_hwc_window_t *hwc_window) +{ + pepper_tdm_hwc_prop_t *prop, *tmp; + tdm_error terror; + + pepper_list_for_each_safe(prop, tmp, &hwc_window->prop_list, link) { + terror = tdm_hwc_window_set_property(hwc_window->thwc_window, prop->id, prop->value); + PEPPER_CHECK(terror == TDM_ERROR_NONE, return PEPPER_FALSE, + "tdm_hwc_window_set_info() failed.\n"); + + // delete the prop + pepper_list_remove(&prop->link); + free(prop); + } + + return PEPPER_TRUE; +} + +// TODO: update the composition type of the view +pepper_bool_t +pepper_tdm_hwc_update_changes(pepper_tdm_hwc_t *hwc, const pepper_list_t *view_list) +{ + pepper_bool_t changed = PEPPER_FALSE; + pepper_tdm_hwc_window_t *hwc_window; + + PEPPER_INFO("\n"); + + changed = __hwc_update_visible_window_list(hwc, view_list); + + pepper_list_for_each(hwc_window, &hwc->window_list, link) { + PEPPER_INFO("hwc_window:%p thwc_window:%p\n", hwc_window, hwc_window->thwc_window); + + // reset the composition types of visible windows + __hwc_window_update_composition_type(hwc_window, TDM_HWC_WIN_COMPOSITION_NONE); + + changed = __hwc_window_update_buffer(hwc_window); + changed = __hwc_window_update_info(hwc_window); + changed = __hwc_window_update_prop(hwc_window); + } + + // set the composition types of visible windows + // TODO: all gl composite... for verifiying . + if (changed) { + pepper_list_for_each(hwc_window, hwc->visible_window_list, visible_window_link) + __hwc_window_update_composition_type(hwc_window, TDM_HWC_WIN_COMPOSITION_CLIENT); + } + + return PEPPER_TRUE; +} + +static pepper_tdm_hwc_window_t * +__hwc_find_hwc_window_with_thwc_window(pepper_tdm_hwc_t *hwc, tdm_hwc_window *thwc_window) +{ + pepper_tdm_hwc_window_t *hwc_window; + + pepper_list_for_each(hwc_window, &hwc->window_list, link) { + if (hwc_window->thwc_window == thwc_window) { + return hwc_window; + } + } + + return NULL; +} + +static pepper_bool_t +__hwc_update_validated_changes(pepper_tdm_hwc_t *hwc, uint32_t num_changes) +{ + pepper_tdm_hwc_window_t *hwc_window; + tdm_hwc_window **changed_hwc_window = NULL; + tdm_hwc_window_composition *composition_types = NULL; + tdm_error terror; + uint32_t i; + + changed_hwc_window = calloc(num_changes, sizeof(tdm_hwc_window *)); + PEPPER_CHECK(changed_hwc_window, goto error, + "changed_hwc_window allocation failed.\n"); + + composition_types = calloc(num_changes, sizeof(tdm_hwc_window_composition)); + PEPPER_CHECK(composition_types, goto error, + "composition_types allocation failed.\n"); + + terror = tdm_hwc_get_changed_composition_types(hwc->thwc, + &num_changes, changed_hwc_window, + composition_types); + PEPPER_CHECK(terror == TDM_ERROR_NONE, goto error, + "tdm_hwc_get_changed_composition_types() failed.\n"); + + // update the tdm compostioin types + for (i = 0; i < num_changes; ++i) { + hwc_window = __hwc_find_hwc_window_with_thwc_window(hwc, changed_hwc_window[i]); + PEPPER_CHECK(hwc_window, goto error, + "__hwc_find_hwc_window_with_thwc_window() failed.\n"); + + __hwc_window_update_composition_type(hwc_window, composition_types[i]); + } + + free(changed_hwc_window); + free(composition_types); + + return PEPPER_TRUE; + +error: + if (changed_hwc_window) + free(changed_hwc_window); + if (composition_types) + free(composition_types); + + return PEPPER_FALSE; +} + +static pepper_bool_t +__hwc_validate(pepper_tdm_hwc_t *hwc) +{ + pepper_tdm_hwc_window_t *hwc_window; + tdm_hwc_window **thwc_windows = NULL; + tdm_error terror; + uint32_t i, n_thw, num_changes; + pepper_bool_t ret; + + n_thw = hwc->num_visible_wins; + if (n_thw) { + thwc_windows = calloc(n_thw, sizeof(tdm_hwc_window *)); + PEPPER_CHECK(thwc_windows, return PEPPER_FALSE, "thwc_window allocation failed.\n"); + i = 0; + pepper_list_for_each(hwc_window, hwc->visible_window_list, visible_window_link) { + PEPPER_INFO("[%d] hwc_window:%p thwc_window:%p\n", i, hwc_window, hwc_window->thwc_window); + thwc_windows[i++] = hwc_window->thwc_window; + } + } + + terror = tdm_hwc_validate(hwc->thwc, thwc_windows, n_thw, &num_changes); + PEPPER_CHECK(terror == TDM_ERROR_NONE , goto error, "tdm_hwc_validate() failed.\n"); + + if (num_changes > 0) { + ret = __hwc_update_validated_changes(hwc, num_changes); + PEPPER_CHECK(ret, goto error, "__hwc_update_validated_changes() failed.\n"); + } + + if (thwc_windows) + free(thwc_windows); + + return PEPPER_TRUE; + +error: + if (thwc_windows) + free(thwc_windows); + + return PEPPER_FALSE; +} + +pepper_bool_t +pepper_tdm_hwc_evaluate(pepper_tdm_hwc_t *hwc, const pepper_list_t *view_list) +{ + pepper_tdm_hwc_window_t *hwc_window; + pepper_list_t *l; + pepper_view_t *view; + pepper_bool_t ret; + uint32_t num_client = 0, num_device = 0, num_video = 0, num_cursor = 0; + + PEPPER_INFO("\n"); + + // validate the hwc_windows on visible_hwc_window + ret = __hwc_validate(hwc); + PEPPER_CHECK(ret == PEPPER_TRUE, goto error, "__hwc_validate() failed.\n"); + + // assign a entry to render when the composition type is client type. + pepper_list_for_each_list(l, view_list) { + view = l->item; + hwc_window = pepper_object_get_user_data((pepper_object_t *)view, hwc); + if (!hwc_window) { + PEPPER_ERROR("There is no hwc_window from view.\n"); + continue; + } + + if (hwc_window->tcomposition_type != TDM_HWC_WIN_COMPOSITION_CLIENT) + continue; + + // assign the entry to target render when the hwc_window of the view has client type. + pepper_view_assign_hwc_entry(view, hwc->output->base, PEPPER_TRUE); + } + + // count the number of each composition type. + pepper_list_for_each(hwc_window, &hwc->window_list, link) { + if (hwc_window->tcomposition_type == TDM_HWC_WIN_COMPOSITION_CLIENT) + num_client++; + if (hwc_window->tcomposition_type == TDM_HWC_WIN_COMPOSITION_DEVICE) + num_device++; + if (hwc_window->tcomposition_type == TDM_HWC_WIN_COMPOSITION_CURSOR) + num_cursor++; + if (hwc_window->tcomposition_type == TDM_HWC_WIN_COMPOSITION_VIDEO) + num_video++; + } + + // TODO: figure out the conditions to re-evaludate the hwc. + // set hwc->accept_validation to be PEPPER_FALSE if re-evaluation is needed. + // do not call tdm_hwc_accept_validation and tdm_hwc_commit + // when hwc->accept_validataion is PEPPER_FALSETRUE. + hwc->accept_validation = PEPPER_TRUE; + + return PEPPER_TRUE; + +error: + hwc->accept_validation = PEPPER_FALSE; + + return PEPPER_FALSE; +} + +static pepper_tdm_hwc_window_commit_data_t * +__hwc_create_window_commit_data(pepper_tdm_hwc_window_t *hwc_window) +{ + pepper_tdm_hwc_window_commit_data_t *window_commit_data; + + window_commit_data = calloc(1, sizeof(pepper_tdm_hwc_window_commit_data_t)); + PEPPER_CHECK(window_commit_data, return NULL, + "commit_data allocation failed.\n"); + window_commit_data->hwc_window = hwc_window; + + return window_commit_data; +} + +static pepper_tdm_hwc_commit_data_t * +__hwc_create_commit_data(pepper_tdm_hwc_t *hwc) +{ + pepper_tdm_hwc_window_t *hwc_window; + pepper_tdm_hwc_commit_data_t *commit_data; + pepper_tdm_hwc_window_commit_data_t *window_commit_data; + + commit_data = calloc(1, sizeof(pepper_tdm_hwc_commit_data_t)); + PEPPER_CHECK(commit_data, goto error, + "commit_data allocation failed.\n"); + commit_data->hwc = hwc; + + pepper_list_init(&commit_data->window_commit_data_list); + + pepper_list_for_each(hwc_window, &hwc->window_list, link) { + window_commit_data = __hwc_create_window_commit_data(hwc_window); + if (!window_commit_data) + continue; + + pepper_list_insert(&commit_data->window_commit_data_list, &window_commit_data->link); + } + + return commit_data; + +error: + if (commit_data) + free(commit_data); + + return NULL; +} + +static void +__hwc_destory_window_commit_data(pepper_tdm_hwc_t *hwc, + pepper_tdm_hwc_window_commit_data_t *window_commit_data, + unsigned int sequence, unsigned int tv_sec, unsigned int tv_usec) +{ + // TODO: do something here + + pepper_list_remove(&window_commit_data->link); + free(window_commit_data); +} + +static void +__hwc_destroy_commit_data(pepper_tdm_hwc_t *hwc, + pepper_tdm_hwc_commit_data_t *commit_data, + unsigned int sequence, unsigned int tv_sec, unsigned int tv_usec) +{ + pepper_tdm_hwc_window_commit_data_t *window_commit_data, *tmp; + + pepper_list_for_each_safe(window_commit_data, tmp, &commit_data->window_commit_data_list, link) { + // TODO: do something here + + __hwc_destory_window_commit_data(hwc, window_commit_data, sequence, tv_sec, tv_usec); + } + + free(commit_data); +} + +static void +__hwc_commit_handler(tdm_hwc *thwc, unsigned int sequence, + unsigned int tv_sec, unsigned int tv_usec, + void *user_data) +{ + pepper_tdm_hwc_commit_data_t *commit_data = (pepper_tdm_hwc_commit_data_t *)user_data; + // TODO: do something here + + pepper_tdm_output_commit_cb(commit_data->hwc->output, sequence, tv_sec, tv_usec); + + __hwc_destroy_commit_data(commit_data->hwc, commit_data, sequence, tv_sec, tv_usec); +} + +pepper_bool_t +pepper_tdm_hwc_commit(pepper_tdm_hwc_t *hwc) +{ + pepper_tdm_hwc_commit_data_t *commit_data = NULL; + tdm_error terror; + + PEPPER_INFO("\n"); + + // do not commit when the accept_validateion is not allowed. + if (!hwc->accept_validation) { + PEPPER_INFO("accept_validation:%d\n", hwc->accept_validation); + return PEPPER_TRUE; + } + hwc->accept_validation = PEPPER_FALSE; + + /* accept validataion */ + terror = tdm_hwc_accept_validation(hwc->thwc); + PEPPER_CHECK(terror == TDM_ERROR_NONE , return PEPPER_FALSE, "tdm_hwc_accept_validation() failed.\n"); + + commit_data = __hwc_create_commit_data(hwc); + PEPPER_CHECK(terror == TDM_ERROR_NONE , return PEPPER_FALSE, "__hwc_create_commit_data() failed.\n"); + + terror = tdm_hwc_commit(hwc->thwc, 0, __hwc_commit_handler, commit_data); + PEPPER_CHECK(terror == TDM_ERROR_NONE , goto error, "tdm_hwc_commit() failed.\n"); + + return PEPPER_TRUE; + +error: + if (commit_data) + __hwc_destroy_commit_data(hwc, commit_data, 0, 0, 0); + + hwc->accept_validation = PEPPER_FALSE; + + return PEPPER_FALSE; +} + +pepper_bool_t +pepper_tdm_hwc_set_client_target_buffer(pepper_tdm_hwc_t *hwc, tbm_surface_h tsurface) +{ + tdm_region fb_damage; + tdm_error terror; + + CLEAR(fb_damage); + terror = tdm_hwc_set_client_target_buffer(hwc->thwc, tsurface, fb_damage); + PEPPER_CHECK(terror == TDM_ERROR_NONE , return PEPPER_FALSE, "tdm_hwc_set_client_target_buffer() failed.\n"); + + return PEPPER_TRUE; +} diff --git a/src/lib/tdm/tdm-internal.h b/src/lib/tdm/tdm-internal.h index cd69f08..74907ec 100644 --- a/src/lib/tdm/tdm-internal.h +++ b/src/lib/tdm/tdm-internal.h @@ -167,4 +167,13 @@ struct pepper_tdm_hwc_commit_data { int pepper_tdm_output_init(pepper_tdm_t *tdm); +void pepper_tdm_output_commit_cb(pepper_tdm_output_t *output, unsigned int sequence, + unsigned int tv_sec, unsigned int tv_usec); + +pepper_bool_t pepper_tdm_hwc_attach_surface(pepper_tdm_hwc_t *hwc, pepper_surface_t *surface); +pepper_bool_t pepper_tdm_hwc_update_changes(pepper_tdm_hwc_t *hwc, const pepper_list_t *view_list); +pepper_bool_t pepper_tdm_hwc_evaluate(pepper_tdm_hwc_t *hwc, const pepper_list_t *view_list); +pepper_bool_t pepper_tdm_hwc_commit(pepper_tdm_hwc_t *hwc); +pepper_bool_t pepper_tdm_hwc_set_client_target_buffer(pepper_tdm_hwc_t *hwc, tbm_surface_h tsurface); + #endif /* DRM_INTERNAL_H */ diff --git a/src/lib/tdm/tdm-output.c b/src/lib/tdm/tdm-output.c index eeb4a09..30dbd82 100644 --- a/src/lib/tdm/tdm-output.c +++ b/src/lib/tdm/tdm-output.c @@ -347,14 +347,13 @@ error: return PEPPER_FALSE; } -static void -__tdm_output_commit_cb(tdm_output *o, unsigned int sequence, - unsigned int tv_sec, unsigned int tv_usec, void *user_data) +void +pepper_tdm_output_commit_cb(pepper_tdm_output_t *output, unsigned int sequence, + unsigned int tv_sec, unsigned int tv_usec) { PEPPER_INFO("\n"); - pepper_tdm_output_t *output = user_data; - struct timespec ts; + struct timespec ts; if (output->page_flip_pending == PEPPER_TRUE) { output->page_flip_pending = PEPPER_FALSE; @@ -372,6 +371,15 @@ __tdm_output_commit_cb(tdm_output *o, unsigned int sequence, pepper_output_finish_frame(output->base, &ts); } +static void +__tdm_output_commit_cb(tdm_output *o, unsigned int sequence, + unsigned int tv_sec, unsigned int tv_usec, void *user_data) +{ + pepper_tdm_output_t *output = user_data; + + pepper_tdm_output_commit_cb(output, sequence, tv_sec, tv_usec); +} + static void pepper_tdm_output_destroy(void *o) { -- 2.34.1