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