tdm: implement the tdm_hwc display 17/263817/1
authorSooChan Lim <sc1.lim@samsung.com>
Fri, 10 Sep 2021 08:08:54 +0000 (17:08 +0900)
committerSooChan Lim <sc1.lim@samsung.com>
Fri, 10 Sep 2021 08:08:54 +0000 (17:08 +0900)
output uses tdm_hwc.

Change-Id: I99bfc15c95c80d52a53aefcd60813ead77e1e1a0

src/lib/tdm/tdm-output.c

index 30dbd82..8183a83 100644 (file)
@@ -88,21 +88,56 @@ __tdm_renderer_pixman_get_target(tbm_surface_h surface)
        return target;
 }
 
+static const pepper_list_t *
+__tdm_output_get_render_list(pepper_tdm_output_t *output)
+{
+       const pepper_list_t *render_list;
+
+       if (output->hwc)
+               render_list = pepper_hwc_get_render_list(output->hwc->base);
+       else
+               render_list = pepper_plane_get_render_list(output->primary_plane->base);
+
+       return render_list;
+}
+
+static pepper_region_t *
+__tdm_output_get_damage_region(pepper_tdm_output_t *output)
+{
+       pepper_region_t *damage;
+
+       if (output->hwc)
+               damage = pepper_hwc_get_damage_region(output->hwc->base);
+       else
+               damage = pepper_plane_get_damage_region(output->primary_plane->base);
+
+       return damage;
+}
+
+static void
+__tdm_output_clear_damage_region(pepper_tdm_output_t *output)
+{
+       if (output->hwc)
+               pepper_hwc_clear_damage_region(output->hwc->base);
+       else
+               pepper_plane_clear_damage_region(output->primary_plane->base);
+}
+
 static void
 __tdm_renderer_pixman_render(pepper_tdm_output_t *output)
 {
        PEPPER_INFO("\n");
 
-       const pepper_list_t *render_list = pepper_plane_get_render_list(
-                                                                                  output->primary_plane->base);
-       pepper_region_t   *damage = pepper_plane_get_damage_region(
-                                                                         output->primary_plane->base);
-       pepper_region_t    total_damage;
-       tbm_surface_h       back;
+       const pepper_list_t    *render_list;
+       pepper_region_t        *damage;
+       pepper_region_t         total_damage;
+       tbm_surface_h           back;
        pepper_render_target_t *target;
-
        int ret;
 
+       render_list = __tdm_output_get_render_list(output);
+       damage = __tdm_output_get_damage_region(output);
+
        /*Set render target*/
        ret = tbm_surface_queue_dequeue(output->tbm_surface_queue, &back);
        PEPPER_CHECK(ret == TBM_SURFACE_QUEUE_ERROR_NONE, return,
@@ -122,7 +157,15 @@ __tdm_renderer_pixman_render(pepper_tdm_output_t *output)
                                                                        &total_damage);
 
        pepper_region_fini(&total_damage);
-       pepper_plane_clear_damage_region(output->primary_plane->base);
+
+       __tdm_output_clear_damage_region(output);
+
+#if 0 // for debugging
+       static int dump_cnt = 0;
+       char filename[256];
+       snprintf(filename, sizeof filename, "/tmp/pixman_render_%d.png", dump_cnt++);
+       tdm_helper_dump_buffer(back, (const char*)filename);
+#endif
 
        output->back = back;
 }
@@ -137,8 +180,13 @@ __tdm_renderer_pixman_fini(pepper_tdm_output_t *output)
        if (output->render_target)
                pepper_render_target_destroy(output->render_target);
 
-       if (output->tbm_surface_queue)
-               tbm_surface_queue_destroy(output->tbm_surface_queue);
+       if (output->tbm_surface_queue) {
+               // DO NOT destroy tbm_surface_queue_h
+               if (output->hwc)
+                       output->tbm_surface_queue = NULL;
+               else
+                       tbm_surface_queue_destroy(output->tbm_surface_queue);
+       }
 
        output->renderer = NULL;
        output->render_target = NULL;
