From 024636d86aa5e2c43ba2f6c5b68f751cad237b78 Mon Sep 17 00:00:00 2001 From: SooChan Lim Date: Thu, 19 May 2022 10:38:44 +0900 Subject: [PATCH] client: add simple-shm-shell sample This is a simple wayland-client which use wl_shm and wl_shell interface. Change-Id: I3d27d37d56097ab84e46d7c59fc52329b5c9605e --- packaging/libds.spec | 1 + src/clients/meson.build | 12 ++ src/clients/simple-shm-shell.c | 339 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 352 insertions(+) create mode 100644 src/clients/simple-shm-shell.c diff --git a/packaging/libds.spec b/packaging/libds.spec index 2ffdca0..5258295 100644 --- a/packaging/libds.spec +++ b/packaging/libds.spec @@ -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 diff --git a/src/clients/meson.build b/src/clients/meson.build index 360c425..009016c 100644 --- a/src/clients/meson.build +++ b/src/clients/meson.build @@ -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 index 0000000..52d9ed2 --- /dev/null +++ b/src/clients/simple-shm-shell.c @@ -0,0 +1,339 @@ +/* +Copyright (C) 2015 - 2016 Samsung Electronics co., Ltd. All Rights Reserved. + +Contact: + SooChan Lim + Changyeon Lee + JunKyeong Kim + Boram Park + +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 +#include +#include +#include +#include +#include +#include + +#include + +#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, ®istry_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; +} -- 2.7.4