seperate tdm_func_ouput, tdm_func_layer from tdm_func_diplay
[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_conn_status(tdm_output *output, tdm_output_conn_status *status)
369 {
370     OUTPUT_FUNC_ENTRY();
371
372     TDM_RETURN_VAL_IF_FAIL(status != NULL, TDM_ERROR_INVALID_PARAMETER);
373
374     pthread_mutex_lock(&private_display->lock);
375
376     *status = private_output->caps.status;
377
378     pthread_mutex_unlock(&private_display->lock);
379
380     return ret;
381 }
382
383 EXTERN tdm_error
384 tdm_output_get_output_type(tdm_output *output, tdm_output_type *type)
385 {
386     OUTPUT_FUNC_ENTRY();
387
388     TDM_RETURN_VAL_IF_FAIL(type != NULL, TDM_ERROR_INVALID_PARAMETER);
389
390     pthread_mutex_lock(&private_display->lock);
391
392     *type = private_output->caps.type;
393
394     pthread_mutex_unlock(&private_display->lock);
395
396     return ret;
397 }
398
399 EXTERN tdm_error
400 tdm_output_get_layer_count(tdm_output *output, int *count)
401 {
402     tdm_private_layer *private_layer = NULL;
403
404     OUTPUT_FUNC_ENTRY();
405
406     TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
407
408     pthread_mutex_lock(&private_display->lock);
409
410     *count = 0;
411     LIST_FOR_EACH_ENTRY(private_layer, &private_output->layer_list, link)
412         (*count)++;
413     if (*count == 0)
414     {
415         pthread_mutex_unlock(&private_display->lock);
416         return TDM_ERROR_NONE;
417     }
418
419     pthread_mutex_unlock(&private_display->lock);
420
421     return ret;
422 }
423
424
425 EXTERN tdm_layer*
426 tdm_output_get_layer(tdm_output *output, int index, tdm_error *error)
427 {
428     tdm_private_layer *private_layer = NULL;
429     int i = 0;
430
431     OUTPUT_FUNC_ENTRY_ERROR();
432
433     pthread_mutex_lock(&private_display->lock);
434
435     if (error)
436         *error = TDM_ERROR_NONE;
437
438     LIST_FOR_EACH_ENTRY(private_layer, &private_output->layer_list, link)
439     {
440         if (i == index)
441         {
442             pthread_mutex_unlock(&private_display->lock);
443             return private_layer;
444         }
445         i++;
446     }
447
448     pthread_mutex_unlock(&private_display->lock);
449
450     return NULL;
451 }
452
453 EXTERN tdm_error
454 tdm_output_get_available_properties(tdm_output *output, const tdm_prop **props, int *count)
455 {
456     OUTPUT_FUNC_ENTRY();
457
458     TDM_RETURN_VAL_IF_FAIL(props != NULL, TDM_ERROR_INVALID_PARAMETER);
459     TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
460
461     pthread_mutex_lock(&private_display->lock);
462
463     *props = (const tdm_prop*)private_output->caps.props;
464     *count = private_output->caps.prop_count;
465
466     pthread_mutex_unlock(&private_display->lock);
467
468     return ret;
469 }
470
471 EXTERN tdm_error
472 tdm_output_get_available_modes(tdm_output *output, const tdm_output_mode **modes, int *count)
473 {
474     OUTPUT_FUNC_ENTRY();
475
476     TDM_RETURN_VAL_IF_FAIL(modes != NULL, TDM_ERROR_INVALID_PARAMETER);
477     TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
478
479     pthread_mutex_lock(&private_display->lock);
480
481     *modes = (const tdm_output_mode*)private_output->caps.modes;
482     *count = private_output->caps.mode_count;
483
484     pthread_mutex_unlock(&private_display->lock);
485
486     return ret;
487 }
488
489 EXTERN tdm_error
490 tdm_output_get_available_size(tdm_output *output, int *min_w, int *min_h,
491                               int *max_w, int *max_h, int *preferred_align)
492 {
493     OUTPUT_FUNC_ENTRY();
494
495     pthread_mutex_lock(&private_display->lock);
496
497     if (min_w)
498         *min_w = private_output->caps.min_w;
499     if (min_h)
500         *min_h = private_output->caps.min_h;
501     if (max_w)
502         *max_w = private_output->caps.max_w;
503     if (max_h)
504         *max_h = private_output->caps.max_h;
505     if (preferred_align)
506         *preferred_align = private_output->caps.preferred_align;
507
508     pthread_mutex_unlock(&private_display->lock);
509
510     return ret;
511 }
512
513 EXTERN tdm_error
514 tdm_output_get_physical_size(tdm_output *output, unsigned int *mmWidth, unsigned int *mmHeight)
515 {
516     OUTPUT_FUNC_ENTRY();
517
518     pthread_mutex_lock(&private_display->lock);
519
520     if (mmWidth)
521         *mmWidth = private_output->caps.mmWidth;
522     if (mmHeight)
523         *mmHeight = private_output->caps.mmHeight;
524
525     pthread_mutex_unlock(&private_display->lock);
526
527     return ret;
528 }
529
530 EXTERN tdm_error
531 tdm_output_get_subpixel(tdm_output *output, unsigned int *subpixel)
532 {
533     OUTPUT_FUNC_ENTRY();
534     TDM_RETURN_VAL_IF_FAIL(subpixel != NULL, TDM_ERROR_INVALID_PARAMETER);
535
536     pthread_mutex_lock(&private_display->lock);
537
538     *subpixel = private_output->caps.subpixel;
539
540     pthread_mutex_unlock(&private_display->lock);
541
542     return ret;
543 }
544
545 EXTERN tdm_error
546 tdm_output_get_pipe(tdm_output *output, unsigned int *pipe)
547 {
548     OUTPUT_FUNC_ENTRY();
549     TDM_RETURN_VAL_IF_FAIL(pipe != NULL, TDM_ERROR_INVALID_PARAMETER);
550
551     pthread_mutex_lock(&private_display->lock);
552
553     *pipe = private_output->pipe;
554
555     pthread_mutex_unlock(&private_display->lock);
556
557     return ret;
558 }
559
560
561 EXTERN tdm_error
562 tdm_output_set_property(tdm_output *output, unsigned int id, tdm_value value)
563 {
564     tdm_func_output *func_output;
565     OUTPUT_FUNC_ENTRY();
566
567     pthread_mutex_lock(&private_display->lock);
568
569     func_output = &private_display->func_output;
570
571     if (!func_output->output_set_property)
572     {
573         pthread_mutex_unlock(&private_display->lock);
574         return TDM_ERROR_NONE;
575     }
576
577     ret = func_output->output_set_property(private_output->output_backend, id, value);
578
579     pthread_mutex_unlock(&private_display->lock);
580
581     return ret;
582 }
583
584 EXTERN tdm_error
585 tdm_output_get_property(tdm_output *output, unsigned int id, tdm_value *value)
586 {
587     tdm_func_output *func_output;
588     OUTPUT_FUNC_ENTRY();
589
590     TDM_RETURN_VAL_IF_FAIL(value != NULL, TDM_ERROR_INVALID_PARAMETER);
591
592     pthread_mutex_lock(&private_display->lock);
593
594     func_output = &private_display->func_output;
595
596     if (!func_output->output_get_property)
597     {
598         pthread_mutex_unlock(&private_display->lock);
599         return TDM_ERROR_NONE;
600     }
601
602     ret = func_output->output_get_property(private_output->output_backend, id, value);
603
604     pthread_mutex_unlock(&private_display->lock);
605
606     return ret;
607 }
608
609 static void
610 _tdm_output_cb_vblank(tdm_output *output_backend, unsigned int sequence,
611                       unsigned int tv_sec, unsigned int tv_usec, void *user_data)
612 {
613     tdm_private_vblank_handler *vblank_handler = user_data;
614     tdm_private_display *private_display;
615
616     TDM_RETURN_IF_FAIL(vblank_handler);
617
618     private_display = vblank_handler->private_output->private_display;
619
620     if (vblank_handler->func)
621     {
622         pthread_mutex_unlock(&private_display->lock);
623         vblank_handler->func(vblank_handler->private_output, sequence,
624                              tv_sec, tv_usec, vblank_handler->user_data);
625         pthread_mutex_lock(&private_display->lock);
626     }
627
628     LIST_DEL(&vblank_handler->link);
629     free(vblank_handler);
630 }
631
632 static void
633 _tdm_output_cb_commit(tdm_output *output_backend, unsigned int sequence,
634                       unsigned int tv_sec, unsigned int tv_usec, void *user_data)
635 {
636     tdm_private_commit_handler *commit_handler = user_data;
637     tdm_private_display *private_display;
638     tdm_private_output *private_output;
639     tdm_private_layer *private_layer = NULL;
640
641     TDM_RETURN_IF_FAIL(commit_handler);
642
643     private_output = commit_handler->private_output;
644     private_display = private_output->private_display;
645
646     LIST_FOR_EACH_ENTRY(private_layer, &private_output->layer_list, link)
647     {
648         if (!private_layer->waiting_buffer)
649             continue;
650
651         if (private_layer->showing_buffer)
652         {
653             pthread_mutex_unlock(&private_display->lock);
654             tdm_buffer_unref_backend(private_layer->showing_buffer);
655             pthread_mutex_lock(&private_display->lock);
656
657             if (private_layer->buffer_queue)
658             {
659                 pthread_mutex_unlock(&private_display->lock);
660                 tbm_surface_queue_release(private_layer->buffer_queue,
661                                         private_layer->showing_buffer);
662                 pthread_mutex_lock(&private_display->lock);
663             }
664         }
665
666         private_layer->showing_buffer = private_layer->waiting_buffer;
667         private_layer->waiting_buffer = NULL;
668     }
669
670     if (commit_handler->func)
671     {
672         pthread_mutex_unlock(&private_display->lock);
673         commit_handler->func(private_output, sequence,
674                              tv_sec, tv_usec, commit_handler->user_data);
675         pthread_mutex_lock(&private_display->lock);
676     }
677
678     LIST_DEL(&commit_handler->link);
679     free(commit_handler);
680 }
681
682 EXTERN tdm_error
683 tdm_output_wait_vblank(tdm_output *output, int interval, int sync,
684                        tdm_output_vblank_handler func, void *user_data)
685 {
686     tdm_func_output *func_output;
687     tdm_private_vblank_handler *vblank_handler;
688     OUTPUT_FUNC_ENTRY();
689
690     pthread_mutex_lock(&private_display->lock);
691
692     func_output = &private_display->func_output;
693
694     if (!func_output->output_wait_vblank)
695     {
696         pthread_mutex_unlock(&private_display->lock);
697         return TDM_ERROR_NONE;
698     }
699
700     vblank_handler = calloc(1, sizeof(tdm_private_vblank_handler));
701     if (!vblank_handler)
702     {
703         TDM_ERR("failed: alloc memory");
704         pthread_mutex_unlock(&private_display->lock);
705         return TDM_ERROR_OUT_OF_MEMORY;
706     }
707
708     LIST_ADD(&vblank_handler->link, &private_output->vblank_handler_list);
709     vblank_handler->private_output = private_output;
710     vblank_handler->func = func;
711     vblank_handler->user_data = user_data;
712
713     ret = func_output->output_wait_vblank(private_output->output_backend, interval,
714                                            sync, vblank_handler);
715     if (ret != TDM_ERROR_NONE)
716     {
717         pthread_mutex_unlock(&private_display->lock);
718         return ret;
719     }
720
721     if (!private_output->regist_vblank_cb)
722     {
723         private_output->regist_vblank_cb = 1;
724         ret = func_output->output_set_vblank_handler(private_output->output_backend,
725                                                       _tdm_output_cb_vblank);
726     }
727
728     pthread_mutex_unlock(&private_display->lock);
729
730     return ret;
731 }
732
733 static tdm_error
734 _tdm_output_commit(tdm_output *output, int sync, tdm_output_commit_handler func, void *user_data)
735 {
736     tdm_func_output *func_output;
737     tdm_private_commit_handler *commit_handler;
738     OUTPUT_FUNC_ENTRY();
739
740     func_output = &private_display->func_output;
741
742     if (!func_output->output_commit)
743     {
744         return TDM_ERROR_NONE;
745     }
746
747     commit_handler = calloc(1, sizeof(tdm_private_commit_handler));
748     if (!commit_handler)
749     {
750         TDM_ERR("failed: alloc memory");
751         return TDM_ERROR_OUT_OF_MEMORY;
752     }
753
754     LIST_ADD(&commit_handler->link, &private_output->commit_handler_list);
755     commit_handler->private_output = private_output;
756     commit_handler->func = func;
757     commit_handler->user_data = user_data;
758
759     ret = func_output->output_commit(private_output->output_backend, sync, commit_handler);
760     if (ret != TDM_ERROR_NONE)
761     {
762         return ret;
763     }
764
765     if (!private_output->regist_commit_cb)
766     {
767         private_output->regist_commit_cb = 1;
768         ret = func_output->output_set_commit_handler(private_output->output_backend,
769                                                       _tdm_output_cb_commit);
770     }
771
772     return ret;
773 }
774
775 EXTERN tdm_error
776 tdm_output_commit(tdm_output *output, int sync, tdm_output_commit_handler func, void *user_data)
777 {
778     OUTPUT_FUNC_ENTRY();
779
780     pthread_mutex_lock(&private_display->lock);
781
782     ret = _tdm_output_commit(output, sync, func, user_data);
783
784     pthread_mutex_unlock(&private_display->lock);
785
786     return ret;
787 }
788
789 EXTERN tdm_error
790 tdm_output_set_mode(tdm_output *output, const tdm_output_mode *mode)
791 {
792     tdm_func_output *func_output;
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_output = &private_display->func_output;
800
801     if (!func_output->output_set_mode)
802     {
803         pthread_mutex_unlock(&private_display->lock);
804         return TDM_ERROR_NONE;
805     }
806
807     ret = func_output->output_set_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_get_mode(tdm_output *output, const tdm_output_mode **mode)
816 {
817     tdm_func_output *func_output;
818     OUTPUT_FUNC_ENTRY();
819
820     TDM_RETURN_VAL_IF_FAIL(mode != NULL, TDM_ERROR_INVALID_PARAMETER);
821
822     pthread_mutex_lock(&private_display->lock);
823
824     func_output = &private_display->func_output;
825
826     if (!func_output->output_get_mode)
827     {
828         pthread_mutex_unlock(&private_display->lock);
829         return TDM_ERROR_NONE;
830     }
831
832     ret = func_output->output_get_mode(private_output->output_backend, mode);
833
834     pthread_mutex_unlock(&private_display->lock);
835
836     return ret;
837 }
838
839 EXTERN tdm_error
840 tdm_output_set_dpms(tdm_output *output, tdm_output_dpms dpms_value)
841 {
842     tdm_func_output *func_output;
843     OUTPUT_FUNC_ENTRY();
844
845     if (dpms_value < TDM_OUTPUT_DPMS_ON)
846         dpms_value = TDM_OUTPUT_DPMS_ON;
847     else if (dpms_value > TDM_OUTPUT_DPMS_OFF)
848         dpms_value = TDM_OUTPUT_DPMS_OFF;
849
850     pthread_mutex_lock(&private_display->lock);
851
852     func_output = &private_display->func_output;
853
854     if (!func_output->output_set_dpms)
855     {
856         pthread_mutex_unlock(&private_display->lock);
857         return TDM_ERROR_NONE;
858     }
859
860     ret = func_output->output_set_dpms(private_output->output_backend, dpms_value);
861
862     pthread_mutex_unlock(&private_display->lock);
863
864     return ret;
865 }
866
867 EXTERN tdm_error
868 tdm_output_get_dpms(tdm_output *output, tdm_output_dpms *dpms_value)
869 {
870     tdm_func_output *func_output;
871     OUTPUT_FUNC_ENTRY();
872
873     TDM_RETURN_VAL_IF_FAIL(dpms_value != NULL, TDM_ERROR_INVALID_PARAMETER);
874
875     pthread_mutex_lock(&private_display->lock);
876
877     func_output = &private_display->func_output;
878
879     if (!func_output->output_get_dpms)
880     {
881         pthread_mutex_unlock(&private_display->lock);
882         return TDM_ERROR_NONE;
883     }
884
885     ret = func_output->output_get_dpms(private_output->output_backend, dpms_value);
886
887     pthread_mutex_unlock(&private_display->lock);
888
889     return ret;
890 }
891
892 EXTERN tdm_capture*
893 tdm_output_create_capture(tdm_output *output, tdm_error *error)
894 {
895     tdm_capture *capture = NULL;
896
897     OUTPUT_FUNC_ENTRY_ERROR();
898
899     pthread_mutex_lock(&private_display->lock);
900
901     capture = (tdm_capture*)tdm_capture_create_output_internal(private_output, error);
902
903     pthread_mutex_unlock(&private_display->lock);
904
905     return capture;
906 }
907
908 EXTERN tdm_error
909 tdm_layer_get_capabilities(tdm_layer *layer, tdm_layer_capability *capabilities)
910 {
911     LAYER_FUNC_ENTRY();
912
913     TDM_RETURN_VAL_IF_FAIL(capabilities != NULL, TDM_ERROR_INVALID_PARAMETER);
914
915     pthread_mutex_lock(&private_display->lock);
916
917     *capabilities = private_layer->caps.capabilities;
918
919     pthread_mutex_unlock(&private_display->lock);
920
921     return ret;
922 }
923
924 EXTERN tdm_error
925 tdm_layer_get_available_formats(tdm_layer *layer, const tbm_format **formats, int *count)
926 {
927     LAYER_FUNC_ENTRY();
928
929     TDM_RETURN_VAL_IF_FAIL(formats != NULL, TDM_ERROR_INVALID_PARAMETER);
930     TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
931
932     pthread_mutex_lock(&private_display->lock);
933
934     *formats = (const tbm_format*)private_layer->caps.formats;
935     *count = private_layer->caps.format_count;
936
937     pthread_mutex_unlock(&private_display->lock);
938
939     return ret;
940 }
941
942 EXTERN tdm_error
943 tdm_layer_get_available_properties(tdm_layer *layer, const tdm_prop **props, int *count)
944 {
945     LAYER_FUNC_ENTRY();
946
947     TDM_RETURN_VAL_IF_FAIL(props != NULL, TDM_ERROR_INVALID_PARAMETER);
948     TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
949
950     pthread_mutex_lock(&private_display->lock);
951
952     *props = (const tdm_prop*)private_layer->caps.props;
953     *count = private_layer->caps.prop_count;
954
955     pthread_mutex_unlock(&private_display->lock);
956
957     return ret;
958 }
959
960 EXTERN tdm_error
961 tdm_layer_get_zpos(tdm_layer *layer, unsigned int *zpos)
962 {
963     LAYER_FUNC_ENTRY();
964
965     TDM_RETURN_VAL_IF_FAIL(zpos != NULL, TDM_ERROR_INVALID_PARAMETER);
966
967     pthread_mutex_lock(&private_display->lock);
968
969     *zpos = private_layer->caps.zpos;
970
971     pthread_mutex_unlock(&private_display->lock);
972
973     return ret;
974 }
975
976 EXTERN tdm_error
977 tdm_layer_set_property(tdm_layer *layer, unsigned int id, tdm_value value)
978 {
979     tdm_func_layer *func_layer;
980     LAYER_FUNC_ENTRY();
981
982     pthread_mutex_lock(&private_display->lock);
983
984     func_layer = &private_display->func_layer;
985
986     if (!func_layer->layer_set_property)
987     {
988         pthread_mutex_unlock(&private_display->lock);
989         return TDM_ERROR_NONE;
990     }
991
992     ret = func_layer->layer_set_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_get_property(tdm_layer *layer, unsigned int id, tdm_value *value)
1001 {
1002     tdm_func_layer *func_layer;
1003     LAYER_FUNC_ENTRY();
1004
1005     TDM_RETURN_VAL_IF_FAIL(value != NULL, TDM_ERROR_INVALID_PARAMETER);
1006
1007     pthread_mutex_lock(&private_display->lock);
1008
1009     func_layer = &private_display->func_layer;
1010
1011     if (!func_layer->layer_get_property)
1012     {
1013         pthread_mutex_unlock(&private_display->lock);
1014         return TDM_ERROR_NONE;
1015     }
1016
1017     ret = func_layer->layer_get_property(private_layer->layer_backend, id, value);
1018
1019     pthread_mutex_unlock(&private_display->lock);
1020
1021     return ret;
1022 }
1023
1024 EXTERN tdm_error
1025 tdm_layer_set_info(tdm_layer *layer, tdm_info_layer *info)
1026 {
1027     tdm_func_layer *func_layer;
1028     LAYER_FUNC_ENTRY();
1029
1030     TDM_RETURN_VAL_IF_FAIL(info != NULL, TDM_ERROR_INVALID_PARAMETER);
1031
1032     pthread_mutex_lock(&private_display->lock);
1033
1034     func_layer = &private_display->func_layer;
1035
1036     private_layer->usable = 0;
1037
1038     if (!func_layer->layer_set_info)
1039     {
1040         pthread_mutex_unlock(&private_display->lock);
1041         return TDM_ERROR_NONE;
1042     }
1043
1044     ret = func_layer->layer_set_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_get_info(tdm_layer *layer, tdm_info_layer *info)
1053 {
1054     tdm_func_layer *func_layer;
1055     LAYER_FUNC_ENTRY();
1056
1057     TDM_RETURN_VAL_IF_FAIL(info != NULL, TDM_ERROR_INVALID_PARAMETER);
1058
1059     pthread_mutex_lock(&private_display->lock);
1060
1061     func_layer = &private_display->func_layer;
1062
1063     if (!func_layer->layer_get_info)
1064     {
1065         pthread_mutex_unlock(&private_display->lock);
1066         return TDM_ERROR_NONE;
1067     }
1068
1069     ret = func_layer->layer_get_info(private_layer->layer_backend, info);
1070
1071     pthread_mutex_unlock(&private_display->lock);
1072
1073     return ret;
1074 }
1075
1076 EXTERN tdm_error
1077 tdm_layer_set_buffer(tdm_layer *layer, tbm_surface_h buffer)
1078 {
1079     tdm_func_layer *func_layer;
1080     LAYER_FUNC_ENTRY();
1081
1082     TDM_RETURN_VAL_IF_FAIL(buffer != NULL, TDM_ERROR_INVALID_PARAMETER);
1083
1084     pthread_mutex_lock(&private_display->lock);
1085
1086     func_layer = &private_display->func_layer;
1087
1088     private_layer->usable = 0;
1089
1090     if (!func_layer->layer_set_buffer)
1091     {
1092         pthread_mutex_unlock(&private_display->lock);
1093         return TDM_ERROR_NONE;
1094     }
1095
1096     if (private_layer->waiting_buffer)
1097     {
1098         pthread_mutex_unlock(&private_display->lock);
1099         tdm_buffer_unref_backend(private_layer->waiting_buffer);
1100         pthread_mutex_lock(&private_display->lock);
1101     }
1102
1103     private_layer->waiting_buffer = tdm_buffer_ref_backend(buffer);
1104
1105     ret = func_layer->layer_set_buffer(private_layer->layer_backend, buffer);
1106
1107     pthread_mutex_unlock(&private_display->lock);
1108
1109     return ret;
1110 }
1111
1112 EXTERN tdm_error
1113 tdm_layer_unset_buffer(tdm_layer *layer)
1114 {
1115     tdm_func_layer *func_layer;
1116     LAYER_FUNC_ENTRY();
1117
1118     pthread_mutex_lock(&private_display->lock);
1119
1120     func_layer = &private_display->func_layer;
1121
1122     if (private_layer->waiting_buffer)
1123     {
1124         pthread_mutex_unlock(&private_display->lock);
1125         tdm_buffer_unref_backend(private_layer->waiting_buffer);
1126         pthread_mutex_lock(&private_display->lock);
1127         private_layer->waiting_buffer = NULL;
1128     }
1129
1130     if (private_layer->showing_buffer)
1131     {
1132         pthread_mutex_unlock(&private_display->lock);
1133         tdm_buffer_unref_backend(private_layer->showing_buffer);
1134         pthread_mutex_lock(&private_display->lock);
1135         private_layer->showing_buffer = NULL;
1136     }
1137
1138     private_layer->usable = 1;
1139
1140     if (!func_layer->layer_unset_buffer)
1141     {
1142         pthread_mutex_unlock(&private_display->lock);
1143         return TDM_ERROR_NONE;
1144     }
1145
1146     ret = func_layer->layer_unset_buffer(private_layer->layer_backend);
1147
1148     pthread_mutex_unlock(&private_display->lock);
1149
1150     return ret;
1151 }
1152
1153 static void
1154 _tbm_layer_queue_acquirable_cb(tbm_surface_queue_h surface_queue, void *data)
1155 {
1156     TDM_RETURN_IF_FAIL(data != NULL);
1157     tdm_layer *layer = data;
1158     tdm_func_layer *func_layer;
1159     tbm_surface_h surface = NULL;
1160     LAYER_FUNC_ENTRY_VOID_RETURN();
1161
1162     pthread_mutex_lock(&private_display->lock);
1163
1164     func_layer = &private_display->func_layer;
1165     if (!func_layer->layer_set_buffer)
1166     {
1167         pthread_mutex_unlock(&private_display->lock);
1168         return;
1169     }
1170
1171     if (TBM_SURFACE_QUEUE_ERROR_NONE != tbm_surface_queue_acquire(private_layer->buffer_queue, &surface) ||
1172         surface == NULL)
1173     {
1174         TDM_ERR("tbm_surface_queue_acquire() failed surface:%p", surface);
1175         pthread_mutex_unlock(&private_display->lock);
1176         return;
1177     }
1178
1179     if (private_layer->waiting_buffer)
1180     {
1181         pthread_mutex_unlock(&private_display->lock);
1182         tdm_buffer_unref_backend(private_layer->waiting_buffer);
1183         tbm_surface_queue_release(private_layer->buffer_queue, private_layer->waiting_buffer);
1184         pthread_mutex_lock(&private_display->lock);
1185     }
1186
1187     private_layer->waiting_buffer = tdm_buffer_ref_backend(surface);
1188
1189     func_layer->layer_set_buffer(private_layer->layer_backend, surface);
1190
1191     ret = _tdm_output_commit(private_layer->private_output, 0, NULL, NULL);
1192     if (ret != TDM_ERROR_NONE)
1193         TDM_ERR("_tdm_output_commit() is fail");
1194
1195     pthread_mutex_unlock(&private_display->lock);
1196 }
1197
1198 static void
1199 _tbm_layer_queue_destroy_cb(tbm_surface_queue_h surface_queue, void *data)
1200 {
1201     TDM_RETURN_IF_FAIL(data != NULL);
1202     tdm_layer *layer = data;
1203     LAYER_FUNC_ENTRY_VOID_RETURN();
1204     TDM_RETURN_IF_FAIL(ret == TDM_ERROR_NONE);
1205
1206     pthread_mutex_lock(&private_display->lock);
1207
1208     if (private_layer->waiting_buffer)
1209     {
1210         pthread_mutex_unlock(&private_display->lock);
1211         tdm_buffer_unref_backend(private_layer->waiting_buffer);
1212         tbm_surface_queue_release(private_layer->buffer_queue, private_layer->waiting_buffer);
1213         pthread_mutex_lock(&private_display->lock);
1214     }
1215
1216     private_layer->buffer_queue = NULL;
1217
1218     pthread_mutex_unlock(&private_display->lock);
1219 }
1220
1221 EXTERN tdm_error
1222 tdm_layer_set_buffer_queue(tdm_layer *layer, tbm_surface_queue_h buffer_queue)
1223 {
1224     tdm_func_layer *func_layer;
1225     LAYER_FUNC_ENTRY();
1226
1227     TDM_RETURN_VAL_IF_FAIL(buffer_queue != NULL, TDM_ERROR_INVALID_PARAMETER);
1228
1229     pthread_mutex_lock(&private_display->lock);
1230
1231     func_layer = &private_display->func_layer;
1232
1233     private_layer->usable = 0;
1234
1235     if (!func_layer->layer_set_buffer)
1236     {
1237         pthread_mutex_unlock(&private_display->lock);
1238         return TDM_ERROR_NONE;
1239     }
1240
1241     if (buffer_queue == private_layer->buffer_queue)
1242     {
1243         pthread_mutex_unlock(&private_display->lock);
1244         return TDM_ERROR_NONE;
1245     }
1246
1247     if (private_layer->waiting_buffer)
1248     {
1249         pthread_mutex_unlock(&private_display->lock);
1250         tdm_buffer_unref_backend(private_layer->waiting_buffer);
1251         tbm_surface_queue_release(private_layer->buffer_queue, private_layer->waiting_buffer);
1252         private_layer->waiting_buffer = NULL;
1253         pthread_mutex_lock(&private_display->lock);
1254     }
1255
1256     private_layer->buffer_queue = buffer_queue;
1257     tbm_surface_queue_set_acquirable_cb(private_layer->buffer_queue,
1258                             _tbm_layer_queue_acquirable_cb,
1259                             layer);
1260     tbm_surface_queue_set_destroy_cb(private_layer->buffer_queue,
1261                             _tbm_layer_queue_destroy_cb,
1262                             layer);
1263     pthread_mutex_unlock(&private_display->lock);
1264
1265     return ret;
1266 }
1267
1268 EXTERN tdm_error
1269 tdm_layer_unset_buffer_queue(tdm_layer *layer)
1270 {
1271     tdm_func_layer *func_layer;
1272     LAYER_FUNC_ENTRY();
1273
1274     pthread_mutex_lock(&private_display->lock);
1275
1276     func_layer = &private_display->func_layer;
1277
1278     if (private_layer->waiting_buffer)
1279     {
1280         pthread_mutex_unlock(&private_display->lock);
1281         tdm_buffer_unref_backend(private_layer->waiting_buffer);
1282         tbm_surface_queue_release(private_layer->buffer_queue, private_layer->waiting_buffer);
1283         private_layer->waiting_buffer = NULL;
1284         pthread_mutex_lock(&private_display->lock);
1285     }
1286
1287     if (private_layer->showing_buffer)
1288     {
1289         pthread_mutex_unlock(&private_display->lock);
1290         tdm_buffer_unref_backend(private_layer->showing_buffer);
1291         tbm_surface_queue_release(private_layer->buffer_queue, private_layer->showing_buffer);
1292         pthread_mutex_lock(&private_display->lock);
1293         private_layer->showing_buffer = NULL;
1294     }
1295
1296     tbm_surface_queue_set_acquirable_cb(private_layer->buffer_queue, NULL, NULL);
1297     tbm_surface_queue_set_destroy_cb(private_layer->buffer_queue, NULL, NULL);
1298     private_layer->buffer_queue = NULL;
1299     private_layer->usable = 1;
1300
1301     if (!func_layer->layer_unset_buffer)
1302     {
1303         pthread_mutex_unlock(&private_display->lock);
1304         return TDM_ERROR_NONE;
1305     }
1306
1307     ret = func_layer->layer_unset_buffer(private_layer->layer_backend);
1308
1309     pthread_mutex_unlock(&private_display->lock);
1310
1311     return ret;
1312 }
1313
1314 EXTERN tdm_error
1315 tdm_layer_is_usable(tdm_layer *layer, unsigned int *usable)
1316 {
1317     LAYER_FUNC_ENTRY();
1318
1319     TDM_RETURN_VAL_IF_FAIL(usable != NULL, TDM_ERROR_INVALID_PARAMETER);
1320
1321     pthread_mutex_lock(&private_display->lock);
1322
1323     *usable = private_layer->usable;
1324
1325     pthread_mutex_unlock(&private_display->lock);
1326
1327     return ret;
1328 }
1329
1330 EXTERN tdm_error
1331 tdm_layer_set_video_pos(tdm_layer *layer, int zpos)
1332 {
1333     tdm_func_layer *func_layer;
1334     LAYER_FUNC_ENTRY();
1335
1336     pthread_mutex_lock(&private_display->lock);
1337
1338     func_layer = &private_display->func_layer;
1339
1340     if (!(private_layer->caps.capabilities & TDM_LAYER_CAPABILITY_VIDEO))
1341     {
1342         TDM_ERR("layer is not video layer");
1343         pthread_mutex_unlock(&private_display->lock);
1344         return TDM_ERROR_INVALID_PARAMETER;
1345     }
1346
1347     if (!func_layer->layer_set_video_pos)
1348     {
1349         pthread_mutex_unlock(&private_display->lock);
1350         return TDM_ERROR_NONE;
1351     }
1352
1353     ret = func_layer->layer_set_video_pos(private_layer->layer_backend, zpos);
1354
1355     pthread_mutex_unlock(&private_display->lock);
1356
1357     return ret;
1358 }
1359
1360 EXTERN tdm_capture*
1361 tdm_layer_create_capture(tdm_layer *layer, tdm_error *error)
1362 {
1363     tdm_capture *capture = NULL;
1364
1365     LAYER_FUNC_ENTRY_ERROR();
1366
1367     pthread_mutex_lock(&private_display->lock);
1368
1369     capture = (tdm_capture*)tdm_capture_create_layer_internal(private_layer, error);
1370
1371     pthread_mutex_unlock(&private_display->lock);
1372
1373     return capture;
1374 }