impelement libds-tizen-memory-flusher 30/278630/1
authorSooChan Lim <sc1.lim@samsung.com>
Thu, 21 Jul 2022 06:41:35 +0000 (15:41 +0900)
committerSooChan Lim <sc1.lim@samsung.com>
Fri, 22 Jul 2022 14:00:35 +0000 (23:00 +0900)
This is the server implementation for
tizen_surface_shm/tizen_surface_shm_flusher protocol.

Change-Id: I0731be582066cd3085fb03da9000b6a1697e093b

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

diff --git a/include/libds-tizen/memory_flusher.h b/include/libds-tizen/memory_flusher.h
new file mode 100644 (file)
index 0000000..0b72425
--- /dev/null
@@ -0,0 +1,49 @@
+#ifndef LIBDS_TIZEN_MEMORY_FLUSHER_H
+#define LIBDS_TIZEN_MEMORY_FLUSHER_H
+
+#include <stdint.h>
+#include <wayland-server.h>
+#include <libds/surface.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct ds_tizen_memory_flusher;
+struct ds_tizen_memory_flusher_info;
+
+struct ds_tizen_memory_flusher *
+ds_tizen_memory_flusher_create(struct wl_display *display);
+
+void
+ds_tizen_memory_flusher_add_destroy_listener(
+        struct ds_tizen_memory_flusher *memory_flusher,
+        struct wl_listener *listener);
+
+void
+ds_tizen_memory_flusher_add_get_flusher_info_listener(
+        struct ds_tizen_memory_flusher *memory_flusher,
+        struct wl_listener *listener);
+
+void
+ds_tizen_memory_flusher_info_add_destroy_listener(
+        struct ds_tizen_memory_flusher_info *info,
+        struct wl_listener *listener);
+
+struct ds_surface *
+ds_tizen_memory_flusher_info_get_surface(
+        struct ds_tizen_memory_flusher_info *info);
+
+void
+ds_tizen_memory_flusher_info_send_flush(
+    struct ds_tizen_memory_flusher_info *info);
+
+void
+ds_tizen_memory_flusher_info_send_free_flush(
+    struct ds_tizen_memory_flusher_info *info);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
index 5ec3a14..d1db0c9 100644 (file)
@@ -26,6 +26,8 @@ BuildRequires:  pkgconfig(wayland-tbm-server)
 BuildRequires:  pkgconfig(wayland-tbm-client)
 BuildRequires:  pkgconfig(tizen-dpms-server)
 BuildRequires:  pkgconfig(tizen-dpms-client)
+BuildRequires:  pkgconfig(tizen-surface-server)
+BuildRequires:  pkgconfig(tizen-surface-client)
 BuildRequires:  pkgconfig(cynara-client)
 BuildRequires:  pkgconfig(cynara-session)
 BuildRequires:  pkgconfig(libsmack)
@@ -184,6 +186,21 @@ Group:   Development/Libraries
 %description display-policy-devel
 Development package for tizen display-policy
 
+## libds-tizen-memory-flusher
+%package memory-flusher
+Summary: Library for tizen memory flusher
+Group:   Development/Libraries
+
+%description memory-flusher
+Library for tizen memory flusher
+
+%package memory-flusher-devel
+Summary: Development package for tizen memory flusher
+Group:   Development/Libraries
+
+%description memory-flusher-devel
+Development package for tizen memory flusher
+
 %prep
 %setup -q
 cp %{SOURCE1001} .
@@ -355,3 +372,17 @@ ninja -C builddir install
 %{_libdir}/pkgconfig/libds-tizen-display-policy.pc
 %{_libdir}/libds-tizen-display-policy.so
 %{_bindir}/libds-tizen-display-policy-tests
