client: add simple-shm-shell sample 97/278197/1
authorSooChan Lim <sc1.lim@samsung.com>
Thu, 19 May 2022 01:38:44 +0000 (10:38 +0900)
committerSooChan Lim <sc1.lim@samsung.com>
Mon, 18 Jul 2022 05:58:43 +0000 (14:58 +0900)
This is a simple wayland-client which use wl_shm and wl_shell interface.

Change-Id: I3d27d37d56097ab84e46d7c59fc52329b5c9605e

packaging/libds.spec
src/clients/meson.build
src/clients/simple-shm-shell.c [new file with mode: 0644]

index 2ffdca0..5258295 100644 (file)
@@ -103,6 +103,7 @@ ninja -C builddir install
 %{_bindir}/tinyds-tdm
 %{_bindir}/ds-simple-tbm
 %{_bindir}/tinyds-tdm-libinput
+%{_bindir}/ds-simple-shm-shell
 
 %files tizen-keyrouter
 %manifest %{name}.manifest
index 360c425..009016c 100644 (file)
@@ -1,3 +1,15 @@
+simple_shm_shell_files = ['simple-shm-shell.c']
+simple_shm_shell_deps = [
+  dependency('wayland-client', required: true),
+]
+
+executable('ds-simple-shm-shell',
+  simple_shm_shell_files,
+  dependencies: simple_shm_shell_deps,
+  install_dir: libds_bindir,
+  install: true,
+)
+
 wayland_tbm_client = dependency('wayland-tbm-client', required: false)
 libtbm = dependency('libtbm', required: false)
 
