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