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 {
47 struct wl_event_source *wl_source;
48 } tdm_event_loop_source_base;
50 typedef struct _tdm_event_loop_source_fd {
51 tdm_event_loop_source_base base;
52 tdm_private_display *private_display;
53 tdm_event_loop_fd_handler func;
55 } tdm_event_loop_source_fd;
57 typedef struct _tdm_event_loop_source_timer {
58 tdm_event_loop_source_base base;
59 tdm_private_display *private_display;
60 tdm_event_loop_timer_handler func;
62 } tdm_event_loop_source_timer;
65 _tdm_event_loop_main_fd_handler(int fd, tdm_event_loop_mask mask, void *user_data)
67 tdm_private_display *private_display = (tdm_private_display*)user_data;
68 tdm_private_loop *private_loop;
69 tdm_func_display *func_display;
72 TDM_RETURN_VAL_IF_FAIL(TDM_MUTEX_IS_LOCKED(), TDM_ERROR_OPERATION_FAILED);
73 TDM_RETURN_VAL_IF_FAIL(private_display != NULL, TDM_ERROR_OPERATION_FAILED);
74 TDM_RETURN_VAL_IF_FAIL(private_display->private_loop != NULL, TDM_ERROR_OPERATION_FAILED);
76 private_loop = private_display->private_loop;
79 TDM_INFO("backend fd(%d) event happens", private_loop->backend_fd);
81 func_display = &private_display->func_display;
82 if (!func_display->display_handle_events)
83 return TDM_ERROR_NONE;
85 ret = func_display->display_handle_events(private_display->bdata);
91 tdm_event_loop_init(tdm_private_display *private_display)
93 tdm_private_loop *private_loop;
96 TDM_RETURN_VAL_IF_FAIL(TDM_MUTEX_IS_LOCKED(), TDM_ERROR_OPERATION_FAILED);
98 if (private_display->private_loop)
99 return TDM_ERROR_NONE;
101 private_loop = calloc(1, sizeof * private_loop);
103 TDM_ERR("alloc failed");
104 return TDM_ERROR_OUT_OF_MEMORY;
107 private_loop->backend_fd = -1;
109 private_loop->wl_display = wl_display_create();
110 if (!private_loop->wl_display) {
111 TDM_ERR("creating a wayland display failed");
113 return TDM_ERROR_OUT_OF_MEMORY;
115 private_loop->wl_loop = wl_display_get_event_loop(private_loop->wl_display);
117 ret = tdm_server_init(private_loop);
118 if (ret != TDM_ERROR_NONE) {
119 TDM_ERR("server init failed");
120 wl_display_destroy(private_loop->wl_display);
122 return TDM_ERROR_OPERATION_FAILED;
125 private_loop->dpy = private_display;
126 private_display->private_loop = private_loop;
128 ret = tdm_thread_init(private_loop);
129 if (ret != TDM_ERROR_NONE) {
130 TDM_ERR("thread init failed");
131 tdm_server_deinit(private_loop);
132 wl_display_destroy(private_loop->wl_display);
134 return TDM_ERROR_OPERATION_FAILED;
137 TDM_INFO("event loop fd(%d)", wl_event_loop_get_fd(private_loop->wl_loop));
139 return TDM_ERROR_NONE;
143 tdm_event_loop_deinit(tdm_private_display *private_display)
145 TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED());
147 if (!private_display->private_loop)
150 tdm_thread_deinit(private_display->private_loop);
151 tdm_server_deinit(private_display->private_loop);
153 if (private_display->private_loop->backend_source)
154 tdm_event_loop_source_remove(private_display->private_loop->backend_source);
156 if (private_display->private_loop->wl_display)
157 wl_display_destroy(private_display->private_loop->wl_display);
159 free(private_display->private_loop);
160 private_display->private_loop = NULL;
164 tdm_event_loop_create_backend_source(tdm_private_display *private_display)
166 tdm_private_loop *private_loop = private_display->private_loop;
167 tdm_func_display *func_display;
171 TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED());
172 TDM_RETURN_IF_FAIL(private_loop != NULL);
174 func_display = &private_display->func_display;
175 if (!func_display->display_get_fd) {
176 TDM_INFO("TDM backend module won't offer a display fd");
180 ret = func_display->display_get_fd(private_display->bdata, &fd);
182 TDM_ERR("TDM backend module returns fd(%d)", fd);
186 if (!func_display->display_handle_events) {
187 TDM_ERR("no display_handle_events function");
191 private_loop->backend_source =
192 tdm_event_loop_add_fd_handler(private_display, fd,
193 TDM_EVENT_LOOP_READABLE,
194 _tdm_event_loop_main_fd_handler,
195 private_display, &ret);
196 if (!private_loop->backend_source) {
197 TDM_ERR("no backend fd(%d) source", fd);
201 private_loop->backend_fd = fd;
203 TDM_INFO("backend fd(%d) source created", private_loop->backend_fd);
207 tdm_event_loop_get_fd(tdm_private_display *private_display)
209 tdm_private_loop *private_loop = private_display->private_loop;
211 /* DON'T check TDM_MUTEX_IS_LOCKED here */
213 TDM_RETURN_VAL_IF_FAIL(private_loop->wl_loop != NULL, -1);
215 return wl_event_loop_get_fd(private_loop->wl_loop);
219 tdm_event_loop_dispatch(tdm_private_display *private_display)
221 tdm_private_loop *private_loop = private_display->private_loop;
223 /* DON'T check TDM_MUTEX_IS_LOCKED here */
225 TDM_RETURN_VAL_IF_FAIL(private_loop->wl_loop != NULL, TDM_ERROR_OPERATION_FAILED);
227 if (tdm_debug_thread)
228 TDM_INFO("dispatch");
230 if (tdm_thread_is_running() &&
231 tdm_thread_in_display_thread(syscall(SYS_gettid))) {
232 TDM_NEVER_GET_HERE();
233 return TDM_ERROR_OPERATION_FAILED;
236 /* Don't set timeout to -1. It can make deadblock by two mutex locks.
237 * If need to set -1, use poll() and call tdm_event_loop_dispatch() after
240 if (wl_event_loop_dispatch(private_loop->wl_loop, 0) < 0)
241 TDM_ERR("dispatch failed");
243 wl_display_flush_clients(private_loop->wl_display);
245 return TDM_ERROR_NONE;
250 tdm_event_loop_flush(tdm_private_display *private_display)
252 tdm_private_loop *private_loop = private_display->private_loop;
254 /* DON'T check TDM_MUTEX_IS_LOCKED here */
256 TDM_RETURN_IF_FAIL(private_loop->wl_display != NULL);
258 if (tdm_thread_is_running() &&
259 tdm_thread_in_display_thread(syscall(SYS_gettid))) {
260 TDM_NEVER_GET_HERE();
264 wl_display_flush_clients(private_loop->wl_display);
268 _tdm_event_loop_fd_func(int fd, uint32_t wl_mask, void *data)
270 tdm_event_loop_source_fd *fd_source = (tdm_event_loop_source_fd*)data;
271 tdm_private_display *private_display;
272 tdm_event_loop_mask mask = 0;
274 /* DON'T check TDM_MUTEX_IS_LOCKED here */
276 TDM_RETURN_VAL_IF_FAIL(fd_source, 1);
277 TDM_RETURN_VAL_IF_FAIL(fd_source->func, 1);
279 private_display = fd_source->private_display;
281 if (wl_mask & WL_EVENT_READABLE)
282 mask |= TDM_EVENT_LOOP_READABLE;
283 if (wl_mask & WL_EVENT_WRITABLE)
284 mask |= TDM_EVENT_LOOP_WRITABLE;
285 if (wl_mask & WL_EVENT_HANGUP)
286 mask |= TDM_EVENT_LOOP_HANGUP;
287 if (wl_mask & WL_EVENT_ERROR)
288 mask |= TDM_EVENT_LOOP_ERROR;
290 _pthread_mutex_lock(&private_display->lock);
291 fd_source->func(fd, mask, fd_source->user_data);
292 _pthread_mutex_unlock(&private_display->lock);
297 EXTERN tdm_event_loop_source *
298 tdm_event_loop_add_fd_handler(tdm_display *dpy, int fd, tdm_event_loop_mask mask,
299 tdm_event_loop_fd_handler func, void *user_data,
302 tdm_private_display *private_display;
303 tdm_private_loop *private_loop;
304 tdm_event_loop_source_fd *fd_source;
305 uint32_t wl_mask = 0;
308 TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(TDM_MUTEX_IS_LOCKED(), TDM_ERROR_OPERATION_FAILED, NULL);
309 TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(dpy, TDM_ERROR_INVALID_PARAMETER, NULL);
310 TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(fd >= 0, TDM_ERROR_INVALID_PARAMETER, NULL);
311 TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(func, TDM_ERROR_INVALID_PARAMETER, NULL);
313 private_display = (tdm_private_display*)dpy;
314 private_loop = private_display->private_loop;
315 TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(private_loop, TDM_ERROR_INVALID_PARAMETER, NULL);
316 TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(private_loop->wl_loop, TDM_ERROR_INVALID_PARAMETER, NULL);
318 fd_source = calloc(1, sizeof(tdm_event_loop_source_fd));
319 TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(fd_source, TDM_ERROR_OUT_OF_MEMORY, NULL);
321 if (mask & TDM_EVENT_LOOP_READABLE)
322 wl_mask |= WL_EVENT_READABLE;
323 if (mask & TDM_EVENT_LOOP_WRITABLE)
324 wl_mask |= WL_EVENT_WRITABLE;
326 fd_source->base.wl_source =
327 wl_event_loop_add_fd(private_loop->wl_loop,
328 fd, wl_mask, _tdm_event_loop_fd_func, fd_source);
329 if (!fd_source->base.wl_source) {
331 *error = TDM_ERROR_OUT_OF_MEMORY;
336 fd_source->private_display = private_display;
337 fd_source->func = func;
338 fd_source->user_data = user_data;
341 *error = TDM_ERROR_NONE;
343 return (tdm_event_loop_source *)fd_source;
347 tdm_event_loop_source_fd_update(tdm_event_loop_source *source, tdm_event_loop_mask mask)
349 tdm_event_loop_source_fd *fd_source = source;
350 uint32_t wl_mask = 0;
352 TDM_RETURN_VAL_IF_FAIL(TDM_MUTEX_IS_LOCKED(), TDM_ERROR_OPERATION_FAILED);
353 TDM_RETURN_VAL_IF_FAIL(fd_source, TDM_ERROR_INVALID_PARAMETER);
355 if (mask & TDM_EVENT_LOOP_READABLE)
356 wl_mask |= WL_EVENT_READABLE;
357 if (mask & TDM_EVENT_LOOP_WRITABLE)
358 wl_mask |= WL_EVENT_WRITABLE;
360 if (wl_event_source_fd_update(fd_source->base.wl_source, wl_mask) < 0) {
361 TDM_ERR("source update failed: %m");
362 return TDM_ERROR_OPERATION_FAILED;
365 return TDM_ERROR_NONE;
369 _tdm_event_loop_timer_func(void *data)
371 tdm_event_loop_source_timer *timer_source = (tdm_event_loop_source_timer*)data;
372 tdm_private_display *private_display;
374 /* DON'T check TDM_MUTEX_IS_LOCKED here */
376 TDM_RETURN_VAL_IF_FAIL(timer_source, 1);
377 TDM_RETURN_VAL_IF_FAIL(timer_source->func, 1);
379 private_display = timer_source->private_display;
381 _pthread_mutex_lock(&private_display->lock);
382 timer_source->func(timer_source->user_data);
383 _pthread_mutex_unlock(&private_display->lock);
388 EXTERN tdm_event_loop_source *
389 tdm_event_loop_add_timer_handler(tdm_display *dpy, tdm_event_loop_timer_handler func,
390 void *user_data, tdm_error *error)
392 tdm_private_display *private_display;
393 tdm_private_loop *private_loop;
394 tdm_event_loop_source_timer *timer_source;
397 TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(TDM_MUTEX_IS_LOCKED(), TDM_ERROR_OPERATION_FAILED, NULL);
398 TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(dpy, TDM_ERROR_INVALID_PARAMETER, NULL);
399 TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(func, TDM_ERROR_INVALID_PARAMETER, NULL);
401 private_display = (tdm_private_display*)dpy;
402 private_loop = private_display->private_loop;
403 TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(private_loop, TDM_ERROR_INVALID_PARAMETER, NULL);
404 TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(private_loop->wl_loop, TDM_ERROR_INVALID_PARAMETER, NULL);
406 timer_source = calloc(1, sizeof(tdm_event_loop_source_timer));
407 TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(timer_source, TDM_ERROR_OUT_OF_MEMORY, NULL);
409 timer_source->base.wl_source =
410 wl_event_loop_add_timer(private_loop->wl_loop,
411 _tdm_event_loop_timer_func, timer_source);
412 if (!timer_source->base.wl_source) {
414 *error = TDM_ERROR_OUT_OF_MEMORY;
419 timer_source->private_display = private_display;
420 timer_source->func = func;
421 timer_source->user_data = user_data;
424 *error = TDM_ERROR_NONE;
426 return (tdm_event_loop_source *)timer_source;
430 tdm_event_loop_source_timer_update(tdm_event_loop_source *source, unsigned int ms_delay)
432 tdm_event_loop_source_timer *timer_source = source;
434 TDM_RETURN_VAL_IF_FAIL(TDM_MUTEX_IS_LOCKED(), TDM_ERROR_OPERATION_FAILED);
435 TDM_RETURN_VAL_IF_FAIL(timer_source, TDM_ERROR_INVALID_PARAMETER);
437 if (wl_event_source_timer_update(timer_source->base.wl_source, ms_delay) < 0) {
438 TDM_ERR("source update failed: %m");
439 return TDM_ERROR_OPERATION_FAILED;
442 return TDM_ERROR_NONE;
446 tdm_event_loop_source_remove(tdm_event_loop_source *source)
448 tdm_event_loop_source_base *base = (tdm_event_loop_source_base*)source;
450 TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED());
455 wl_event_source_remove(base->wl_source);