tdm: add pepper_tdm_output_create_pixman_renderer function 81/263881/1
authorSooChan Lim <sc1.lim@samsung.com>
Mon, 13 Sep 2021 05:42:21 +0000 (14:42 +0900)
committerSooChan Lim <sc1.lim@samsung.com>
Mon, 13 Sep 2021 06:22:45 +0000 (15:22 +0900)
This function provides pepper_tdm_renderer which contains
built-in pixman renderer.

Change-Id: Ied4fbf79a39ab5fc603dcd851ce60c7e9d6d95c1

src/lib/tdm/Makefile.am
src/lib/tdm/pepper-tdm.h
src/lib/tdm/tdm-renderer-pixman.c [new file with mode: 0644]

index eb8b821..597927e 100644 (file)
@@ -8,8 +8,9 @@ libpepper_tdm_include_HEADERS = pepper-tdm.h
 libpepper_tdm_la_CFLAGS = $(AM_CFLAGS) $(PEPPER_TDM_CFLAGS)
 libpepper_tdm_la_LIBADD = $(PEPPER_TDM_LIBS)
 
-libpepper_tdm_la_SOURCES =  tdm-internal.h  \
-                            tdm-common.c    \
-                            tdm-output.c    \
-                            tdm-hwc.c       \
-                            tdm-renderer.c
+libpepper_tdm_la_SOURCES =  tdm-internal.h        \
+                            tdm-common.c          \
+                            tdm-output.c          \
+                            tdm-hwc.c             \
+                            tdm-renderer.c        \
+                            tdm-renderer-pixman.c
index 886b342..d407b8f 100644 (file)
@@ -100,6 +100,9 @@ pepper_tdm_output_create_renderer(pepper_tdm_output_t *output,
                                                tbm_surface_queue_h tsurface_queue,
                                                void *renderer_data);
 
+PEPPER_API pepper_tdm_renderer_t *
+pepper_tdm_output_create_pixman_renderer(pepper_tdm_output_t *output);
+
 PEPPER_API void
 pepper_tdm_renderer_destroy(pepper_tdm_renderer_t *renderer);
 