+
+%files memory-flusher
+%manifest %{name}.manifest
+%defattr(-,root,root,-)
+%license LICENSE
+%{_libdir}/libds-tizen-memory-flusher.so.*
+
+%files memory-flusher-devel
+%manifest %{name}.manifest
+%defattr(-,root,root,-)
+%license LICENSE
+%{_includedir}/libds-tizen/memory_flusher.h
+%{_libdir}/pkgconfig/libds-tizen-memory-flusher.pc
+%{_libdir}/libds-tizen-memory-flusher.so
diff --git a/src/memory_flusher/memory_flusher.c b/src/memory_flusher/memory_flusher.c
new file mode 100644 (file)
index 0000000..499e05d
--- /dev/null
@@ -0,0 +1,341 @@
+#include <assert.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <wayland-server.h>
+#include <tizen-surface-server-protocol.h>
+#include <libds/log.h>
+
+#include "util.h"
+#include "libds-tizen/memory_flusher.h"
+
+#define TIZEN_MEMORY_FLUSHER_VERSION 2
+
+struct ds_tizen_memory_flusher
+{
+    struct wl_global *global;
+
+    struct wl_list clients;
+
+    struct wl_listener destroy;
+
+    struct {
+        struct wl_signal destroy;
+        struct wl_signal get_flusher;
+    } events;
+};
+
+struct ds_tizen_memory_flusher_client
+{
+    struct ds_tizen_memory_flusher *memory_flusher;
+
+    struct wl_resource *resource;
+    struct wl_client *wl_client;
+
+    struct wl_list infos;
+
+    struct {
+        struct wl_signal destroy;
+    } events;
+
+    struct wl_list link; // ds_tizen_memory_flusher::clients
+};
+
+struct ds_tizen_memory_flusher_info
+{
+    struct ds_tizen_memory_flusher_client *client;
+
+    struct wl_resource *resource;
+
+    struct ds_surface *surface;
+
+    struct wl_list link; // ds_tizen_memory_flusher_client::infos
+};
+
+static void memory_flusher_handle_display_destroy(struct wl_listener *listener,
+        void *data);
+
+static void memory_flusher_bind(struct wl_client *wl_client, void *data,
+        uint32_t version, uint32_t id);
+
+static struct ds_tizen_memory_flusher_info *tizen_memory_flusher_client_find_info(
+    struct ds_tizen_memory_flusher_client *client,
+    struct ds_surface *surface);
+
+static struct ds_tizen_memory_flusher_info *tizen_memory_flusher_client_get_info(
+        struct ds_tizen_memory_flusher_client *client,
+        struct ds_surface *surface);
+
+WL_EXPORT struct ds_tizen_memory_flusher *
+ds_tizen_memory_flusher_create(struct wl_display *display)
+{
+    struct ds_tizen_memory_flusher *memory_flusher;
+
+    memory_flusher = calloc(1, sizeof *memory_flusher);
+    if (!memory_flusher) {
+        ds_err("calloc() failed.");
+        return NULL;
+    }
+
+    memory_flusher->global = wl_global_create(display, &tizen_surface_shm_interface,
+            TIZEN_MEMORY_FLUSHER_VERSION, memory_flusher, memory_flusher_bind);
+    if (!memory_flusher->global) {
+        ds_err("wl_global_create() failed. tizen_surface_shm_interface");
+        free(memory_flusher);
+        return NULL;
+    }
+
+    wl_list_init(&memory_flusher->clients);
+
+    memory_flusher->destroy.notify = memory_flusher_handle_display_destroy;
+    wl_display_add_destroy_listener(display, &memory_flusher->destroy);
+
+    wl_signal_init(&memory_flusher->events.destroy);
+    wl_signal_init(&memory_flusher->events.get_flusher);
+
+    ds_inf("Global created: tizen_memory_flusher(%p)", memory_flusher);
+
+    return memory_flusher;
+}
+
+WL_EXPORT void
+ds_tizen_memory_flusher_add_destroy_listener(
+        struct ds_tizen_memory_flusher *memory_flusher,
+        struct wl_listener *listener)
+{
+    wl_signal_add(&memory_flusher->events.destroy, listener);
+}
+
+WL_EXPORT void
+ds_tizen_memory_flusher_add_get_flusher_info_listener(
+        struct ds_tizen_memory_flusher *memory_flusher,
+        struct wl_listener *listener)
+{
+    wl_signal_add(&memory_flusher->events.get_flusher, listener);
+}
+
+WL_EXPORT void
+ds_tizen_memory_flusher_info_add_destroy_listener(
+        struct ds_tizen_memory_flusher_info *info,
+        struct wl_listener *listener)
+{
+    wl_signal_add(&info->client->events.destroy, listener);
+}
+
+WL_EXPORT struct ds_surface *
+ds_tizen_memory_flusher_info_get_surface(
+        struct ds_tizen_memory_flusher_info *info)
+{
+    return info->surface;
+}
+
+WL_EXPORT void
+ds_tizen_memory_flusher_info_send_flush(
+    struct ds_tizen_memory_flusher_info *info)
+{
+    tizen_surface_shm_flusher_send_flush(info->resource);
+}
+
+WL_EXPORT void
+ds_tizen_memory_flusher_info_send_free_flush(
+    struct ds_tizen_memory_flusher_info *info)
+{
+    tizen_surface_shm_flusher_send_free_flush(info->resource);
+}
+
+static struct ds_tizen_memory_flusher_info *
+tizen_memory_flusher_client_find_info(struct ds_tizen_memory_flusher_client *client,
+    struct ds_surface *surface)
+{
+    struct ds_tizen_memory_flusher_info *info;
+
+    wl_list_for_each(info, &client->infos, link) {
+        if (surface == info->surface)
+            return info;
+    }
+
+    return NULL;
+}
+
+static struct ds_tizen_memory_flusher_info *
+tizen_memory_flusher_client_get_info(struct ds_tizen_memory_flusher_client *client,
+    struct ds_surface *surface)
+{
+    struct ds_tizen_memory_flusher_info *info;
+
+    info = tizen_memory_flusher_client_find_info(client, surface);
+    if (info)
+        return info;
+
+    info = calloc(1, sizeof *info);
+    if (info == NULL) {
+        ds_err("calloc() failed. tizen_memory_flusher");
+        return NULL;
+    }
+
+    info->client = client;
+    info->surface = surface;
+
+    wl_list_insert(&client->infos, &info->link);
+
+    return info;
+}
+
+static void
+memory_flusher_handle_display_destroy(struct wl_listener *listener, void *data)
+{
+    struct ds_tizen_memory_flusher *memory_flusher;
+
+    memory_flusher = wl_container_of(listener, memory_flusher, destroy);
+
+    ds_inf("Global destroy: memory_flusher(%p)", memory_flusher);
+
+    wl_signal_emit(&memory_flusher->events.destroy, memory_flusher);
+    wl_list_remove(&memory_flusher->destroy.link);
+    wl_global_destroy(memory_flusher->global);
+    free(memory_flusher);
+}
+
+static void
+flusher_handle_destroy(struct wl_client *wl_client,
+    struct wl_resource *resource)
+{
+    wl_resource_destroy(resource);
+}
+
+static const struct tizen_surface_shm_flusher_interface flusher_impl =
+{
+   flusher_handle_destroy,
+};
+
+static void
+_tizen_memory_flusher_info_handle_destroy(struct wl_resource *resource)
+{
+    struct ds_tizen_memory_flusher_info *info;
+
+    info = wl_resource_get_user_data(resource);
+
+    ds_inf("_tizen_memory_flusher_info_handle_destroy (info:%p)", info);
+
+    wl_signal_emit(&info->client->events.destroy, info);
+    wl_list_remove(&info->link);
+    free(info);
+}
+
+static void
+memory_flusher_handle_get_flusher(struct wl_client *wl_client,
+    struct wl_resource *resource,uint32_t id,
+    struct wl_resource *surface_resource)
+{
+    struct ds_tizen_memory_flusher_client *client;
+    struct ds_tizen_memory_flusher_info *info;
+    struct ds_surface *surface;
+
+    ds_inf("tizen_memory_flusher: get_flusher");
+
+    client = wl_resource_get_user_data(resource);
+    surface = ds_surface_from_resource(surface_resource);
+
+    info = tizen_memory_flusher_client_get_info(client, surface);
+    if (info == NULL) {
+        ds_err("tizen_memory_flusher_client_get_info() failed.");
+        wl_client_post_no_memory(wl_client);
+        return;
+    }
+
+    info->resource = wl_resource_create(wl_client,
+        &tizen_surface_shm_flusher_interface, wl_resource_get_version(resource),
+        id);
+    if (info->resource == NULL) {
+        ds_err("tizen_memory_flusher : wl_resource_create() failed.");
+        wl_list_remove(&info->link);
+        free(info);
+        wl_client_post_no_memory(wl_client);
+        return;
+    }
+
+    wl_resource_set_implementation(info->resource, &flusher_impl, info,
+        _tizen_memory_flusher_info_handle_destroy);
+
+    wl_signal_emit(&client->memory_flusher->events.get_flusher, info);
+}
+
+static void
+memory_flusher_handle_destroy(struct wl_client *wl_client,
+    struct wl_resource *resource)
+{
+    struct ds_tizen_memory_flusher_client *client;
+
+    client = wl_resource_get_user_data(resource);
+
+    if (!wl_list_empty(&client->infos)) {
+        ds_err("tizen_memory_flusher was destroyed before children");
+        return;
+    }
+
+    wl_resource_destroy(resource);
+}
+
+static const struct tizen_surface_shm_interface memory_flusher_impl =
+{
+   memory_flusher_handle_get_flusher,
+   memory_flusher_handle_destroy,
+};
+
+static void
+_tizen_memory_flusher_client_handle_destroy(struct wl_resource *resource)
+{
+    struct ds_tizen_memory_flusher_client *client;
+    struct ds_tizen_memory_flusher_info *info, *tmp;
+
+    client = wl_resource_get_user_data(resource);
+
+    ds_inf("_tizen_memory_flusher_client_handle_destroy (client:%p)", client);
+
+    wl_list_for_each_safe(info, tmp, &client->infos, link) {
+        wl_signal_emit(&client->events.destroy, info);
+        wl_list_remove(&info->link);
+        free(info);
+    }
+
+    wl_list_remove(&client->link);
+    free(client);
+}
+
+static void
+memory_flusher_bind(struct wl_client *wl_client, void *data, uint32_t version,
+        uint32_t id)
+{
+    struct ds_tizen_memory_flusher *memory_flusher = data;
+    struct ds_tizen_memory_flusher_client *client;
+
+    client = calloc(1, sizeof *client);
+    if (client == NULL) {
+        ds_err("calloc() failed. tizen_memory_flusher");
+        wl_client_post_no_memory(wl_client);
+        return;
+    }
+
+    ds_inf("tizen_memory_flusher_client binds. (client:%p)", client);
+
+    client->memory_flusher = memory_flusher;
+    client->wl_client = wl_client;
+
+    wl_list_init(&client->infos);
+
+    client->resource = wl_resource_create(wl_client, &tizen_surface_shm_interface,
+            MIN(version, TIZEN_MEMORY_FLUSHER_VERSION), id);
+
+    if (client->resource == NULL) {
+        ds_err("tizen_memory_flusher : wl_resource_create() failed.");
+        free(client);
+        wl_client_post_no_memory(wl_client);
+        return;
+    }
+
+    wl_resource_set_implementation(client->resource, &memory_flusher_impl, client,
+            _tizen_memory_flusher_client_handle_destroy);
+
+    wl_signal_init(&client->events.destroy);
+
+    wl_list_insert(&memory_flusher->clients, &client->link);
+}
diff --git a/src/memory_flusher/meson.build b/src/memory_flusher/meson.build
new file mode 100644 (file)
index 0000000..440022a
--- /dev/null
@@ -0,0 +1,29 @@
+libds_tizen_memory_flusher_files = [
+  'memory_flusher.c',
+]
+
+libds_tizen_memory_flusher_deps = [
+  deps_libds_tizen,
+  dependency('tizen-surface-server', required: true),
+]
+
+lib_libds_tizen_memory_flusher = shared_library('ds-tizen-memory-flusher', libds_tizen_memory_flusher_files,
+  dependencies: libds_tizen_memory_flusher_deps,
+  include_directories: [ common_inc, include_directories('.'), include_directories('..') ],
+  version: meson.project_version(),
+  install: true
+)
+
+deps_libds_tizen_memory_flusher = declare_dependency(
+  link_with: lib_libds_tizen_memory_flusher,
+  dependencies: libds_tizen_memory_flusher_deps,
+  include_directories: [ common_inc, include_directories('.') ],
+)
+
+pkgconfig = import('pkgconfig')
+pkgconfig.generate(lib_libds_tizen_memory_flusher,
+  version: meson.project_version(),
+  filebase: 'libds-tizen-memory-flusher',
+  name: 'libds-tizen-memory-flusher',
+  description: 'tizen memory flusher extension of libds-tizen for tizen platform',
+)
index d0bb024..c1c88ac 100644 (file)
@@ -37,3 +37,4 @@ subdir('indicator')
 subdir('clipboard')
 subdir('launch')
 subdir('display_policy')
+subdir('memory_flusher')