1 /**************************************************************************
5 Copyright 2015 Samsung Electronics co., Ltd. All Rights Reserved.
7 Contact: Eunchul Kim <chulspro.kim@samsung.com>,
8 JinYoung Jeon <jy0.jeon@samsung.com>,
9 Taeheon Kim <th908.kim@samsung.com>,
10 YoungJun Cho <yj44.cho@samsung.com>,
11 SooChan Lim <sc1.lim@samsung.com>,
12 Boram Park <sc1.lim@samsung.com>
14 Permission is hereby granted, free of charge, to any person obtaining a
15 copy of this software and associated documentation files (the
16 "Software"), to deal in the Software without restriction, including
17 without limitation the rights to use, copy, modify, merge, publish,
18 distribute, sub license, and/or sell copies of the Software, and to
19 permit persons to whom the Software is furnished to do so, subject to
20 the following conditions:
22 The above copyright notice and this permission notice (including the
23 next paragraph) shall be included in all copies or substantial portions
26 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
27 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
28 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
29 IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
30 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
31 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
32 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
34 **************************************************************************/
41 #include "tdm_private.h"
44 #include <wayland-server-core.h>
46 typedef struct _tdm_event_loop_source_base
48 struct wl_event_source *wl_source;
49 } tdm_event_loop_source_base;
51 typedef struct _tdm_event_loop_source_fd
53 tdm_event_loop_source_base base;
54 tdm_private_display *private_display;
55 tdm_event_loop_fd_handler func;
57 } tdm_event_loop_source_fd;
59 typedef struct _tdm_event_loop_source_timer
61 tdm_event_loop_source_base base;
62 tdm_private_display *private_display;
63 tdm_event_loop_timer_handler func;
65 } tdm_event_loop_source_timer;
68 _tdm_event_loop_main_fd_handler(int fd, tdm_event_loop_mask mask, void *user_data)
70 tdm_private_display *private_display = (tdm_private_display*)user_data;
71 tdm_private_loop *private_loop;
72 tdm_func_display *func_display;
75 TDM_RETURN_VAL_IF_FAIL(TDM_MUTEX_IS_LOCKED(), TDM_ERROR_OPERATION_FAILED);
76 TDM_RETURN_VAL_IF_FAIL(private_display != NULL, TDM_ERROR_OPERATION_FAILED);
77 TDM_RETURN_VAL_IF_FAIL(private_display->private_loop != NULL, TDM_ERROR_OPERATION_FAILED);
79 private_loop = private_display->private_loop;
82 TDM_INFO("backend fd(%d) event happens", private_loop->backend_fd);
84 func_display = &private_display->func_display;
85 if (!func_display->display_handle_events)
86 return TDM_ERROR_NONE;
88 ret = func_display->display_handle_events(private_display->bdata);
94 tdm_event_loop_init(tdm_private_display *private_display)
96 tdm_private_loop *private_loop;
99 TDM_RETURN_VAL_IF_FAIL(TDM_MUTEX_IS_LOCKED(), TDM_ERROR_OPERATION_FAILED);
101 if (private_display->private_loop)
102 return TDM_ERROR_NONE;
104 private_loop = calloc(1, sizeof *private_loop);
106 TDM_ERR("alloc failed");
107 return TDM_ERROR_OUT_OF_MEMORY;
110 private_loop->backend_fd = -1;
112 private_loop->wl_display = wl_display_create();
113 if (!private_loop->wl_display) {
114 TDM_ERR("creating a wayland display failed");
116 return TDM_ERROR_OUT_OF_MEMORY;
118 private_loop->wl_loop = wl_display_get_event_loop(private_loop->wl_display);
120 ret = tdm_server_init(private_loop);
121 if (ret != TDM_ERROR_NONE) {
122 TDM_ERR("server init failed");
123 wl_display_destroy(private_loop->wl_display);
125 return TDM_ERROR_OPERATION_FAILED;
128 private_loop->dpy = private_display;
129 private_display->private_loop = private_loop;
131 ret = tdm_thread_init(private_loop);
132 if (ret != TDM_ERROR_NONE) {
133 TDM_ERR("thread init failed");
134 tdm_server_deinit(private_loop);
135 wl_display_destroy(private_loop->wl_display);
137 return TDM_ERROR_OPERATION_FAILED;
140 TDM_INFO("event loop fd(%d)", wl_event_loop_get_fd(private_loop->wl_loop));
142 return TDM_ERROR_NONE;
146 tdm_event_loop_deinit(tdm_private_display *private_display)
148 TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED());
150 if (!private_display->private_loop)
153 tdm_thread_deinit(private_display->private_loop);
154 tdm_server_deinit(private_display->private_loop);
156 if (private_display->private_loop->backend_source)
157 tdm_event_loop_source_remove(private_display->private_loop->backend_source);
159 if (private_display->private_loop->wl_display)
160 wl_display_destroy(private_display->private_loop->wl_display);
162 free(private_display->private_loop);
163 private_display->private_loop = NULL;
167 tdm_event_loop_create_backend_source(tdm_private_display *private_display)
169 tdm_private_loop *private_loop = private_display->private_loop;
170 tdm_func_display *func_display;
174 TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED());
175 TDM_RETURN_IF_FAIL(private_loop != NULL);
177 func_display = &private_display->func_display;
178 if (!func_display->display_get_fd) {
179 TDM_INFO("TDM backend module won't offer a display fd");
183 ret = func_display->display_get_fd(private_display->bdata, &fd);
185 TDM_ERR("TDM backend module returns fd(%d)", fd);
189 if (!func_display->display_handle_events) {
190 TDM_ERR("no display_handle_events function");
194 private_loop->backend_source =
195 tdm_event_loop_add_fd_handler(private_display, fd,
196 TDM_EVENT_LOOP_READABLE,
197 _tdm_event_loop_main_fd_handler,
198 private_display, &ret);
199 if (!private_loop->backend_source) {
200 TDM_ERR("no backend fd(%d) source", fd);
204 private_loop->backend_fd = fd;
206 TDM_INFO("backend fd(%d) source created", private_loop->backend_fd);
210 tdm_event_loop_get_fd(tdm_private_display *private_display)
212 tdm_private_loop *private_loop = private_display->private_loop;
214 /* DON'T check TDM_MUTEX_IS_LOCKED here */
216 TDM_RETURN_VAL_IF_FAIL(private_loop->wl_loop != NULL, -1);
218 return wl_event_loop_get_fd(private_loop->wl_loop);
222 tdm_event_loop_dispatch(tdm_private_display *private_display)
224 tdm_private_loop *private_loop = private_display->private_loop;
226 /* DON'T check TDM_MUTEX_IS_LOCKED here */
228 TDM_RETURN_VAL_IF_FAIL(private_loop->wl_loop != NULL, TDM_ERROR_OPERATION_FAILED);
230 if (tdm_debug_thread)
231 TDM_INFO("dispatch");
233 /* Don't set timeout to -1. It can make deadblock by two mutex locks.
234 * If need to set -1, use poll() and call tdm_event_loop_dispatch() after
237 if (wl_event_loop_dispatch(private_loop->wl_loop, 0) < 0)
238 TDM_ERR("dispatch failed");
240 return TDM_ERROR_NONE;
245 tdm_event_loop_flush(tdm_private_display *private_display)
247 tdm_private_loop *private_loop = private_display->private_loop;
249 /* DON'T check TDM_MUTEX_IS_LOCKED here */
251 TDM_RETURN_IF_FAIL(private_loop->wl_display != NULL);
253 wl_display_flush_clients(private_loop->wl_display);
257 _tdm_event_loop_fd_func(int fd, uint32_t wl_mask, void *data)
259 tdm_event_loop_source_fd *fd_source = (tdm_event_loop_source_fd*)data;
260 tdm_private_display *private_display;
261 tdm_event_loop_mask mask = 0;
263 /* DON'T check TDM_MUTEX_IS_LOCKED here */
265 TDM_RETURN_VAL_IF_FAIL(fd_source, 1);
266 TDM_RETURN_VAL_IF_FAIL(fd_source->func, 1);
268 private_display = fd_source->private_display;
270 if (wl_mask & WL_EVENT_READABLE)
271 mask |= TDM_EVENT_LOOP_READABLE;
272 if (wl_mask & WL_EVENT_WRITABLE)
273 mask |= TDM_EVENT_LOOP_WRITABLE;
274 if (wl_mask & WL_EVENT_HANGUP)
275 mask |= TDM_EVENT_LOOP_HANGUP;
276 if (wl_mask & WL_EVENT_ERROR)
277 mask |= TDM_EVENT_LOOP_ERROR;
279 _pthread_mutex_lock(&private_display->lock);
280 fd_source->func(fd, mask, fd_source->user_data);
281 _pthread_mutex_unlock(&private_display->lock);
286 EXTERN tdm_event_loop_source*
287 tdm_event_loop_add_fd_handler(tdm_display *dpy, int fd, tdm_event_loop_mask mask,
288 tdm_event_loop_fd_handler func, void *user_data,
291 tdm_private_display *private_display;
292 tdm_private_loop *private_loop;
293 tdm_event_loop_source_fd *fd_source;
294 uint32_t wl_mask = 0;
297 TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(TDM_MUTEX_IS_LOCKED(), TDM_ERROR_OPERATION_FAILED, NULL);
298 TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(dpy, TDM_ERROR_INVALID_PARAMETER, NULL);
299 TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(fd >= 0, TDM_ERROR_INVALID_PARAMETER, NULL);
300 TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(func, TDM_ERROR_INVALID_PARAMETER, NULL);
302 private_display = (tdm_private_display*)dpy;
303 private_loop = private_display->private_loop;
304 TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(private_loop, TDM_ERROR_INVALID_PARAMETER, NULL);
305 TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(private_loop->wl_loop, TDM_ERROR_INVALID_PARAMETER, NULL);
307 fd_source = calloc(1, sizeof(tdm_event_loop_source_fd));
308 TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(fd_source, TDM_ERROR_OUT_OF_MEMORY, NULL);
310 if (mask & TDM_EVENT_LOOP_READABLE)
311 wl_mask |= WL_EVENT_READABLE;
312 if (mask & TDM_EVENT_LOOP_WRITABLE)
313 wl_mask |= WL_EVENT_WRITABLE;
315 fd_source->base.wl_source =
316 wl_event_loop_add_fd(private_loop->wl_loop,
317 fd, wl_mask, _tdm_event_loop_fd_func, fd_source);
318 if (!fd_source->base.wl_source) {
320 *error = TDM_ERROR_OUT_OF_MEMORY;
325 fd_source->private_display = private_display;
326 fd_source->func = func;
327 fd_source->user_data = user_data;
330 *error = TDM_ERROR_NONE;
332 return (tdm_event_loop_source*)fd_source;
336 tdm_event_loop_source_fd_update(tdm_event_loop_source *source, tdm_event_loop_mask mask)
338 tdm_event_loop_source_fd *fd_source = source;
339 uint32_t wl_mask = 0;
341 TDM_RETURN_VAL_IF_FAIL(TDM_MUTEX_IS_LOCKED(), TDM_ERROR_OPERATION_FAILED);
342 TDM_RETURN_VAL_IF_FAIL(fd_source, TDM_ERROR_INVALID_PARAMETER);
344 if (mask & TDM_EVENT_LOOP_READABLE)
345 wl_mask |= WL_EVENT_READABLE;
346 if (mask & TDM_EVENT_LOOP_WRITABLE)
347 wl_mask |= WL_EVENT_WRITABLE;
349 if (wl_event_source_fd_update(fd_source->base.wl_source, wl_mask) < 0) {
350 TDM_ERR("source update failed: %m");
351 return TDM_ERROR_OPERATION_FAILED;
354 return TDM_ERROR_NONE;
358 _tdm_event_loop_timer_func(void *data)
360 tdm_event_loop_source_timer *timer_source = (tdm_event_loop_source_timer*)data;
361 tdm_private_display *private_display;
363 /* DON'T check TDM_MUTEX_IS_LOCKED here */
365 TDM_RETURN_VAL_IF_FAIL(timer_source, 1);
366 TDM_RETURN_VAL_IF_FAIL(timer_source->func, 1);
368 private_display = timer_source->private_display;
370 _pthread_mutex_lock(&private_display->lock);
371 timer_source->func(timer_source->user_data);
372 _pthread_mutex_unlock(&private_display->lock);
377 EXTERN tdm_event_loop_source*
378 tdm_event_loop_add_timer_handler(tdm_display *dpy, tdm_event_loop_timer_handler func,
379 void *user_data, tdm_error *error)
381 tdm_private_display *private_display;
382 tdm_private_loop *private_loop;
383 tdm_event_loop_source_timer *timer_source;
386 TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(TDM_MUTEX_IS_LOCKED(), TDM_ERROR_OPERATION_FAILED, NULL);
387 TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(dpy, TDM_ERROR_INVALID_PARAMETER, NULL);
388 TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(func, TDM_ERROR_INVALID_PARAMETER, NULL);
390 private_display = (tdm_private_display*)dpy;
391 private_loop = private_display->private_loop;
392 TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(private_loop, TDM_ERROR_INVALID_PARAMETER, NULL);
393 TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(private_loop->wl_loop, TDM_ERROR_INVALID_PARAMETER, NULL);
395 timer_source = calloc(1, sizeof(tdm_event_loop_source_timer));
396 TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(timer_source, TDM_ERROR_OUT_OF_MEMORY, NULL);
398 timer_source->base.wl_source =
399 wl_event_loop_add_timer(private_loop->wl_loop,
400 _tdm_event_loop_timer_func, timer_source);
401 if (!timer_source->base.wl_source) {
403 *error = TDM_ERROR_OUT_OF_MEMORY;
408 timer_source->private_display = private_display;
409 timer_source->func = func;
410 timer_source->user_data = user_data;
413 *error = TDM_ERROR_NONE;
415 return (tdm_event_loop_source*)timer_source;
419 tdm_event_loop_source_timer_update(tdm_event_loop_source *source, int ms_delay)
421 tdm_event_loop_source_timer *timer_source = source;
423 TDM_RETURN_VAL_IF_FAIL(TDM_MUTEX_IS_LOCKED(), TDM_ERROR_OPERATION_FAILED);
424 TDM_RETURN_VAL_IF_FAIL(timer_source, TDM_ERROR_INVALID_PARAMETER);
426 if (wl_event_source_timer_update(timer_source->base.wl_source, ms_delay) < 0) {
427 TDM_ERR("source update failed: %m");
428 return TDM_ERROR_OPERATION_FAILED;
431 return TDM_ERROR_NONE;
435 tdm_event_loop_source_remove(tdm_event_loop_source *source)
437 tdm_event_loop_source_base *base = (tdm_event_loop_source_base*)source;
439 TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED());
444 wl_event_source_remove(base->wl_source);