add ds_tizen_blender 56/303556/1
authorChangyeon Lee <cyeon.lee@samsung.com>
Tue, 19 Dec 2023 06:26:11 +0000 (15:26 +0900)
committerTizen Window System <tizen.windowsystem@gmail.com>
Tue, 2 Jan 2024 06:27:58 +0000 (15:27 +0900)
Change-Id: Icea8fd11ae642bad90dd6f094a6fc71583218e18

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

diff --git a/include/libds-tizen/blender.h b/include/libds-tizen/blender.h
new file mode 100644 (file)
index 0000000..2161c7b
--- /dev/null
@@ -0,0 +1,67 @@
+#ifndef LIBDS_TIZEN_BLENDER_H
+#define LIBDS_TIZEN_BLENDER_H
+
+#include <stdint.h>
+#include <wayland-server.h>
+#include <libds/surface.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct ds_tizen_blender;
+struct ds_tizen_blend;
+
+enum ds_tizen_blend_state_field {
+    DS_TIZEN_BLEND_STATE_NONE = 0,
+    DS_TIZEN_BLEND_STATE_ALPHA = (1 << 0),
+    DS_TIZEN_BLEND_STATE_EQUATION = (1 << 1),
+};
+
+enum ds_tizen_blend_equation {
+    DS_TIZEN_BLEND_EQUATION_PREMULTIPLIED = 0,
+    DS_TIZEN_BLEND_EQUATION_NONE = (1 << 0),
+};
+
+struct ds_tizen_blend_state
+{
+    enum ds_tizen_blend_state_field committed;
+
+   uint32_t alpha;
+   enum ds_tizen_blend_equation equation;
+};
+
+struct ds_tizen_blender *
+ds_tizen_blender_create(struct wl_display *display);
+
+void
+ds_tizen_blender_add_destroy_listener(struct ds_tizen_blender *blender,
+        struct wl_listener *listener);
+
+void
+ds_tizen_blender_add_destroy_listener(struct ds_tizen_blender *blender,
+        struct wl_listener *listener);
+
+void
+ds_tizen_blender_add_new_blend_listener(struct ds_tizen_blender *blender,
+        struct wl_listener *listener);
+
+void
+ds_tizen_blend_add_destroy_listener(struct ds_tizen_blend *blend,
+        struct wl_listener *listener);
+
+void
+ds_tizen_blend_add_commit_listener(struct ds_tizen_blend *blend,
+        struct wl_listener *listener);
+
+struct ds_surface *
+ds_tizen_blend_get_surface(struct ds_tizen_blend *blend);
+
+struct ds_tizen_blend_state *
+ds_tizen_blend_get_state(struct ds_tizen_blend *blend);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
index 4aa73be..e2c980c 100644 (file)
@@ -46,6 +46,7 @@ BuildRequires:  pkgconfig(eom-server)
 BuildRequires:  pkgconfig(eom)
 BuildRequires:  pkgconfig(xdg-shell-unstable-v6-server)
 BuildRequires:  pkgconfig(gbm)
+BuildRequires:  pkgconfig(wtz-blender-server)
 
 %description
 Wayland Compositor Library for Tizen
