clients: Fix null dereferencing
[platform/core/uifw/libds.git] / 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 #include <linux/limits.h>
38
39 #include <wayland-client.h>
40
41 #define BUF_WIDTH 1920
42 #define BUF_HEIGHT 1080
43
44 #define RETURN_VAL_IF_FAIL(c,v) {\
45     if(!((c))){\
46         fprintf(stderr, "[%s(%d)] '%s' failed.", __func__, __LINE__, #c);\
47         return (v);\
48     }\
49 }
50
51 #define GOTO_IF_FAIL(c,l) {\
52         if(!(c)) {\
53                 fprintf(stderr, "[%s(%d)] '%s' failed.", __func__, __LINE__, #c);\
54                 goto l;\
55         }\
56 }
57
58 #define EXIT_IF_FAIL(c) {\
59         if(!(c)) {\
60                 fprintf (stderr, "[%s(%d)] '%s' failed.\n",__func__,__LINE__,#c);\
61                 exit(0);\
62         }\
63 }
64
65 struct wl_test_info {
66         int width;
67         int height;
68         int stride;
69         int format;
70         int size;
71
72         struct wl_display *display;
73         struct wl_registry *registry;
74
75         /* global objects */
76         struct wl_compositor *compositor;
77         struct wl_shm *shm;
78         struct wl_shell *shell;
79         struct wl_shm_pool *shm_pool;
80
81         /* objects */
82         struct wl_surface *surface;
83         struct wl_shell_surface *shell_surface;
84         struct wl_buffer *buffer;
85 };
86
87 static int
88 _create_anonymous_file (off_t size)
89 {
90         static const char template[] =
91         "/shooter-XXXXXX";
92         const char *path;
93         char name[PATH_MAX] = "";
94         int fd = -1;
95         int ret = -1;
96
97         path = getenv("XDG_RUNTIME_DIR");
98         if (!path) {
99                 errno = ENOENT;
100                 return -1;
101         }
102
103         if (strlen(path) + strlen(template) > (PATH_MAX - 1)) {
104                 errno = ENAMETOOLONG;
105                 return -1;
106         }
107
108         strncpy(name, path, PATH_MAX);
109         name[PATH_MAX - 1] = '\0';
110         strncat(name, template, strlen(template));
111
112         fd = mkstemp(name);
113         if (fd < 0)
114                 return -1;
115
116         unlink(name);
117
118         ret = ftruncate(fd, size);
119         if (ret < 0) {
120                 close(fd);
121                 return -1;
122         }
123
124         return fd;
125 }
126
127 static void
128 _destroy_anonymous_file(int fd)
129 {
130         if (fd < 0) return;
131
132         close(fd);
133 }
134
135
136 static struct wl_test_info *
137 _create_wl_test_info (void)
138 {
139         struct wl_test_info *test_info = NULL;
140
141         test_info = calloc(1, sizeof(struct wl_test_info));
142         RETURN_VAL_IF_FAIL(test_info != NULL, NULL);
143
144         return test_info;
145 }
146
147 static void
148 _destroy_wl_test_info (struct wl_test_info *test_info)
149 {
150         if (!test_info) return;
151
152         free(test_info);
153 }
154
155 static struct wl_shm_pool *
156 _create_shm_pool(struct wl_shm *shm, int size)
157 {
158         struct wl_shm_pool *shm_pool = NULL;
159         void *data = NULL;
160         int fd = -1;
161
162         fd = _create_anonymous_file(size);
163         GOTO_IF_FAIL(fd >= 0, fail);
164
165         data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
166         GOTO_IF_FAIL(data != NULL, fail);
167
168         memset(data, 0xff, size);
169         munmap(data, size);
170
171         shm_pool = wl_shm_create_pool(shm, fd, size);
172         GOTO_IF_FAIL(shm_pool != NULL, fail);
173
174         _destroy_anonymous_file(fd);
175
176         return shm_pool;
177
178 fail:
179         if (fd > 0)
180                 _destroy_anonymous_file(fd);
181
182         return NULL;
183 }
184
185 void
186 _destroy_shm_pool(struct wl_shm_pool *shm_pool)
187 {
188         if (!shm_pool) return;
189
190         wl_shm_pool_destroy(shm_pool);
191 }
192
193 static void
194 handle_global(void *data, struct wl_registry *registry, uint32_t name,
195               const char *interface, uint32_t version)
196 {
197         struct wl_test_info *ti = (struct wl_test_info *)data;
198
199         if (strcmp(interface, "wl_compositor") == 0) {
200                 ti->compositor = wl_registry_bind(registry, name,
201                         &wl_compositor_interface, 3);
202                 if (!ti->compositor)
203                         printf("%s(%d): Error. fail to bind  %s.\n",
204                                         __func__, __LINE__, interface);
205                 else
206                         printf("%s(%d): bind %s.\n", __func__, __LINE__, interface);
207         } else if (strcmp(interface, "wl_shm") == 0) {
208                 ti->shm = wl_registry_bind(registry, name, &wl_shm_interface, 1);
209                 if (!ti->shm)
210                         printf("%s(%d): Error. fail to bind  %s.\n",
211                                         __func__, __LINE__, interface);
212                 else
213                         printf("%s(%d): bind %s.\n", __func__, __LINE__, interface);
214
215                 ti->shm_pool = _create_shm_pool(ti->shm, ti->size);
216                 if (!ti->shm_pool)
217                         printf("%s(%d): Error. fail to create wl_shm_pool.\n",
218                                         __func__, __LINE__);
219                 else
220                         printf("%s(%d): success to create wl_shm_pool.\n",
221                                         __func__, __LINE__);
222
223         } else if (strcmp(interface, "wl_shell") == 0) {
224                 ti->shell = wl_registry_bind(registry, name, &wl_shell_interface, 1);
225                 if (!ti->shell)
226                         printf("%s(%d): Error. fail to bind  %s.\n",
227                                         __func__, __LINE__, interface);
228                 else
229                         printf("%s(%d): bind %s.\n", __func__, __LINE__, interface);
230         } else {
231                 printf("%s(%d): Not bind %s.\n", __func__, __LINE__, interface);
232         }
233 }
234
235 static void
236 handle_global_remove(void *data, struct wl_registry *registry, uint32_t name)
237 {
238
239 }
240
241 static const struct wl_registry_listener registry_listener = {
242         handle_global,
243         handle_global_remove
244 };
245
246 int main (void)
247 {
248         struct wl_test_info *ti = NULL;
249         int ret = 0;
250
251         /* create test info */
252         ti = _create_wl_test_info ();
253         if (!ti)
254                 return -1;
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 }