add pepper_tdm_hwc functions 16/263816/1
authorSooChan Lim <sc1.lim@samsung.com>
Fri, 10 Sep 2021 08:07:04 +0000 (17:07 +0900)
committerSooChan Lim <sc1.lim@samsung.com>
Fri, 10 Sep 2021 08:07:04 +0000 (17:07 +0900)
Change-Id: Idff22254f676132d1bf28d9e2760da2800db4d92

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

index c3e5e64..e52cac1 100644 (file)
@@ -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 (file)
index 0000000..d2f6a2a
--- /dev/null
@@ -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;
+}
index cd69f08..74907ec 100644 (file)
@@ -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 */
index eeb4a09..30dbd82 100644 (file)
@@ -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;
@@ -373,6 +372,15 @@ __tdm_output_commit_cb(tdm_output *o, unsigned int sequence,
 }
 
 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)
 {
        PEPPER_INFO("\n");