@@ -148,7 +196,9 @@ __tdm_renderer_pixman_fini(pepper_tdm_output_t *output)
 static void
 __tdm_renderer_pixman_init(pepper_tdm_output_t *output)
 {
-       pepper_tdm_t   *tdm = output->tdm;
+       pepper_tdm_t     *tdm = output->tdm;
+       pepper_tdm_hwc_t *hwc = output->hwc;
+
        const tdm_output_mode *mode;
        tdm_error err = TDM_ERROR_NONE;
 
@@ -164,12 +214,19 @@ __tdm_renderer_pixman_init(pepper_tdm_output_t *output)
 
        err = tdm_output_get_mode(output->toutput, &mode);
        PEPPER_CHECK(err == TDM_ERROR_NONE, goto error,
-                       "tdm_output_get_mode() failed.\n");
-       output->tbm_surface_queue = tbm_surface_queue_create(3,
-                                                       mode->hdisplay, mode->vdisplay,
-                                                       TBM_FORMAT_XBGR8888, TBM_BO_SCANOUT);
-       PEPPER_CHECK(output->tbm_surface_queue, goto error,
-               "tbm_surface_queue_create() failed.\n");
+                                        "tdm_output_get_mode() failed.\n");
+
+       if (output->hwc) {
+               output->tbm_surface_queue = tdm_hwc_get_client_target_buffer_queue(hwc->thwc, &err);
+               PEPPER_CHECK(output->tbm_surface_queue, goto error,
+                                       "tdm_hwc_get_client_target_buffer_queue() failed.\n");
+       } else {
+               output->tbm_surface_queue = tbm_surface_queue_create(3,
+                                                                                                               mode->hdisplay, mode->vdisplay,
+                                                                                                               TBM_FORMAT_XBGR8888, TBM_BO_SCANOUT);
+               PEPPER_CHECK(output->tbm_surface_queue, goto error,
+                                               "tbm_surface_queue_create() failed.\n");
+       }
 
        pepper_region_init(&output->previous_damage);
        output->render_type = TDM_RENDER_TYPE_PIXMAN;
@@ -186,14 +243,14 @@ __tdm_renderer_gl_render(pepper_tdm_output_t *output)
        PEPPER_INFO("\n");
 
        int ret;
+       const pepper_list_t *render_list;
+       pepper_region_t *damage;
 
-       const pepper_list_t *render_list = pepper_plane_get_render_list(
-                                                                                  output->primary_plane->base);
-       pepper_region_t   *damage = pepper_plane_get_damage_region(
-                                                                         output->primary_plane->base);
+       render_list = __tdm_output_get_render_list(output);
+       damage = __tdm_output_get_damage_region(output);
 
        pepper_renderer_repaint_output(output->renderer, output->base, render_list,
-                                                                  damage);
+                                                                       damage);
 
        ret = tbm_surface_queue_can_acquire(output->tbm_surface_queue, 1);
        PEPPER_CHECK(ret > 0, return, "tbm_surface_queue_can_acquire() failed.\n");
@@ -202,7 +259,7 @@ __tdm_renderer_gl_render(pepper_tdm_output_t *output)
        PEPPER_CHECK(ret == TBM_SURFACE_QUEUE_ERROR_NONE, return,
                                 "tbm_surface_queue_acquire() failed.\n");
 
-       pepper_plane_clear_damage_region(output->primary_plane->base);
+       __tdm_output_clear_damage_region(output);
 }
 
 static void
@@ -213,8 +270,13 @@ __tdm_renderer_gl_fini(pepper_tdm_output_t *output)
        if (output->render_target)
                pepper_render_target_destroy(output->render_target);
 
-       if (output->tbm_surface_queue)
-               tbm_surface_queue_destroy(output->tbm_surface_queue);
+       if (output->tbm_surface_queue) {
+               // DO NOT destroy tbm_surface_queue_h
+               if (output->hwc)
+                       output->tbm_surface_queue = NULL;
+               else
+                       tbm_surface_queue_destroy(output->tbm_surface_queue);
+       }
 
        output->renderer = NULL;
        output->render_target = NULL;
