From: Changyeon Lee Date: Mon, 4 Sep 2023 04:25:27 +0000 (+0900) Subject: Add gbm_server for supporting gbm_bo buffer X-Git-Tag: accepted/tizen/8.0/unified/20231005.094159^0 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=3e114164525d3cbe087ceae22bffd597795ee657;p=platform%2Fcore%2Fuifw%2Flibds-tizen.git Add gbm_server for supporting gbm_bo buffer Change-Id: Ic6191bb3cf025acfacdb15a385b0b1d9eb7c275c --- diff --git a/include/libds-tizen/gbm_server.h b/include/libds-tizen/gbm_server.h new file mode 100644 index 0000000..dab0ce4 --- /dev/null +++ b/include/libds-tizen/gbm_server.h @@ -0,0 +1,32 @@ +#ifndef LIBDS_TIZEN_GBM_SERVER_H +#define LIBDS_TIZEN_GBM_SERVER_H + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct ds_gbm_server; + +struct ds_gbm_client_buffer; + +struct ds_gbm_server * +ds_gbm_server_create(int fd); + +void +ds_gbm_server_destroy(struct ds_gbm_server *gbm); + +struct ds_gbm_client_buffer * +ds_gbm_client_buffer_from_buffer(struct ds_buffer *ds_buffer); + +struct gbm_bo * +ds_gbm_client_buffer_get_gbm_bo(struct ds_gbm_client_buffer *buffer); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/libds-tizen/types/gbm_server.h b/include/libds-tizen/types/gbm_server.h new file mode 100644 index 0000000..2574d3b --- /dev/null +++ b/include/libds-tizen/types/gbm_server.h @@ -0,0 +1,12 @@ +#ifndef LIBDS_TIZEN_TYPES_GBM_SERVER_H +#define LIBDS_TIZEN_TYPES_GBM_SERVER_H + +#include +#include + +struct ds_gbm_server +{ + struct gbm_device *gbm_device; +}; + +#endif diff --git a/packaging/libds-tizen.spec b/packaging/libds-tizen.spec index 6311697..8c42e4e 100644 --- a/packaging/libds-tizen.spec +++ b/packaging/libds-tizen.spec @@ -45,6 +45,7 @@ BuildRequires: pkgconfig(scaler-client) BuildRequires: pkgconfig(eom-server) BuildRequires: pkgconfig(eom) BuildRequires: pkgconfig(xdg-shell-unstable-v6-server) +BuildRequires: pkgconfig(gbm) %description @@ -410,6 +411,21 @@ Group: Development/Libraries %description remote-surface-devel Development package for tizen remote surface +## libds-tizen-gbm-server +%package gbm-server +Summary: Library for wayland-gbm-server +Group: Development/Libraries + +%description gbm-server +Library for tizen input devicemgr + +%package gbm-server-devel +Summary: Development package for wayland-gbm-server +Group: Development/Libraries + +%description gbm-server-devel +Development package for tizen wayland-gbm-server + %prep %setup -q cp %{SOURCE1001} . @@ -789,3 +805,18 @@ ninja -C builddir install %{_libdir}/pkgconfig/libds-tizen-remote-surface.pc %{_libdir}/libds-tizen-remote-surface.so* %{_bindir}/libds-tizen-remote-surface-tests + +%files gbm-server +%manifest %{name}.manifest +%defattr(-,root,root,-) +%license LICENSE +%{_libdir}/libds-tizen-gbm-server.so.* + +%files gbm-server-devel +%manifest %{name}.manifest +%defattr(-,root,root,-) +%license LICENSE +%{_includedir}/libds-tizen/gbm_server.h +%{_includedir}/libds-tizen/types/gbm_server.h +%{_libdir}/pkgconfig/libds-tizen-gbm-server.pc +%{_libdir}/libds-tizen-gbm-server.so diff --git a/src/gbm_server/gbm_server.c b/src/gbm_server/gbm_server.c new file mode 100644 index 0000000..d0d6035 --- /dev/null +++ b/src/gbm_server/gbm_server.c @@ -0,0 +1,264 @@ +#include +#include +#include + +#include +#include +#include "shared/pixel_format.h" +#include "gbm_server.h" + +static const struct ds_buffer_resource_interface gbm_buffer_resource_iface; +static const struct ds_buffer_interface gbm_client_buffer_iface; + +static struct ds_gbm_server *gbm_server; + +WL_EXPORT struct ds_gbm_server * +ds_gbm_server_create(int fd) +{ + struct ds_gbm_server *gbm; + + if (gbm_server) { + ds_inf("gbm server already created"); + return gbm_server; + } + + gbm = calloc(1, sizeof *gbm); + if (!gbm) + return NULL; + + gbm->gbm_device = gbm_create_device(fd); + if (!gbm->gbm_device) { + free(gbm); + return NULL; + } + + ds_buffer_register_resource_interface(&gbm_buffer_resource_iface); + + gbm_server = gbm; + + return gbm; +} + +WL_EXPORT void +ds_gbm_server_destroy(struct ds_gbm_server *gbm) +{ + gbm_device_destroy(gbm->gbm_device); + + free(gbm); + + gbm_server = NULL; +} + +WL_EXPORT struct ds_gbm_client_buffer * +ds_gbm_client_buffer_from_buffer(struct ds_buffer *ds_buffer) +{ + if (ds_buffer->iface != &gbm_client_buffer_iface) + return NULL; + return (struct ds_gbm_client_buffer *)ds_buffer; +} + +WL_EXPORT struct gbm_bo * +ds_gbm_client_buffer_get_gbm_bo(struct ds_gbm_client_buffer *buffer) +{ + if (buffer->base.iface != &gbm_client_buffer_iface) + return NULL; + return buffer->gbm_bo; +} + +static void +gbm_client_buffer_handle_release(struct wl_listener *listener, void *data) +{ + struct ds_gbm_client_buffer *buffer; + + buffer = wl_container_of(listener, buffer, buffer_release); + if (buffer->resource) + wl_buffer_send_release(buffer->resource); +} + +static void +gbm_client_buffer_handle_resource_destroy(struct wl_listener *listener, + void *data) +{ + struct ds_gbm_client_buffer *buffer; + + buffer = wl_container_of(listener, buffer, resource_destroy); + + buffer->resource = NULL; + + wl_list_remove(&buffer->resource_destroy.link); + wl_list_init(&buffer->resource_destroy.link); + + ds_buffer_drop(&buffer->base); +} + +static struct ds_gbm_client_buffer * +gbm_client_buffer_from_buffer(struct ds_buffer *ds_buffer) +{ + assert(ds_buffer->iface == &gbm_client_buffer_iface); + return (struct ds_gbm_client_buffer *)ds_buffer; +} + +static void +gbm_client_buffer_iface_destroy(struct ds_buffer *ds_buffer) +{ + struct ds_gbm_client_buffer *buffer; + + buffer = gbm_client_buffer_from_buffer(ds_buffer); + + ds_dbg("Destroy gbm client buffer(%p)", buffer); + + gbm_bo_destroy(buffer->gbm_bo); + + wl_list_remove(&buffer->resource_destroy.link); + wl_list_remove(&buffer->buffer_release.link); + free(buffer); +} + +static bool +gbm_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 ds_gbm_client_buffer *buffer; + uint32_t gbm_flags = 0, map_stride; + void *map, *map_data; + + buffer = gbm_client_buffer_from_buffer(ds_buffer); + + if (flags & DS_BUFFER_DATA_PTR_ACCESS_READ) + gbm_flags |= GBM_BO_TRANSFER_READ; + + if (flags & DS_BUFFER_DATA_PTR_ACCESS_WRITE) + gbm_flags |= GBM_BO_TRANSFER_WRITE; + + map = gbm_bo_map(buffer->gbm_bo, 0, 0, ds_buffer->width, ds_buffer->height, + gbm_flags, &map_stride, &map_data); + if (!map) { + ds_err("Failed gbm_surface_map()"); + return false; + } + + buffer->map_data = map_data; + + *format = convert_tbm_format_to_drm(buffer->format); + *stride = map_stride; + *data = map; + + return true; +} + +static void +gbm_client_buffer_iface_end_ptr_access(struct ds_buffer *ds_buffer) +{ + struct ds_gbm_client_buffer *buffer; + + buffer = gbm_client_buffer_from_buffer(ds_buffer); + + gbm_bo_unmap(buffer->gbm_bo, buffer->map_data); + + buffer->map_data = NULL; +} + +static struct wl_resource * +gbm_client_buffer_iface_get_resource(struct ds_buffer *ds_buffer) +{ + struct ds_gbm_client_buffer *buffer; + + buffer = gbm_client_buffer_from_buffer(ds_buffer); + + return buffer->resource; +} + +static const struct ds_buffer_interface gbm_client_buffer_iface = { + .destroy = gbm_client_buffer_iface_destroy, + .begin_data_ptr_access = gbm_client_buffer_iface_begin_data_ptr_access, + .end_data_ptr_access = gbm_client_buffer_iface_end_ptr_access, + .get_resource = gbm_client_buffer_iface_get_resource, +}; + +static struct ds_gbm_client_buffer * +gbm_client_buffer_create(struct wl_resource *resource) +{ + struct ds_gbm_client_buffer *buffer; + struct gbm_bo *gbm_bo; + int32_t width, height; + + gbm_bo = gbm_bo_import(gbm_server->gbm_device, GBM_BO_IMPORT_WL_BUFFER, + resource, GBM_BO_USE_RENDERING); + if (!gbm_bo) return NULL; + + width = gbm_bo_get_width(gbm_bo); + height = gbm_bo_get_height(gbm_bo); + + buffer = calloc(1, sizeof *buffer); + if (!buffer) { + gbm_bo_destroy(gbm_bo); + return NULL; + } + + ds_buffer_init(&buffer->base, &gbm_client_buffer_iface, width, height); + + buffer->resource = resource; + buffer->gbm_bo = gbm_bo; + buffer->format = gbm_bo_get_format(gbm_bo); + buffer->stride = gbm_bo_get_stride(gbm_bo); + + buffer->buffer_release.notify = gbm_client_buffer_handle_release; + ds_buffer_add_release_listener(&buffer->base, &buffer->buffer_release); + + buffer->resource_destroy.notify = + gbm_client_buffer_handle_resource_destroy; + wl_resource_add_destroy_listener(resource, &buffer->resource_destroy); + + ds_dbg("gbm client buffer(%p) created", buffer); + + return buffer; +} + +static struct ds_gbm_client_buffer * +gbm_client_buffer_get_or_create(struct wl_resource *resource) +{ + struct ds_gbm_client_buffer *buffer; + struct wl_listener *resource_destroy_listener; + + resource_destroy_listener = wl_resource_get_destroy_listener(resource, + gbm_client_buffer_handle_resource_destroy);; + if (resource_destroy_listener) { + buffer = wl_container_of(resource_destroy_listener, + buffer, resource_destroy); + return buffer; + } + + return gbm_client_buffer_create(resource); +} + +static bool +gbm_buffer_resource_iface_is_instance(struct wl_resource *resource) +{ + if (!gbm_server) return false; + + if (!gbm_client_buffer_get_or_create(resource)) + return false; + + return true; +} + +static struct ds_buffer * +gbm_buffer_resource_iface_from_resource(struct wl_resource *resource) +{ + struct ds_gbm_client_buffer *buffer; + + buffer = gbm_client_buffer_get_or_create(resource); + if (!buffer) { + ds_err("Could not get or create ds_gbm_client_buffer"); + return NULL; + } + + return &buffer->base; +} + +static const struct ds_buffer_resource_interface gbm_buffer_resource_iface = { + .name = "gbm", + .is_instance = gbm_buffer_resource_iface_is_instance, + .from_resource = gbm_buffer_resource_iface_from_resource, +}; diff --git a/src/gbm_server/gbm_server.h b/src/gbm_server/gbm_server.h new file mode 100644 index 0000000..659c5f6 --- /dev/null +++ b/src/gbm_server/gbm_server.h @@ -0,0 +1,24 @@ +#ifndef DS_TIZEN_GBM_SERVER_H +#define DS_TIZEN_GBM_SERVER_H + +#include +#include +#include + +struct ds_gbm_client_buffer +{ + struct ds_buffer base; + + struct gbm_bo *gbm_bo; + struct wl_resource *resource; + + struct wl_listener buffer_release; + struct wl_listener resource_destroy; + + uint32_t format; + uint32_t stride; + + void *map_data; +}; + +#endif diff --git a/src/gbm_server/meson.build b/src/gbm_server/meson.build new file mode 100644 index 0000000..592a79d --- /dev/null +++ b/src/gbm_server/meson.build @@ -0,0 +1,30 @@ +libds_tizen_gbm_server_files = [ + 'gbm_server.c', +] + +libds_tizen_gbm_server_deps = [ + deps_libds_tizen, + dep_libshared, + dependency('gbm', required: true), +] + +lib_libds_tizen_gbm_server = shared_library('ds-tizen-gbm-server', libds_tizen_gbm_server_files, + dependencies: libds_tizen_gbm_server_deps, + include_directories: [ common_inc, include_directories('.'), include_directories('..') ], + version: meson.project_version(), + install: true +) + +deps_libds_tizen_gbm_server = declare_dependency( + link_with: lib_libds_tizen_gbm_server, + dependencies: libds_tizen_gbm_server_deps, + include_directories: [ common_inc, include_directories('.') ], +) + +pkgconfig = import('pkgconfig') +pkgconfig.generate(lib_libds_tizen_gbm_server, + version: meson.project_version(), + filebase: 'libds-tizen-gbm-server', + name: 'libds-tizen-gbm-server', + description: '-gbm extension of libds-tizen for tizen platform', +) diff --git a/src/meson.build b/src/meson.build index d0c0e13..15c2b62 100644 --- a/src/meson.build +++ b/src/meson.build @@ -56,3 +56,4 @@ subdir('scaler') subdir('video') subdir('eom') subdir('remote_surface') +subdir('gbm_server')