From e381ba22141a56e5dc669be04248cdf8c1beeebf Mon Sep 17 00:00:00 2001 From: Changyeon Lee Date: Wed, 15 Nov 2023 19:12:45 +0900 Subject: [PATCH] add ds_tizen_blur implementation of wtz-blur protocol Change-Id: Idcf10764a957e53ce6aa3bc49381d4dbbfd37aea --- include/libds-tizen/blur.h | 62 +++++++ packaging/libds-tizen.spec | 2 + src/blur/blur.c | 426 +++++++++++++++++++++++++++++++++++++++++++++ src/meson.build | 3 + 4 files changed, 493 insertions(+) create mode 100644 include/libds-tizen/blur.h create mode 100644 src/blur/blur.c diff --git a/include/libds-tizen/blur.h b/include/libds-tizen/blur.h new file mode 100644 index 0000000..84fe80f --- /dev/null +++ b/include/libds-tizen/blur.h @@ -0,0 +1,62 @@ +#ifndef LIBDS_TIZEN_BLUR_H +#define LIBDS_TIZEN_BLUR_H + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct ds_tizen_blur_manager; +struct ds_tizen_blur; + +enum ds_tizen_blur_state_field { + DS_TIZEN_BLUR_STATE_NONE = 0, + DS_TIZEN_BLUR_STATE_REGION = (1 << 0), + DS_TIZEN_BLUR_STATE_RADIUS = (1 << 1), +}; + +struct ds_tizen_blur_state +{ + enum ds_tizen_blur_state_field committed; + + pixman_region32_t region; + uint32_t radius; +}; + +struct ds_tizen_blur_manager * +ds_tizen_blur_manager_create(struct wl_display *display); + +void +ds_tizen_blur_manager_add_destroy_listener(struct ds_tizen_blur_manager *blur, + struct wl_listener *listener); + +void +ds_tizen_blur_manager_add_destroy_listener(struct ds_tizen_blur_manager *blur, + struct wl_listener *listener); + +void +ds_tizen_blur_manager_add_new_blur_listener(struct ds_tizen_blur_manager *blur, + struct wl_listener *listener); + +void +ds_tizen_blur_add_destroy_listener(struct ds_tizen_blur *blur, + struct wl_listener *listener); + +void +ds_tizen_blur_add_commit_listener(struct ds_tizen_blur *blur, + struct wl_listener *listener); + +struct ds_surface * +ds_tizen_blur_get_surface(struct ds_tizen_blur *blur); + +struct ds_tizen_blur_state * +ds_tizen_blur_get_state(struct ds_tizen_blur *blur); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/packaging/libds-tizen.spec b/packaging/libds-tizen.spec index e2c980c..0de56b1 100644 --- a/packaging/libds-tizen.spec +++ b/packaging/libds-tizen.spec @@ -47,6 +47,7 @@ BuildRequires: pkgconfig(eom) BuildRequires: pkgconfig(xdg-shell-unstable-v6-server) BuildRequires: pkgconfig(gbm) BuildRequires: pkgconfig(wtz-blender-server) +BuildRequires: pkgconfig(wtz-blur-server) %description Wayland Compositor Library for Tizen @@ -434,6 +435,7 @@ Group: Development/Libraries %description gbm-server-devel Development package for tizen wayland-gbm-server + %prep %setup -q cp %{SOURCE1001} . diff --git a/src/blur/blur.c b/src/blur/blur.c new file mode 100644 index 0000000..ad75eb9 --- /dev/null +++ b/src/blur/blur.c @@ -0,0 +1,426 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "util.h" +#include "libds-tizen/blur.h" + +#define TIZEN_BLUR_VERSION 1 + +struct ds_tizen_blur_manager +{ + struct wl_global *global; + + struct wl_list clients; + + struct wl_listener destroy; + + struct { + struct wl_signal destroy; + struct wl_signal new_blur; + } events; +}; + +struct ds_tizen_blur_client +{ + struct wl_list link; //clients + + struct ds_tizen_blur_manager *blur_manager; + + struct wl_resource *resource; + struct wl_client *wl_client; + + struct { + struct wl_signal destroy; + } events; +}; + +struct ds_tizen_blur +{ + struct wl_resource *resource; + struct wl_client *wl_client; + + struct ds_tizen_blur_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 +blur_manager_handle_display_destroy(struct wl_listener *listener, void *data); +static void +blur_manager_bind(struct wl_client *wl_client, void *data, uint32_t version, + uint32_t id); + +WL_EXPORT struct ds_tizen_blur_manager * +ds_tizen_blur_manager_create(struct wl_display *display) +{ + struct ds_tizen_blur_manager *blur_manager; + + blur_manager = calloc(1, sizeof *blur_manager); + if (!blur_manager) { + ds_err("calloc() failed."); + return NULL; + } + + blur_manager->global = wl_global_create(display, &wtz_blur_manager_interface, + TIZEN_BLUR_VERSION, blur_manager, blur_manager_bind); + if (!blur_manager->global) { + ds_err("wl_global_create() failed. tizen_surface_shm_interface"); + free(blur_manager); + return NULL; + } + + wl_list_init(&blur_manager->clients); + + blur_manager->destroy.notify = blur_manager_handle_display_destroy; + wl_display_add_destroy_listener(display, &blur_manager->destroy); + + wl_signal_init(&blur_manager->events.destroy); + wl_signal_init(&blur_manager->events.new_blur); + + ds_inf("Global created: tizen_blur_manager(%p)", blur_manager); + + return blur_manager; +} + +WL_EXPORT void +ds_tizen_blur_manager_add_destroy_listener(struct ds_tizen_blur_manager *blur, + struct wl_listener *listener) +{ + wl_signal_add(&blur->events.destroy, listener); +} + +WL_EXPORT void +ds_tizen_blur_manager_add_new_blur_listener(struct ds_tizen_blur_manager *blur, + struct wl_listener *listener) +{ + wl_signal_add(&blur->events.new_blur, listener); +} + +WL_EXPORT void +ds_tizen_blur_add_destroy_listener(struct ds_tizen_blur *blur, + struct wl_listener *listener) +{ + wl_signal_add(&blur->events.destroy, listener); +} + +WL_EXPORT void +ds_tizen_blur_add_commit_listener(struct ds_tizen_blur *blur, + struct wl_listener *listener) +{ + wl_signal_add(&blur->events.commit, listener); +} + +WL_EXPORT struct ds_surface * +ds_tizen_blur_get_surface(struct ds_tizen_blur *blur) +{ + return blur->surface; +} + +WL_EXPORT struct ds_tizen_blur_state * +ds_tizen_blur_get_state(struct ds_tizen_blur *blur) +{ + return &blur->current; +} + +static void +blur_manager_handle_display_destroy(struct wl_listener *listener, void *data) +{ + struct ds_tizen_blur_manager *blur_manager; + + blur_manager = wl_container_of(listener, blur_manager, destroy); + + ds_inf("Global destroy: blur_manager(%p)", blur_manager); + + wl_signal_emit_mutable(&blur_manager->events.destroy, blur_manager); + wl_list_remove(&blur_manager->destroy.link); + wl_global_destroy(blur_manager->global); + free(blur_manager); +} + +static void +blur_handle_destroy(struct wl_client *client, struct wl_resource *resource) +{ + wl_resource_destroy(resource); +} + +static void +blur_handle_set_region(struct wl_client *client, struct wl_resource *resource, + struct wl_resource *region_resource) +{ + struct ds_tizen_blur *blur; + pixman_region32_t *region; + + blur = wl_resource_get_user_data(resource); + region = ds_region_from_resource(region_resource); + + if (region) { + pixman_region32_copy(&blur->pending.region, region); + } else { + pixman_region32_fini(&blur->pending.region); + pixman_region32_init_rect(&blur->pending.region, INT32_MIN, INT32_MIN, UINT32_MAX, UINT32_MAX); + } + + blur->pending.committed |= DS_TIZEN_BLUR_STATE_REGION; +} + +static void +blur_handle_set_radius(struct wl_client *client, struct wl_resource *resource, + uint32_t radius) +{ + struct ds_tizen_blur *blur; + + blur = wl_resource_get_user_data(resource); + + blur->pending.radius = radius; + blur->pending.committed |= DS_TIZEN_BLUR_STATE_RADIUS; +} + +static const struct wtz_blur_interface blur_impl = { + blur_handle_destroy, + blur_handle_set_region, + blur_handle_set_radius, +}; + +static void +blur_destroy(struct ds_tizen_blur *blur) +{ + ds_inf("blur_destroy (blur:%p)", blur); + + wl_signal_emit_mutable(&blur->events.destroy, blur); + + if (blur->listener.surface_commit.notify) + wl_list_remove(&blur->listener.surface_commit.link); + + if (blur->surface) + ds_addon_finish(&blur->surface_addon); + + pixman_region32_fini(&blur->pending.region); + pixman_region32_fini(&blur->current.region); + free(blur); +} + +static void +blur_handle_resource_destroy(struct wl_resource *resource) +{ + struct ds_tizen_blur *blur; + + blur = wl_resource_get_user_data(resource); + + ds_inf("blur_handle_resource_destroy (blur:%p)", blur); + + if (blur->surface) { + blur->resource = NULL; + return; + } + + blur_destroy(blur); +} + +static void +blur_handle_surface_commit(struct wl_listener *listener, void *data) +{ + struct ds_tizen_blur *blur; + + blur = wl_container_of(listener, blur, listener.surface_commit); + + if (!blur->resource) { + blur_destroy(blur); + return; + } + + if (blur->pending.committed == DS_TIZEN_BLUR_STATE_NONE) + return; + + if (blur->pending.committed & DS_TIZEN_BLUR_STATE_REGION) + pixman_region32_copy(&blur->current.region, &blur->pending.region); + + if (blur->pending.committed & DS_TIZEN_BLUR_STATE_RADIUS) + blur->current.radius = blur->pending.radius; + + blur->current.committed = blur->pending.committed; + blur->pending.committed = DS_TIZEN_BLUR_STATE_NONE; + + wl_signal_emit_mutable(&blur->events.commit, blur); +} + +static void +blur_handle_surface_destroy(struct ds_addon *addon) +{ + struct ds_tizen_blur *blur; + + blur = wl_container_of(addon, blur, surface_addon); + + if (blur->listener.surface_commit.notify) { + wl_list_remove(&blur->listener.surface_commit.link); + blur->listener.surface_commit.notify = NULL; + } + + ds_addon_finish(&blur->surface_addon); + blur->surface = NULL; + + if (!blur->resource) + blur_destroy(blur); +} + +static struct ds_addon_interface blur_addon_impl = { + .name = "ds_tizen_blur", + .destroy = blur_handle_surface_destroy, +}; + +static struct ds_tizen_blur * +blur_client_get_from_surface(struct ds_tizen_blur_client *client, struct ds_surface *surface) +{ + struct ds_addon *addon; + struct ds_tizen_blur *blur; + + addon = ds_addon_find(&surface->addons, client, &blur_addon_impl); + if (!addon) return NULL; + + blur = wl_container_of(addon, blur, surface_addon); + + return blur; +} + +static void +blur_manager_handle_get_blur(struct wl_client *wl_client, + struct wl_resource *resource, + uint32_t id, struct wl_resource *surface_resource) +{ + struct ds_tizen_blur_client *client; + struct ds_surface *surface; + struct ds_tizen_blur *blur; + + ds_inf("tizen_blur: get_blur"); + + 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; + } + + blur = blur_client_get_from_surface(client, surface); + if (blur) { + wl_resource_post_error(resource, WTZ_BLUR_MANAGER_ERROR_BLUR_EXISTS, + "blend object already exists"); + return; + } + + blur = calloc(1, sizeof *blur); + if (blur == NULL) { + ds_err("calloc() failed. tizen_blur"); + wl_client_post_no_memory(wl_client); + return; + } + + blur->resource = wl_resource_create(wl_client, &wtz_blur_interface, + wl_resource_get_version(resource), id); + if (blur->resource == NULL) { + ds_err("tizen_blur : wl_resource_create() failed."); + free(blur); + wl_client_post_no_memory(wl_client); + return; + } + + pixman_region32_init_rect(&blur->pending.region, INT32_MIN, INT32_MIN, UINT32_MAX, UINT32_MAX); + pixman_region32_init_rect(&blur->current.region, INT32_MIN, INT32_MIN, UINT32_MAX, UINT32_MAX); + + wl_resource_set_implementation(blur->resource, &blur_impl, blur, + blur_handle_resource_destroy); + + ds_addon_init(&blur->surface_addon, &surface->addons, client, &blur_addon_impl); + + blur->listener.surface_commit.notify = blur_handle_surface_commit; + ds_surface_add_commit_listener(surface, &blur->listener.surface_commit); + + blur->surface = surface; + + wl_signal_init(&blur->events.destroy); + wl_signal_init(&blur->events.commit); + + wl_signal_emit_mutable(&client->blur_manager->events.new_blur, blur); +} + +static void +blur_manager_handle_destroy(struct wl_client *wl_client, + struct wl_resource *resource) +{ + wl_resource_destroy(resource); +} + +static const struct wtz_blur_manager_interface blur_manager_impl = +{ + blur_manager_handle_destroy, + blur_manager_handle_get_blur, +}; + +static void +blur_manager_client_handle_destroy(struct wl_resource *resource) +{ + struct ds_tizen_blur_client *client; + + client = wl_resource_get_user_data(resource); + + ds_inf("blur_manager_client_handle_destroy (client:%p)", client); + + wl_list_remove(&client->link); + free(client); +} + +static void +blur_manager_bind(struct wl_client *wl_client, void *data, uint32_t version, + uint32_t id) +{ + struct ds_tizen_blur_manager *blur_manager = data; + struct ds_tizen_blur_client *client; + + client = calloc(1, sizeof *client); + if (client == NULL) { + ds_err("calloc() failed. tizen_blur"); + wl_client_post_no_memory(wl_client); + return; + } + + ds_inf("tizen_blur_client binds. (client:%p)", client); + + client->blur_manager = blur_manager; + client->wl_client = wl_client; + + client->resource = wl_resource_create(wl_client, &wtz_blur_manager_interface, + MIN(version, TIZEN_BLUR_VERSION), id); + if (client->resource == NULL) { + ds_err("tizen_blur : wl_resource_create() failed."); + free(client); + wl_client_post_no_memory(wl_client); + return; + } + + wl_resource_set_implementation(client->resource, &blur_manager_impl, client, + blur_manager_client_handle_destroy); + + wl_signal_init(&client->events.destroy); + + wl_list_insert(&blur_manager->clients, &client->link); +} diff --git a/src/meson.build b/src/meson.build index 4a3a6b5..2e0d09d 100644 --- a/src/meson.build +++ b/src/meson.build @@ -90,6 +90,7 @@ libds_tizen_files = [ 'display_policy/display_policy.c', 'screen/screen.c', 'blender/blender.c', + 'blur/blur.c', ] libds_tizen_deps = [ @@ -115,6 +116,7 @@ libds_tizen_deps = [ dependency('xkbcommon', required: true), dependency('wtz-screen-server', required: true), dependency('wtz-blender-server', required: true), + dependency('wtz-blur-server', required: true), dependency('pixman-1', required: true), ] @@ -132,6 +134,7 @@ lib_libds_tizen = shared_library('ds-tizen', libds_tizen_files, include_directories('./tbm_server'), include_directories('./video'), include_directories('./blender'), + include_directories('./blur'), ], version: meson.project_version(), c_args: [ '-DKEYLAYOUT_DIR="@0@"'.format(keylayout_dir) ], -- 2.7.4