From c4099daf581890fa536baf8a7fd7dab3d3a1f796 Mon Sep 17 00:00:00 2001 From: SooChan Lim Date: Mon, 13 Sep 2021 14:42:21 +0900 Subject: [PATCH] tdm: add pepper_tdm_output_create_pixman_renderer function This function provides pepper_tdm_renderer which contains built-in pixman renderer. Change-Id: Ied4fbf79a39ab5fc603dcd851ce60c7e9d6d95c1 --- src/lib/tdm/Makefile.am | 11 +- src/lib/tdm/pepper-tdm.h | 3 + src/lib/tdm/tdm-renderer-pixman.c | 245 ++++++++++++++++++++++++++++++ 3 files changed, 254 insertions(+), 5 deletions(-) create mode 100644 src/lib/tdm/tdm-renderer-pixman.c diff --git a/src/lib/tdm/Makefile.am b/src/lib/tdm/Makefile.am index eb8b821..597927e 100644 --- a/src/lib/tdm/Makefile.am +++ b/src/lib/tdm/Makefile.am @@ -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 diff --git a/src/lib/tdm/pepper-tdm.h b/src/lib/tdm/pepper-tdm.h index 886b342..d407b8f 100644 --- a/src/lib/tdm/pepper-tdm.h +++ b/src/lib/tdm/pepper-tdm.h @@ -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 index 0000000..1d873ed --- /dev/null +++ b/src/lib/tdm/tdm-renderer-pixman.c @@ -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 + +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; +} -- 2.34.1