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