--- /dev/null
+/*
+* 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;
+}