Implement linux_explicit_sync (wip) dev/shiin
authorSeunghun Lee <shiin.lee@samsung.com>
Thu, 29 Jun 2023 06:27:13 +0000 (15:27 +0900)
committerSeunghun Lee <shiin.lee@samsung.com>
Thu, 28 Dec 2023 02:06:01 +0000 (11:06 +0900)
include/libds/linux_explicit_sync_v1.h [new file with mode: 0644]
include/libds/types/ds_surface.h
src/linux_explicit_sync_v1.c [new file with mode: 0644]
src/meson.build
src/util.h

diff --git a/include/libds/linux_explicit_sync_v1.h b/include/libds/linux_explicit_sync_v1.h
new file mode 100644 (file)
index 0000000..70a8991
--- /dev/null
@@ -0,0 +1,19 @@
+#ifndef LIBDS_COMPOSITOR_H
+#define LIBDS_COMPOSITOR_H
+
+#include <wayland-server.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct ds_linux_explicit_sync_v1;
+
+struct ds_linux_explicit_sync_v1 *
+ds_linux_explicit_sync_v1_create(struct wl_display *display);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
index c1bb45a..5d1ee5d 100644 (file)
@@ -54,6 +54,8 @@ struct ds_surface_state
         struct ds_fbox src;
         int dst_width, dst_height;
     } viewport;
+
+    int acquire_fence_fd;
 };
 
 struct ds_surface_viewport