@@ -226,10 +288,11 @@ __tdm_renderer_gl_init(pepper_tdm_output_t *output)
 {
        PEPPER_INFO("\n");
 
-       pepper_tdm_t    *tdm = output->tdm;
+       pepper_tdm_t          *tdm = output->tdm;
+       pepper_tdm_hwc_t      *hwc = output->hwc;
        const tdm_output_mode *mode;
-       uint32_t                  native_visual_id = TBM_FORMAT_XRGB8888;
-       tdm_error err = TDM_ERROR_NONE;
+       uint32_t                       native_visual_id = TBM_FORMAT_XRGB8888;
+       tdm_error              err = TDM_ERROR_NONE;
 
        if (!tdm->gl_renderer) {
                  tdm->gl_renderer = pepper_gl_renderer_create(tdm->compositor, tdm->bufmgr,
@@ -243,18 +306,29 @@ __tdm_renderer_gl_init(pepper_tdm_output_t *output)
        PEPPER_CHECK(err == TDM_ERROR_NONE, goto error,
                                         "tdm_output_get_mode() failed.\n");
 
-       output->tbm_surface_queue = tbm_surface_queue_create(3,
-                                                       mode->hdisplay, mode->vdisplay,
-                                                       TBM_FORMAT_XRGB8888,
-                                                       TBM_BO_SCANOUT);
-       PEPPER_CHECK(output->tbm_surface_queue, goto error,
-                               "tbm_surface_queue_create() failed.\n");
-
-       output->render_target = pepper_gl_renderer_create_target(tdm->gl_renderer,
-                                                               output->tbm_surface_queue,
-                                                               PEPPER_FORMAT_XRGB8888,
-                                                               &native_visual_id,
-                                                               mode->hdisplay, mode->vdisplay);
+       if (output->hwc) {
+               output->tbm_surface_queue = tdm_hwc_get_client_target_buffer_queue(hwc->thwc, &err);
+               PEPPER_CHECK(err == TDM_ERROR_NONE, goto error,
+                                       "tdm_hwc_get_client_target_buffer_queue() failed.\n");
+               output->render_target = pepper_gl_renderer_create_target(tdm->gl_renderer,
+                                                                                                                               output->tbm_surface_queue,
+                                                                                                                               PEPPER_FORMAT_XRGB8888,
+                                                                                                                               &native_visual_id,
+                                                                                                                               mode->hdisplay, mode->vdisplay);
+       } else {
+               output->tbm_surface_queue = tbm_surface_queue_create(3,
+                                                                                                                       mode->hdisplay, mode->vdisplay,
+                                                                                                                       TBM_FORMAT_XRGB8888,
+                                                                                                                       TBM_BO_SCANOUT);
+               PEPPER_CHECK(output->tbm_surface_queue, goto error,
+                                               "tbm_surface_queue_create() failed.\n");
+
+               output->render_target = pepper_gl_renderer_create_target(tdm->gl_renderer,
+                                                                                                                               output->tbm_surface_queue,
+                                                                                                                               PEPPER_FORMAT_XRGB8888,
+                                                                                                                               &native_visual_id,
+                                                                                                                               mode->hdisplay, mode->vdisplay);
+       }
        PEPPER_CHECK(output->render_target, goto error,
                                         "pepper_gl_renderer_create_target() failed.\n");
        output->render_type = TDM_RENDER_TYPE_GL;
@@ -268,6 +342,78 @@ error:
 }
 
 static void
+__tdm_hwc_destroy(pepper_event_listener_t *listener, pepper_object_t *object,
+                                       uint32_t id, void *info, void *data)
+{
+       PEPPER_INFO("\n");
+
+       free(data);
+}
+
+static int
+__tdm_output_hwc_init(pepper_tdm_output_t *output)
+{
+       pepper_tdm_hwc_t *hwc;
+       tdm_hwc *thwc;
+       tdm_error err;
+
+       PEPPER_INFO("\n");
+
+       hwc = (pepper_tdm_hwc_t *)calloc(1, sizeof(pepper_tdm_hwc_t));
+       PEPPER_CHECK(hwc, return PEPPER_FALSE, "calloc failed\n");
+       hwc->output = output;
+
+       thwc = tdm_output_get_hwc(output->toutput, &err);
+       PEPPER_CHECK(thwc, goto error, "Failed to get tdm_hwc\n");
+       hwc->thwc = thwc;
+
+       err = tdm_hwc_get_capabilities(hwc->thwc, &hwc->caps);
+       PEPPER_CHECK(err == TDM_ERROR_NONE, goto error,
+                                        "tdm_hwc_get_capabilities failed err:%d\n", err);
+
+       // TODO: check and save the video capabiliites. initialize the video capabilities.
+       /* for examples below.
+               // hwc video capabilities
+               if (hwc_caps & TDM_HWC_CAPABILITY_VIDEO_STREAM)
+                       hwc->tdm_hwc_video_stream = EINA_TRUE;
+               if (hwc_caps & TDM_HWC_CAPABILITY_VIDEO_SCALE)
+                       hwc->tdm_hwc_video_scale = EINA_TRUE;
+               if (hwc_caps & TDM_HWC_CAPABILITY_VIDEO_TRANSFORM)
+                       hwc->tdm_hwc_video_transform = EINA_TRUE;
+               if (hwc_caps & TDM_HWC_CAPABILITY_VIDEO_SCANOUT)
+                       hwc->tdm_hwc_video_scanout = EINA_TRUE;
+               if (hwc_caps & TDM_HWC_CAPABILITY_FENCE)
+                       hwc->tdm_hwc_fence = EINA_TRUE;
+        */
+
+       // initialize a hwc_window list.
+       pepper_list_init(&hwc->window_list);
+
+       // Add pepper_hwc of pepper_output and set it to hwc->base
+       hwc->base = pepper_output_initialize_hwc(output->base);
+       PEPPER_CHECK(hwc->base, goto error, "pepper_output_initialize_hwc() failed\n");
+
+       // add destory handler for pepper_hwc object
+       pepper_object_add_event_listener((pepper_object_t *)hwc->base,
+                                                                        PEPPER_EVENT_OBJECT_DESTROY,
+                                                                        0,
+                                                                        __tdm_hwc_destroy, hwc);
+
+       output->hwc = hwc;
+
+       return PEPPER_TRUE;
+
+error:
+       if (hwc->base)
+               pepper_hwc_destroy(hwc->base);
+
+       if (hwc)
+               free(hwc);
+
+       return PEPPER_FALSE;
+}
+
+static void
 __tdm_plane_destroy(pepper_event_listener_t *listener, pepper_object_t *object,
                                        uint32_t id, void *info, void *data)
 {
@@ -389,6 +535,9 @@ pepper_tdm_output_destroy(void *o)
 
        /* TODO: */
 
+       if (output->hwc)
+               pepper_hwc_destroy(output->hwc->base);
+
        free(output);
 }
 
@@ -503,13 +652,22 @@ pepper_tdm_output_assign_planes(void *o, const pepper_list_t *view_list)
 
        PEPPER_INFO("\n");
 
-       pepper_list_for_each_list(l, view_list) {
-               pepper_view_t      *view = l->item;
-               pepper_plane_t     *plane = NULL;
+       if (output->hwc) {
+               // update info, buffer, compostiion type of hwc_windows
+               if (!pepper_tdm_hwc_update_changes(output->hwc, view_list))
+                       return;
 
-               plane = output->primary_plane->base;
+               if (!pepper_tdm_hwc_evaluate(output->hwc, view_list))
+                       return;
+       } else {
+               pepper_list_for_each_list(l, view_list) {
+                       pepper_view_t    *view = l->item;
+                       pepper_plane_t   *plane = NULL;
 
-               pepper_view_assign_plane(view, output->base, plane);
+                       plane = output->primary_plane->base;
+
+                       pepper_view_assign_plane(view, output->base, plane);
+               }
        }
 }
 
@@ -519,7 +677,7 @@ pepper_tdm_output_start_repaint_loop(void *o)
        PEPPER_INFO("\n");
 
        pepper_tdm_output_t *output = (pepper_tdm_output_t *)o;
-       struct timespec     ts;
+       struct timespec   ts;
 
        pepper_compositor_get_time(output->tdm->compositor, &ts);
        pepper_output_finish_frame(output->base, &ts);
@@ -531,8 +689,9 @@ pepper_tdm_output_repaint(void *o, const pepper_list_t *plane_list)
        PEPPER_INFO("\n");
 
        pepper_tdm_output_t *output = (pepper_tdm_output_t *)o;
-       tdm_error err;
+       tdm_error terror;
 
+       // render
        if (!output->back) {
                if (output->render_type == TDM_RENDER_TYPE_GL)
                        __tdm_renderer_gl_render(output);
@@ -544,13 +703,25 @@ pepper_tdm_output_repaint(void *o, const pepper_list_t *plane_list)
                }
        }
 
-       if (output->back) {
-               err = tdm_layer_set_buffer((tdm_layer *)output->primary_plane->layer,
-                                                                  output->back);
-               PEPPER_CHECK(err == TDM_ERROR_NONE, return, "tdm_layer_set_buffer() failed");
+       // TODO: fix this...
+       if (!output->back)
+               return;
+
+       if (output->hwc) {
+               // set back buffer as a client_target_buffer
+               pepper_tdm_hwc_set_client_target_buffer(output->hwc, output->back);
+
+               if (!pepper_tdm_hwc_commit(output->hwc))
+                       return;
+
+               output->page_flip_pending = PEPPER_TRUE;
+       } else {
+               terror = tdm_layer_set_buffer((tdm_layer *)output->primary_plane->layer,
+                                                                       output->back);
+               PEPPER_CHECK(terror == TDM_ERROR_NONE, return, "tdm_layer_set_buffer() failed");
 
-               err = tdm_output_commit(output->toutput, 0, __tdm_output_commit_cb, output);
-               PEPPER_CHECK(err == TDM_ERROR_NONE, return, "tdm_output_commit() failed");
+               terror = tdm_output_commit(output->toutput, 0, __tdm_output_commit_cb, output);
+               PEPPER_CHECK(terror == TDM_ERROR_NONE, return, "tdm_output_commit() failed");
 
                output->page_flip_pending = PEPPER_TRUE;
        }
@@ -563,12 +734,16 @@ pepper_tdm_output_attach_surface(void *o, pepper_surface_t *surface, int *w,
        PEPPER_INFO("\n");
 
        pepper_tdm_output_t *output = (pepper_tdm_output_t *)o;
+
+       if (output->hwc)
+               pepper_tdm_hwc_attach_surface(output->hwc, surface);
+
        pepper_renderer_attach_surface(output->renderer, surface, w, h);
 }
 
 static void
 pepper_tdm_output_flush_surface_damage(void *o, pepper_surface_t *surface,
-                                                                          pepper_bool_t *keep_buffer)
+                                                                               pepper_bool_t *keep_buffer)
 {
        PEPPER_INFO("\n");
 
@@ -583,6 +758,8 @@ pepper_tdm_output_flush_surface_damage(void *o, pepper_surface_t *surface,
        } else {
                *keep_buffer = PEPPER_TRUE;
        }
+
+       // HWC :
 }
 
 struct pepper_output_backend tdm_output_backend = {
@@ -607,6 +784,7 @@ int
 pepper_tdm_output_init(pepper_tdm_t *tdm)
 {
        pepper_tdm_output_t *output;
+       tdm_hwc *thwc;
        tdm_error err;
        int i;
 
@@ -668,6 +846,24 @@ pepper_tdm_output_init(pepper_tdm_t *tdm)
                                                 "tdm_output_set_mode() failed err:%d\n", err);
                }
 
+               /*Add pepper_output to compositor*/
+               output->base = pepper_compositor_add_output(tdm->compositor,
+                                               &tdm_output_backend,
+                                               "tdm_output",
+                                               output,
+                                               WL_OUTPUT_TRANSFORM_NORMAL, 1);
+               PEPPER_CHECK(err == TDM_ERROR_NONE, goto error,
+                                        "pepper_compositor_add_output() failed err:%d\n", err);
+
+               // check if tdm_output has tdm_hwc.
+               thwc = tdm_output_get_hwc(output->toutput, &err);
+               if (thwc && err == TDM_ERROR_NONE)
+                       PEPPER_CHECK(PEPPER_TRUE == __tdm_output_hwc_init(output), goto error,
+                                                "pepper_tdm_hwc_init() failed\n");
+               else
+                       PEPPER_CHECK(PEPPER_TRUE == __tdm_output_plane_init(output), goto error,
+                                                "pepper_tdm_plane_init() failed\n");
+
                /*Setup renderer*/
                if (render_env && !strcmp(render_env, "gl")) {
                        __tdm_renderer_gl_init(output);
@@ -680,18 +876,6 @@ pepper_tdm_output_init(pepper_tdm_t *tdm)
                        PEPPER_CHECK(output->renderer, goto error,
                                                 "Failed to initialize pixman_renderer.\n");
                }
-
-               /*Add pepper_output to compositor*/
-               output->base = pepper_compositor_add_output(tdm->compositor,
-                                          &tdm_output_backend,
-                                          "tdm_output",
-                                          output,
-                                          WL_OUTPUT_TRANSFORM_NORMAL, 1);
-               PEPPER_CHECK(err == TDM_ERROR_NONE, goto error,
-                                        "pepper_compositor_add_output() failed err:%d\n", err);
-
-               PEPPER_CHECK(PEPPER_TRUE == __tdm_output_plane_init(output), goto error,
-                                        "pepper_tdm_plane_init() failed\n");
        }
 
        return PEPPER_TRUE;