client: add simple-shm-shell sample
[platform/core/uifw/libds-tizen.git] / src / clients / simple-shm-shell.c
1 /*
2 Copyright (C) 2015 - 2016 Samsung Electronics co., Ltd. All Rights Reserved.
3
4 Contact:
5       SooChan Lim <sc1.lim@samsung.com>
6       Changyeon Lee <cyeon.lee@samsung.com>
7       JunKyeong Kim <jk0430.kim@samsung.com>
8       Boram Park <boram1288.park@samsung.com>
9
10 Permission is hereby granted, free of charge, to any person obtaining a
11 copy of this software and associated documentation files (the "Software"),
12 to deal in the Software without restriction, including without limitation
13 the rights to use, copy, modify, merge, publish, distribute, sublicense,
14 and/or sell copies of the Software, and to permit persons to whom the
15 Software is furnished to do so, subject to the following conditions:
16
17 The above copyright notice and this permission notice (including the next
18 paragraph) shall be included in all copies or substantial portions of the
19 Software.
20
21 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
24 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27 DEALINGS IN THE SOFTWARE.
28 */
29
30 #include <errno.h>
31 #include <stdio.h>
32 #include <string.h>
33 #include <fcntl.h>
34 #include <unistd.h>
35 #include <sys/mman.h>
36 #include <stdlib.h>
37
38 #include <wayland-client.h>
39
40 #define BUF_WIDTH 1920
41 #define BUF_HEIGHT 1080
42
43 #define RETURN_VAL_IF_FAIL(c,v) {\
44     if(!((c))){\
45         fprintf(stderr, "[%s(%d)] '%s' failed.", __func__, __LINE__, #c);\
46         return (v);\
47     }\
48 }
49
50 #define GOTO_IF_FAIL(c,l) {\
51         if(!(c)) {\
52                 fprintf(stderr, "[%s(%d)] '%s' failed.", __func__, __LINE__, #c);\
53                 goto l;\
54         }\
55 }
56
57 #define EXIT_IF_FAIL(c) {\
58         if(!(c)) {\
59                 fprintf (stderr, "[%s(%d)] '%s' failed.\n",__func__,__LINE__,#c);\
60                 exit(0);\
61         }\
62 }
63
64 struct wl_test_info {
65         int width;
66         int height;
67         int stride;
68         int format;
69         int size;
70
71         struct wl_display *display;
72         struct wl_registry *registry;
73
74         /* global objects */
75         struct wl_compositor *compositor;
76         struct wl_shm *shm;
77         struct wl_shell *shell;
78         struct wl_shm_pool *shm_pool;
79
80         /* objects */
81         struct wl_surface *surface;
82         struct wl_shell_surface *shell_surface;
83         struct wl_buffer *buffer;
84 };
85
86 static int
87 _create_anonymous_file (off_t size)
88 {
89         static const char template[] =
90         "/shooter-XXXXXX";
91         const char *path;
92         char *name = NULL;
93         int fd = -1;
94         int ret = -1;
95
96         path = getenv("XDG_RUNTIME_DIR");
97         if (!path) {
98                 errno = ENOENT;
99                 return -1;
100         }
101
102         name = malloc(strlen(path) + sizeof(template));
103         GOTO_IF_FAIL(name != NULL, fail);
104
105         strcpy(name, path);
106         strcat(name, template);
107
108         fd = mkstemp(name);
109         if (fd >= 0)
110                 unlink(name);
111
112         ret = ftruncate(fd, size);
113         GOTO_IF_FAIL(ret >= 0, fail);
114
115         free(name);
116
117         return fd;
118 fail:
119         if (fd >= 0)
120                 close(fd);
121
122         if (name)
123                 free(name);
124
125         return -1;
126 }
127
128 static void
129 _destroy_anonymous_file(int fd)
130 {
131         if (fd < 0) return;
132
133         close(fd);
134 }
135
136
137 static struct wl_test_info *
138 _create_wl_test_info (void)
139 {
140         struct wl_test_info *test_info = NULL;
141
142         test_info = calloc(1, sizeof(struct wl_test_info));
143         RETURN_VAL_IF_FAIL(test_info != NULL, NULL);
144
145         return test_info;
146 }
147
148 static void
149 _destroy_wl_test_info (struct wl_test_info *test_info)
150 {
151         if (!test_info) return;
152
153         free(test_info);
154 }
155
156 static struct wl_shm_pool *
157 _create_shm_pool(struct wl_shm *shm, int size)
158 {
159         struct wl_shm_pool *shm_pool = NULL;
160         void *data = NULL;
161         int fd = -1;
162
163         fd = _create_anonymous_file(size);
164         GOTO_IF_FAIL(fd >= 0, fail);
165
166         data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
167         GOTO_IF_FAIL(data != NULL, fail);
168
169         memset(data, 0xff, size);
170         munmap(data, size);
171
172         shm_pool = wl_shm_create_pool(shm, fd, size);
173         GOTO_IF_FAIL(shm_pool != NULL, fail);
174
175         _destroy_anonymous_file(fd);
176
177         return shm_pool;
178
179 fail:
180         if (fd > 0)
181                 _destroy_anonymous_file(fd);
182
183         return NULL;
184 }
185
186 void
187 _destroy_shm_pool(struct wl_shm_pool *shm_pool)
188 {
189         if (!shm_pool) return;
190
191         wl_shm_pool_destroy(shm_pool);
192 }
193
194 static void
195 handle_global(void *data, struct wl_registry *registry, uint32_t name,
196               const char *interface, uint32_t version)
197 {
198         struct wl_test_info *ti = (struct wl_test_info *)data;
199
200         if (strcmp(interface, "wl_compositor") == 0) {
201                 ti->compositor = wl_registry_bind(registry, name,
202                         &wl_compositor_interface, 3);
203                 if (!ti->compositor)
204                         printf("%s(%d): Error. fail to bind  %s.\n",
205                                         __func__, __LINE__, interface);
206                 else
207                         printf("%s(%d): bind %s.\n", __func__, __LINE__, interface);
208         } else if (strcmp(interface, "wl_shm") == 0) {
209                 ti->shm = wl_registry_bind(registry, name, &wl_shm_interface, 1);
210                 if (!ti->shm)
211                         printf("%s(%d): Error. fail to bind  %s.\n",
212                                         __func__, __LINE__, interface);
213                 else
214                         printf("%s(%d): bind %s.\n", __func__, __LINE__, interface);
215
216                 ti->shm_pool = _create_shm_pool(ti->shm, ti->size);
217                 if (!ti->shm_pool)
218                         printf("%s(%d): Error. fail to create wl_shm_pool.\n",
219                                         __func__, __LINE__);
220                 else
221                         printf("%s(%d): success to create wl_shm_pool.\n",
222                                         __func__, __LINE__);
223
224         } else if (strcmp(interface, "wl_shell") == 0) {
225                 ti->shell = wl_registry_bind(registry, name, &wl_shell_interface, 1);
226                 if (!ti->shell)
227                         printf("%s(%d): Error. fail to bind  %s.\n",
228                                         __func__, __LINE__, interface);
229                 else
230                         printf("%s(%d): bind %s.\n", __func__, __LINE__, interface);
231         } else {
232                 printf("%s(%d): Not bind %s.\n", __func__, __LINE__, interface);
233         }
234 }
235
236 static void
237 handle_global_remove(void *data, struct wl_registry *registry, uint32_t name)
238 {
239
240 }
241
242 static const struct wl_registry_listener registry_listener = {
243         handle_global,
244         handle_global_remove
245 };
246
247 int main (void)
248 {
249         struct wl_test_info *ti = NULL;
250         int ret = 0;
251
252         /* create test info */
253         ti = _create_wl_test_info ();
254         GOTO_IF_FAIL(ti != NULL, fail);
255
256         /* init */
257         ti->width = BUF_WIDTH;
258         ti->height = BUF_HEIGHT;
259         ti->stride = ti->width * 4;
260         ti->format = WL_SHM_FORMAT_XRGB8888;
261         ti->size = ti->stride * ti->height;
262
263         /* connect display */
264         ti->display = wl_display_connect(NULL);
265         GOTO_IF_FAIL(ti->display != NULL, fail);
266
267         /* get the registry */
268         ti->registry = wl_display_get_registry(ti->display);
269         GOTO_IF_FAIL(ti->registry != NULL, fail);
270
271         /* get the global objects */
272         wl_registry_add_listener(ti->registry, &registry_listener, ti);
273         wl_display_dispatch(ti->display);
274         wl_display_roundtrip(ti->display);
275
276         /* check the global objects */
277         GOTO_IF_FAIL(ti->compositor != NULL, fail);
278         GOTO_IF_FAIL(ti->shm != NULL, fail);
279         GOTO_IF_FAIL(ti->shell != NULL, fail);
280         GOTO_IF_FAIL(ti->shm_pool != NULL, fail);
281
282         /* create objects */
283         ti->surface = wl_compositor_create_surface(ti->compositor);
284         GOTO_IF_FAIL(ti->surface != NULL, fail);
285
286         ti->shell_surface = wl_shell_get_shell_surface(ti->shell, ti->surface);
287         GOTO_IF_FAIL(ti->shell_surface != NULL, fail);
288
289         wl_shell_surface_set_toplevel(ti->shell_surface);
290
291         ti->buffer = wl_shm_pool_create_buffer(ti->shm_pool, 0,
292                 ti->width, ti->height, ti->stride, ti->format);
293         GOTO_IF_FAIL(ti->buffer != NULL, fail);
294
295         wl_surface_attach(ti->surface, ti->buffer, 0, 0);
296         wl_surface_damage(ti->surface, 0, 0, ti->width, ti->height);
297         wl_surface_commit(ti->surface);
298
299         wl_display_roundtrip(ti->display);
300
301         /* main loop */
302         printf("%s(%d): loop start.\n", __func__, __LINE__);
303         while (ret >= 0) {
304                 ret = wl_display_dispatch(ti->display);
305                 printf("%s(%d): loop running(ret=%d).\n", __func__, __LINE__, ret);
306         }
307         printf("%s(%d): loop end.\n", __func__, __LINE__);
308
309 fail:
310         /* destory objects */
311         if (ti->shell_surface)
312                 wl_shell_surface_destroy(ti->shell_surface);
313         if (ti->surface)
314                 wl_surface_destroy(ti->surface);
315         if (ti->buffer)
316                 wl_buffer_destroy(ti->buffer);
317
318         /* destroy global objects */
319         if (ti->shell)
320                 wl_shell_destroy(ti->shell);
321         if (ti->shm_pool)
322                 _destroy_shm_pool(ti->shm_pool);
323         if (ti->shm)
324                 wl_shm_destroy(ti->shm);
325         if (ti->compositor)
326                 wl_compositor_destroy(ti->compositor);
327
328         /* destory registry and display */
329         if (ti->registry)
330                 wl_registry_destroy(ti->registry);
331         if (ti->display)
332                 wl_display_disconnect(ti->display);
333
334         /* destroy test_info */
335         if (ti)
336                 _destroy_wl_test_info(ti);
337
338         return 0;
339 }