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