correct email address
[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 <boram1288.park@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 #define BACKEND_FUNC_ENTRY() \
59         tdm_private_module *private_module; \
60         tdm_private_display *private_display; \
61         tdm_error ret = TDM_ERROR_NONE; /* default TDM_ERROR_NONE */\
62         TDM_RETURN_VAL_IF_FAIL(module != NULL, TDM_ERROR_INVALID_PARAMETER); \
63         private_module = (tdm_private_module*)module; \
64         private_display = private_module->private_display;
65
66 EXTERN tdm_error
67 tdm_display_get_capabilities(tdm_display *dpy,
68                                                          tdm_display_capability *capabilities)
69 {
70         tdm_private_module *private_module = NULL;
71
72         DISPLAY_FUNC_ENTRY();
73
74         TDM_RETURN_VAL_IF_FAIL(capabilities != NULL, TDM_ERROR_INVALID_PARAMETER);
75
76         _pthread_mutex_lock(&private_display->lock);
77
78         *capabilities = 0;
79
80         LIST_FOR_EACH_ENTRY(private_module, &private_display->module_list, link) {
81                 *capabilities |= private_module->capabilities;
82         }
83
84         _pthread_mutex_unlock(&private_display->lock);
85
86         return ret;
87 }
88
89 EXTERN tdm_error
90 tdm_display_get_pp_capabilities(tdm_display *dpy,
91                                                                 tdm_pp_capability *capabilities)
92 {
93         tdm_private_module *pp_module;
94
95         DISPLAY_FUNC_ENTRY();
96
97         TDM_RETURN_VAL_IF_FAIL(capabilities != NULL, TDM_ERROR_INVALID_PARAMETER);
98
99         _pthread_mutex_lock(&private_display->lock);
100
101         if (!private_display->pp_module) {
102                 /* LCOV_EXCL_START */
103                 TDM_ERR("no pp capability");
104                 _pthread_mutex_unlock(&private_display->lock);
105                 return TDM_ERROR_NO_CAPABILITY;
106                 /* LCOV_EXCL_STOP */
107         }
108
109         pp_module = private_display->pp_module;
110
111         *capabilities = pp_module->caps_pp.capabilities;
112
113         _pthread_mutex_unlock(&private_display->lock);
114
115         return ret;
116 }
117
118 EXTERN tdm_error
119 tdm_display_get_pp_available_formats(tdm_display *dpy,
120                                                                          const tbm_format **formats, int *count)
121 {
122         tdm_private_module *pp_module;
123
124         DISPLAY_FUNC_ENTRY();
125
126         TDM_RETURN_VAL_IF_FAIL(formats != NULL, TDM_ERROR_INVALID_PARAMETER);
127         TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
128
129         _pthread_mutex_lock(&private_display->lock);
130
131         if (!private_display->pp_module) {
132                 /* LCOV_EXCL_START */
133                 TDM_ERR("no pp capability");
134                 _pthread_mutex_unlock(&private_display->lock);
135                 return TDM_ERROR_NO_CAPABILITY;
136                 /* LCOV_EXCL_STOP */
137         }
138
139         pp_module = private_display->pp_module;
140
141         *formats = (const tbm_format *)pp_module->caps_pp.formats;
142         *count = pp_module->caps_pp.format_count;
143
144         _pthread_mutex_unlock(&private_display->lock);
145
146         return ret;
147 }
148
149 EXTERN tdm_error
150 tdm_display_get_pp_available_size(tdm_display *dpy, int *min_w, int *min_h,
151                                                                   int *max_w, int *max_h, int *preferred_align)
152 {
153         tdm_private_module *pp_module;
154
155         DISPLAY_FUNC_ENTRY();
156
157         _pthread_mutex_lock(&private_display->lock);
158
159         if (!private_display->pp_module) {
160                 /* LCOV_EXCL_START */
161                 TDM_ERR("no pp capability");
162                 _pthread_mutex_unlock(&private_display->lock);
163                 return TDM_ERROR_NO_CAPABILITY;
164                 /* LCOV_EXCL_STOP */
165         }
166
167         pp_module = private_display->pp_module;
168
169         if (min_w)
170                 *min_w = TDM_FRONT_VALUE(pp_module->caps_pp.min_w);
171         if (min_h)
172                 *min_h = TDM_FRONT_VALUE(pp_module->caps_pp.min_h);
173         if (max_w)
174                 *max_w = TDM_FRONT_VALUE(pp_module->caps_pp.max_w);
175         if (max_h)
176                 *max_h = TDM_FRONT_VALUE(pp_module->caps_pp.max_h);
177         if (preferred_align)
178                 *preferred_align = TDM_FRONT_VALUE(pp_module->caps_pp.preferred_align);
179
180         _pthread_mutex_unlock(&private_display->lock);
181
182         return ret;
183 }
184
185 EXTERN tdm_error
186 tdm_display_get_capture_capabilities(tdm_display *dpy,
187                                                                          tdm_capture_capability *capabilities)
188 {
189         tdm_private_module *capture_module;
190
191         DISPLAY_FUNC_ENTRY();
192
193         TDM_RETURN_VAL_IF_FAIL(capabilities != NULL, TDM_ERROR_INVALID_PARAMETER);
194
195         _pthread_mutex_lock(&private_display->lock);
196
197         if (!private_display->capture_module) {
198                 /* LCOV_EXCL_START */
199                 TDM_ERR("no capture capability");
200                 _pthread_mutex_unlock(&private_display->lock);
201                 return TDM_ERROR_NO_CAPABILITY;
202                 /* LCOV_EXCL_STOP */
203         }
204
205         capture_module = private_display->capture_module;
206
207         *capabilities = capture_module->caps_capture.capabilities;
208
209         _pthread_mutex_unlock(&private_display->lock);
210
211         return ret;
212 }
213
214 EXTERN tdm_error
215 tdm_display_get_capture_available_formats(tdm_display *dpy,
216                 const tbm_format **formats, int *count)
217 {
218         tdm_private_module *capture_module;
219
220         DISPLAY_FUNC_ENTRY();
221
222         TDM_RETURN_VAL_IF_FAIL(formats != NULL, TDM_ERROR_INVALID_PARAMETER);
223         TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
224
225         _pthread_mutex_lock(&private_display->lock);
226
227         if (!private_display->capture_module) {
228                 /* LCOV_EXCL_START */
229                 TDM_ERR("no capture capability");
230                 _pthread_mutex_unlock(&private_display->lock);
231                 return TDM_ERROR_NO_CAPABILITY;
232                 /* LCOV_EXCL_STOP */
233         }
234
235         capture_module = private_display->capture_module;
236
237         *formats = (const tbm_format *)capture_module->caps_capture.formats;
238         *count = capture_module->caps_capture.format_count;
239
240         _pthread_mutex_unlock(&private_display->lock);
241
242         return ret;
243 }
244
245 EXTERN tdm_error
246 tdm_display_get_capture_available_size(tdm_display *dpy, int *min_w, int *min_h,
247                                                                            int *max_w, int *max_h, int *preferred_align)
248 {
249         tdm_private_module *capture_module;
250
251         DISPLAY_FUNC_ENTRY();
252
253         _pthread_mutex_lock(&private_display->lock);
254
255         if (!private_display->capture_module) {
256                 /* LCOV_EXCL_START */
257                 TDM_ERR("no capture capability");
258                 _pthread_mutex_unlock(&private_display->lock);
259                 return TDM_ERROR_NO_CAPABILITY;
260                 /* LCOV_EXCL_STOP */
261         }
262
263         capture_module = private_display->capture_module;
264
265         if (min_w)
266                 *min_w = TDM_FRONT_VALUE(capture_module->caps_capture.min_w);
267         if (min_h)
268                 *min_h = TDM_FRONT_VALUE(capture_module->caps_capture.min_h);
269         if (max_w)
270                 *max_w = TDM_FRONT_VALUE(capture_module->caps_capture.max_w);
271         if (max_h)
272                 *max_h = TDM_FRONT_VALUE(capture_module->caps_capture.max_h);
273         if (preferred_align)
274                 *preferred_align = TDM_FRONT_VALUE(capture_module->caps_capture.preferred_align);
275
276         _pthread_mutex_unlock(&private_display->lock);
277
278         return ret;
279 }
280
281 EXTERN tdm_error
282 tdm_display_get_max_layer_count(tdm_display *dpy, int *max_count)
283 {
284         TDM_RETURN_VAL_IF_FAIL(dpy != NULL, TDM_ERROR_INVALID_PARAMETER);
285         TDM_RETURN_VAL_IF_FAIL(max_count != NULL, TDM_ERROR_INVALID_PARAMETER);
286
287         TDM_DEPRECATED(NULL);
288
289         *max_count = -1;
290
291         return TDM_ERROR_NONE;
292 }
293
294 EXTERN tdm_error
295 tdm_display_get_output_count(tdm_display *dpy, int *count)
296 {
297         tdm_private_module *private_module = NULL;
298         tdm_private_output *private_output = NULL;
299
300         DISPLAY_FUNC_ENTRY();
301
302         TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
303
304         _pthread_mutex_lock(&private_display->lock);
305
306         *count = 0;
307         LIST_FOR_EACH_ENTRY(private_module, &private_display->module_list, link) {
308                 LIST_FOR_EACH_ENTRY(private_output, &private_module->output_list, link) {
309                         (*count)++;
310                 }
311         }
312
313         _pthread_mutex_unlock(&private_display->lock);
314
315         return ret;
316 }
317
318
319 EXTERN tdm_output *
320 tdm_display_get_output(tdm_display *dpy, int index, tdm_error *error)
321 {
322         tdm_private_module *private_module = NULL;
323         tdm_private_output *private_output = NULL;
324
325         DISPLAY_FUNC_ENTRY_ERROR();
326
327         _pthread_mutex_lock(&private_display->lock);
328
329         if (error)
330                 *error = TDM_ERROR_NONE;
331
332         LIST_FOR_EACH_ENTRY(private_module, &private_display->module_list, link) {
333                 LIST_FOR_EACH_ENTRY(private_output, &private_module->output_list, link) {
334                         if (private_output->index == index) {
335                                 _pthread_mutex_unlock(&private_display->lock);
336                                 return private_output;
337                         }
338                 }
339         }
340
341         _pthread_mutex_unlock(&private_display->lock);
342
343         return NULL;
344 }
345
346 EXTERN tdm_output *
347 tdm_display_find_output(tdm_display *dpy, const char *name, tdm_error *error)
348 {
349         tdm_private_module *private_module = NULL;
350         tdm_private_output *private_output = NULL;
351
352         DISPLAY_FUNC_ENTRY_ERROR();
353
354         if (!strncasecmp(name, "primary", 7) || !strncasecmp(name, "default", 7)) {
355                 return tdm_display_get_output(dpy, 0, error);
356         }
357
358         _pthread_mutex_lock(&private_display->lock);
359
360         if (error)
361                 *error = TDM_ERROR_NONE;
362
363         LIST_FOR_EACH_ENTRY(private_module, &private_display->module_list, link) {
364                 LIST_FOR_EACH_ENTRY(private_output, &private_module->output_list, link) {
365                         if (strncmp(private_output->caps.model, name, TDM_NAME_LEN))
366                                 continue;
367                         _pthread_mutex_unlock(&private_display->lock);
368                         return private_output;
369                 }
370         }
371
372         _pthread_mutex_unlock(&private_display->lock);
373
374         return NULL;
375 }
376
377 EXTERN tdm_error
378 tdm_display_get_fd(tdm_display *dpy, int *fd)
379 {
380         DISPLAY_FUNC_ENTRY();
381
382         TDM_RETURN_VAL_IF_FAIL(fd != NULL, TDM_ERROR_INVALID_PARAMETER);
383
384         _pthread_mutex_lock(&private_display->lock);
385
386         if (tdm_thread_is_running())
387                 *fd = tdm_thread_get_fd(private_display->private_loop);
388         else
389                 *fd = tdm_event_loop_get_fd(private_display);
390
391         _pthread_mutex_unlock(&private_display->lock);
392
393         return ret;
394 }
395
396 EXTERN tdm_error
397 tdm_display_handle_events(tdm_display *dpy)
398 {
399         struct pollfd fds;
400         int fd = -1;
401
402         DISPLAY_FUNC_ENTRY();
403
404         ret = tdm_display_get_fd(dpy, &fd);
405         TDM_RETURN_VAL_IF_FAIL(fd >= 0, ret);
406
407         fds.events = POLLIN;
408         fds.fd = fd;
409         fds.revents = 0;
410
411         if (tdm_debug_module & TDM_DEBUG_EVENT)
412                 TDM_INFO("fd(%d) polling in", fd);
413
414         while (poll(&fds, 1, -1) < 0) {
415                 /* LCOV_EXCL_START */
416                 if (errno == EINTR || errno == EAGAIN)  /* normal case */
417                         continue;
418                 else {
419                         TDM_ERR("poll failed: %m");
420                         return TDM_ERROR_OPERATION_FAILED;
421                 }
422                 /* LCOV_EXCL_STOP */
423         }
424
425         if (tdm_debug_module & TDM_DEBUG_EVENT)
426                 TDM_INFO("fd(%d) polling out", fd);
427
428         if (tdm_thread_is_running()) {
429                 _pthread_mutex_lock(&private_display->lock);
430                 ret = tdm_thread_handle_cb(private_display->private_loop);
431                 _pthread_mutex_unlock(&private_display->lock);
432         } else {
433                 ret = tdm_event_loop_dispatch(private_display);
434         }
435
436         return ret;
437 }
438
439 EXTERN void
440 tdm_display_flush(tdm_display *dpy)
441 {
442         tdm_private_display *private_display;
443
444         TDM_RETURN_IF_FAIL(dpy != NULL);
445         private_display = (tdm_private_display*)dpy;
446
447         if (tdm_thread_is_running())
448                 return;
449
450         tdm_event_loop_flush(private_display);
451 }
452
453 EXTERN tdm_error
454 tdm_display_get_backend_info(tdm_display *dpy, const char **name,
455                                                          const char **vendor, int *major, int *minor)
456 {
457         tdm_private_module *private_module = NULL;
458         tdm_backend_module *module_data = NULL;
459
460         DISPLAY_FUNC_ENTRY();
461
462         TDM_DEPRECATED("Use tdm_module_get_info");
463
464         _pthread_mutex_lock(&private_display->lock);
465
466         /* use first backend */
467         LIST_FOR_EACH_ENTRY(private_module, &private_display->module_list, link) {
468                 module_data = private_module->module_data;
469                 break;
470         }
471
472         assert(module_data != NULL);
473
474         if (name)
475                 *name = module_data->name;
476         if (vendor)
477                 *vendor = module_data->vendor;
478         if (major)
479                 *major = TDM_BACKEND_GET_ABI_MAJOR(module_data->abi_version);
480         if (minor)
481                 *minor = TDM_BACKEND_GET_ABI_MINOR(module_data->abi_version);
482
483         _pthread_mutex_unlock(&private_display->lock);
484
485         return ret;
486 }
487
488 EXTERN tdm_error
489 tdm_module_get_info(tdm_module *module, const char **name,
490                                         const char **vendor, int *major, int *minor)
491 {
492         tdm_backend_module *module_data;
493
494         BACKEND_FUNC_ENTRY();
495
496         _pthread_mutex_lock(&private_display->lock);
497
498         module_data = private_module->module_data;
499
500         if (name)
501                 *name = module_data->name;
502         if (vendor)
503                 *vendor = module_data->vendor;
504         if (major)
505                 *major = TDM_BACKEND_GET_ABI_MAJOR(module_data->abi_version);
506         if (minor)
507                 *minor = TDM_BACKEND_GET_ABI_MINOR(module_data->abi_version);
508
509         _pthread_mutex_unlock(&private_display->lock);
510
511         return ret;
512 }
513
514 EXTERN tdm_pp *
515 tdm_display_create_pp(tdm_display *dpy, tdm_error *error)
516 {
517         tdm_pp *pp;
518
519         DISPLAY_FUNC_ENTRY_ERROR();
520
521         _pthread_mutex_lock(&private_display->lock);
522
523         pp = (tdm_pp *)tdm_pp_create_internal(private_display->pp_module, error);
524
525         _pthread_mutex_unlock(&private_display->lock);
526
527         return pp;
528 }