add verification for tdm_display
[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.h"
41 #include "tdm_backend.h"
42 #include "tdm_private.h"
43 #include "tdm_helper.h"
44
45 #define COUNT_MAX   10
46
47 #define DISPLAY_FUNC_ENTRY() \
48         tdm_private_display *private_display; \
49         tdm_error ret = TDM_ERROR_NONE; /* default TDM_ERROR_NONE */\
50         TDM_RETURN_VAL_IF_FAIL(dpy != NULL, TDM_ERROR_INVALID_PARAMETER); \
51         TDM_RETURN_VAL_IF_FAIL(tdm_display_is_valide(dpy), TDM_ERROR_INVALID_PARAMETER); \
52         private_display = (tdm_private_display*)dpy;
53
54 #define DISPLAY_FUNC_ENTRY_ERROR() \
55         tdm_private_display *private_display; \
56         tdm_error ret = TDM_ERROR_NONE; /* default TDM_ERROR_NONE */\
57         TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(dpy != NULL, TDM_ERROR_INVALID_PARAMETER, NULL); \
58         TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(tdm_display_is_valide(dpy), TDM_ERROR_INVALID_PARAMETER, NULL); \
59         private_display = (tdm_private_display*)dpy;
60
61 EXTERN tdm_error
62 tdm_display_get_capabilities(tdm_display *dpy,
63                                                          tdm_display_capability *capabilities)
64 {
65         DISPLAY_FUNC_ENTRY();
66
67         TDM_RETURN_VAL_IF_FAIL(capabilities != NULL, TDM_ERROR_INVALID_PARAMETER);
68
69         _pthread_mutex_lock(&private_display->lock);
70
71         *capabilities = private_display->capabilities;
72
73         _pthread_mutex_unlock(&private_display->lock);
74
75         return ret;
76 }
77
78 EXTERN tdm_error
79 tdm_display_get_pp_capabilities(tdm_display *dpy,
80                                                                 tdm_pp_capability *capabilities)
81 {
82         DISPLAY_FUNC_ENTRY();
83
84         TDM_RETURN_VAL_IF_FAIL(capabilities != NULL, TDM_ERROR_INVALID_PARAMETER);
85
86         _pthread_mutex_lock(&private_display->lock);
87
88         if (!(private_display->capabilities & TDM_DISPLAY_CAPABILITY_PP)) {
89                 /* LCOV_EXCL_START */
90                 TDM_ERR("no pp capability");
91                 _pthread_mutex_unlock(&private_display->lock);
92                 return TDM_ERROR_NO_CAPABILITY;
93                 /* LCOV_EXCL_STOP */
94         }
95
96         *capabilities = private_display->caps_pp.capabilities;
97
98         _pthread_mutex_unlock(&private_display->lock);
99
100         return ret;
101 }
102
103 EXTERN tdm_error
104 tdm_display_get_pp_available_formats(tdm_display *dpy,
105                                                                          const tbm_format **formats, int *count)
106 {
107         DISPLAY_FUNC_ENTRY();
108
109         TDM_RETURN_VAL_IF_FAIL(formats != NULL, TDM_ERROR_INVALID_PARAMETER);
110         TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
111
112         _pthread_mutex_lock(&private_display->lock);
113
114         if (!(private_display->capabilities & TDM_DISPLAY_CAPABILITY_PP)) {
115                 /* LCOV_EXCL_START */
116                 TDM_ERR("no pp capability");
117                 _pthread_mutex_unlock(&private_display->lock);
118                 return TDM_ERROR_NO_CAPABILITY;
119                 /* LCOV_EXCL_STOP */
120         }
121
122         *formats = (const tbm_format *)private_display->caps_pp.formats;
123         *count = private_display->caps_pp.format_count;
124
125         _pthread_mutex_unlock(&private_display->lock);
126
127         return ret;
128 }
129
130 EXTERN tdm_error
131 tdm_display_get_pp_available_size(tdm_display *dpy, int *min_w, int *min_h,
132                                                                   int *max_w, int *max_h, int *preferred_align)
133 {
134         DISPLAY_FUNC_ENTRY();
135
136         _pthread_mutex_lock(&private_display->lock);
137
138         if (!(private_display->capabilities & TDM_DISPLAY_CAPABILITY_PP)) {
139                 /* LCOV_EXCL_START */
140                 TDM_ERR("no pp capability");
141                 _pthread_mutex_unlock(&private_display->lock);
142                 return TDM_ERROR_NO_CAPABILITY;
143                 /* LCOV_EXCL_STOP */
144         }
145
146         if (min_w)
147                 *min_w = TDM_FRONT_VALUE(private_display->caps_pp.min_w);
148         if (min_h)
149                 *min_h = TDM_FRONT_VALUE(private_display->caps_pp.min_h);
150         if (max_w)
151                 *max_w = TDM_FRONT_VALUE(private_display->caps_pp.max_w);
152         if (max_h)
153                 *max_h = TDM_FRONT_VALUE(private_display->caps_pp.max_h);
154         if (preferred_align)
155                 *preferred_align = TDM_FRONT_VALUE(private_display->caps_pp.preferred_align);
156
157         _pthread_mutex_unlock(&private_display->lock);
158
159         return ret;
160 }
161
162 EXTERN tdm_error
163 tdm_display_get_capture_capabilities(tdm_display *dpy,
164                                                                          tdm_capture_capability *capabilities)
165 {
166         DISPLAY_FUNC_ENTRY();
167
168         TDM_RETURN_VAL_IF_FAIL(capabilities != NULL, TDM_ERROR_INVALID_PARAMETER);
169
170         _pthread_mutex_lock(&private_display->lock);
171
172         if (!(private_display->capabilities & TDM_DISPLAY_CAPABILITY_CAPTURE)) {
173                 /* LCOV_EXCL_START */
174                 TDM_ERR("no capture capability");
175                 _pthread_mutex_unlock(&private_display->lock);
176                 return TDM_ERROR_NO_CAPABILITY;
177                 /* LCOV_EXCL_STOP */
178         }
179
180         *capabilities = private_display->caps_capture.capabilities;
181
182         _pthread_mutex_unlock(&private_display->lock);
183
184         return ret;
185 }
186
187 EXTERN tdm_error
188 tdm_display_get_catpure_available_formats(tdm_display *dpy,
189                 const tbm_format **formats, int *count)
190 {
191         DISPLAY_FUNC_ENTRY();
192
193         TDM_RETURN_VAL_IF_FAIL(formats != NULL, TDM_ERROR_INVALID_PARAMETER);
194         TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
195
196         _pthread_mutex_lock(&private_display->lock);
197
198         if (!(private_display->capabilities & TDM_DISPLAY_CAPABILITY_CAPTURE)) {
199                 /* LCOV_EXCL_START */
200                 TDM_ERR("no capture capability");
201                 _pthread_mutex_unlock(&private_display->lock);
202                 return TDM_ERROR_NO_CAPABILITY;
203                 /* LCOV_EXCL_STOP */
204         }
205
206         *formats = (const tbm_format *)private_display->caps_capture.formats;
207         *count = private_display->caps_capture.format_count;
208
209         _pthread_mutex_unlock(&private_display->lock);
210
211         return ret;
212 }
213
214 EXTERN tdm_error
215 tdm_display_get_capture_available_size(tdm_display *dpy, int *min_w, int *min_h,
216                                                                            int *max_w, int *max_h, int *preferred_align)
217 {
218         DISPLAY_FUNC_ENTRY();
219
220         _pthread_mutex_lock(&private_display->lock);
221
222         if (!(private_display->capabilities & TDM_DISPLAY_CAPABILITY_CAPTURE)) {
223                 /* LCOV_EXCL_START */
224                 TDM_ERR("no capture capability");
225                 _pthread_mutex_unlock(&private_display->lock);
226                 return TDM_ERROR_NO_CAPABILITY;
227                 /* LCOV_EXCL_STOP */
228         }
229
230         if (min_w)
231                 *min_w = TDM_FRONT_VALUE(private_display->caps_capture.min_w);
232         if (min_h)
233                 *min_h = TDM_FRONT_VALUE(private_display->caps_capture.min_h);
234         if (max_w)
235                 *max_w = TDM_FRONT_VALUE(private_display->caps_capture.max_w);
236         if (max_h)
237                 *max_h = TDM_FRONT_VALUE(private_display->caps_capture.max_h);
238         if (preferred_align)
239                 *preferred_align = TDM_FRONT_VALUE(private_display->caps_capture.preferred_align);
240
241         _pthread_mutex_unlock(&private_display->lock);
242
243         return ret;
244 }
245
246 EXTERN tdm_error
247 tdm_display_get_max_layer_count(tdm_display *dpy, int *max_count)
248 {
249         DISPLAY_FUNC_ENTRY();
250
251         TDM_RETURN_VAL_IF_FAIL(max_count != NULL, TDM_ERROR_INVALID_PARAMETER);
252
253         _pthread_mutex_lock(&private_display->lock);
254
255         *max_count = TDM_FRONT_VALUE(private_display->caps_display.max_layer_count);
256
257         _pthread_mutex_unlock(&private_display->lock);
258
259         return ret;
260 }
261
262 EXTERN tdm_error
263 tdm_display_get_output_count(tdm_display *dpy, int *count)
264 {
265         tdm_private_output *private_output = NULL;
266
267         DISPLAY_FUNC_ENTRY();
268
269         TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
270
271         _pthread_mutex_lock(&private_display->lock);
272
273         *count = 0;
274         LIST_FOR_EACH_ENTRY(private_output, &private_display->output_list, link)
275         (*count)++;
276
277         if (*count == 0) {
278                 /* LCOV_EXCL_START */
279                 _pthread_mutex_unlock(&private_display->lock);
280                 return TDM_ERROR_NONE;
281                 /* LCOV_EXCL_STOP */
282         }
283
284         _pthread_mutex_unlock(&private_display->lock);
285
286         return ret;
287 }
288
289
290 EXTERN tdm_output *
291 tdm_display_get_output(tdm_display *dpy, int index, tdm_error *error)
292 {
293         tdm_private_output *private_output = NULL;
294
295         DISPLAY_FUNC_ENTRY_ERROR();
296
297         _pthread_mutex_lock(&private_display->lock);
298
299         if (error)
300                 *error = TDM_ERROR_NONE;
301
302         LIST_FOR_EACH_ENTRY(private_output, &private_display->output_list, link) {
303                 if (private_output->index == index) {
304                         _pthread_mutex_unlock(&private_display->lock);
305                         return private_output;
306                 }
307         }
308
309         _pthread_mutex_unlock(&private_display->lock);
310
311         return NULL;
312 }
313
314 EXTERN tdm_error
315 tdm_display_get_fd(tdm_display *dpy, int *fd)
316 {
317         DISPLAY_FUNC_ENTRY();
318
319         TDM_RETURN_VAL_IF_FAIL(fd != NULL, TDM_ERROR_INVALID_PARAMETER);
320
321         _pthread_mutex_lock(&private_display->lock);
322
323         if (tdm_thread_is_running())
324                 *fd = tdm_thread_get_fd(private_display->private_loop);
325         else
326                 *fd = tdm_event_loop_get_fd(private_display);
327
328         _pthread_mutex_unlock(&private_display->lock);
329
330         return ret;
331 }
332
333 EXTERN tdm_error
334 tdm_display_handle_events(tdm_display *dpy)
335 {
336         struct pollfd fds;
337         int fd = -1;
338
339         DISPLAY_FUNC_ENTRY();
340
341         ret = tdm_display_get_fd(dpy, &fd);
342         TDM_RETURN_VAL_IF_FAIL(fd >= 0, ret);
343
344         fds.events = POLLIN;
345         fds.fd = fd;
346         fds.revents = 0;
347
348         if (tdm_debug_module & TDM_DEBUG_THREAD)
349                 TDM_INFO("fd(%d) polling in", fd);
350
351         while (poll(&fds, 1, -1) < 0) {
352                 /* LCOV_EXCL_START */
353                 if (errno == EINTR || errno == EAGAIN)  /* normal case */
354                         continue;
355                 else {
356                         TDM_ERR("poll failed: %m");
357                         return TDM_ERROR_OPERATION_FAILED;
358                 }
359                 /* LCOV_EXCL_STOP */
360         }
361
362         if (tdm_debug_module & TDM_DEBUG_THREAD)
363                 TDM_INFO("fd(%d) polling out", fd);
364
365         if (tdm_thread_is_running())
366                 ret = tdm_thread_handle_cb(private_display->private_loop);
367         else
368                 ret = tdm_event_loop_dispatch(private_display);
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 }