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 if (tdm_thread_is_running() &&
234 tdm_thread_in_display_thread(syscall(SYS_gettid))) {
235 TDM_NEVER_GET_HERE();
236 return TDM_ERROR_OPERATION_FAILED;
239 /* Don't set timeout to -1. It can make deadblock by two mutex locks.
240 * If need to set -1, use poll() and call tdm_event_loop_dispatch() after
243 if (wl_event_loop_dispatch(private_loop->wl_loop, 0) < 0)
244 TDM_ERR("dispatch failed");
246 wl_display_flush_clients(private_loop->wl_display);
248 return TDM_ERROR_NONE;
253 tdm_event_loop_flush(tdm_private_display *private_display)
255 tdm_private_loop *private_loop = private_display->private_loop;
257 /* DON'T check TDM_MUTEX_IS_LOCKED here */
259 TDM_RETURN_IF_FAIL(private_loop->wl_display != NULL);
261 if (tdm_thread_is_running() &&
262 tdm_thread_in_display_thread(syscall(SYS_gettid))) {
263 TDM_NEVER_GET_HERE();
267 wl_display_flush_clients(private_loop->wl_display);
271 _tdm_event_loop_fd_func(int fd, uint32_t wl_mask, void *data)
273 tdm_event_loop_source_fd *fd_source = (tdm_event_loop_source_fd*)data;
274 tdm_private_display *private_display;
275 tdm_event_loop_mask mask = 0;
277 /* DON'T check TDM_MUTEX_IS_LOCKED here */
279 TDM_RETURN_VAL_IF_FAIL(fd_source, 1);
280 TDM_RETURN_VAL_IF_FAIL(fd_source->func, 1);
282 private_display = fd_source->private_display;
284 if (wl_mask & WL_EVENT_READABLE)
285 mask |= TDM_EVENT_LOOP_READABLE;
286 if (wl_mask & WL_EVENT_WRITABLE)
287 mask |= TDM_EVENT_LOOP_WRITABLE;
288 if (wl_mask & WL_EVENT_HANGUP)
289 mask |= TDM_EVENT_LOOP_HANGUP;
290 if (wl_mask & WL_EVENT_ERROR)
291 mask |= TDM_EVENT_LOOP_ERROR;
293 _pthread_mutex_lock(&private_display->lock);
294 fd_source->func(fd, mask, fd_source->user_data);
295 _pthread_mutex_unlock(&private_display->lock);
300 EXTERN tdm_event_loop_source*
301 tdm_event_loop_add_fd_handler(tdm_display *dpy, int fd, tdm_event_loop_mask mask,
302 tdm_event_loop_fd_handler func, void *user_data,
305 tdm_private_display *private_display;
306 tdm_private_loop *private_loop;
307 tdm_event_loop_source_fd *fd_source;
308 uint32_t wl_mask = 0;
311 TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(TDM_MUTEX_IS_LOCKED(), TDM_ERROR_OPERATION_FAILED, NULL);
312 TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(dpy, TDM_ERROR_INVALID_PARAMETER, NULL);
313 TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(fd >= 0, TDM_ERROR_INVALID_PARAMETER, NULL);
314 TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(func, TDM_ERROR_INVALID_PARAMETER, NULL);
316 private_display = (tdm_private_display*)dpy;
317 private_loop = private_display->private_loop;
318 TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(private_loop, TDM_ERROR_INVALID_PARAMETER, NULL);
319 TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(private_loop->wl_loop, TDM_ERROR_INVALID_PARAMETER, NULL);
321 fd_source = calloc(1, sizeof(tdm_event_loop_source_fd));
322 TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(fd_source, TDM_ERROR_OUT_OF_MEMORY, NULL);
324 if (mask & TDM_EVENT_LOOP_READABLE)
325 wl_mask |= WL_EVENT_READABLE;
326 if (mask & TDM_EVENT_LOOP_WRITABLE)
327 wl_mask |= WL_EVENT_WRITABLE;
329 fd_source->base.wl_source =
330 wl_event_loop_add_fd(private_loop->wl_loop,
331 fd, wl_mask, _tdm_event_loop_fd_func, fd_source);
332 if (!fd_source->base.wl_source) {
334 *error = TDM_ERROR_OUT_OF_MEMORY;
339 fd_source->private_display = private_display;
340 fd_source->func = func;
341 fd_source->user_data = user_data;
344 *error = TDM_ERROR_NONE;
346 return (tdm_event_loop_source*)fd_source;
350 tdm_event_loop_source_fd_update(tdm_event_loop_source *source, tdm_event_loop_mask mask)
352 tdm_event_loop_source_fd *fd_source = source;
353 uint32_t wl_mask = 0;
355 TDM_RETURN_VAL_IF_FAIL(TDM_MUTEX_IS_LOCKED(), TDM_ERROR_OPERATION_FAILED);
356 TDM_RETURN_VAL_IF_FAIL(fd_source, TDM_ERROR_INVALID_PARAMETER);
358 if (mask & TDM_EVENT_LOOP_READABLE)
359 wl_mask |= WL_EVENT_READABLE;
360 if (mask & TDM_EVENT_LOOP_WRITABLE)
361 wl_mask |= WL_EVENT_WRITABLE;
363 if (wl_event_source_fd_update(fd_source->base.wl_source, wl_mask) < 0) {
364 TDM_ERR("source update failed: %m");
365 return TDM_ERROR_OPERATION_FAILED;
368 return TDM_ERROR_NONE;
372 _tdm_event_loop_timer_func(void *data)
374 tdm_event_loop_source_timer *timer_source = (tdm_event_loop_source_timer*)data;
375 tdm_private_display *private_display;
377 /* DON'T check TDM_MUTEX_IS_LOCKED here */
379 TDM_RETURN_VAL_IF_FAIL(timer_source, 1);
380 TDM_RETURN_VAL_IF_FAIL(timer_source->func, 1);
382 private_display = timer_source->private_display;
384 _pthread_mutex_lock(&private_display->lock);
385 timer_source->func(timer_source->user_data);
386 _pthread_mutex_unlock(&private_display->lock);
391 EXTERN tdm_event_loop_source*
392 tdm_event_loop_add_timer_handler(tdm_display *dpy, tdm_event_loop_timer_handler func,
393 void *user_data, tdm_error *error)
395 tdm_private_display *private_display;
396 tdm_private_loop *private_loop;
397 tdm_event_loop_source_timer *timer_source;
400 TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(TDM_MUTEX_IS_LOCKED(), TDM_ERROR_OPERATION_FAILED, NULL);
401 TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(dpy, TDM_ERROR_INVALID_PARAMETER, NULL);
402 TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(func, TDM_ERROR_INVALID_PARAMETER, NULL);
404 private_display = (tdm_private_display*)dpy;
405 private_loop = private_display->private_loop;
406 TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(private_loop, TDM_ERROR_INVALID_PARAMETER, NULL);
407 TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(private_loop->wl_loop, TDM_ERROR_INVALID_PARAMETER, NULL);
409 timer_source = calloc(1, sizeof(tdm_event_loop_source_timer));
410 TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(timer_source, TDM_ERROR_OUT_OF_MEMORY, NULL);
412 timer_source->base.wl_source =
413 wl_event_loop_add_timer(private_loop->wl_loop,
414 _tdm_event_loop_timer_func, timer_source);
415 if (!timer_source->base.wl_source) {
417 *error = TDM_ERROR_OUT_OF_MEMORY;
422 timer_source->private_display = private_display;
423 timer_source->func = func;
424 timer_source->user_data = user_data;
427 *error = TDM_ERROR_NONE;
429 return (tdm_event_loop_source*)timer_source;
433 tdm_event_loop_source_timer_update(tdm_event_loop_source *source, unsigned int ms_delay)
435 tdm_event_loop_source_timer *timer_source = source;
437 TDM_RETURN_VAL_IF_FAIL(TDM_MUTEX_IS_LOCKED(), TDM_ERROR_OPERATION_FAILED);
438 TDM_RETURN_VAL_IF_FAIL(timer_source, TDM_ERROR_INVALID_PARAMETER);
440 if (wl_event_source_timer_update(timer_source->base.wl_source, ms_delay) < 0) {
441 TDM_ERR("source update failed: %m");
442 return TDM_ERROR_OPERATION_FAILED;
445 return TDM_ERROR_NONE;
449 tdm_event_loop_source_remove(tdm_event_loop_source *source)
451 tdm_event_loop_source_base *base = (tdm_event_loop_source_base*)source;
453 TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED());
458 wl_event_source_remove(base->wl_source);