From: Seunghun Date: Tue, 23 Aug 2022 05:51:43 +0000 (+0900) Subject: Add ds_tizen_scaler for wl_scaler X-Git-Tag: accepted/tizen/unified/20220919.021617~1 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=refs%2Fchanges%2F51%2F281351%2F1;p=platform%2Fcore%2Fuifw%2Flibds-tizen.git Add ds_tizen_scaler for wl_scaler Change-Id: Ib6d1f7e43aee8f96f05ecaf2b81f855bce66648e --- diff --git a/include/libds-tizen/scaler.h b/include/libds-tizen/scaler.h new file mode 100644 index 0000000..4a52b4e --- /dev/null +++ b/include/libds-tizen/scaler.h @@ -0,0 +1,18 @@ +#ifndef LIBDS_TIZEN_SCALER_H +#define LIBDS_TIZEN_SCALER_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct ds_tizen_scaler; + +struct ds_tizen_scaler *ds_tizen_scaler_create(struct wl_display *display); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/packaging/libds-tizen.spec b/packaging/libds-tizen.spec index 485abfc..4ef8195 100644 --- a/packaging/libds-tizen.spec +++ b/packaging/libds-tizen.spec @@ -38,6 +38,7 @@ BuildRequires: pkgconfig(cynara-client) BuildRequires: pkgconfig(cynara-session) BuildRequires: pkgconfig(libsmack) BuildRequires: pkgconfig(gmock) +BuildRequires: pkgconfig(scaler-server) %description Wayland Compositor Library for Tizen @@ -342,6 +343,21 @@ Group: Development/Libraries %description screenshooter-devel Development package for tizen screenshooter +## libds-tizen-scaler +%package scaler +Summary: Library for tizen scaler +Group: Development/Libraries + +%description scaler +Library for tizen scaler + +%package scaler-devel +Summary: Development package for tizen scaler +Group: Development/Libraries + +%description scaler-devel +Development package for tizen scaler + %prep %setup -q cp %{SOURCE1001} . @@ -661,3 +677,17 @@ ninja -C builddir install %{_libdir}/pkgconfig/libds-tizen-screenshooter.pc %{_libdir}/libds-tizen-screenshooter.so %{_bindir}/libds-tizen-screenshooter-tests + +%files scaler +%manifest %{name}.manifest +%defattr(-,root,root,-) +%license LICENSE +%{_libdir}/libds-tizen-scaler.so.* + +%files scaler-devel +%manifest %{name}.manifest +%defattr(-,root,root,-) +%license LICENSE +%{_includedir}/libds-tizen/scaler.h +%{_libdir}/pkgconfig/libds-tizen-scaler.pc +%{_libdir}/libds-tizen-scaler.so diff --git a/src/meson.build b/src/meson.build index 9cc81b5..b039f9d 100644 --- a/src/meson.build +++ b/src/meson.build @@ -47,3 +47,4 @@ subdir('text_input') subdir('hwc') subdir('policy') subdir('screenshooter') +subdir('scaler') diff --git a/src/scaler/meson.build b/src/scaler/meson.build new file mode 100644 index 0000000..cfcc71b --- /dev/null +++ b/src/scaler/meson.build @@ -0,0 +1,25 @@ +libds_tizen_scaler_deps = [ + deps_libds_tizen, + dependency('scaler-server', required: true), +] + +lib_libds_tizen_scaler = shared_library('ds-tizen-scaler', 'scaler.c', + dependencies: libds_tizen_scaler_deps, + include_directories: [ common_inc, include_directories('.'), include_directories('..') ], + version: meson.project_version(), + install: true +) + +deps_libds_tizen_scaler = declare_dependency( + link_with: lib_libds_tizen_scaler, + dependencies: libds_tizen_scaler_deps, + include_directories: [ common_inc, include_directories('.') ], +) + +pkgconfig = import('pkgconfig') +pkgconfig.generate(lib_libds_tizen_scaler, + version: meson.project_version(), + filebase: 'libds-tizen-scaler', + name: 'libds-tizen-scaler', + description: 'tizen scaler extension of libds-tizen for tizen platform', +) diff --git a/src/scaler/scaler.c b/src/scaler/scaler.c new file mode 100644 index 0000000..9cd3b42 --- /dev/null +++ b/src/scaler/scaler.c @@ -0,0 +1,291 @@ +#include + +#include +#include + +#include +#include + +#define SCALER_VERSION 2 + +struct ds_tizen_scaler +{ + struct wl_global *global; + + struct wl_listener display_destroy; +}; + +struct viewport +{ + struct wl_resource *resource; + struct ds_surface_viewport *surface_viewport; + + struct wl_listener surface_destroy; + struct wl_listener surface_commit; +}; + +static void scaler_bind(struct wl_client *client, void *data, uint32_t version, + uint32_t id); +static void scaler_handle_display_destroy(struct wl_listener *listener, + void *data); +static void viewport_set_source(struct viewport *viewport, + wl_fixed_t x_fixed, wl_fixed_t y_fixed, + wl_fixed_t width_fixed, wl_fixed_t height_fixed); +static void viewport_set_destination(struct viewport *viewport, + int32_t width, int32_t height); + +struct ds_tizen_scaler * +ds_tizen_scaler_create(struct wl_display *display) +{ + struct ds_tizen_scaler *scaler; + + scaler = calloc(1, sizeof *scaler); + if (!scaler) + return NULL; + + scaler->global = wl_global_create(display, &wl_scaler_interface, + SCALER_VERSION, NULL, scaler_bind); + if (!scaler->global) { + free(scaler); + return NULL; + } + + scaler->display_destroy.notify = scaler_handle_display_destroy; + wl_display_add_destroy_listener(display, &scaler->display_destroy); + + return scaler; +} + +static void +viewport_destroy(struct viewport *viewport) +{ + ds_surface_viewport_release(viewport->surface_viewport); + + wl_resource_set_user_data(viewport->resource, NULL); + wl_list_remove(&viewport->surface_commit.link); + wl_list_remove(&viewport->surface_destroy.link); + free(viewport); +} + +static void +viewport_handle_destroy(struct wl_client *client, struct wl_resource *resource) +{ + wl_resource_destroy(resource); +} + +static void +viewport_handle_set(struct wl_client *client, struct wl_resource *resource, + wl_fixed_t src_x, wl_fixed_t src_y, + wl_fixed_t src_width, wl_fixed_t src_height, + int32_t dst_width, int32_t dst_height) +{ + struct viewport *viewport; + + viewport = wl_resource_get_user_data(resource); + if (!viewport) { + ds_err("wl_viewport@%d.set sent after wl_surface has been destroyed", + wl_resource_get_id(resource)); + return; + } + + viewport_set_source(viewport, src_x, src_y, src_width, src_height); + viewport_set_destination(viewport, dst_width, dst_height); +} + +static void +viewport_handle_set_source(struct wl_client *client, + struct wl_resource *resource, wl_fixed_t x, wl_fixed_t y, + wl_fixed_t width, wl_fixed_t height) +{ + struct viewport *viewport; + + viewport = wl_resource_get_user_data(resource); + if (!viewport) { + ds_err("wl_viewport@%d.set_source sent after wl_surface has been " + "destroyed", wl_resource_get_id(resource)); + return; + } + + viewport_set_source(viewport, x, y, width, height); +} + +static void +viewport_handle_set_destination(struct wl_client *client, + struct wl_resource *resource, int32_t width, int32_t height) +{ + struct viewport *viewport; + + viewport = wl_resource_get_user_data(resource); + if (!viewport) { + ds_err("wl_viewport@%d.set_destination sent after wl_surface has been " + "destroyed", wl_resource_get_id(resource)); + return; + } + + viewport_set_destination(viewport, width, height); +} + +static const struct wl_viewport_interface viewport_iface = { + .destroy = viewport_handle_destroy, + .set = viewport_handle_set, + .set_source = viewport_handle_set_source, + .set_destination = viewport_handle_set_destination, +}; + +static void +viewport_handle_surface_destroy(struct wl_listener *listener, void *data) +{ + struct viewport *viewport; + + viewport = wl_container_of(listener, viewport, surface_destroy); + viewport_destroy(viewport); +} + +static void +viewport_handle_resource_destroy(struct wl_resource *resource) +{ + struct viewport *viewport; + + viewport = wl_resource_get_user_data(resource); + if (viewport) + viewport_destroy(viewport); +} + +static void +viewport_handle_surface_commit(struct wl_listener *listener, void *data) +{ + struct viewport *viewport; + + viewport = wl_container_of(listener, viewport, surface_commit); + + // TODO +} + +static void +scaler_handle_destroy(struct wl_client *client, struct wl_resource *resource) +{ + wl_resource_destroy(resource); +} + +static void +scaler_handle_get_viewport(struct wl_client *client, + struct wl_resource *resource, uint32_t id, + struct wl_resource *surface_resource) +{ + struct viewport *viewport; + struct ds_surface *surface; + struct ds_surface_viewport *surface_viewport; + + surface = ds_surface_from_resource(surface_resource); + surface_viewport = ds_surface_take_viewport(surface); + if (!surface_viewport) { + wl_resource_post_error(resource, WL_SCALER_ERROR_VIEWPORT_EXISTS, + "a viewport for that surface already exists"); + return; + } + + viewport = calloc(1, sizeof *viewport); + if (!viewport) { + wl_resource_post_no_memory(resource); + return; + } + + viewport->resource = wl_resource_create(client, &wl_viewport_interface, + wl_resource_get_version(resource), id); + if (!viewport->resource) { + wl_resource_post_no_memory(resource); + free(viewport); + return; + } + wl_resource_set_implementation(viewport->resource, &viewport_iface, + viewport, viewport_handle_resource_destroy); + + viewport->surface_viewport = surface_viewport; + + viewport->surface_destroy.notify = viewport_handle_surface_destroy; + ds_surface_add_destroy_listener(surface, &viewport->surface_destroy); + + viewport->surface_commit.notify = viewport_handle_surface_commit; + ds_surface_add_commit_listener(surface, &viewport->surface_commit); +} + +static const struct wl_scaler_interface scaler_iface = { + .destroy = scaler_handle_destroy, + .get_viewport = scaler_handle_get_viewport, +}; + +static void +scaler_bind(struct wl_client *client, void *data, uint32_t version, + uint32_t id) +{ + struct wl_resource *resource; + uint32_t bind_version; + + bind_version = version < SCALER_VERSION ? version : SCALER_VERSION; + resource = wl_resource_create(client, &wl_scaler_interface, bind_version, + id); + if (!resource) { + wl_client_post_no_memory(client); + return; + } + wl_resource_set_implementation(resource, &scaler_iface, NULL, NULL); +} + +static void +scaler_handle_display_destroy(struct wl_listener *listener, void *data) +{ + struct ds_tizen_scaler *scaler; + + scaler = wl_container_of(listener, scaler, display_destroy); + wl_list_remove(&scaler->display_destroy.link); + wl_global_destroy(scaler->global); + free(scaler); +} + +static void +viewport_set_source(struct viewport *viewport, + wl_fixed_t x_fixed, wl_fixed_t y_fixed, + wl_fixed_t width_fixed, wl_fixed_t height_fixed) +{ + double x, y, width, height; + + x = wl_fixed_to_double(x_fixed); + y = wl_fixed_to_double(y_fixed); + width = wl_fixed_to_double(width_fixed); + height = wl_fixed_to_double(height_fixed); + + if (width == -1.0 && height == -1.0) { + ds_surface_viewport_unset_source(viewport->surface_viewport); + } + else if (x < 0 || y < 0 || width <= 0 || height <= 0) { + ds_inf("wl_viewport.set_source sent with invalid values (%f %f %fx%f)", + x, y, width, height); + if (width <= 0 || height <= 0) { + wl_resource_post_error(viewport->resource, + WL_VIEWPORT_ERROR_BAD_VALUE, + "wl_viewport.set_source sent with invalid values"); + } + } + else { + ds_surface_viewport_set_source(viewport->surface_viewport, + x, y, width, height); + } +} + +static void +viewport_set_destination(struct viewport *viewport, + int32_t width, int32_t height) +{ + if (width == -1 && height == -1) { + ds_surface_viewport_unset_destination(viewport->surface_viewport); + } + else if (width <= 0 || height <= 0) { + wl_resource_post_error(viewport->resource, WL_VIEWPORT_ERROR_BAD_VALUE, + "destination size must be positive (%dx%d)", + width, height); + } + else { + ds_surface_viewport_set_destination(viewport->surface_viewport, + width, height); + } +}