diff --git a/src/lib/tdm/tdm-renderer-pixman.c b/src/lib/tdm/tdm-renderer-pixman.c
new file mode 100644 (file)
index 0000000..1d873ed
--- /dev/null
@@ -0,0 +1,245 @@
+/*
+* 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"
+#include <pepper-pixman-renderer.h>
+
+typedef struct pepper_tdm_renderer_pixman_data    pepper_tdm_renderer_pixman_data_t;
+
+struct pepper_tdm_renderer_pixman_data {
+       pepper_renderer_t        *renderer;
+       pepper_render_target_t   *target;
+       pepper_region_t           previous_damage;
+       tbm_surface_queue_h       tsurface_queue;
+
+       pepper_compositor_t      *compositor;
+       pepper_tdm_output_t      *output;
+};
+
+static int key_render_target;
+
+#define KEY_RENDER_TARGET ((unsigned long)&key_render_target)
+
+static void
+__tdm_renderer_pixman_free_target(void *user_data)
+{
+       PEPPER_INFO("\n");
+
+       pepper_render_target_t *target = user_data;
+
+       if (target)
+               pepper_render_target_destroy(target);
+}
+
+static pepper_render_target_t *
+__tdm_renderer_pixman_get_target(tbm_surface_h surface)
+{
+       PEPPER_INFO("\n");
+
+       tbm_bo bo;
+       pepper_render_target_t *target = NULL;
+
+       bo = tbm_surface_internal_get_bo(surface, 0);
+       if (!tbm_bo_get_user_data(bo, KEY_RENDER_TARGET, (void **)&target)) {
+               tbm_surface_info_s info;
+               pepper_format_t format;
+
+               tbm_bo_add_user_data(bo, KEY_RENDER_TARGET, __tdm_renderer_pixman_free_target);
+
+               tbm_surface_get_info(surface, &info);
+               switch (info.format) {
+               case TBM_FORMAT_XRGB8888:
+                       format = PEPPER_FORMAT_XRGB8888;
+                       break;
+               case TBM_FORMAT_ARGB8888:
+                       format = PEPPER_FORMAT_ARGB8888;
+                       break;
+               default:
+                       tbm_bo_delete_user_data(bo, KEY_RENDER_TARGET);
+                       PEPPER_ERROR("Unknown tbm format\n");
+                       return NULL;
+               }
+               target = pepper_pixman_renderer_create_target(format, info.planes[0].ptr,
+                                info.planes[0].stride,
+                                info.width, info.height);
+               if (!target) {
+                       tbm_bo_delete_user_data(bo, KEY_RENDER_TARGET);
+                       PEPPER_ERROR("pepper_pixman_renderer_create_target() fail\n");
+                       return NULL;
+               }
+               tbm_bo_set_user_data(bo, KEY_RENDER_TARGET, target);
+       }
+
+       return target;
+}
+
+static void
+pepper_tdm_renderer_pixman_destroy_impl(void *renderer_data)
+{
+       PEPPER_INFO("\n");
+
+       pepper_tdm_renderer_pixman_data_t *pixman_data = renderer_data;
+
+       if (pixman_data->target)
+               pepper_render_target_destroy(pixman_data->target);
+
+       if (pixman_data->renderer)
+               pepper_renderer_destroy(pixman_data->renderer);
+
+       free(renderer_data);
+}
+
+static pepper_bool_t
+pepper_tdm_renderer_pixman_setup_impl(void *renderer_data)
+{
+       PEPPER_INFO("\n");
+
+       pepper_tdm_renderer_pixman_data_t *pixman_data = renderer_data;
+
+       pixman_data->renderer = pepper_pixman_renderer_create(pixman_data->compositor);
+       PEPPER_CHECK(pixman_data->renderer, return PEPPER_FALSE,
+                               "pepper_pixman_renderer_create() failed.\n");
+
+       return PEPPER_TRUE;
+}
+
+static pepper_bool_t
+pepper_tdm_renderer_pixman_attach_surface_impl(void *renderer_data,
+                                                                       pepper_surface_t *surface,
+                                                                       int *w, int *h)
+{
+       PEPPER_INFO("\n");
+
+       pepper_tdm_renderer_pixman_data_t *pixman_data = renderer_data;
+
+       pepper_renderer_attach_surface(pixman_data->renderer, surface, w, h);
+
+       return PEPPER_TRUE;
+}
+
+static pepper_bool_t
+pepper_tdm_renderer_pixman_flush_surface_damage_impl(void *renderer_data,
+                                                                               pepper_surface_t *surface)
+{
+       PEPPER_INFO("\n");
+
+       pepper_tdm_renderer_pixman_data_t *pixman_data = renderer_data;
+
+       pepper_renderer_flush_surface_damage(pixman_data->renderer, surface);
+
+       return PEPPER_TRUE;
+}
+
+static pepper_bool_t
+pepper_tdm_renderer_pixman_render_once_impl(void *renderer_data,
+                                                                       const pepper_list_t *render_list,
+                                                                       pepper_region_t *damage)
+{
+       PEPPER_INFO("\n");
+
+       pepper_tdm_renderer_pixman_data_t *pixman_data =  renderer_data;
+       pepper_output_t         *output = pepper_tdm_output_get_pepper_output(pixman_data->output);
+       pepper_render_target_t  *target;
+       pepper_region_t          total_damage;
+       tbm_surface_h            surface;
+       int ret;
+
+       // set a render target
+       ret = tbm_surface_queue_dequeue(pixman_data->tsurface_queue, &surface);
+       PEPPER_CHECK(ret == TBM_SURFACE_QUEUE_ERROR_NONE, return PEPPER_FALSE,
+                                "tbm_surface_queue_dequeue() failed\n");
+
+       target = __tdm_renderer_pixman_get_target(surface);
+       if (PEPPER_FALSE == pepper_renderer_set_target(pixman_data->renderer, target)) {
+               PEPPER_ERROR("pepper_renderer_set_target() failed\n");
+               return PEPPER_FALSE;
+       }
+
+       // repaint
+       pepper_region_init(&total_damage);
+       pepper_region_union(&total_damage, damage, &pixman_data->previous_damage);
+       pepper_region_copy(&pixman_data->previous_damage, damage);
+
+       pepper_renderer_repaint_output(pixman_data->renderer, output, render_list,
+                                                                       &total_damage);
+
+       pepper_region_fini(&total_damage);
+
+       // enqueue a rendered surface into a surface queue.
+       ret = tbm_surface_queue_enqueue(pixman_data->tsurface_queue, surface);
+       PEPPER_CHECK(ret == TBM_SURFACE_QUEUE_ERROR_NONE, return PEPPER_FALSE,
+                                "tbm_surface_queue_enqueue() failed\n");
+
+       return PEPPER_TRUE;
+}
+
+static const pepper_tdm_renderer_iface_t tdm_renderer_pixman_iface = {
+       pepper_tdm_renderer_pixman_destroy_impl,
+       pepper_tdm_renderer_pixman_setup_impl,
+       pepper_tdm_renderer_pixman_attach_surface_impl,
+       pepper_tdm_renderer_pixman_flush_surface_damage_impl,
+       pepper_tdm_renderer_pixman_render_once_impl,
+};
+
+PEPPER_API pepper_tdm_renderer_t *
+pepper_tdm_output_create_pixman_renderer(pepper_tdm_output_t *output)
+{
+       PEPPER_INFO("\n");
+
+       pepper_tdm_renderer_t             *renderer;
+       pepper_tdm_renderer_pixman_data_t *pixman_data = NULL;
+       tbm_surface_queue_h                tsurface_queue;
+
+       PEPPER_CHECK(!output->renderer, return PEPPER_FALSE,
+                               "renderer:%p already assigned.\n");
+
+       tsurface_queue = pepper_tdm_output_get_display_buffer_queue(output);
+       PEPPER_CHECK(tsurface_queue, return PEPPER_FALSE,
+                               "pepper_tdm_output_get_display_buffer_queue() failed.\n");
+
+       pixman_data = calloc(1, sizeof(pepper_tdm_renderer_pixman_data_t));
+       PEPPER_CHECK(tsurface_queue, return PEPPER_FALSE,
+                               "fail to allocate pepper_tdm_renderer_pixman_data_t.\n");
+
+       pixman_data->tsurface_queue = tsurface_queue;
+       pepper_region_init(&pixman_data->previous_damage);
+       pixman_data->compositor = output->tdm->compositor;
+       pixman_data->output = output;
+
+       renderer = pepper_tdm_output_create_renderer(output,
+                                                                                       &tdm_renderer_pixman_iface,
+                                                                                       tsurface_queue,
+                                                                                       (void *)pixman_data);
+       PEPPER_CHECK(renderer, goto error,
+                               "pepper_tdm_output_create_renderer() failed.\n");
+
+       output->render_type = TDM_RENDER_TYPE_PIXMAN;
+
+       return renderer;
+
+error:
+       if (pixman_data)
+               free(pixman_data);
+
+       return NULL;
+}