diff --git a/src/linux_explicit_sync_v1.c b/src/linux_explicit_sync_v1.c
new file mode 100644 (file)
index 0000000..fd1b717
--- /dev/null
@@ -0,0 +1,233 @@
+#include <wayland-server.h>
+#include <linux-explicit-synchronization-unstable-v1-server-protocol.h>
+
+#include "libds/types/ds_surface.h"
+#include "libds/log.h"
+#include "libds/util/defs.h"
+#include "libds/util/addon.h"
+#include "util.h"
+
+#define ZWP_LINUX_EXPLICIT_SYNCHRONIZATION_VERSION 2
+
+struct ds_linux_explicit_sync_v1 {
+    struct wl_global *global;
+
+    struct wl_listener display_destroy;
+};
+
+struct ds_linux_explicit_sync_v1_state {
+    int acquire_fence_fd;
+};
+
+struct ds_linux_explicit_sync_v1_surface {
+    struct wl_resource *resource;
+    struct ds_linux_explicit_sync_v1 *explicit_sync;
+    struct ds_surface *surface;
+
+    struct ds_linux_explicit_sync_v1_state pending, cache, current;
+    struct ds_addon addon;
+
+    struct wl_listener surface_destroy;
+};
+
+static void linux_explicit_sync_v1_handle_display_destroy(struct wl_listener *listener, void *data);
+static void linux_explicit_sync_v1_bind(struct wl_client *client, void *data, uint32_t version, uint32_t id);
+
+WL_EXPORT struct ds_linux_explicit_sync_v1 *
+ds_linux_explicit_sync_v1_create(struct wl_display *display);
+{
+    struct ds_linux_explicit_sync_v1 *explicit_sync;
+
+    explicit_sync = calloc(1, sizeof *explicit_sync);
+    if (!explicit_sync)
+        return NULL;
+
+    explicit_sync->global = wl_global_create(display,
+            &zwp_linux_explicit_synchronization_v1_interface,
+            ZWP_LINUX_EXPLICIT_SYNCHRONIZATION_VERSION,
+            explicit_sync,
+            linux_explicit_sync_v1_bind);
+    if (!explicit_sync->global) {
+        ds_err("Could not create global");
+        free(explicit_sync);
+        return NULL;
+    }
+
+    explicit_sync->display_destroy.notify =
+        linux_explicit_sync_v1_handle_display_destroy;
+    wl_display_add_destroy_listener(display, &explicit_sync->display_destroy);
+
+    ds_inf("Create ds_linux_explicit_sync_v1");
+
+    return explicit_sync;
+}
+
+static void
+linux_explicit_sync_v1_handle_display_destroy(struct wl_listener *listener, void *data)
+{
+    struct ds_linux_explicit_sync_v1 *explicit_sync;
+
+    explicit_sync = wl_container_of(listener, explicit_sync, display_destroy);
+
+    wl_global_destroy(explicit_sync->global);
+    free(explicit_sync);
+}
+
+static void
+surface_destroy(struct ds_linux_explicit_sync_v1_surface *surface)
+{
+    fd_clear(&surface->pending.acquire_fence_fd);
+    ds_addon_finish(&surface->addon);
+    free(surface);
+}
+
+static void
+surface_addon_destroy(struct ds_addon *addon)
+{
+    struct ds_linux_explicit_sync_v1_surface *surface;
+
+    surface = wl_container_of(addon, surface, addon);
+    surface_destroy(surface);
+}
+
+static const struct ds_addon_interface surface_addon_impl = {
+    .name = "ds_linux_explicit_sync_v1_surface",
+    .destroy = surface_addon_destroy,
+};
+
+static ds_linux_explicit_sync_v1_surface *
+create_surface(struct ds_linux_explicit_sync_v1 *explicit_sync,
+        struct ds_surface *ds_surface)
+{
+    struct ds_linux_explicit_sync_v1_surface *surface;
+
+    surface = calloc(1, sizeof(*surface));
+    if (!surface)
+        return NULL;
+
+    surface->surface = ds_surface;
+    surface->explicit_sync = explicit_sync;
+
+    ds_addon_init(&surface->addon, &ds_surface->addons, explicit_sync,
+            &surface_addon_impl);
+}
+
+static void
+linux_explicit_sync_v1_destroy(struct wl_client *client,
+        struct wl_resource *resource)
+{
+    wl_resource_destroy(resource);
+}
+
+static void
+surface_handle_resource_destroy(struct wl_resource *resource)
+{
+    struct ds_linux_explicit_sync_v1_surface *surface;
+
+    surface = wl_resource_get_user_data(resource);
+    if (!surface)
+        return;
+
+    surface_destroy(surface);
+    surface->synchronization_resource = NULL;
+}
+
+static void
+surface_sync_handle_destroy(struct wl_client *client,
+        struct wl_resource *resource)
+{
+    wl_resource_destroy(resource);
+}
+
+static void
+surface_sync_handle_set_acquire_fence(struct wl_client *client,
+        struct wl_resource *resource, int32_t fd)
+{
+    struct ds_surface *surface;
+
+    surface = wl_resource_get_user_data(resource);
+}
+
+static void
+surface_sync_handle_get_release(struct wl_client *client,
+        struct wl_resource *resource, int32_t id)
+{
+
+}
+
+const struct zwp_linux_surface_synchronization_v1_interface
+surface_impl = {
+    .destroy = surface_sync_handle_destroy,
+    .set_acquire_fence = surface_sync_handle_set_acquire_fence,
+    .get_release = surface_sync_handle_get_release,
+}
+
+static void
+linux_explicit_sync_handle_get_synchronization(struct wl_client *client,
+        struct wl_resource *resource,
+        uint32_t id,
+        struct wl_resource *surface_resource)
+{
+    struct ds_linux_explicit_sync_v1 *explicit_sync;
+    struct ds_linux_explicit_sync_v1_surface *surface;
+    struct ds_surface *ds_surface;
+    struct ds_addon *addon;
+
+    explicit_sync = wl_resource_get_user_data(resource);
+
+    ds_surface = ds_surface_from_resource(surface_resource);
+    DS_ASSERT(ds_surface);
+
+    addon = ds_addon_find(&ds_surface->addons, explicit_sync, &surface_addon_impl);
+    if (addon) {
+        wl_resource_post_error(resource,
+                ZWP_LINUX_EXPLICIT_SYNCHRONIZATION_V1_ERROR_SYNCHRONIZATION_EXISTS,
+                "wl_surface@d already has a synchronization object",
+                wl_resource_get_id(surface_resource));
+        return;
+    }
+
+    surface = create_surface(explicit_sync, ds_surface);
+    if (!surface) {
+        wl_client_post_no_memory(client);
+        return;
+    }
+
+    surface->resource = wl_resource_create(client,
+            &zwp_linux_surface_synchronization_v1_interface,
+            wl_resource_get_version(resource), id);
+    if (!surface->resource) {
+        wl_client_post_no_memory(client);
+        return;
+    }
+
+    wl_resource_set_implementation(surface->resource,
+            &surface_impl,
+            surface,
+            surface_handle_resource_destroy);
+}
+
+static const struct zwp_linux_explicit_synchronization_v1_interface
+linux_explicit_sync_v1_impl = {
+    .destroy = linux_explicit_sync_v1_destroy,
+    .get_synchronization = linux_explicit_sync_handle_get_synchronization,
+}
+
+static void
+linux_explicit_sync_v1_bind(struct wl_client *client, void *data, uint32_t version,
+        uint32_t id)
+{
+    struct ds_linux_explicit_sync_v1 *explicit_sync = data;
+    struct wl_resource *resource;
+
+    resource = wl_resource_create(client,
+            &zwp_linux_explicit_synchronization_v1_interface, version, id);
+    if (!resource) {
+        wl_client_post_no_memory(client);
+        return;
+    }
+
+    wl_resource_set_implementation(resource, &linux_explicit_sync_v1_impl,
+            explicit_sync, NULL);
+}
+
index 7bed33b..28efbde 100644 (file)
@@ -30,11 +30,13 @@ libds_files = [
   'seat/seat_touch.c',
   'shell.c',
   'shell_surface.c',
+  'explicit_sync.c',
 ]
 
 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',
+  'linux-explicit-synchronization': wl_protocol_dir / 'unstable/linux-explicit-synchronization/linux-explicit-synchronization-unstable-v1.xml',
 }
 
 protocols_code = {}
index 26a63eb..708da90 100644 (file)
@@ -5,6 +5,7 @@
 #include <stdint.h>
 #include <time.h>
 #include <stdlib.h>
+#include <unistd.h>
 
 #include "libds/util/defs.h"
 
@@ -20,4 +21,29 @@ allocate_shm_file(size_t size);
 bool
 allocate_shm_file_pair(size_t size, int *rw_fd_ptr, int *ro_fd_ptr);
 
+static inline void
+fd_update(int *fd, int new_fd)
+{
+    if (*fd == new_fd)
+        return;
+    if (*fd >= 0)
+        close(*fd);
+    *fd = new_fd;
+}
+
+static inline void
+fd_move(int *dest, int *src)
+{
+    if (dest == src)
+        return;
+    fd_update(dest, *src);
+    *src = -1;
+}
+
+static inline void
+fd_clear(int *fd)
+{
+    fd_update(fd, -1);
+}
+
 #endif