From a134f56809f5996b8bfc78dc104517df2502bc7e Mon Sep 17 00:00:00 2001 From: Changyeon Lee Date: Tue, 19 Dec 2023 15:26:11 +0900 Subject: [PATCH] add ds_tizen_blender Change-Id: Icea8fd11ae642bad90dd6f094a6fc71583218e18 --- include/libds-tizen/blender.h | 67 +++++++ packaging/libds-tizen.spec | 1 + src/blender/blender.c | 411 ++++++++++++++++++++++++++++++++++++++++++ src/meson.build | 4 + 4 files changed, 483 insertions(+) create mode 100644 include/libds-tizen/blender.h create mode 100644 src/blender/blender.c diff --git a/include/libds-tizen/blender.h b/include/libds-tizen/blender.h new file mode 100644 index 0000000..2161c7b --- /dev/null +++ b/include/libds-tizen/blender.h @@ -0,0 +1,67 @@ +#ifndef LIBDS_TIZEN_BLENDER_H +#define LIBDS_TIZEN_BLENDER_H + +#include +#include +#include + +#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 diff --git a/packaging/libds-tizen.spec b/packaging/libds-tizen.spec index 4aa73be..e2c980c 100644 --- a/packaging/libds-tizen.spec +++ b/packaging/libds-tizen.spec @@ -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 index 0000000..7e70a85 --- /dev/null +++ b/src/blender/blender.c @@ -0,0 +1,411 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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); +} diff --git a/src/meson.build b/src/meson.build index 4bb67a0..4a3a6b5 100644 --- a/src/meson.build +++ b/src/meson.build @@ -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) ], -- 2.7.4