From d59ec989f24b316865d7b78f301926b091362b32 Mon Sep 17 00:00:00 2001 From: Seunghun Lee Date: Mon, 28 Mar 2022 20:03:20 +0900 Subject: [PATCH] Add ds_tbm_server ds_tbm_server initializes wayland_tbm to allow wl_client to use tbm_surface as a wl_buffer. Change-Id: I5fcf1f37bd9f410f7d400ac3a918c159dbb07fbc --- include/libds-tizen/tbm_server.h | 24 +++ src/examples/meson.build | 6 +- src/examples/tbm-server-helper.h | 41 ----- src/examples/tinyds-tdm.c | 23 ++- src/libds-tizen/meson.build | 8 +- src/libds-tizen/pixel_format.c | 61 ++++++ src/libds-tizen/pixel_format.h | 10 + .../tbm_server.c} | 204 ++++++++++++--------- src/libds-tizen/tbm_server.h | 34 ++++ 9 files changed, 272 insertions(+), 139 deletions(-) create mode 100644 include/libds-tizen/tbm_server.h delete mode 100644 src/examples/tbm-server-helper.h create mode 100644 src/libds-tizen/pixel_format.c create mode 100644 src/libds-tizen/pixel_format.h rename src/{examples/tbm-server-helper.c => libds-tizen/tbm_server.c} (66%) create mode 100644 src/libds-tizen/tbm_server.h diff --git a/include/libds-tizen/tbm_server.h b/include/libds-tizen/tbm_server.h new file mode 100644 index 0000000..c48977e --- /dev/null +++ b/include/libds-tizen/tbm_server.h @@ -0,0 +1,24 @@ +#ifndef LIBDS_TIZEN_TBM_SERVER_H +#define LIBDS_TIZEN_TBM_SERVER_H + +#include +#include + +struct ds_tbm_server; + +struct ds_tbm_client_buffer; + +struct ds_tbm_server * +ds_tbm_server_create(struct wl_display *display); + +void +ds_tbm_server_add_destroy_listener(struct ds_tbm_server *tbm, + struct wl_listener *listener); + +struct ds_tbm_client_buffer * +ds_tbm_client_buffer_from_buffer(struct ds_buffer *ds_buffer); + +tbm_surface_h +ds_tbm_client_buffer_get_tbm_surface(struct ds_tbm_client_buffer *buffer); + +#endif diff --git a/src/examples/meson.build b/src/examples/meson.build index c60b610..ddb0792 100644 --- a/src/examples/meson.build +++ b/src/examples/meson.build @@ -35,19 +35,15 @@ if get_option('tizen') tinyds_tdm_files = [ 'tinyds-tdm.c', - 'tinyds-tdm-renderer.c', - 'tbm-server-helper.c', 'pixman-helper.c', 'pixman-tbm-helper.c', + 'tinyds-tdm-renderer.c', ] executable('tinyds-tdm', tinyds_tdm_files, dependencies: [ common_deps, dependency('pixman-1', required: true), - dependency('libdrm', required: true), - dependency('libtbm', required: true), - dependency('wayland-tbm-server', required: true), dependency('threads', required: true), ], install_dir: libds_bindir, diff --git a/src/examples/tbm-server-helper.h b/src/examples/tbm-server-helper.h deleted file mode 100644 index 609f370..0000000 --- a/src/examples/tbm-server-helper.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef EXAMPLES_TBM_SERVER_H -#define EXAMPLES_TBM_SERVER_H - -#include -#include -#include -#include -#include - -struct tbm_server -{ - struct wayland_tbm_server *wl_tbm; - - struct wl_listener display_destroy; -}; - -struct tbm_client_buffer -{ - struct ds_buffer base; - - tbm_surface_h surface; - struct wl_resource *resource; - - struct wl_listener buffer_release; - struct wl_listener resource_destroy; - - uint32_t format; - size_t stride; -}; - -bool -tbm_server_init_display(struct tbm_server *tbm_server, - struct wl_display *display); - -struct tbm_client_buffer * -tbm_client_buffer_from_buffer(struct ds_buffer *ds_buffer); - -tbm_surface_h -tbm_client_buffer_get_tbm_surface(struct tbm_client_buffer *buffer); - -#endif diff --git a/src/examples/tinyds-tdm.c b/src/examples/tinyds-tdm.c index 6ec1156..c14cb9e 100644 --- a/src/examples/tinyds-tdm.c +++ b/src/examples/tinyds-tdm.c @@ -15,6 +15,7 @@ #include #include #include +#include #define USE_TDM_BUFFER_QUEUE @@ -25,7 +26,6 @@ #include #endif -#include "tbm-server-helper.h" #include "pixman-helper.h" #define TINYDS_UNUSED __attribute__((unused)) @@ -55,7 +55,7 @@ struct tinyds_output struct tinyds_server { - struct tbm_server tbm_server; + struct ds_tbm_server *tbm_server; struct wl_display *display; @@ -127,9 +127,6 @@ main(void) res = init_server(server, display); assert(res); - res = tbm_server_init_display(&server->tbm_server, display); - assert(res); - socket = wl_display_add_socket_auto(display); assert(socket); @@ -314,6 +311,12 @@ init_server(struct tinyds_server *server, struct wl_display *display) return false; } + server->tbm_server = ds_tbm_server_create(display); + if (!server->tbm_server) { + ds_backend_destroy(server->backend); + return false; + } + server->xdg_shell = ds_xdg_shell_create(display); if (!server->xdg_shell) { ds_backend_destroy(server->backend); @@ -426,7 +429,7 @@ output_draw_with_renderer(struct tinyds_output *output) wl_list_for_each(view, &output->server->views, link) { struct ds_buffer *ds_buffer; - struct tbm_client_buffer *buffer; + struct ds_tbm_client_buffer *tbm_buffer; tbm_surface_h surface; if (!view->mapped) @@ -434,12 +437,12 @@ output_draw_with_renderer(struct tinyds_output *output) ds_buffer = ds_surface_get_buffer( ds_xdg_surface_get_surface(view->xdg_surface)); - assert(buffer); + assert(ds_buffer); - buffer = tbm_client_buffer_from_buffer(ds_buffer); - assert(buffer); + tbm_buffer = ds_tbm_client_buffer_from_buffer(ds_buffer); + assert(tbm_buffer); - surface = tbm_client_buffer_get_tbm_surface(buffer); + surface = ds_tbm_client_buffer_get_tbm_surface(tbm_buffer); renderer_add_texture(&output->renderer, surface, view->x, view->y); diff --git a/src/libds-tizen/meson.build b/src/libds-tizen/meson.build index e9ca734..4f76b68 100644 --- a/src/libds-tizen/meson.build +++ b/src/libds-tizen/meson.build @@ -1,7 +1,13 @@ -libds_tizen_files = [] +libds_tizen_files = [ + 'pixel_format.c', + 'tbm_server.c', +] libds_tizen_deps = [ dep_libds, + dependency('libdrm', required: true), + dependency('libtbm', required: true), + dependency('wayland-tbm-server', required: true), ] subdir('allocator') diff --git a/src/libds-tizen/pixel_format.c b/src/libds-tizen/pixel_format.c new file mode 100644 index 0000000..021652e --- /dev/null +++ b/src/libds-tizen/pixel_format.c @@ -0,0 +1,61 @@ +#include +#include +#include + +#include "libds/log.h" +#include "pixel_format.h" + +#ifdef ARRAY_LENGTH +#undef ARRAY_LENGTH +#endif + +#define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0]) + +struct ds_tbm_format +{ + uint32_t drm_format; + uint32_t tbm_format; +}; + +static const struct ds_tbm_format formats[] = +{ + { + .drm_format = DRM_FORMAT_ARGB8888, + .tbm_format = TBM_FORMAT_ARGB8888, + }, + { + .drm_format = DRM_FORMAT_XRGB8888, + .tbm_format = TBM_FORMAT_XRGB8888, + }, + /* TODO more format */ +}; + +uint32_t +convert_drm_format_to_tbm(uint32_t fmt) +{ + size_t i; + + for (i = 0; i < ARRAY_LENGTH(formats); i++) { + if (formats[i].drm_format == fmt) + return formats[i].tbm_format; + } + + ds_err("DRM format 0x%"PRIX32" has no TBM equivalent", fmt); + + return 0; +} + +uint32_t +convert_tbm_format_to_drm(uint32_t fmt) +{ + size_t i; + + for (i = 0; i < ARRAY_LENGTH(formats); i++) { + if (formats[i].tbm_format == fmt) + return formats[i].drm_format; + } + + ds_err("TBM format 0x%"PRIX32" has no DRM equivalent", fmt); + + return 0; +} diff --git a/src/libds-tizen/pixel_format.h b/src/libds-tizen/pixel_format.h new file mode 100644 index 0000000..a63d096 --- /dev/null +++ b/src/libds-tizen/pixel_format.h @@ -0,0 +1,10 @@ +#ifndef DS_TIZEN_PIXEL_FORMAT_H +#define DS_TIZEN_PIXEL_FORMAT_H + +#include + +uint32_t convert_drm_format_to_tbm(uint32_t fmt); + +uint32_t convert_tbm_format_to_drm(uint32_t fmt); + +#endif diff --git a/src/examples/tbm-server-helper.c b/src/libds-tizen/tbm_server.c similarity index 66% rename from src/examples/tbm-server-helper.c rename to src/libds-tizen/tbm_server.c index 320ee4f..ecb46db 100644 --- a/src/examples/tbm-server-helper.c +++ b/src/libds-tizen/tbm_server.c @@ -1,82 +1,111 @@ -#include "tbm-server-helper.h" - #include #include #include -#include + #include -#include + +#include "libds/log.h" +#include "pixel_format.h" +#include "tbm_server.h" static const struct ds_buffer_resource_interface tbm_buffer_resource_iface; static const struct ds_buffer_interface tbm_client_buffer_iface; static void tbm_server_handle_display_destroy(struct wl_listener *listener, void *data); -static struct tbm_client_buffer * -tbm_client_buffer_create(struct wl_resource *resource); -bool -tbm_server_init_display(struct tbm_server *tbm, struct wl_display *display) +WL_EXPORT struct ds_tbm_server * +ds_tbm_server_create(struct wl_display *display) { + struct ds_tbm_server *tbm; tbm_bufmgr bufmgr; + tbm = calloc(1, sizeof *tbm); + if (!tbm) + return NULL; + + wl_signal_init(&tbm->events.destroy); + tbm->wl_tbm = wayland_tbm_server_init(display, NULL, -1, 0); if (!tbm->wl_tbm) { - return false; + goto err_wl_tbm; } bufmgr = wayland_tbm_server_get_bufmgr(tbm->wl_tbm); if (!bufmgr) { - wayland_tbm_server_deinit(tbm->wl_tbm); - return false; + goto err_bind; } if (!tbm_bufmgr_bind_native_display(bufmgr, (void *)display)) { - wayland_tbm_server_deinit(tbm->wl_tbm); - return false; + goto err_bind; } - ds_buffer_register_resource_interface(&tbm_buffer_resource_iface); - tbm->display_destroy.notify = tbm_server_handle_display_destroy; wl_display_add_destroy_listener(display, &tbm->display_destroy); - return true; + ds_buffer_register_resource_interface(&tbm_buffer_resource_iface); + + return tbm; + +err_bind: + wayland_tbm_server_deinit(tbm->wl_tbm); +err_wl_tbm: + free(tbm); + + return NULL; } -struct tbm_client_buffer * -tbm_client_buffer_from_buffer(struct ds_buffer *ds_buffer) +WL_EXPORT void +ds_tbm_server_add_destroy_listener(struct ds_tbm_server *tbm, + struct wl_listener *listener) { - assert(ds_buffer->iface == &tbm_client_buffer_iface); - return (struct tbm_client_buffer *)ds_buffer; + wl_signal_add(&tbm->events.destroy, listener); +} + +WL_EXPORT struct ds_tbm_client_buffer * +ds_tbm_client_buffer_from_buffer(struct ds_buffer *ds_buffer) +{ + if (ds_buffer->iface != &tbm_client_buffer_iface) + return NULL; + return (struct ds_tbm_client_buffer *)ds_buffer; } -tbm_surface_h -tbm_client_buffer_get_tbm_surface(struct tbm_client_buffer *buffer) +WL_EXPORT tbm_surface_h +ds_tbm_client_buffer_get_tbm_surface(struct ds_tbm_client_buffer *buffer) { + if (buffer->base.iface != &tbm_client_buffer_iface) + return NULL; return buffer->surface; } static void tbm_server_handle_display_destroy(struct wl_listener *listener, void *data) { - struct tbm_server *tbm; + struct ds_tbm_server *tbm; tbm = wl_container_of(listener, tbm, display_destroy); + + wl_signal_emit(&tbm->events.destroy, tbm); + wayland_tbm_server_deinit(tbm->wl_tbm); + free(tbm); } -static bool -tbm_buffer_resource_iface_is_instance(struct wl_resource *resource) +static void +tbm_client_buffer_handle_release(struct wl_listener *listener, void *data) { - return !!wayland_tbm_server_get_surface(NULL, resource); + struct ds_tbm_client_buffer *buffer; + + buffer = wl_container_of(listener, buffer, buffer_release); + if (buffer->resource) + wl_buffer_send_release(buffer->resource); } static void tbm_client_buffer_handle_resource_destroy(struct wl_listener *listener, void *data) { - struct tbm_client_buffer *buffer; + struct ds_tbm_client_buffer *buffer; buffer = wl_container_of(listener, buffer, resource_destroy); @@ -88,44 +117,17 @@ tbm_client_buffer_handle_resource_destroy(struct wl_listener *listener, ds_buffer_drop(&buffer->base); } -static struct tbm_client_buffer * -tbm_client_buffer_get_or_create(struct wl_resource *resource) -{ - struct tbm_client_buffer *buffer; - struct wl_listener *resource_destroy_listener; - - resource_destroy_listener = wl_resource_get_destroy_listener(resource, - tbm_client_buffer_handle_resource_destroy);; - if (resource_destroy_listener) { - buffer = wl_container_of(resource_destroy_listener, - buffer, resource_destroy); - return buffer; - } - - return tbm_client_buffer_create(resource); -} - -static struct ds_buffer * -tbm_buffer_resource_iface_from_resource(struct wl_resource *resource) +static struct ds_tbm_client_buffer * +tbm_client_buffer_from_buffer(struct ds_buffer *ds_buffer) { - struct tbm_client_buffer *buffer; - - buffer = tbm_client_buffer_get_or_create(resource); - assert(buffer); - - return &buffer->base; + assert(ds_buffer->iface == &tbm_client_buffer_iface); + return (struct ds_tbm_client_buffer *)ds_buffer; } -static const struct ds_buffer_resource_interface tbm_buffer_resource_iface = { - .name = "tbm", - .is_instance = tbm_buffer_resource_iface_is_instance, - .from_resource = tbm_buffer_resource_iface_from_resource, -}; - static void -tbm_client_buffer_destroy(struct ds_buffer *ds_buffer) +tbm_client_buffer_iface_destroy(struct ds_buffer *ds_buffer) { - struct tbm_client_buffer *buffer; + struct ds_tbm_client_buffer *buffer; buffer = tbm_client_buffer_from_buffer(ds_buffer); @@ -137,11 +139,11 @@ tbm_client_buffer_destroy(struct ds_buffer *ds_buffer) } static bool -tbm_client_buffer_begin_data_ptr_access(struct ds_buffer *ds_buffer, +tbm_client_buffer_iface_begin_data_ptr_access(struct ds_buffer *ds_buffer, enum ds_buffer_data_ptr_access_flag flags, void **data, uint32_t *format, size_t *stride) { - struct tbm_client_buffer *buffer; + struct ds_tbm_client_buffer *buffer; tbm_surface_info_s info; tbm_bo_access_option op = TBM_OPTION_NONE; int err; @@ -160,7 +162,7 @@ tbm_client_buffer_begin_data_ptr_access(struct ds_buffer *ds_buffer, return false; } - *format = DRM_FORMAT_XRGB8888; // FIXME + *format = convert_tbm_format_to_drm(buffer->format); *stride = info.planes[0].stride; *data = info.planes[0].ptr; @@ -168,9 +170,9 @@ tbm_client_buffer_begin_data_ptr_access(struct ds_buffer *ds_buffer, } static void -tbm_client_buffer_end_data_ptr_access(struct ds_buffer *ds_buffer) +tbm_client_buffer_iface_end_ptr_access(struct ds_buffer *ds_buffer) { - struct tbm_client_buffer *buffer; + struct ds_tbm_client_buffer *buffer; buffer = tbm_client_buffer_from_buffer(ds_buffer); @@ -178,36 +180,31 @@ tbm_client_buffer_end_data_ptr_access(struct ds_buffer *ds_buffer) } static const struct ds_buffer_interface tbm_client_buffer_iface = { - .destroy = tbm_client_buffer_destroy, - .begin_data_ptr_access = tbm_client_buffer_begin_data_ptr_access, - .end_data_ptr_access = tbm_client_buffer_end_data_ptr_access, + .destroy = tbm_client_buffer_iface_destroy, + .begin_data_ptr_access = tbm_client_buffer_iface_begin_data_ptr_access, + .end_data_ptr_access = tbm_client_buffer_iface_end_ptr_access, }; -static void -tbm_client_buffer_handle_release(struct wl_listener *listener, void *data) -{ - struct tbm_client_buffer *buffer; - - buffer = wl_container_of(listener, buffer, buffer_release); - if (buffer->resource) - wl_buffer_send_release(buffer->resource); -} - -static struct tbm_client_buffer * +static struct ds_tbm_client_buffer * tbm_client_buffer_create(struct wl_resource *resource) { - struct tbm_client_buffer *buffer; + struct ds_tbm_client_buffer *buffer; tbm_surface_h surface; int32_t width, height; surface = wayland_tbm_server_get_surface(NULL, resource); - assert(surface); + if (!surface) { + ds_err("Could not get tbm_surface from wl_resource@%d", + wl_resource_get_id(resource)); + return NULL; + } width = tbm_surface_get_width(surface); height = tbm_surface_get_height(surface); buffer = calloc(1, sizeof *buffer); - assert(buffer); + if (!buffer) + return NULL; ds_buffer_init(&buffer->base, &tbm_client_buffer_iface, width, height); @@ -226,3 +223,46 @@ tbm_client_buffer_create(struct wl_resource *resource) return buffer; } + +static struct ds_tbm_client_buffer * +tbm_client_buffer_get_or_create(struct wl_resource *resource) +{ + struct ds_tbm_client_buffer *buffer; + struct wl_listener *resource_destroy_listener; + + resource_destroy_listener = wl_resource_get_destroy_listener(resource, + tbm_client_buffer_handle_resource_destroy);; + if (resource_destroy_listener) { + buffer = wl_container_of(resource_destroy_listener, + buffer, resource_destroy); + return buffer; + } + + return tbm_client_buffer_create(resource); +} + +static bool +tbm_buffer_resource_iface_is_instance(struct wl_resource *resource) +{ + return !!wayland_tbm_server_get_surface(NULL, resource); +} + +static struct ds_buffer * +tbm_buffer_resource_iface_from_resource(struct wl_resource *resource) +{ + struct ds_tbm_client_buffer *buffer; + + buffer = tbm_client_buffer_get_or_create(resource); + if (!buffer) { + ds_err("Could not get or create ds_tbm_client_buffer"); + return NULL; + } + + return &buffer->base; +} + +static const struct ds_buffer_resource_interface tbm_buffer_resource_iface = { + .name = "tbm", + .is_instance = tbm_buffer_resource_iface_is_instance, + .from_resource = tbm_buffer_resource_iface_from_resource, +}; diff --git a/src/libds-tizen/tbm_server.h b/src/libds-tizen/tbm_server.h new file mode 100644 index 0000000..be56746 --- /dev/null +++ b/src/libds-tizen/tbm_server.h @@ -0,0 +1,34 @@ +#ifndef DS_TIZEN_TBM_SERVER_H +#define DS_TIZEN_TBM_SERVER_H + +#include +#include +#include +#include "libds/interfaces/buffer.h" + +struct ds_tbm_server +{ + struct wayland_tbm_server *wl_tbm; + + struct wl_listener display_destroy; + + struct { + struct wl_signal destroy; + } events; +}; + +struct ds_tbm_client_buffer +{ + struct ds_buffer base; + + tbm_surface_h surface; + struct wl_resource *resource; + + struct wl_listener buffer_release; + struct wl_listener resource_destroy; + + uint32_t format; + size_t stride; +}; + +#endif -- 2.7.4