diff --git a/src/clients/simple-shm-shell.c b/src/clients/simple-shm-shell.c
new file mode 100644 (file)
index 0000000..52d9ed2
--- /dev/null
@@ -0,0 +1,339 @@
+/*
+Copyright (C) 2015 - 2016 Samsung Electronics co., Ltd. All Rights Reserved.
+
+Contact:
+      SooChan Lim <sc1.lim@samsung.com>
+      Changyeon Lee <cyeon.lee@samsung.com>
+      JunKyeong Kim <jk0430.kim@samsung.com>
+      Boram Park <boram1288.park@samsung.com>
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+*/
+
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <stdlib.h>
+
+#include <wayland-client.h>
+
+#define BUF_WIDTH 1920
+#define BUF_HEIGHT 1080
+
+#define RETURN_VAL_IF_FAIL(c,v) {\
+    if(!((c))){\
+        fprintf(stderr, "[%s(%d)] '%s' failed.", __func__, __LINE__, #c);\
+        return (v);\
+    }\
+}
+
+#define GOTO_IF_FAIL(c,l) {\
+       if(!(c)) {\
+               fprintf(stderr, "[%s(%d)] '%s' failed.", __func__, __LINE__, #c);\
+               goto l;\
+       }\
+}
+
+#define EXIT_IF_FAIL(c) {\
+       if(!(c)) {\
+               fprintf (stderr, "[%s(%d)] '%s' failed.\n",__func__,__LINE__,#c);\
+               exit(0);\
+       }\
+}
+
+struct wl_test_info {
+       int width;
+       int height;
+       int stride;
+       int format;
+       int size;
+
+       struct wl_display *display;
+       struct wl_registry *registry;
+
+       /* global objects */
+       struct wl_compositor *compositor;
+       struct wl_shm *shm;
+       struct wl_shell *shell;
+       struct wl_shm_pool *shm_pool;
+
+       /* objects */
+       struct wl_surface *surface;
+       struct wl_shell_surface *shell_surface;
+       struct wl_buffer *buffer;
+};
+
+static int
+_create_anonymous_file (off_t size)
+{
+       static const char template[] =
+       "/shooter-XXXXXX";
+       const char *path;
+       char *name = NULL;
+       int fd = -1;
+       int ret = -1;
+
+       path = getenv("XDG_RUNTIME_DIR");
+       if (!path) {
+               errno = ENOENT;
+               return -1;
+       }
+
+       name = malloc(strlen(path) + sizeof(template));
+       GOTO_IF_FAIL(name != NULL, fail);
+
+       strcpy(name, path);
+       strcat(name, template);
+
+       fd = mkstemp(name);
+       if (fd >= 0)
+               unlink(name);
+
+       ret = ftruncate(fd, size);
+       GOTO_IF_FAIL(ret >= 0, fail);
+
+       free(name);
+
+       return fd;
+fail:
+       if (fd >= 0)
+               close(fd);
+
+       if (name)
+               free(name);
+
+       return -1;
+}
+
+static void
+_destroy_anonymous_file(int fd)
+{
+       if (fd < 0) return;
+
+       close(fd);
+}
+
+
+static struct wl_test_info *
+_create_wl_test_info (void)
+{
+       struct wl_test_info *test_info = NULL;
+
+       test_info = calloc(1, sizeof(struct wl_test_info));
+       RETURN_VAL_IF_FAIL(test_info != NULL, NULL);
+
+       return test_info;
+}
+
+static void
+_destroy_wl_test_info (struct wl_test_info *test_info)
+{
+       if (!test_info) return;
+
+       free(test_info);
+}
+
+static struct wl_shm_pool *
+_create_shm_pool(struct wl_shm *shm, int size)
+{
+       struct wl_shm_pool *shm_pool = NULL;
+       void *data = NULL;
+       int fd = -1;
+
+       fd = _create_anonymous_file(size);
+       GOTO_IF_FAIL(fd >= 0, fail);
+
+       data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+       GOTO_IF_FAIL(data != NULL, fail);
+
+       memset(data, 0xff, size);
+       munmap(data, size);
+
+       shm_pool = wl_shm_create_pool(shm, fd, size);
+       GOTO_IF_FAIL(shm_pool != NULL, fail);
+
+       _destroy_anonymous_file(fd);
+
+       return shm_pool;
+
+fail:
+       if (fd > 0)
+               _destroy_anonymous_file(fd);
+
+       return NULL;
+}
+
+void
+_destroy_shm_pool(struct wl_shm_pool *shm_pool)
+{
+       if (!shm_pool) return;
+
+       wl_shm_pool_destroy(shm_pool);
+}
+
+static void
+handle_global(void *data, struct wl_registry *registry, uint32_t name,
+              const char *interface, uint32_t version)
+{
+       struct wl_test_info *ti = (struct wl_test_info *)data;
+
+       if (strcmp(interface, "wl_compositor") == 0) {
+               ti->compositor = wl_registry_bind(registry, name,
+                       &wl_compositor_interface, 3);
+               if (!ti->compositor)
+                       printf("%s(%d): Error. fail to bind  %s.\n",
+                                       __func__, __LINE__, interface);
+               else
+                       printf("%s(%d): bind %s.\n", __func__, __LINE__, interface);
+       } else if (strcmp(interface, "wl_shm") == 0) {
+               ti->shm = wl_registry_bind(registry, name, &wl_shm_interface, 1);
+               if (!ti->shm)
+                       printf("%s(%d): Error. fail to bind  %s.\n",
+                                       __func__, __LINE__, interface);
+               else
+                       printf("%s(%d): bind %s.\n", __func__, __LINE__, interface);
+
+               ti->shm_pool = _create_shm_pool(ti->shm, ti->size);
+               if (!ti->shm_pool)
+                       printf("%s(%d): Error. fail to create wl_shm_pool.\n",
+                                       __func__, __LINE__);
+               else
+                       printf("%s(%d): success to create wl_shm_pool.\n",
+                                       __func__, __LINE__);
+
+       } else if (strcmp(interface, "wl_shell") == 0) {
+               ti->shell = wl_registry_bind(registry, name, &wl_shell_interface, 1);
+               if (!ti->shell)
+                       printf("%s(%d): Error. fail to bind  %s.\n",
+                                       __func__, __LINE__, interface);
+               else
+                       printf("%s(%d): bind %s.\n", __func__, __LINE__, interface);
+       } else {
+               printf("%s(%d): Not bind %s.\n", __func__, __LINE__, interface);
+       }
+}
+
+static void
+handle_global_remove(void *data, struct wl_registry *registry, uint32_t name)
+{
+
+}
+
+static const struct wl_registry_listener registry_listener = {
+       handle_global,
+       handle_global_remove
+};
+
+int main (void)
+{
+       struct wl_test_info *ti = NULL;
+       int ret = 0;
+
+       /* create test info */
+       ti = _create_wl_test_info ();
+       GOTO_IF_FAIL(ti != NULL, fail);
+
+       /* init */
+       ti->width = BUF_WIDTH;
+       ti->height = BUF_HEIGHT;
+       ti->stride = ti->width * 4;
+       ti->format = WL_SHM_FORMAT_XRGB8888;
+       ti->size = ti->stride * ti->height;
+
+       /* connect display */
+       ti->display = wl_display_connect(NULL);
+       GOTO_IF_FAIL(ti->display != NULL, fail);
+
+       /* get the registry */
+       ti->registry = wl_display_get_registry(ti->display);
+       GOTO_IF_FAIL(ti->registry != NULL, fail);
+
+       /* get the global objects */
+       wl_registry_add_listener(ti->registry, &registry_listener, ti);
+       wl_display_dispatch(ti->display);
+       wl_display_roundtrip(ti->display);
+
+       /* check the global objects */
+       GOTO_IF_FAIL(ti->compositor != NULL, fail);
+       GOTO_IF_FAIL(ti->shm != NULL, fail);
+       GOTO_IF_FAIL(ti->shell != NULL, fail);
+       GOTO_IF_FAIL(ti->shm_pool != NULL, fail);
+
+       /* create objects */
+       ti->surface = wl_compositor_create_surface(ti->compositor);
+       GOTO_IF_FAIL(ti->surface != NULL, fail);
+
+       ti->shell_surface = wl_shell_get_shell_surface(ti->shell, ti->surface);
+       GOTO_IF_FAIL(ti->shell_surface != NULL, fail);
+
+       wl_shell_surface_set_toplevel(ti->shell_surface);
+
+       ti->buffer = wl_shm_pool_create_buffer(ti->shm_pool, 0,
+               ti->width, ti->height, ti->stride, ti->format);
+       GOTO_IF_FAIL(ti->buffer != NULL, fail);
+
+       wl_surface_attach(ti->surface, ti->buffer, 0, 0);
+       wl_surface_damage(ti->surface, 0, 0, ti->width, ti->height);
+       wl_surface_commit(ti->surface);
+
+       wl_display_roundtrip(ti->display);
+
+       /* main loop */
+       printf("%s(%d): loop start.\n", __func__, __LINE__);
+       while (ret >= 0) {
+               ret = wl_display_dispatch(ti->display);
+               printf("%s(%d): loop running(ret=%d).\n", __func__, __LINE__, ret);
+       }
+       printf("%s(%d): loop end.\n", __func__, __LINE__);
+
+fail:
+       /* destory objects */
+       if (ti->shell_surface)
+               wl_shell_surface_destroy(ti->shell_surface);
+       if (ti->surface)
+               wl_surface_destroy(ti->surface);
+       if (ti->buffer)
+               wl_buffer_destroy(ti->buffer);
+
+       /* destroy global objects */
+       if (ti->shell)
+               wl_shell_destroy(ti->shell);
+       if (ti->shm_pool)
+               _destroy_shm_pool(ti->shm_pool);
+       if (ti->shm)
+               wl_shm_destroy(ti->shm);
+       if (ti->compositor)
+               wl_compositor_destroy(ti->compositor);
+
+       /* destory registry and display */
+       if (ti->registry)
+               wl_registry_destroy(ti->registry);
+       if (ti->display)
+               wl_display_disconnect(ti->display);
+
+       /* destroy test_info */
+       if (ti)
+               _destroy_wl_test_info(ti);
+
+       return 0;
+}