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