Add ds_single_pixel_buffer_manager_v1 35/298235/1 accepted/tizen/unified/20230904.165046
authorSeunghun Lee <shiin.lee@samsung.com>
Fri, 1 Sep 2023 08:38:56 +0000 (17:38 +0900)
committerTizen Window System <tizen.windowsystem@gmail.com>
Mon, 4 Sep 2023 05:01:04 +0000 (14:01 +0900)
This implements the single-pixel-buffer-v1 protocol [1], to allow
clients to create 1x1 buffers with a single color.

[1]: https://gitlab.freedesktop.org/wayland/wayland-protocols/-/merge_requests/104

Change-Id: I15da75b51762d7e0a2727d27ea3255ca8ab833cc

include/libds/single_pixel_buffer_v1.h [new file with mode: 0644]
src/client_buffer/single_pixel_buffer_v1.c [new file with mode: 0644]
src/meson.build

diff --git a/include/libds/single_pixel_buffer_v1.h b/include/libds/single_pixel_buffer_v1.h
new file mode 100644 (file)
index 0000000..8c32a8d
--- /dev/null
@@ -0,0 +1,17 @@
+#ifndef LIBDS_SINGLE_PIXEL_BUFFER_V1_H
+#define LIBDS_SINGLE_PIXEL_BUFFER_V1_H
+
+#include <wayland-server.h>
+#include <libds/buffer.h>
+
+struct ds_single_pixel_buffer_manager_v1;
+
+struct ds_single_pixel_buffer_v1;
+
+struct ds_single_pixel_buffer_manager_v1 *
+ds_single_pixel_buffer_manager_v1_create(struct wl_display *display);
+
+struct ds_single_pixel_buffer_v1 *
+ds_single_pixel_buffer_v1_from_buffer(struct ds_buffer *ds_buffer);
+
+#endif
diff --git a/src/client_buffer/single_pixel_buffer_v1.c b/src/client_buffer/single_pixel_buffer_v1.c
new file mode 100644 (file)
index 0000000..c1d0923
--- /dev/null
@@ -0,0 +1,231 @@
+#include <stdlib.h>
+#include <drm_fourcc.h>
+
+#include "libds/log.h"
+#include "libds/util/defs.h"
+#include "libds/interfaces/buffer.h"
+
+#include "pixel_format.h"
+#include "single-pixel-buffer-v1-server-protocol.h"
+
+#define SINGLE_PIXEL_BUFFER_MANAGER_V1_VERSION 1
+
+struct ds_single_pixel_buffer_manager_v1
+{
+    struct wl_global *global;
+
+    struct wl_listener display_destroy;
+};
+
+struct ds_single_pixel_buffer_v1 {
+    struct ds_buffer base;
+    struct wl_resource *resource;
+    uint32_t r, g, b, a;
+    uint32_t argb8888;
+};
+
+static const struct wl_buffer_interface single_pixel_buffer_wl_impl;
+
+static bool
+single_pixel_buffer_is_instance(struct wl_resource *resource)
+{
+    return wl_resource_instance_of(resource, &wl_buffer_interface,
+            &single_pixel_buffer_wl_impl);
+}
+
+static struct ds_single_pixel_buffer_v1 *
+single_pixel_buffer_v1_from_resource(struct wl_resource *resource)
+{
+    DS_ASSERT(single_pixel_buffer_is_instance(resource));
+    return wl_resource_get_user_data(resource);
+}
+
+static struct ds_buffer *
+single_pixel_buffer_from_resource(struct wl_resource *resource)
+{
+    struct ds_single_pixel_buffer_v1 *buffer;
+
+    buffer = single_pixel_buffer_v1_from_resource(resource);
+    return &buffer->base;
+}
+
+static const struct ds_buffer_resource_interface
+single_pixel_buffer_resource_iface = {
+    .name = "ds_single_pixel_buffer_v1",
+    .is_instance = single_pixel_buffer_is_instance,
+    .from_resource = single_pixel_buffer_from_resource,
+};
+
+static void
+destroy_resource(struct wl_client *client, struct wl_resource *resource)
+{
+    wl_resource_destroy(resource);
+}
+
+static const struct wl_buffer_interface single_pixel_buffer_wl_impl = {
+    .destroy = destroy_resource,
+};
+
+static void
+single_pixel_buffer_handle_resource_destroy(struct wl_resource *resource)
+{
+    struct ds_single_pixel_buffer_v1 *buffer;
+
+    buffer = wl_resource_get_user_data(resource);
+    ds_buffer_drop(&buffer->base);
+}
+
+static void
+single_pixel_buffer_iface_destroy(struct ds_buffer *ds_buffer)
+{
+    struct ds_single_pixel_buffer_v1 *buffer;
+
+    buffer = wl_container_of(ds_buffer, buffer, base);
+    free(buffer);
+}
+
+static bool
+single_pixel_buffer_iface_begin_data_ptr_access(struct ds_buffer *ds_buffer,
+        uint32_t flags, void **data, uint32_t *format, size_t *stride)
+{
+    struct ds_single_pixel_buffer_v1 *buffer;
+
+    if (flags & ~DS_BUFFER_DATA_PTR_ACCESS_READ)
+        return false;
+
+    buffer = wl_container_of(ds_buffer, buffer, base);
+    *data = &buffer->argb8888;
+    *format = DRM_FORMAT_ARGB8888;
+    *stride = sizeof(buffer->argb8888);
+
+    return true;
+}
+
+static void
+single_pixel_buffer_iface_end_data_ptr_access(struct ds_buffer *ds_buffer)
+{
+    // This space is intentionally left blank
+}
+
+static struct wl_resource *
+single_pixel_buffer_iface_get_resource(struct ds_buffer *ds_buffer)
+{
+    struct ds_single_pixel_buffer_v1 *buffer;
+
+    buffer = wl_container_of(ds_buffer, buffer, base);
+    return buffer->resource;
+}
+
+static const struct ds_buffer_interface single_pixel_buffer_iface = {
+    .destroy = single_pixel_buffer_iface_destroy,
+    .begin_data_ptr_access = single_pixel_buffer_iface_begin_data_ptr_access,
+    .end_data_ptr_access = single_pixel_buffer_iface_end_data_ptr_access,
+    .get_resource = single_pixel_buffer_iface_get_resource,
+};
+
+static void
+manager_handle_create_u32_rgba_buffer(struct wl_client *client,
+        struct wl_resource *resource, uint32_t id, uint32_t r, uint32_t g,
+        uint32_t b, uint32_t a)
+{
+    struct ds_single_pixel_buffer_v1 *buffer;
+
+    buffer = calloc(1, sizeof *buffer);
+    if (!buffer) {
+        wl_client_post_no_memory(client);
+        return;
+    }
+
+    buffer->resource = wl_resource_create(client, &wl_buffer_interface, 1, id);
+    if (!buffer->resource) {
+        wl_client_post_no_memory(client);
+        free(buffer);
+        return;
+    }
+    wl_resource_set_implementation(buffer->resource,
+            &single_pixel_buffer_wl_impl, buffer, single_pixel_buffer_handle_resource_destroy);
+
+    ds_buffer_init(&buffer->base, &single_pixel_buffer_iface, 1, 1);
+
+    buffer->r = r;
+    buffer->g = g;
+    buffer->b = b;
+    buffer->a = a;
+
+    buffer->argb8888 = (((uint32_t)((a / (double)0xffffffff) * 255)) << 24) |
+        (((uint32_t)((r / (double)0xffffffff) * 255)) << 16) |
+        (((uint32_t)((g / (double)0xffffffff) * 255)) << 8) |
+        ((uint32_t)((b / (double)0xffffffff) * 255));
+}
+
+static const struct wp_single_pixel_buffer_manager_v1_interface manager_impl = {
+    .destroy = destroy_resource,
+    .create_u32_rgba_buffer = manager_handle_create_u32_rgba_buffer,
+};
+
+static void manager_bind(struct wl_client *client, void *data,
+        uint32_t version, uint32_t id)
+{
+    struct wl_resource *resource;
+
+    resource = wl_resource_create(client,
+            &wp_single_pixel_buffer_manager_v1_interface, version, id);
+    if (!resource) {
+        wl_client_post_no_memory(client);
+        return;
+    }
+
+    wl_resource_set_implementation(resource, &manager_impl, NULL, NULL);
+}
+
+static void
+manager_handle_display_destroy(struct wl_listener *listener, void *data)
+{
+    struct ds_single_pixel_buffer_manager_v1 *manager;
+
+    manager = wl_container_of(listener, manager, display_destroy);
+    wl_global_destroy(manager->global);
+    free(manager);
+}
+
+WL_EXPORT struct ds_single_pixel_buffer_manager_v1 *
+ds_single_pixel_buffer_manager_v1_create(struct wl_display *display)
+{
+    struct ds_single_pixel_buffer_manager_v1 *manager;
+
+    DS_RETURN_VAL_IF_FAIL(display, NULL);
+
+    manager = calloc(1, sizeof *manager);
+    if (manager == NULL)
+        return NULL;
+
+    manager->global = wl_global_create(display,
+            &wp_single_pixel_buffer_manager_v1_interface,
+            SINGLE_PIXEL_BUFFER_MANAGER_V1_VERSION,
+            NULL, manager_bind);
+    if (!manager->global) {
+        free(manager);
+        return NULL;
+    }
+
+    manager->display_destroy.notify = manager_handle_display_destroy;
+    wl_display_add_destroy_listener(display, &manager->display_destroy);
+
+    ds_buffer_register_resource_interface(&single_pixel_buffer_resource_iface);
+
+    return manager;
+}
+
+WL_EXPORT struct ds_single_pixel_buffer_v1 *
+ds_single_pixel_buffer_v1_from_buffer(struct ds_buffer *ds_buffer)
+{
+    struct ds_single_pixel_buffer_v1 *buffer;
+
+    DS_RETURN_VAL_IF_FAIL(ds_buffer, NULL);
+
+    if (ds_buffer->iface != &single_pixel_buffer_iface)
+        return NULL;
+
+    return wl_container_of(ds_buffer, buffer, base);
+}
+
index 59043e3..7bed33b 100644 (file)
@@ -14,6 +14,7 @@ libds_files = [
   'compositor/surface.c',
   'compositor/subsurface.c',
   'client_buffer/shm_client_buffer.c',
+  'client_buffer/single_pixel_buffer_v1.c',
   'xdg_shell/xdg_shell.c',
   'xdg_shell/xdg_surface.c',
   'xdg_shell/xdg_toplevel.c',
@@ -33,6 +34,7 @@ libds_files = [
 
 protocols = {
   'xdg-shell': wl_protocol_dir / 'stable/xdg-shell/xdg-shell.xml',
+  'single-pixel-buffer-v1': wl_protocol_dir / 'staging/single-pixel-buffer/single-pixel-buffer-v1.xml',
 }
 
 protocols_code = {}