Add ds_tizen_scaler for wl_scaler 51/281351/1
authorSeunghun <chwila927@gmail.com>
Tue, 23 Aug 2022 05:51:43 +0000 (14:51 +0900)
committerTizen Window System <tizen.windowsystem@gmail.com>
Fri, 16 Sep 2022 00:29:30 +0000 (09:29 +0900)
Change-Id: Ib6d1f7e43aee8f96f05ecaf2b81f855bce66648e

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

diff --git a/include/libds-tizen/scaler.h b/include/libds-tizen/scaler.h
new file mode 100644 (file)
index 0000000..4a52b4e
--- /dev/null
@@ -0,0 +1,18 @@
+#ifndef LIBDS_TIZEN_SCALER_H
+#define LIBDS_TIZEN_SCALER_H
+
+#include <wayland-server.h>
+
+#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
index 485abfc..4ef8195 100644 (file)
@@ -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
index 9cc81b5..b039f9d 100644 (file)
@@ -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 (file)
index 0000000..cfcc71b
--- /dev/null
@@ -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 (file)
index 0000000..9cd3b42
--- /dev/null
@@ -0,0 +1,291 @@
+#include <stdlib.h>
+
+#include <wayland-server.h>
+#include <scaler-server-protocol.h>
+
+#include <libds/log.h>
+#include <libds/surface.h>
+
+#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);
+    }
+}