add doxygen document
[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
44 #define COUNT_MAX   10
45
46 #define DISPLAY_FUNC_ENTRY() \
47     tdm_private_display *private_display; \
48     tdm_error ret = TDM_ERROR_NONE; /* default TDM_ERROR_NONE */\
49     TDM_RETURN_VAL_IF_FAIL(dpy != NULL, TDM_ERROR_INVALID_PARAMETER); \
50     private_display = (tdm_private_display*)dpy;
51
52 #define DISPLAY_FUNC_ENTRY_ERROR() \
53     tdm_private_display *private_display; \
54     tdm_error ret = TDM_ERROR_NONE; /* default TDM_ERROR_NONE */\
55     TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(dpy != NULL, TDM_ERROR_INVALID_PARAMETER, NULL); \
56     private_display = (tdm_private_display*)dpy;
57
58 #define OUTPUT_FUNC_ENTRY() \
59     tdm_private_display *private_display; \
60     tdm_private_output *private_output; \
61     tdm_error ret = TDM_ERROR_NONE; /* default TDM_ERROR_NONE */\
62     TDM_RETURN_VAL_IF_FAIL(output != NULL, TDM_ERROR_INVALID_PARAMETER); \
63     private_output = (tdm_private_output*)output; \
64     private_display = private_output->private_display
65
66 #define OUTPUT_FUNC_ENTRY_ERROR() \
67     tdm_private_display *private_display; \
68     tdm_private_output *private_output; \
69     tdm_error ret = TDM_ERROR_NONE; /* default TDM_ERROR_NONE */\
70     TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(output != NULL, TDM_ERROR_INVALID_PARAMETER, NULL); \
71     private_output = (tdm_private_output*)output; \
72     private_display = private_output->private_display
73
74 #define LAYER_FUNC_ENTRY() \
75     tdm_private_display *private_display; \
76     tdm_private_output *private_output; \
77     tdm_private_layer *private_layer; \
78     tdm_error ret = TDM_ERROR_NONE; /* default TDM_ERROR_NONE */\
79     TDM_RETURN_VAL_IF_FAIL(layer != NULL, TDM_ERROR_INVALID_PARAMETER); \
80     private_layer = (tdm_private_layer*)layer; \
81     private_output = private_layer->private_output; \
82     private_display = private_output->private_display
83
84 #define LAYER_FUNC_ENTRY_ERROR() \
85     tdm_private_display *private_display; \
86     tdm_private_output *private_output; \
87     tdm_private_layer *private_layer; \
88     tdm_error ret = TDM_ERROR_NONE; /* default TDM_ERROR_NONE */\
89     TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(layer != NULL, TDM_ERROR_INVALID_PARAMETER, NULL); \
90     private_layer = (tdm_private_layer*)layer; \
91     private_output = private_layer->private_output; \
92     private_display = private_output->private_display
93
94 EXTERN tdm_error
95 tdm_display_get_capabilities(tdm_display *dpy, tdm_display_capability *capabilities)
96 {
97     DISPLAY_FUNC_ENTRY();
98
99     TDM_RETURN_VAL_IF_FAIL(capabilities != NULL, TDM_ERROR_INVALID_PARAMETER);
100
101     pthread_mutex_lock(&private_display->lock);
102
103     *capabilities = private_display->capabilities;
104
105     pthread_mutex_unlock(&private_display->lock);
106
107     return ret;
108 }
109
110 EXTERN tdm_error
111 tdm_display_get_pp_capabilities(tdm_display *dpy, tdm_pp_capability *capabilities)
112 {
113     DISPLAY_FUNC_ENTRY();
114
115     TDM_RETURN_VAL_IF_FAIL(capabilities != NULL, TDM_ERROR_INVALID_PARAMETER);
116
117     pthread_mutex_lock(&private_display->lock);
118
119     if (!(private_display->capabilities & TDM_DISPLAY_CAPABILITY_PP))
120     {
121         TDM_ERR("no pp capability");
122         pthread_mutex_unlock(&private_display->lock);
123         return TDM_ERROR_NO_CAPABILITY;
124     }
125
126     *capabilities = private_display->caps_pp.capabilities;
127
128     pthread_mutex_unlock(&private_display->lock);
129
130     return ret;
131 }
132
133 EXTERN tdm_error
134 tdm_display_get_pp_available_formats(tdm_display *dpy, const tbm_format **formats, int *count)
135 {
136     DISPLAY_FUNC_ENTRY();
137
138     TDM_RETURN_VAL_IF_FAIL(formats != NULL, TDM_ERROR_INVALID_PARAMETER);
139     TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
140
141     pthread_mutex_lock(&private_display->lock);
142
143     if (!(private_display->capabilities & TDM_DISPLAY_CAPABILITY_PP))
144     {
145         TDM_ERR("no pp capability");
146         pthread_mutex_unlock(&private_display->lock);
147         return TDM_ERROR_NO_CAPABILITY;
148     }
149
150     *formats = (const tbm_format*)private_display->caps_pp.formats;
151     *count = private_display->caps_pp.format_count;
152
153     pthread_mutex_unlock(&private_display->lock);
154
155     return ret;
156 }
157
158 EXTERN tdm_error
159 tdm_display_get_pp_available_size(tdm_display *dpy, int *min_w, int *min_h,
160                                   int *max_w, int *max_h, int *preferred_align)
161 {
162     DISPLAY_FUNC_ENTRY();
163
164     pthread_mutex_lock(&private_display->lock);
165
166     if (!(private_display->capabilities & TDM_DISPLAY_CAPABILITY_PP))
167     {
168         TDM_ERR("no pp capability");
169         pthread_mutex_unlock(&private_display->lock);
170         return TDM_ERROR_NO_CAPABILITY;
171     }
172
173     if (min_w)
174         *min_w = private_display->caps_pp.min_w;
175     if (min_h)
176         *min_h = private_display->caps_pp.min_h;
177     if (max_w)
178         *max_w = private_display->caps_pp.max_w;
179     if (max_h)
180         *max_h = private_display->caps_pp.max_h;
181     if (preferred_align)
182         *preferred_align = private_display->caps_pp.preferred_align;
183
184     pthread_mutex_unlock(&private_display->lock);
185
186     return ret;
187 }
188
189 EXTERN tdm_error
190 tdm_display_get_capture_capabilities(tdm_display *dpy, tdm_capture_capability *capabilities)
191 {
192     DISPLAY_FUNC_ENTRY();
193
194     TDM_RETURN_VAL_IF_FAIL(capabilities != NULL, TDM_ERROR_INVALID_PARAMETER);
195
196     pthread_mutex_lock(&private_display->lock);
197
198     if (!(private_display->capabilities & TDM_DISPLAY_CAPABILITY_CAPTURE))
199     {
200         TDM_ERR("no capture capability");
201         pthread_mutex_unlock(&private_display->lock);
202         return TDM_ERROR_NO_CAPABILITY;
203     }
204
205     *capabilities = private_display->caps_capture.capabilities;
206
207     pthread_mutex_unlock(&private_display->lock);
208
209     return ret;
210 }
211
212 EXTERN tdm_error
213 tdm_display_get_catpure_available_formats(tdm_display *dpy, const tbm_format **formats, int *count)
214 {
215     DISPLAY_FUNC_ENTRY();
216
217     TDM_RETURN_VAL_IF_FAIL(formats != NULL, TDM_ERROR_INVALID_PARAMETER);
218     TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
219
220     pthread_mutex_lock(&private_display->lock);
221
222     if (!(private_display->capabilities & TDM_DISPLAY_CAPABILITY_CAPTURE))
223     {
224         TDM_ERR("no capture capability");
225         pthread_mutex_unlock(&private_display->lock);
226         return TDM_ERROR_NO_CAPABILITY;
227     }
228
229     *formats = (const tbm_format*)private_display->caps_capture.formats;
230     *count = private_display->caps_capture.format_count;
231
232     pthread_mutex_unlock(&private_display->lock);
233
234     return ret;
235 }
236
237 EXTERN tdm_error
238 tdm_display_get_output_count(tdm_display *dpy, int *count)
239 {
240     tdm_private_output *private_output = NULL;
241
242     DISPLAY_FUNC_ENTRY();
243
244     TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
245
246     pthread_mutex_lock(&private_display->lock);
247
248     *count = 0;
249     LIST_FOR_EACH_ENTRY(private_output, &private_display->output_list, link)
250         (*count)++;
251
252     if (*count == 0)
253     {
254         pthread_mutex_unlock(&private_display->lock);
255         return TDM_ERROR_NONE;
256     }
257
258     pthread_mutex_unlock(&private_display->lock);
259
260     return ret;
261 }
262
263
264 EXTERN tdm_output*
265 tdm_display_get_output(tdm_display *dpy, int index, tdm_error *error)
266 {
267     tdm_private_output *private_output = NULL;
268     int i = 0;
269
270     DISPLAY_FUNC_ENTRY_ERROR();
271
272     pthread_mutex_lock(&private_display->lock);
273
274     if (error)
275         *error = TDM_ERROR_NONE;
276
277     i = 0;
278     LIST_FOR_EACH_ENTRY(private_output, &private_display->output_list, link)
279     {
280         if (i == index)
281         {
282             pthread_mutex_unlock(&private_display->lock);
283             return private_output;
284         }
285         i++;
286     }
287
288     pthread_mutex_unlock(&private_display->lock);
289
290     return NULL;
291 }
292
293 EXTERN tdm_error
294 tdm_display_get_fd(tdm_display *dpy, int *fd)
295 {
296     tdm_func_display *func_display;
297     DISPLAY_FUNC_ENTRY();
298
299     TDM_RETURN_VAL_IF_FAIL(fd != NULL, TDM_ERROR_INVALID_PARAMETER);
300
301     pthread_mutex_lock(&private_display->lock);
302
303     func_display = &private_display->func_display;
304
305     if (!func_display->display_get_fd)
306     {
307         pthread_mutex_unlock(&private_display->lock);
308         return TDM_ERROR_NONE;
309     }
310
311     ret = func_display->display_get_fd(private_display->bdata, fd);
312
313     pthread_mutex_unlock(&private_display->lock);
314
315     return ret;
316 }
317
318 EXTERN tdm_error
319 tdm_display_handle_events(tdm_display *dpy)
320 {
321     tdm_func_display *func_display;
322     DISPLAY_FUNC_ENTRY();
323
324     pthread_mutex_lock(&private_display->lock);
325
326     func_display = &private_display->func_display;
327
328     if (!func_display->display_handle_events)
329     {
330         pthread_mutex_unlock(&private_display->lock);
331         return TDM_ERROR_NONE;
332     }
333
334     ret = func_display->display_handle_events(private_display->bdata);
335
336     pthread_mutex_unlock(&private_display->lock);
337
338     return ret;
339 }
340
341 EXTERN tdm_pp*
342 tdm_display_create_pp(tdm_display *dpy, tdm_error *error)
343 {
344     tdm_pp *pp;
345
346     DISPLAY_FUNC_ENTRY_ERROR();
347
348     pthread_mutex_lock(&private_display->lock);
349
350     pp = (tdm_pp*)tdm_pp_create_internal(private_display, error);
351
352     pthread_mutex_unlock(&private_display->lock);
353
354     return pp;
355 }
356
357 EXTERN tdm_error
358 tdm_output_get_conn_status(tdm_output *output, tdm_output_conn_status *status)
359 {
360     OUTPUT_FUNC_ENTRY();
361
362     TDM_RETURN_VAL_IF_FAIL(status != NULL, TDM_ERROR_INVALID_PARAMETER);
363
364     pthread_mutex_lock(&private_display->lock);
365
366     *status = private_output->caps.status;
367
368     pthread_mutex_unlock(&private_display->lock);
369
370     return ret;
371 }
372
373 EXTERN tdm_error
374 tdm_output_get_output_type(tdm_output *output, tdm_output_type *type)
375 {
376     OUTPUT_FUNC_ENTRY();
377
378     TDM_RETURN_VAL_IF_FAIL(type != NULL, TDM_ERROR_INVALID_PARAMETER);
379
380     pthread_mutex_lock(&private_display->lock);
381
382     *type = private_output->caps.type;
383
384     pthread_mutex_unlock(&private_display->lock);
385
386     return ret;
387 }
388
389 EXTERN tdm_error
390 tdm_output_get_layer_count(tdm_output *output, int *count)
391 {
392     tdm_private_layer *private_layer = NULL;
393
394     OUTPUT_FUNC_ENTRY();
395
396     TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
397
398     pthread_mutex_lock(&private_display->lock);
399
400     *count = 0;
401     LIST_FOR_EACH_ENTRY(private_layer, &private_output->layer_list, link)
402         (*count)++;
403     if (*count == 0)
404     {
405         pthread_mutex_unlock(&private_display->lock);
406         return TDM_ERROR_NONE;
407     }
408
409     pthread_mutex_unlock(&private_display->lock);
410
411     return ret;
412 }
413
414
415 EXTERN tdm_layer*
416 tdm_output_get_layer(tdm_output *output, int index, tdm_error *error)
417 {
418     tdm_private_layer *private_layer = NULL;
419     int i = 0;
420
421     OUTPUT_FUNC_ENTRY_ERROR();
422
423     pthread_mutex_lock(&private_display->lock);
424
425     if (error)
426         *error = TDM_ERROR_NONE;
427
428     LIST_FOR_EACH_ENTRY(private_layer, &private_output->layer_list, link)
429     {
430         if (i == index)
431         {
432             pthread_mutex_unlock(&private_display->lock);
433             return private_layer;
434         }
435         i++;
436     }
437
438     pthread_mutex_unlock(&private_display->lock);
439
440     return NULL;
441 }
442
443 EXTERN tdm_error
444 tdm_output_get_available_properties(tdm_output *output, const tdm_prop **props, int *count)
445 {
446     OUTPUT_FUNC_ENTRY();
447
448     TDM_RETURN_VAL_IF_FAIL(props != NULL, TDM_ERROR_INVALID_PARAMETER);
449     TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
450
451     pthread_mutex_lock(&private_display->lock);
452
453     *props = (const tdm_prop*)private_output->caps.props;
454     *count = private_output->caps.prop_count;
455
456     pthread_mutex_unlock(&private_display->lock);
457
458     return ret;
459 }
460
461 EXTERN tdm_error
462 tdm_output_get_available_modes(tdm_output *output, const tdm_output_mode **modes, int *count)
463 {
464     OUTPUT_FUNC_ENTRY();
465
466     TDM_RETURN_VAL_IF_FAIL(modes != NULL, TDM_ERROR_INVALID_PARAMETER);
467     TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
468
469     pthread_mutex_lock(&private_display->lock);
470
471     *modes = (const tdm_output_mode*)private_output->caps.modes;
472     *count = private_output->caps.mode_count;
473
474     pthread_mutex_unlock(&private_display->lock);
475
476     return ret;
477 }
478
479 EXTERN tdm_error
480 tdm_output_get_available_size(tdm_output *output, int *min_w, int *min_h,
481                               int *max_w, int *max_h, int *preferred_align)
482 {
483     OUTPUT_FUNC_ENTRY();
484
485     pthread_mutex_lock(&private_display->lock);
486
487     if (min_w)
488         *min_w = private_output->caps.min_w;
489     if (min_h)
490         *min_h = private_output->caps.min_h;
491     if (max_w)
492         *max_w = private_output->caps.max_w;
493     if (max_h)
494         *max_h = private_output->caps.max_h;
495     if (preferred_align)
496         *preferred_align = private_output->caps.preferred_align;
497
498     pthread_mutex_unlock(&private_display->lock);
499
500     return ret;
501 }
502
503 EXTERN tdm_error
504 tdm_output_get_physical_size(tdm_output *output, unsigned int *mmWidth, unsigned int *mmHeight)
505 {
506     OUTPUT_FUNC_ENTRY();
507
508     pthread_mutex_lock(&private_display->lock);
509
510     if (mmWidth)
511         *mmWidth = private_output->caps.mmWidth;
512     if (mmHeight)
513         *mmHeight = private_output->caps.mmHeight;
514
515     pthread_mutex_unlock(&private_display->lock);
516
517     return ret;
518 }
519
520 EXTERN tdm_error
521 tdm_output_get_subpixel(tdm_output *output, unsigned int *subpixel)
522 {
523     OUTPUT_FUNC_ENTRY();
524     TDM_RETURN_VAL_IF_FAIL(subpixel != NULL, TDM_ERROR_INVALID_PARAMETER);
525
526     pthread_mutex_lock(&private_display->lock);
527
528     *subpixel = private_output->caps.subpixel;
529
530     pthread_mutex_unlock(&private_display->lock);
531
532     return ret;
533 }
534
535 EXTERN tdm_error
536 tdm_output_get_pipe(tdm_output *output, unsigned int *pipe)
537 {
538     OUTPUT_FUNC_ENTRY();
539     TDM_RETURN_VAL_IF_FAIL(pipe != NULL, TDM_ERROR_INVALID_PARAMETER);
540
541     pthread_mutex_lock(&private_display->lock);
542
543     *pipe = private_output->pipe;
544
545     pthread_mutex_unlock(&private_display->lock);
546
547     return ret;
548 }
549
550
551 EXTERN tdm_error
552 tdm_output_set_property(tdm_output *output, unsigned int id, tdm_value value)
553 {
554     tdm_func_display *func_display;
555     OUTPUT_FUNC_ENTRY();
556
557     pthread_mutex_lock(&private_display->lock);
558
559     func_display = &private_display->func_display;
560
561     if (!func_display->output_set_property)
562     {
563         pthread_mutex_unlock(&private_display->lock);
564         return TDM_ERROR_NONE;
565     }
566
567     ret = func_display->output_set_property(private_output->output_backend, id, value);
568
569     pthread_mutex_unlock(&private_display->lock);
570
571     return ret;
572 }
573
574 EXTERN tdm_error
575 tdm_output_get_property(tdm_output *output, unsigned int id, tdm_value *value)
576 {
577     tdm_func_display *func_display;
578     OUTPUT_FUNC_ENTRY();
579
580     TDM_RETURN_VAL_IF_FAIL(value != NULL, TDM_ERROR_INVALID_PARAMETER);
581
582     pthread_mutex_lock(&private_display->lock);
583
584     func_display = &private_display->func_display;
585
586     if (!func_display->output_get_property)
587     {
588         pthread_mutex_unlock(&private_display->lock);
589         return TDM_ERROR_NONE;
590     }
591
592     ret = func_display->output_get_property(private_output->output_backend, id, value);
593
594     pthread_mutex_unlock(&private_display->lock);
595
596     return ret;
597 }
598
599 static void
600 _tdm_output_cb_vblank(tdm_output *output_backend, unsigned int sequence,
601                       unsigned int tv_sec, unsigned int tv_usec, void *user_data)
602 {
603     tdm_private_vblank_handler *vblank_handler = user_data;
604     tdm_private_display *private_display;
605
606     TDM_RETURN_IF_FAIL(vblank_handler);
607
608     private_display = vblank_handler->private_output->private_display;
609
610     if (vblank_handler->func)
611     {
612         pthread_mutex_unlock(&private_display->lock);
613         vblank_handler->func(vblank_handler->private_output, sequence,
614                              tv_sec, tv_usec, vblank_handler->user_data);
615         pthread_mutex_lock(&private_display->lock);
616     }
617
618     LIST_DEL(&vblank_handler->link);
619     free(vblank_handler);
620 }
621
622 static void
623 _tdm_output_cb_commit(tdm_output *output_backend, unsigned int sequence,
624                       unsigned int tv_sec, unsigned int tv_usec, void *user_data)
625 {
626     tdm_private_commit_handler *commit_handler = user_data;
627     tdm_private_display *private_display;
628     tdm_private_output *private_output;
629     tdm_private_layer *private_layer = NULL;
630
631     TDM_RETURN_IF_FAIL(commit_handler);
632
633     private_output = commit_handler->private_output;
634     private_display = private_output->private_display;
635
636     if (commit_handler->func)
637     {
638         pthread_mutex_unlock(&private_display->lock);
639         commit_handler->func(private_output, sequence,
640                              tv_sec, tv_usec, commit_handler->user_data);
641         pthread_mutex_lock(&private_display->lock);
642     }
643
644     LIST_FOR_EACH_ENTRY(private_layer, &private_output->layer_list, link)
645     {
646         if (!private_layer->waiting_buffer)
647             continue;
648
649         if (private_layer->showing_buffer)
650         {
651             pthread_mutex_unlock(&private_display->lock);
652             tdm_buffer_unref_backend(private_layer->showing_buffer);
653             pthread_mutex_lock(&private_display->lock);
654         }
655
656         private_layer->showing_buffer = private_layer->waiting_buffer;
657         private_layer->waiting_buffer = NULL;
658     }
659
660     LIST_DEL(&commit_handler->link);
661     free(commit_handler);
662 }
663
664 EXTERN tdm_error
665 tdm_output_wait_vblank(tdm_output *output, int interval, int sync,
666                        tdm_output_vblank_handler func, void *user_data)
667 {
668     tdm_func_display *func_display;
669     tdm_private_vblank_handler *vblank_handler;
670     OUTPUT_FUNC_ENTRY();
671
672     pthread_mutex_lock(&private_display->lock);
673
674     func_display = &private_display->func_display;
675
676     if (!func_display->output_wait_vblank)
677     {
678         pthread_mutex_unlock(&private_display->lock);
679         return TDM_ERROR_NONE;
680     }
681
682     vblank_handler = calloc(1, sizeof(tdm_private_vblank_handler));
683     if (!vblank_handler)
684     {
685         TDM_ERR("failed: alloc memory");
686         pthread_mutex_unlock(&private_display->lock);
687         return TDM_ERROR_OUT_OF_MEMORY;
688     }
689
690     LIST_ADD(&vblank_handler->link, &private_output->vblank_handler_list);
691     vblank_handler->private_output = private_output;
692     vblank_handler->func = func;
693     vblank_handler->user_data = user_data;
694
695     ret = func_display->output_wait_vblank(private_output->output_backend, interval,
696                                            sync, vblank_handler);
697     if (ret != TDM_ERROR_NONE)
698     {
699         pthread_mutex_unlock(&private_display->lock);
700         return ret;
701     }
702
703     if (!private_output->regist_vblank_cb)
704     {
705         private_output->regist_vblank_cb = 1;
706         ret = func_display->output_set_vblank_handler(private_output->output_backend,
707                                                       _tdm_output_cb_vblank);
708     }
709
710     pthread_mutex_unlock(&private_display->lock);
711
712     return ret;
713 }
714
715 EXTERN tdm_error
716 tdm_output_commit(tdm_output *output, int sync, tdm_output_commit_handler func, void *user_data)
717 {
718     tdm_func_display *func_display;
719     tdm_private_commit_handler *commit_handler;
720     OUTPUT_FUNC_ENTRY();
721
722     pthread_mutex_lock(&private_display->lock);
723
724     func_display = &private_display->func_display;
725
726     if (!func_display->output_commit)
727     {
728         pthread_mutex_unlock(&private_display->lock);
729         return TDM_ERROR_NONE;
730     }
731
732     commit_handler = calloc(1, sizeof(tdm_private_commit_handler));
733     if (!commit_handler)
734     {
735         TDM_ERR("failed: alloc memory");
736         pthread_mutex_unlock(&private_display->lock);
737         return TDM_ERROR_OUT_OF_MEMORY;
738     }
739
740     LIST_ADD(&commit_handler->link, &private_output->commit_handler_list);
741     commit_handler->private_output = private_output;
742     commit_handler->func = func;
743     commit_handler->user_data = user_data;
744
745     ret = func_display->output_commit(private_output->output_backend, sync, commit_handler);
746     if (ret != TDM_ERROR_NONE)
747     {
748         pthread_mutex_unlock(&private_display->lock);
749         return ret;
750     }
751
752     if (!private_output->regist_commit_cb)
753     {
754         private_output->regist_commit_cb = 1;
755         ret = func_display->output_set_commit_handler(private_output->output_backend,
756                                                       _tdm_output_cb_commit);
757     }
758
759     pthread_mutex_unlock(&private_display->lock);
760
761     return ret;
762 }
763
764 EXTERN tdm_error
765 tdm_output_set_mode(tdm_output *output, const tdm_output_mode *mode)
766 {
767     tdm_func_display *func_display;
768     OUTPUT_FUNC_ENTRY();
769
770     TDM_RETURN_VAL_IF_FAIL(mode != NULL, TDM_ERROR_INVALID_PARAMETER);
771
772     pthread_mutex_lock(&private_display->lock);
773
774     func_display = &private_display->func_display;
775
776     if (!func_display->output_set_mode)
777     {
778         pthread_mutex_unlock(&private_display->lock);
779         return TDM_ERROR_NONE;
780     }
781
782     ret = func_display->output_set_mode(private_output->output_backend, mode);
783
784     pthread_mutex_unlock(&private_display->lock);
785
786     return ret;
787 }
788
789 EXTERN tdm_error
790 tdm_output_get_mode(tdm_output *output, const tdm_output_mode **mode)
791 {
792     tdm_func_display *func_display;
793     OUTPUT_FUNC_ENTRY();
794
795     TDM_RETURN_VAL_IF_FAIL(mode != NULL, TDM_ERROR_INVALID_PARAMETER);
796
797     pthread_mutex_lock(&private_display->lock);
798
799     func_display = &private_display->func_display;
800
801     if (!func_display->output_get_mode)
802     {
803         pthread_mutex_unlock(&private_display->lock);
804         return TDM_ERROR_NONE;
805     }
806
807     ret = func_display->output_get_mode(private_output->output_backend, mode);
808
809     pthread_mutex_unlock(&private_display->lock);
810
811     return ret;
812 }
813
814 EXTERN tdm_error
815 tdm_output_set_dpms(tdm_output *output, tdm_output_dpms dpms_value)
816 {
817     tdm_func_display *func_display;
818     OUTPUT_FUNC_ENTRY();
819
820     if (dpms_value < TDM_OUTPUT_DPMS_ON)
821         dpms_value = TDM_OUTPUT_DPMS_ON;
822     else if (dpms_value > TDM_OUTPUT_DPMS_OFF)
823         dpms_value = TDM_OUTPUT_DPMS_OFF;
824
825     pthread_mutex_lock(&private_display->lock);
826
827     func_display = &private_display->func_display;
828
829     if (!func_display->output_set_dpms)
830     {
831         pthread_mutex_unlock(&private_display->lock);
832         return TDM_ERROR_NONE;
833     }
834
835     ret = func_display->output_set_dpms(private_output->output_backend, dpms_value);
836
837     pthread_mutex_unlock(&private_display->lock);
838
839     return ret;
840 }
841
842 EXTERN tdm_error
843 tdm_output_get_dpms(tdm_output *output, tdm_output_dpms *dpms_value)
844 {
845     tdm_func_display *func_display;
846     OUTPUT_FUNC_ENTRY();
847
848     TDM_RETURN_VAL_IF_FAIL(dpms_value != NULL, TDM_ERROR_INVALID_PARAMETER);
849
850     pthread_mutex_lock(&private_display->lock);
851
852     func_display = &private_display->func_display;
853
854     if (!func_display->output_get_dpms)
855     {
856         pthread_mutex_unlock(&private_display->lock);
857         return TDM_ERROR_NONE;
858     }
859
860     ret = func_display->output_get_dpms(private_output->output_backend, dpms_value);
861
862     pthread_mutex_unlock(&private_display->lock);
863
864     return ret;
865 }
866
867 EXTERN tdm_capture*
868 tdm_output_create_capture(tdm_output *output, tdm_error *error)
869 {
870     tdm_capture *capture = NULL;
871
872     OUTPUT_FUNC_ENTRY_ERROR();
873
874     pthread_mutex_lock(&private_display->lock);
875
876     capture = (tdm_capture*)tdm_capture_create_output_internal(private_output, error);
877
878     pthread_mutex_unlock(&private_display->lock);
879
880     return capture;
881 }
882
883 EXTERN tdm_error
884 tdm_layer_get_capabilities(tdm_layer *layer, tdm_layer_capability *capabilities)
885 {
886     LAYER_FUNC_ENTRY();
887
888     TDM_RETURN_VAL_IF_FAIL(capabilities != NULL, TDM_ERROR_INVALID_PARAMETER);
889
890     pthread_mutex_lock(&private_display->lock);
891
892     *capabilities = private_layer->caps.capabilities;
893
894     pthread_mutex_unlock(&private_display->lock);
895
896     return ret;
897 }
898
899 EXTERN tdm_error
900 tdm_layer_get_available_formats(tdm_layer *layer, const tbm_format **formats, int *count)
901 {
902     LAYER_FUNC_ENTRY();
903
904     TDM_RETURN_VAL_IF_FAIL(formats != NULL, TDM_ERROR_INVALID_PARAMETER);
905     TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
906
907     pthread_mutex_lock(&private_display->lock);
908
909     *formats = (const tbm_format*)private_layer->caps.formats;
910     *count = private_layer->caps.format_count;
911
912     pthread_mutex_unlock(&private_display->lock);
913
914     return ret;
915 }
916
917 EXTERN tdm_error
918 tdm_layer_get_available_properties(tdm_layer *layer, const tdm_prop **props, int *count)
919 {
920     LAYER_FUNC_ENTRY();
921
922     TDM_RETURN_VAL_IF_FAIL(props != NULL, TDM_ERROR_INVALID_PARAMETER);
923     TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
924
925     pthread_mutex_lock(&private_display->lock);
926
927     *props = (const tdm_prop*)private_layer->caps.props;
928     *count = private_layer->caps.prop_count;
929
930     pthread_mutex_unlock(&private_display->lock);
931
932     return ret;
933 }
934
935 EXTERN tdm_error
936 tdm_layer_get_zpos(tdm_layer *layer, unsigned int *zpos)
937 {
938     LAYER_FUNC_ENTRY();
939
940     TDM_RETURN_VAL_IF_FAIL(zpos != NULL, TDM_ERROR_INVALID_PARAMETER);
941
942     pthread_mutex_lock(&private_display->lock);
943
944     *zpos = private_layer->caps.zpos;
945
946     pthread_mutex_unlock(&private_display->lock);
947
948     return ret;
949 }
950
951 EXTERN tdm_error
952 tdm_layer_set_property(tdm_layer *layer, unsigned int id, tdm_value value)
953 {
954     tdm_func_display *func_display;
955     LAYER_FUNC_ENTRY();
956
957     pthread_mutex_lock(&private_display->lock);
958
959     func_display = &private_display->func_display;
960
961     if (!func_display->layer_set_property)
962     {
963         pthread_mutex_unlock(&private_display->lock);
964         return TDM_ERROR_NONE;
965     }
966
967     ret = func_display->layer_set_property(private_layer->layer_backend, id, value);
968
969     pthread_mutex_unlock(&private_display->lock);
970
971     return ret;
972 }
973
974 EXTERN tdm_error
975 tdm_layer_get_property(tdm_layer *layer, unsigned int id, tdm_value *value)
976 {
977     tdm_func_display *func_display;
978     LAYER_FUNC_ENTRY();
979
980     TDM_RETURN_VAL_IF_FAIL(value != NULL, TDM_ERROR_INVALID_PARAMETER);
981
982     pthread_mutex_lock(&private_display->lock);
983
984     func_display = &private_display->func_display;
985
986     if (!func_display->layer_get_property)
987     {
988         pthread_mutex_unlock(&private_display->lock);
989         return TDM_ERROR_NONE;
990     }
991
992     ret = func_display->layer_get_property(private_layer->layer_backend, id, value);
993
994     pthread_mutex_unlock(&private_display->lock);
995
996     return ret;
997 }
998
999 EXTERN tdm_error
1000 tdm_layer_set_info(tdm_layer *layer, tdm_info_layer *info)
1001 {
1002     tdm_func_display *func_display;
1003     LAYER_FUNC_ENTRY();
1004
1005     TDM_RETURN_VAL_IF_FAIL(info != NULL, TDM_ERROR_INVALID_PARAMETER);
1006
1007     pthread_mutex_lock(&private_display->lock);
1008
1009     func_display = &private_display->func_display;
1010
1011     private_layer->usable = 0;
1012
1013     if (!func_display->layer_set_info)
1014     {
1015         pthread_mutex_unlock(&private_display->lock);
1016         return TDM_ERROR_NONE;
1017     }
1018
1019     ret = func_display->layer_set_info(private_layer->layer_backend, info);
1020
1021     pthread_mutex_unlock(&private_display->lock);
1022
1023     return ret;
1024 }
1025
1026 EXTERN tdm_error
1027 tdm_layer_get_info(tdm_layer *layer, tdm_info_layer *info)
1028 {
1029     tdm_func_display *func_display;
1030     LAYER_FUNC_ENTRY();
1031
1032     TDM_RETURN_VAL_IF_FAIL(info != NULL, TDM_ERROR_INVALID_PARAMETER);
1033
1034     pthread_mutex_lock(&private_display->lock);
1035
1036     func_display = &private_display->func_display;
1037
1038     if (!func_display->layer_get_info)
1039     {
1040         pthread_mutex_unlock(&private_display->lock);
1041         return TDM_ERROR_NONE;
1042     }
1043
1044     ret = func_display->layer_get_info(private_layer->layer_backend, info);
1045
1046     pthread_mutex_unlock(&private_display->lock);
1047
1048     return ret;
1049 }
1050
1051 EXTERN tdm_error
1052 tdm_layer_set_buffer(tdm_layer *layer, tbm_surface_h buffer)
1053 {
1054     tdm_func_display *func_display;
1055     LAYER_FUNC_ENTRY();
1056
1057     TDM_RETURN_VAL_IF_FAIL(buffer != NULL, TDM_ERROR_INVALID_PARAMETER);
1058
1059     pthread_mutex_lock(&private_display->lock);
1060
1061     func_display = &private_display->func_display;
1062
1063     private_layer->usable = 0;
1064
1065     if (!func_display->layer_set_buffer)
1066     {
1067         pthread_mutex_unlock(&private_display->lock);
1068         return TDM_ERROR_NONE;
1069     }
1070
1071     if (private_layer->waiting_buffer)
1072     {
1073         pthread_mutex_unlock(&private_display->lock);
1074         tdm_buffer_unref_backend(private_layer->waiting_buffer);
1075         pthread_mutex_lock(&private_display->lock);
1076     }
1077
1078     private_layer->waiting_buffer = tdm_buffer_ref_backend(buffer);
1079
1080     ret = func_display->layer_set_buffer(private_layer->layer_backend, buffer);
1081
1082     pthread_mutex_unlock(&private_display->lock);
1083
1084     return ret;
1085 }
1086
1087 EXTERN tdm_error
1088 tdm_layer_unset_buffer(tdm_layer *layer)
1089 {
1090     tdm_func_display *func_display;
1091     LAYER_FUNC_ENTRY();
1092
1093     pthread_mutex_lock(&private_display->lock);
1094
1095     func_display = &private_display->func_display;
1096
1097     if (private_layer->waiting_buffer)
1098     {
1099         pthread_mutex_unlock(&private_display->lock);
1100         tdm_buffer_unref_backend(private_layer->waiting_buffer);
1101         pthread_mutex_lock(&private_display->lock);
1102         private_layer->waiting_buffer = NULL;
1103     }
1104
1105     if (private_layer->showing_buffer)
1106     {
1107         pthread_mutex_unlock(&private_display->lock);
1108         tdm_buffer_unref_backend(private_layer->showing_buffer);
1109         pthread_mutex_lock(&private_display->lock);
1110         private_layer->showing_buffer = NULL;
1111     }
1112
1113     private_layer->usable = 1;
1114
1115     if (!func_display->layer_unset_buffer)
1116     {
1117         pthread_mutex_unlock(&private_display->lock);
1118         return TDM_ERROR_NONE;
1119     }
1120
1121     ret = func_display->layer_unset_buffer(private_layer->layer_backend);
1122
1123     pthread_mutex_unlock(&private_display->lock);
1124
1125     return ret;
1126 }
1127
1128 EXTERN tdm_error
1129 tdm_layer_is_usable(tdm_layer *layer, unsigned int *usable)
1130 {
1131     LAYER_FUNC_ENTRY();
1132
1133     TDM_RETURN_VAL_IF_FAIL(usable != NULL, TDM_ERROR_INVALID_PARAMETER);
1134
1135     pthread_mutex_lock(&private_display->lock);
1136
1137     *usable = private_layer->usable;
1138
1139     pthread_mutex_unlock(&private_display->lock);
1140
1141     return ret;
1142 }
1143
1144 EXTERN tdm_error
1145 tdm_layer_set_video_pos(tdm_layer *layer, int zpos)
1146 {
1147     tdm_func_display *func_display;
1148     LAYER_FUNC_ENTRY();
1149
1150     pthread_mutex_lock(&private_display->lock);
1151
1152     func_display = &private_display->func_display;
1153
1154     if (!(private_layer->caps.capabilities & TDM_LAYER_CAPABILITY_VIDEO))
1155     {
1156         TDM_ERR("layer is not video layer");
1157         pthread_mutex_unlock(&private_display->lock);
1158         return TDM_ERROR_INVALID_PARAMETER;
1159     }
1160
1161     if (!func_display->layer_set_video_pos)
1162     {
1163         pthread_mutex_unlock(&private_display->lock);
1164         return TDM_ERROR_NONE;
1165     }
1166
1167     ret = func_display->layer_set_video_pos(private_layer->layer_backend, zpos);
1168
1169     pthread_mutex_unlock(&private_display->lock);
1170
1171     return ret;
1172 }
1173
1174 EXTERN tdm_capture*
1175 tdm_layer_create_capture(tdm_layer *layer, tdm_error *error)
1176 {
1177     tdm_capture *capture = NULL;
1178
1179     LAYER_FUNC_ENTRY_ERROR();
1180
1181     pthread_mutex_lock(&private_display->lock);
1182
1183     capture = (tdm_capture*)tdm_capture_create_layer_internal(private_layer, error);
1184
1185     pthread_mutex_unlock(&private_display->lock);
1186
1187     return capture;
1188 }