Add gbm_server for supporting gbm_bo buffer 00/298600/1 accepted/tizen/8.0/unified/20231005.094159 accepted/tizen/unified/20230912.013622 tizen_8.0_m2_release
authorChangyeon Lee <cyeon.lee@samsung.com>
Mon, 4 Sep 2023 04:25:27 +0000 (13:25 +0900)
committerTizen Window System <tizen.windowsystem@gmail.com>
Mon, 11 Sep 2023 08:27:36 +0000 (17:27 +0900)
Change-Id: Ic6191bb3cf025acfacdb15a385b0b1d9eb7c275c

include/libds-tizen/gbm_server.h [new file with mode: 0644]
include/libds-tizen/types/gbm_server.h [new file with mode: 0644]
packaging/libds-tizen.spec
src/gbm_server/gbm_server.c [new file with mode: 0644]
src/gbm_server/gbm_server.h [new file with mode: 0644]
src/gbm_server/meson.build [new file with mode: 0644]
src/meson.build

diff --git a/include/libds-tizen/gbm_server.h b/include/libds-tizen/gbm_server.h
new file mode 100644 (file)
index 0000000..dab0ce4
--- /dev/null
@@ -0,0 +1,32 @@
+#ifndef LIBDS_TIZEN_GBM_SERVER_H
+#define LIBDS_TIZEN_GBM_SERVER_H
+
+#include <wayland-server.h>
+#include <gbm.h>
+#include <libds/buffer.h>
+
+#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 (file)
index 0000000..2574d3b
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef LIBDS_TIZEN_TYPES_GBM_SERVER_H
+#define LIBDS_TIZEN_TYPES_GBM_SERVER_H
+
+#include <wayland-server.h>
+#include <gbm.h>
+
+struct ds_gbm_server
+{
+    struct gbm_device *gbm_device;
+};
+
+#endif
index 631169767e2947e28d4ccc48c2567908550c2547..8c42e4e002897765296df4c2a978ea287be4ee0d 100644 (file)
@@ -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 (file)
index 0000000..d0d6035
--- /dev/null
@@ -0,0 +1,264 @@
+#include <assert.h>
+#include <stdbool.h>
+#include <stdlib.h>
+
+#include <gbm.h>
+#include <libds/log.h>
+#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 (file)
index 0000000..659c5f6
--- /dev/null
@@ -0,0 +1,24 @@
+#ifndef DS_TIZEN_GBM_SERVER_H
+#define DS_TIZEN_GBM_SERVER_H
+
+#include <gbm.h>
+#include <libds/interfaces/buffer.h>
+#include <libds-tizen/types/gbm_server.h>
+
+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 (file)
index 0000000..592a79d
--- /dev/null
@@ -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',
+)
index d0c0e13e168a68a723970f5e1a6dd44008326ce0..15c2b62e5bac645b39aa9eb3c8e805956d441781 100644 (file)
@@ -56,3 +56,4 @@ subdir('scaler')
 subdir('video')
 subdir('eom')
 subdir('remote_surface')
+subdir('gbm_server')