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(private_display != NULL, TDM_ERROR_OPERATION_FAILED);
76 TDM_RETURN_VAL_IF_FAIL(private_display->private_loop != NULL, TDM_ERROR_OPERATION_FAILED);
78 private_loop = private_display->private_loop;
81 TDM_INFO("backend fd(%d) event happens", private_loop->backend_fd);
83 func_display = &private_display->func_display;
84 if (!func_display->display_handle_events)
85 return TDM_ERROR_NONE;
87 ret = func_display->display_handle_events(private_display->bdata);
93 tdm_event_loop_init(tdm_private_display *private_display)
95 tdm_private_loop *private_loop;
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;
116 private_loop->wl_loop = wl_display_get_event_loop(private_loop->wl_display);
117 if (!private_loop->wl_loop) {
118 TDM_ERR("no event loop");
119 wl_display_destroy(private_loop->wl_display);
121 return TDM_ERROR_OPERATION_FAILED;
124 ret = tdm_server_init(private_loop);
125 if (ret != TDM_ERROR_NONE) {
126 TDM_ERR("server init failed");
127 wl_display_destroy(private_loop->wl_display);
129 return TDM_ERROR_OPERATION_FAILED;
132 private_loop->dpy = private_display;
133 private_display->private_loop = private_loop;
135 ret = tdm_thread_init(private_loop);
136 if (ret != TDM_ERROR_NONE) {
137 TDM_ERR("thread init failed");
138 tdm_server_deinit(private_loop);
139 wl_display_destroy(private_loop->wl_display);
141 return TDM_ERROR_OPERATION_FAILED;
144 TDM_INFO("event loop fd(%d)", wl_event_loop_get_fd(private_loop->wl_loop));
146 return TDM_ERROR_NONE;
150 tdm_event_loop_deinit(tdm_private_display *private_display)
152 if (!private_display->private_loop)
155 tdm_thread_deinit(private_display->private_loop);
156 tdm_server_deinit(private_display->private_loop);
158 if (private_display->private_loop->backend_source)
159 tdm_event_loop_source_remove(private_display->private_loop->backend_source);
161 if (private_display->private_loop->wl_display)
162 wl_display_destroy(private_display->private_loop->wl_display);
164 free(private_display->private_loop);
165 private_display->private_loop = NULL;
169 tdm_event_loop_create_backend_source(tdm_private_display *private_display)
171 tdm_private_loop *private_loop = private_display->private_loop;
172 tdm_func_display *func_display;
176 TDM_RETURN_IF_FAIL(private_loop != NULL);
178 func_display = &private_display->func_display;
179 if (!func_display->display_get_fd) {
180 TDM_INFO("TDM backend module won't offer a display fd");
184 ret = func_display->display_get_fd(private_display->bdata, &fd);
186 TDM_WRN("TDM backend module returns fd(%d)", fd);
190 if (!func_display->display_handle_events) {
191 TDM_ERR("no display_handle_events function");
195 private_loop->backend_source =
196 tdm_event_loop_add_fd_handler(private_display, fd,
197 TDM_EVENT_LOOP_READABLE,
198 _tdm_event_loop_main_fd_handler,
199 private_display, &ret);
200 if (!private_loop->backend_source) {
201 TDM_ERR("no backend fd(%d) source", fd);
205 private_loop->backend_fd = fd;
207 TDM_INFO("backend fd(%d) source created", private_loop->backend_fd);
211 tdm_event_loop_get_fd(tdm_private_display *private_display)
213 tdm_private_loop *private_loop = private_display->private_loop;
215 TDM_RETURN_VAL_IF_FAIL(private_loop->wl_loop != NULL, -1);
217 return wl_event_loop_get_fd(private_loop->wl_loop);
221 tdm_event_loop_dispatch(tdm_private_display *private_display)
223 tdm_private_loop *private_loop = private_display->private_loop;
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 /* Don't set timeout to -1. It can make deadblock by two mutex locks.
231 * If need to set -1, use poll() and call tdm_event_loop_dispatch() after
234 if (wl_event_loop_dispatch(private_loop->wl_loop, 0) < 0)
235 TDM_ERR("dispatch failed");
237 return TDM_ERROR_NONE;
242 tdm_event_loop_flush(tdm_private_display *private_display)
244 tdm_private_loop *private_loop = private_display->private_loop;
246 TDM_RETURN_IF_FAIL(private_loop->wl_display != NULL);
248 wl_display_flush_clients(private_loop->wl_display);
252 _tdm_event_loop_fd_func(int fd, uint32_t wl_mask, void *data)
254 tdm_event_loop_source_fd *fd_source = (tdm_event_loop_source_fd*)data;
255 tdm_event_loop_mask mask = 0;
257 TDM_RETURN_VAL_IF_FAIL(fd_source, 1);
258 TDM_RETURN_VAL_IF_FAIL(fd_source->func, 1);
260 if (wl_mask & WL_EVENT_READABLE)
261 mask |= TDM_EVENT_LOOP_READABLE;
262 if (wl_mask & WL_EVENT_WRITABLE)
263 mask |= TDM_EVENT_LOOP_WRITABLE;
264 if (wl_mask & WL_EVENT_HANGUP)
265 mask |= TDM_EVENT_LOOP_HANGUP;
266 if (wl_mask & WL_EVENT_ERROR)
267 mask |= TDM_EVENT_LOOP_ERROR;
269 fd_source->func(fd, mask, fd_source->user_data);
274 EXTERN tdm_event_loop_source*
275 tdm_event_loop_add_fd_handler(tdm_display *dpy, int fd, tdm_event_loop_mask mask,
276 tdm_event_loop_fd_handler func, void *user_data,
279 tdm_private_display *private_display;
280 tdm_private_loop *private_loop;
281 tdm_event_loop_source_fd *fd_source;
282 uint32_t wl_mask = 0;
285 TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(dpy, TDM_ERROR_INVALID_PARAMETER, NULL);
286 TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(fd >= 0, TDM_ERROR_INVALID_PARAMETER, NULL);
287 TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(func, TDM_ERROR_INVALID_PARAMETER, NULL);
289 private_display = (tdm_private_display*)dpy;
290 private_loop = private_display->private_loop;
291 TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(private_loop, TDM_ERROR_INVALID_PARAMETER, NULL);
292 TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(private_loop->wl_loop, TDM_ERROR_INVALID_PARAMETER, NULL);
294 fd_source = calloc(1, sizeof(tdm_event_loop_source_fd));
295 TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(fd_source, TDM_ERROR_OUT_OF_MEMORY, NULL);
297 if (mask & TDM_EVENT_LOOP_READABLE)
298 wl_mask |= WL_EVENT_READABLE;
299 if (mask & TDM_EVENT_LOOP_WRITABLE)
300 wl_mask |= WL_EVENT_WRITABLE;
302 fd_source->base.wl_source =
303 wl_event_loop_add_fd(private_loop->wl_loop,
304 fd, wl_mask, _tdm_event_loop_fd_func, fd_source);
305 if (!fd_source->base.wl_source) {
307 *error = TDM_ERROR_OUT_OF_MEMORY;
312 fd_source->private_display = private_display;
313 fd_source->func = func;
314 fd_source->user_data = user_data;
317 *error = TDM_ERROR_NONE;
319 return (tdm_event_loop_source*)fd_source;
323 tdm_event_loop_source_fd_update(tdm_event_loop_source *source, tdm_event_loop_mask mask)
325 tdm_event_loop_source_fd *fd_source = source;
326 uint32_t wl_mask = 0;
328 TDM_RETURN_VAL_IF_FAIL(fd_source, TDM_ERROR_INVALID_PARAMETER);
330 if (mask & TDM_EVENT_LOOP_READABLE)
331 wl_mask |= WL_EVENT_READABLE;
332 if (mask & TDM_EVENT_LOOP_WRITABLE)
333 wl_mask |= WL_EVENT_WRITABLE;
335 if (wl_event_source_fd_update(fd_source->base.wl_source, wl_mask) < 0) {
336 TDM_ERR("source update failed: %m");
337 return TDM_ERROR_OPERATION_FAILED;
340 return TDM_ERROR_NONE;
344 _tdm_event_loop_timer_func(void *data)
346 tdm_event_loop_source_timer *timer_source = (tdm_event_loop_source_timer*)data;
348 TDM_RETURN_VAL_IF_FAIL(timer_source, 1);
349 TDM_RETURN_VAL_IF_FAIL(timer_source->func, 1);
351 timer_source->func(timer_source->user_data);
356 EXTERN tdm_event_loop_source*
357 tdm_event_loop_add_timer_handler(tdm_display *dpy, tdm_event_loop_timer_handler func,
358 void *user_data, tdm_error *error)
360 tdm_private_display *private_display;
361 tdm_private_loop *private_loop;
362 tdm_event_loop_source_timer *timer_source;
365 TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(dpy, TDM_ERROR_INVALID_PARAMETER, NULL);
366 TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(func, TDM_ERROR_INVALID_PARAMETER, NULL);
368 private_display = (tdm_private_display*)dpy;
369 private_loop = private_display->private_loop;
370 TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(private_loop, TDM_ERROR_INVALID_PARAMETER, NULL);
371 TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(private_loop->wl_loop, TDM_ERROR_INVALID_PARAMETER, NULL);
373 timer_source = calloc(1, sizeof(tdm_event_loop_source_timer));
374 TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(timer_source, TDM_ERROR_OUT_OF_MEMORY, NULL);
376 timer_source->base.wl_source =
377 wl_event_loop_add_timer(private_loop->wl_loop,
378 _tdm_event_loop_timer_func, timer_source);
379 if (!timer_source->base.wl_source) {
381 *error = TDM_ERROR_OUT_OF_MEMORY;
386 timer_source->private_display = private_display;
387 timer_source->func = func;
388 timer_source->user_data = user_data;
391 *error = TDM_ERROR_NONE;
393 return (tdm_event_loop_source*)timer_source;
397 tdm_event_loop_source_timer_update(tdm_event_loop_source *source, int ms_delay)
399 tdm_event_loop_source_timer *timer_source = source;
401 TDM_RETURN_VAL_IF_FAIL(timer_source, TDM_ERROR_INVALID_PARAMETER);
403 if (wl_event_source_timer_update(timer_source->base.wl_source, ms_delay) < 0) {
404 TDM_ERR("source update failed: %m");
405 return TDM_ERROR_OPERATION_FAILED;
408 return TDM_ERROR_NONE;
412 tdm_event_loop_source_remove(tdm_event_loop_source *source)
414 tdm_event_loop_source_base *base = (tdm_event_loop_source_base*)source;
419 wl_event_source_remove(base->wl_source);