diff --git a/src/blender/blender.c b/src/blender/blender.c
new file mode 100644 (file)
index 0000000..7e70a85
--- /dev/null
@@ -0,0 +1,411 @@
+#include <assert.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <wayland-server.h>
+#include <tizen-surface-server-protocol.h>
+#include <wtz-blender-server-protocol.h>
+#include <libds/log.h>
+#include <libds/util/addon.h>
+#include <libds/types/ds_surface.h>
+
+#include "util.h"
+#include "libds-tizen/blender.h"
+
+#define TIZEN_BLENDER_VERSION 1
+
+struct ds_tizen_blender
+{
+    struct wl_global *global;
+
+    struct wl_list clients;
+
+    struct wl_listener destroy;
+
+    struct {
+        struct wl_signal destroy;
+        struct wl_signal new_blend;
+    } events;
+};
+
+struct ds_tizen_blender_client
+{
+    struct wl_list link; //clients
+
+    struct ds_tizen_blender *blender;
+
+    struct wl_resource *resource;
+    struct wl_client *wl_client;
+
+    struct {
+        struct wl_signal destroy;
+    } events;
+};
+
+struct ds_tizen_blend
+{
+    struct wl_resource *resource;
+    struct wl_client *wl_client;
+
+    struct ds_tizen_blend_state current, pending;
+
+    struct ds_surface *surface;
+    struct ds_addon surface_addon;
+
+    struct {
+        struct wl_listener surface_commit;
+    } listener;
+
+    struct {
+        struct wl_signal commit;
+        struct wl_signal destroy;
+    } events;
+};
+
+static void
+blender_handle_display_destroy(struct wl_listener *listener, void *data);
+static void
+blender_bind(struct wl_client *wl_client, void *data, uint32_t version,
+        uint32_t id);
+
+WL_EXPORT struct ds_tizen_blender *
+ds_tizen_blender_create(struct wl_display *display)
+{
+    struct ds_tizen_blender *blender;
+
+    blender = calloc(1, sizeof *blender);
+    if (!blender) {
+        ds_err("calloc() failed.");
+        return NULL;
+    }
+
+    blender->global = wl_global_create(display, &wtz_blender_interface,
+            TIZEN_BLENDER_VERSION, blender, blender_bind);
+    if (!blender->global) {
+        ds_err("wl_global_create() failed. tizen_surface_shm_interface");
+        free(blender);
+        return NULL;
+    }
+
+    wl_list_init(&blender->clients);
+
+    blender->destroy.notify = blender_handle_display_destroy;
+    wl_display_add_destroy_listener(display, &blender->destroy);
+
+    wl_signal_init(&blender->events.destroy);
+    wl_signal_init(&blender->events.new_blend);
+
+    ds_inf("Global created: tizen_blender(%p)", blender);
+
+    return blender;
+}
+
+WL_EXPORT void
+ds_tizen_blender_add_destroy_listener(struct ds_tizen_blender *blender,
+        struct wl_listener *listener)
+{
+    wl_signal_add(&blender->events.destroy, listener);
+}
+
+WL_EXPORT void
+ds_tizen_blender_add_new_blend_listener(struct ds_tizen_blender *blender,
+        struct wl_listener *listener)
+{
+    wl_signal_add(&blender->events.new_blend, listener);
+}
+
+WL_EXPORT void
+ds_tizen_blend_add_destroy_listener(struct ds_tizen_blend *blend,
+        struct wl_listener *listener)
+{
+    wl_signal_add(&blend->events.destroy, listener);
+}
+
+WL_EXPORT void
+ds_tizen_blend_add_commit_listener(struct ds_tizen_blend *blend,
+        struct wl_listener *listener)
+{
+    wl_signal_add(&blend->events.commit, listener);
+}
+
+WL_EXPORT struct ds_surface *
+ds_tizen_blend_get_surface(struct ds_tizen_blend *blend)
+{
+    return blend->surface;
+}
+
+WL_EXPORT struct ds_tizen_blend_state *
+ds_tizen_blend_get_state(struct ds_tizen_blend *blend)
+{
+    return &blend->current;
+}
+
+static void
+blender_handle_display_destroy(struct wl_listener *listener, void *data)
+{
+    struct ds_tizen_blender *blender;
+
+    blender = wl_container_of(listener, blender, destroy);
+
+    ds_inf("Global destroy: blender(%p)", blender);
+
+    wl_signal_emit_mutable(&blender->events.destroy, blender);
+    wl_list_remove(&blender->destroy.link);
+    wl_global_destroy(blender->global);
+    free(blender);
+}
+
+static void
+blend_handle_destroy(struct wl_client *client, struct wl_resource *resource)
+{
+    wl_resource_destroy(resource);
+}
+
+static void
+blend_handle_set_alpha(struct wl_client *client, struct wl_resource *resource,
+        uint32_t alpha)
+{
+    struct ds_tizen_blend *blend;
+
+    blend = wl_resource_get_user_data(resource);
+
+    blend->pending.alpha = alpha;
+    blend->pending.committed |= DS_TIZEN_BLEND_STATE_ALPHA;
+}
+
+static void
+blend_handle_set_equation(struct wl_client *client, struct wl_resource *resource,
+        uint32_t equation)
+{
+    struct ds_tizen_blend *blend;
+
+    blend = wl_resource_get_user_data(resource);
+
+    blend->pending.equation = equation;
+    blend->pending.committed |= DS_TIZEN_BLEND_STATE_EQUATION;
+}
+
+static const struct wtz_blend_interface blend_impl = {
+   blend_handle_destroy,
+   blend_handle_set_alpha,
+   blend_handle_set_equation,
+};
+
+static void
+blend_destroy(struct ds_tizen_blend *blend)
+{
+    ds_inf("blend_destroy (blend:%p)", blend);
+
+    wl_signal_emit_mutable(&blend->events.destroy, blend);
+
+    if (blend->listener.surface_commit.notify)
+        wl_list_remove(&blend->listener.surface_commit.link);
+
+    if (blend->surface)
+        ds_addon_finish(&blend->surface_addon);
+
+    free(blend);
+}
+
+static void
+blend_handle_resource_destroy(struct wl_resource *resource)
+{
+    struct ds_tizen_blend *blend;
+
+    blend = wl_resource_get_user_data(resource);
+
+    ds_inf("blend_handle_resource_destroy (blend:%p)", blend);
+
+    if (blend->surface) {
+        blend->resource = NULL;
+        return;
+    }
+
+    blend_destroy(blend);
+}
+
+static void
+blend_handle_surface_commit(struct wl_listener *listener, void *data)
+{
+    struct ds_tizen_blend *blend;
+
+    blend = wl_container_of(listener, blend, listener.surface_commit);
+
+    if (!blend->resource) {
+        blend_destroy(blend);
+        return;
+    }
+
+    if (blend->pending.committed == DS_TIZEN_BLEND_STATE_NONE)
+        return;
+
+    if (blend->pending.committed & DS_TIZEN_BLEND_STATE_ALPHA)
+        blend->current.alpha = blend->pending.alpha;
+
+    if (blend->pending.committed & DS_TIZEN_BLEND_STATE_EQUATION)
+        blend->current.equation = blend->pending.equation;
+
+    blend->current.committed = blend->pending.committed;
+    blend->pending.committed = DS_TIZEN_BLEND_STATE_NONE;
+
+    wl_signal_emit_mutable(&blend->events.commit, blend);
+}
+
+static void
+blend_handle_surface_destroy(struct ds_addon *addon)
+{
+    struct ds_tizen_blend *blend;
+
+    blend = wl_container_of(addon, blend, surface_addon);
+
+    if (blend->listener.surface_commit.notify) {
+        wl_list_remove(&blend->listener.surface_commit.link);
+        blend->listener.surface_commit.notify = NULL;
+    }
+
+    ds_addon_finish(&blend->surface_addon);
+    blend->surface = NULL;
+
+    if (!blend->resource)
+        blend_destroy(blend);
+}
+
+static struct ds_addon_interface blend_addon_impl = {
+       .name = "ds_tizen_blend",
+       .destroy = blend_handle_surface_destroy,
+};
+
+static struct ds_tizen_blend *
+blend_client_get_from_surface(struct ds_tizen_blender_client *client, struct ds_surface *surface)
+{
+   struct ds_addon *addon;
+   struct ds_tizen_blend *blend;
+
+    addon = ds_addon_find(&surface->addons, client, &blend_addon_impl);
+    if (!addon) return NULL;
+
+    blend = wl_container_of(addon, blend, surface_addon);
+
+    return blend;
+}
+
+static void
+blender_handle_get_blend(struct wl_client *wl_client,
+        struct wl_resource *resource,
+        uint32_t id, struct wl_resource *surface_resource)
+{
+    struct ds_tizen_blender_client *client;
+    struct ds_surface *surface;
+    struct ds_tizen_blend *blend;
+
+    ds_inf("tizen_blender: get_blend");
+
+    client = wl_resource_get_user_data(resource);
+
+    surface = ds_surface_from_resource(surface_resource);
+    if (!surface) {
+        wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
+                "invalid wl_surface resource:%u",
+                (unsigned int)wl_resource_get_id(surface_resource));
+        return;
+    }
+
+    blend = blend_client_get_from_surface(client, surface);
+    if (blend) {
+        wl_resource_post_error(resource, WTZ_BLENDER_ERROR_BLEND_EXISTS,
+                "blend object already exists");
+        return;
+    }
+
+    blend = calloc(1, sizeof *blend);
+    if (blend == NULL) {
+        ds_err("calloc() failed. tizen_blend");
+        wl_client_post_no_memory(wl_client);
+        return;
+    }
+
+    blend->resource = wl_resource_create(wl_client, &wtz_blend_interface,
+           wl_resource_get_version(resource), id);
+    if (blend->resource == NULL) {
+        ds_err("tizen_blend : wl_resource_create() failed.");
+        free(blend);
+        wl_client_post_no_memory(wl_client);
+        return;
+    }
+
+    wl_resource_set_implementation(blend->resource, &blend_impl, blend,
+        blend_handle_resource_destroy);
+
+    ds_addon_init(&blend->surface_addon, &surface->addons, client, &blend_addon_impl);
+
+    blend->listener.surface_commit.notify = blend_handle_surface_commit;
+    ds_surface_add_commit_listener(surface, &blend->listener.surface_commit);
+
+    blend->surface = surface;
+
+    wl_signal_init(&blend->events.destroy);
+    wl_signal_init(&blend->events.commit);
+
+    wl_signal_emit_mutable(&client->blender->events.new_blend, blend);
+}
+
+static void
+blender_handle_destroy(struct wl_client *wl_client,
+        struct wl_resource *resource)
+{
+    wl_resource_destroy(resource);
+}
+
+static const struct wtz_blender_interface blender_impl =
+{
+    blender_handle_destroy,
+    blender_handle_get_blend,
+};
+
+static void
+blender_client_handle_destroy(struct wl_resource *resource)
+{
+    struct ds_tizen_blender_client *client;
+
+    client = wl_resource_get_user_data(resource);
+
+    ds_inf("blender_client_handle_destroy (client:%p)", client);
+
+    wl_list_remove(&client->link);
+    free(client);
+}
+
+static void
+blender_bind(struct wl_client *wl_client, void *data, uint32_t version,
+        uint32_t id)
+{
+    struct ds_tizen_blender *blender = data;
+    struct ds_tizen_blender_client *client;
+
+    client = calloc(1, sizeof *client);
+    if (client == NULL) {
+        ds_err("calloc() failed. tizen_blender");
+        wl_client_post_no_memory(wl_client);
+        return;
+    }
+
+    ds_inf("tizen_blender_client binds. (client:%p)", client);
+
+    client->blender = blender;
+    client->wl_client = wl_client;
+
+    client->resource = wl_resource_create(wl_client, &wtz_blender_interface,
+            MIN(version, TIZEN_BLENDER_VERSION), id);
+    if (client->resource == NULL) {
+        ds_err("tizen_blender : wl_resource_create() failed.");
+        free(client);
+        wl_client_post_no_memory(wl_client);
+        return;
+    }
+
+    wl_resource_set_implementation(client->resource, &blender_impl, client,
+            blender_client_handle_destroy);
+
+    wl_signal_init(&client->events.destroy);
+
+    wl_list_insert(&blender->clients, &client->link);
+}
index 4bb67a0..4a3a6b5 100644 (file)
@@ -89,6 +89,7 @@ libds_tizen_files = [
   'security.c',
   'display_policy/display_policy.c',
   'screen/screen.c',
+  'blender/blender.c',
 ]
 
 libds_tizen_deps = [
@@ -113,6 +114,8 @@ libds_tizen_deps = [
   dependency('tizen-extension-server', required: true),
   dependency('xkbcommon', required: true),
   dependency('wtz-screen-server', required: true),
+  dependency('wtz-blender-server', required: true),
+  dependency('pixman-1', required: true),
 ]
 
 keylayout_dir = get_option('keylayout_dir')
@@ -128,6 +131,7 @@ lib_libds_tizen = shared_library('ds-tizen', libds_tizen_files,
                          include_directories('./screenshooter'),
                          include_directories('./tbm_server'),
                          include_directories('./video'),
+                         include_directories('./blender'),
                        ],
   version: meson.project_version(),
   c_args: [ '-DKEYLAYOUT_DIR="@0@"'.format(keylayout_dir) ],