thread: support cb for multi-thread communication
[platform/core/uifw/libtdm.git] / src / tdm_display.c
1 /**************************************************************************
2  *
3  * libtdm
4  *
5  * Copyright 2015 Samsung Electronics co., Ltd. All Rights Reserved.
6  *
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>
13  *
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:
21  *
22  * The above copyright notice and this permission notice (including the
23  * next paragraph) shall be included in all copies or substantial portions
24  * of the Software.
25  *
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.
33  *
34 **************************************************************************/
35
36 #ifdef HAVE_CONFIG_H
37 #include "config.h"
38 #endif
39
40 #include "tdm_private.h"
41
42 #define COUNT_MAX   10
43
44 #define DISPLAY_FUNC_ENTRY() \
45         tdm_private_display *private_display; \
46         tdm_error ret = TDM_ERROR_NONE; /* default TDM_ERROR_NONE */\
47         TDM_RETURN_VAL_IF_FAIL(dpy != NULL, TDM_ERROR_INVALID_PARAMETER); \
48         TDM_RETURN_VAL_IF_FAIL(tdm_display_is_valid(dpy), TDM_ERROR_INVALID_PARAMETER); \
49         private_display = (tdm_private_display*)dpy;
50
51 #define DISPLAY_FUNC_ENTRY_ERROR() \
52         tdm_private_display *private_display; \
53         tdm_error ret = TDM_ERROR_NONE; /* default TDM_ERROR_NONE */\
54         TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(dpy != NULL, TDM_ERROR_INVALID_PARAMETER, NULL); \
55         TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(tdm_display_is_valid(dpy), TDM_ERROR_INVALID_PARAMETER, NULL); \
56         private_display = (tdm_private_display*)dpy;
57
58 EXTERN tdm_error
59 tdm_display_get_capabilities(tdm_display *dpy,
60                                                          tdm_display_capability *capabilities)
61 {
62         DISPLAY_FUNC_ENTRY();
63
64         TDM_RETURN_VAL_IF_FAIL(capabilities != NULL, TDM_ERROR_INVALID_PARAMETER);
65
66         _pthread_mutex_lock(&private_display->lock);
67
68         *capabilities = private_display->capabilities;
69
70         _pthread_mutex_unlock(&private_display->lock);
71
72         return ret;
73 }
74
75 EXTERN tdm_error
76 tdm_display_get_pp_capabilities(tdm_display *dpy,
77                                                                 tdm_pp_capability *capabilities)
78 {
79         DISPLAY_FUNC_ENTRY();
80
81         TDM_RETURN_VAL_IF_FAIL(capabilities != NULL, TDM_ERROR_INVALID_PARAMETER);
82
83         _pthread_mutex_lock(&private_display->lock);
84
85         if (!(private_display->capabilities & TDM_DISPLAY_CAPABILITY_PP)) {
86                 /* LCOV_EXCL_START */
87                 TDM_ERR("no pp capability");
88                 _pthread_mutex_unlock(&private_display->lock);
89                 return TDM_ERROR_NO_CAPABILITY;
90                 /* LCOV_EXCL_STOP */
91         }
92
93         *capabilities = private_display->caps_pp.capabilities;
94
95         _pthread_mutex_unlock(&private_display->lock);
96
97         return ret;
98 }
99
100 EXTERN tdm_error
101 tdm_display_get_pp_available_formats(tdm_display *dpy,
102                                                                          const tbm_format **formats, int *count)
103 {
104         DISPLAY_FUNC_ENTRY();
105
106         TDM_RETURN_VAL_IF_FAIL(formats != NULL, TDM_ERROR_INVALID_PARAMETER);
107         TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
108
109         _pthread_mutex_lock(&private_display->lock);
110
111         if (!(private_display->capabilities & TDM_DISPLAY_CAPABILITY_PP)) {
112                 /* LCOV_EXCL_START */
113                 TDM_ERR("no pp capability");
114                 _pthread_mutex_unlock(&private_display->lock);
115                 return TDM_ERROR_NO_CAPABILITY;
116                 /* LCOV_EXCL_STOP */
117         }
118
119         *formats = (const tbm_format *)private_display->caps_pp.formats;
120         *count = private_display->caps_pp.format_count;
121
122         _pthread_mutex_unlock(&private_display->lock);
123
124         return ret;
125 }
126
127 EXTERN tdm_error
128 tdm_display_get_pp_available_size(tdm_display *dpy, int *min_w, int *min_h,
129                                                                   int *max_w, int *max_h, int *preferred_align)
130 {
131         DISPLAY_FUNC_ENTRY();
132
133         _pthread_mutex_lock(&private_display->lock);
134
135         if (!(private_display->capabilities & TDM_DISPLAY_CAPABILITY_PP)) {
136                 /* LCOV_EXCL_START */
137                 TDM_ERR("no pp capability");
138                 _pthread_mutex_unlock(&private_display->lock);
139                 return TDM_ERROR_NO_CAPABILITY;
140                 /* LCOV_EXCL_STOP */
141         }
142
143         if (min_w)
144                 *min_w = TDM_FRONT_VALUE(private_display->caps_pp.min_w);
145         if (min_h)
146                 *min_h = TDM_FRONT_VALUE(private_display->caps_pp.min_h);
147         if (max_w)
148                 *max_w = TDM_FRONT_VALUE(private_display->caps_pp.max_w);
149         if (max_h)
150                 *max_h = TDM_FRONT_VALUE(private_display->caps_pp.max_h);
151         if (preferred_align)
152                 *preferred_align = TDM_FRONT_VALUE(private_display->caps_pp.preferred_align);
153
154         _pthread_mutex_unlock(&private_display->lock);
155
156         return ret;
157 }
158
159 EXTERN tdm_error
160 tdm_display_get_capture_capabilities(tdm_display *dpy,
161                                                                          tdm_capture_capability *capabilities)
162 {
163         DISPLAY_FUNC_ENTRY();
164
165         TDM_RETURN_VAL_IF_FAIL(capabilities != NULL, TDM_ERROR_INVALID_PARAMETER);
166
167         _pthread_mutex_lock(&private_display->lock);
168
169         if (!(private_display->capabilities & TDM_DISPLAY_CAPABILITY_CAPTURE)) {
170                 /* LCOV_EXCL_START */
171                 TDM_ERR("no capture capability");
172                 _pthread_mutex_unlock(&private_display->lock);
173                 return TDM_ERROR_NO_CAPABILITY;
174                 /* LCOV_EXCL_STOP */
175         }
176
177         *capabilities = private_display->caps_capture.capabilities;
178
179         _pthread_mutex_unlock(&private_display->lock);
180
181         return ret;
182 }
183
184 EXTERN tdm_error
185 tdm_display_get_capture_available_formats(tdm_display *dpy,
186                 const tbm_format **formats, int *count)
187 {
188         DISPLAY_FUNC_ENTRY();
189
190         TDM_RETURN_VAL_IF_FAIL(formats != NULL, TDM_ERROR_INVALID_PARAMETER);
191         TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
192
193         _pthread_mutex_lock(&private_display->lock);
194
195         if (!(private_display->capabilities & TDM_DISPLAY_CAPABILITY_CAPTURE)) {
196                 /* LCOV_EXCL_START */
197                 TDM_ERR("no capture capability");
198                 _pthread_mutex_unlock(&private_display->lock);
199                 return TDM_ERROR_NO_CAPABILITY;
200                 /* LCOV_EXCL_STOP */
201         }
202
203         *formats = (const tbm_format *)private_display->caps_capture.formats;
204         *count = private_display->caps_capture.format_count;
205
206         _pthread_mutex_unlock(&private_display->lock);
207
208         return ret;
209 }
210
211 EXTERN tdm_error
212 tdm_display_get_capture_available_size(tdm_display *dpy, int *min_w, int *min_h,
213                                                                            int *max_w, int *max_h, int *preferred_align)
214 {
215         DISPLAY_FUNC_ENTRY();
216
217         _pthread_mutex_lock(&private_display->lock);
218
219         if (!(private_display->capabilities & TDM_DISPLAY_CAPABILITY_CAPTURE)) {
220                 /* LCOV_EXCL_START */
221                 TDM_ERR("no capture capability");
222                 _pthread_mutex_unlock(&private_display->lock);
223                 return TDM_ERROR_NO_CAPABILITY;
224                 /* LCOV_EXCL_STOP */
225         }
226
227         if (min_w)
228                 *min_w = TDM_FRONT_VALUE(private_display->caps_capture.min_w);
229         if (min_h)
230                 *min_h = TDM_FRONT_VALUE(private_display->caps_capture.min_h);
231         if (max_w)
232                 *max_w = TDM_FRONT_VALUE(private_display->caps_capture.max_w);
233         if (max_h)
234                 *max_h = TDM_FRONT_VALUE(private_display->caps_capture.max_h);
235         if (preferred_align)
236                 *preferred_align = TDM_FRONT_VALUE(private_display->caps_capture.preferred_align);
237
238         _pthread_mutex_unlock(&private_display->lock);
239
240         return ret;
241 }
242
243 EXTERN tdm_error
244 tdm_display_get_max_layer_count(tdm_display *dpy, int *max_count)
245 {
246         DISPLAY_FUNC_ENTRY();
247
248         TDM_RETURN_VAL_IF_FAIL(max_count != NULL, TDM_ERROR_INVALID_PARAMETER);
249
250         _pthread_mutex_lock(&private_display->lock);
251
252         *max_count = TDM_FRONT_VALUE(private_display->caps_display.max_layer_count);
253
254         _pthread_mutex_unlock(&private_display->lock);
255
256         return ret;
257 }
258
259 EXTERN tdm_error
260 tdm_display_get_output_count(tdm_display *dpy, int *count)
261 {
262         tdm_private_output *private_output = NULL;
263
264         DISPLAY_FUNC_ENTRY();
265
266         TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
267
268         _pthread_mutex_lock(&private_display->lock);
269
270         *count = 0;
271         LIST_FOR_EACH_ENTRY(private_output, &private_display->output_list, link)
272         (*count)++;
273
274         if (*count == 0) {
275                 /* LCOV_EXCL_START */
276                 _pthread_mutex_unlock(&private_display->lock);
277                 return TDM_ERROR_NONE;
278                 /* LCOV_EXCL_STOP */
279         }
280
281         _pthread_mutex_unlock(&private_display->lock);
282
283         return ret;
284 }
285
286
287 EXTERN tdm_output *
288 tdm_display_get_output(tdm_display *dpy, int index, tdm_error *error)
289 {
290         tdm_private_output *private_output = NULL;
291
292         DISPLAY_FUNC_ENTRY_ERROR();
293
294         _pthread_mutex_lock(&private_display->lock);
295
296         if (error)
297                 *error = TDM_ERROR_NONE;
298
299         LIST_FOR_EACH_ENTRY(private_output, &private_display->output_list, link) {
300                 if (private_output->index == index) {
301                         _pthread_mutex_unlock(&private_display->lock);
302                         return private_output;
303                 }
304         }
305
306         _pthread_mutex_unlock(&private_display->lock);
307
308         return NULL;
309 }
310
311 EXTERN tdm_error
312 tdm_display_get_fd(tdm_display *dpy, int *fd)
313 {
314         DISPLAY_FUNC_ENTRY();
315
316         TDM_RETURN_VAL_IF_FAIL(fd != NULL, TDM_ERROR_INVALID_PARAMETER);
317
318         _pthread_mutex_lock(&private_display->lock);
319
320         if (tdm_thread_is_running())
321                 *fd = tdm_thread_get_fd(private_display->private_loop);
322         else
323                 *fd = tdm_event_loop_get_fd(private_display);
324
325         _pthread_mutex_unlock(&private_display->lock);
326
327         return ret;
328 }
329
330 EXTERN tdm_error
331 tdm_display_handle_events(tdm_display *dpy)
332 {
333         struct pollfd fds;
334         int fd = -1;
335
336         DISPLAY_FUNC_ENTRY();
337
338         ret = tdm_display_get_fd(dpy, &fd);
339         TDM_RETURN_VAL_IF_FAIL(fd >= 0, ret);
340
341         fds.events = POLLIN;
342         fds.fd = fd;
343         fds.revents = 0;
344
345         if (tdm_debug_module & TDM_DEBUG_EVENT)
346                 TDM_INFO("fd(%d) polling in", fd);
347
348         while (poll(&fds, 1, -1) < 0) {
349                 /* LCOV_EXCL_START */
350                 if (errno == EINTR || errno == EAGAIN)  /* normal case */
351                         continue;
352                 else {
353                         TDM_ERR("poll failed: %m");
354                         return TDM_ERROR_OPERATION_FAILED;
355                 }
356                 /* LCOV_EXCL_STOP */
357         }
358
359         if (tdm_debug_module & TDM_DEBUG_EVENT)
360                 TDM_INFO("fd(%d) polling out", fd);
361
362         if (tdm_thread_is_running()) {
363                 _pthread_mutex_lock(&private_display->lock);
364                 ret = tdm_thread_handle_cb(private_display->private_loop);
365                 _pthread_mutex_unlock(&private_display->lock);
366         } else {
367                 ret = tdm_event_loop_dispatch(private_display);
368         }
369
370         return ret;
371 }
372
373 EXTERN tdm_error
374 tdm_display_get_backend_info(tdm_display *dpy, const char **name,
375                                                          const char **vendor, int *major, int *minor)
376 {
377         tdm_backend_module *module_data;
378
379         DISPLAY_FUNC_ENTRY();
380
381         _pthread_mutex_lock(&private_display->lock);
382
383         module_data = private_display->module_data;
384
385         if (name)
386                 *name = module_data->name;
387         if (vendor)
388                 *vendor = module_data->vendor;
389         if (major)
390                 *major = TDM_BACKEND_GET_ABI_MAJOR(module_data->abi_version);
391         if (minor)
392                 *minor = TDM_BACKEND_GET_ABI_MINOR(module_data->abi_version);
393
394         _pthread_mutex_unlock(&private_display->lock);
395
396         return ret;
397 }
398
399 EXTERN tdm_pp *
400 tdm_display_create_pp(tdm_display *dpy, tdm_error *error)
401 {
402         tdm_pp *pp;
403
404         DISPLAY_FUNC_ENTRY_ERROR();
405
406         _pthread_mutex_lock(&private_display->lock);
407
408         pp = (tdm_pp *)tdm_pp_create_internal(private_display, error);
409
410         _pthread_mutex_unlock(&private_display->lock);
411
412         return pp;
413 }