082e6b5772697b8656d4024ae75bcfd666b8d4c0
[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_vblank_handler *vblank_handler = user_data;
569     tdm_private_display *private_display;
570
571     TDM_RETURN_IF_FAIL(vblank_handler);
572
573     private_display = vblank_handler->private_output->private_display;
574
575     if (vblank_handler->func)
576     {
577         pthread_mutex_unlock(&private_display->lock);
578         vblank_handler->func(vblank_handler->private_output, sequence,
579                              tv_sec, tv_usec, vblank_handler->user_data);
580         pthread_mutex_lock(&private_display->lock);
581     }
582
583     LIST_DEL(&vblank_handler->link);
584     free(vblank_handler);
585 }
586
587 static void
588 _tdm_output_cb_commit(tdm_output *output_backend, unsigned int sequence,
589                       unsigned int tv_sec, unsigned int tv_usec, void *user_data)
590 {
591     tdm_private_commit_handler *commit_handler = user_data;
592     tdm_private_display *private_display;
593     tdm_private_output *private_output;
594     tdm_private_layer *private_layer;
595
596     TDM_RETURN_IF_FAIL(commit_handler);
597
598     private_output = commit_handler->private_output;
599     private_display = private_output->private_display;
600
601     if (commit_handler->func)
602     {
603         pthread_mutex_unlock(&private_display->lock);
604         commit_handler->func(private_output, sequence,
605                              tv_sec, tv_usec, commit_handler->user_data);
606         pthread_mutex_lock(&private_display->lock);
607     }
608
609     LIST_FOR_EACH_ENTRY(private_layer, &private_output->layer_list, link)
610     {
611         if (!private_layer->waiting_buffer)
612             continue;
613
614         if (private_layer->showing_buffer)
615         {
616             pthread_mutex_unlock(&private_display->lock);
617             tdm_buffer_unref_backend(private_layer->showing_buffer);
618             pthread_mutex_lock(&private_display->lock);
619         }
620
621         private_layer->showing_buffer = private_layer->waiting_buffer;
622         private_layer->waiting_buffer = NULL;
623     }
624
625     LIST_DEL(&commit_handler->link);
626     free(commit_handler);
627 }
628
629 EXTERN tdm_error
630 tdm_output_wait_vblank(tdm_output *output, int interval, int sync,
631                        tdm_output_vblank_handler func, void *user_data)
632 {
633     tdm_func_display *func_display;
634     tdm_private_vblank_handler *vblank_handler;
635     OUTPUT_FUNC_ENTRY();
636
637     pthread_mutex_lock(&private_display->lock);
638
639     func_display = &private_display->func_display;
640
641     if (!func_display->output_wait_vblank)
642     {
643         pthread_mutex_unlock(&private_display->lock);
644         return TDM_ERROR_NONE;
645     }
646
647     vblank_handler = calloc(1, sizeof(tdm_private_vblank_handler));
648     if (!vblank_handler)
649     {
650         TDM_ERR("failed: alloc memory");
651         pthread_mutex_unlock(&private_display->lock);
652         return TDM_ERROR_OUT_OF_MEMORY;
653     }
654
655     LIST_ADD(&vblank_handler->link, &private_output->vblank_handler_list);
656     vblank_handler->private_output = private_output;
657     vblank_handler->func = func;
658     vblank_handler->user_data = user_data;
659
660     ret = func_display->output_wait_vblank(private_output->output_backend, interval,
661                                            sync, vblank_handler);
662     if (ret != TDM_ERROR_NONE)
663     {
664         pthread_mutex_unlock(&private_display->lock);
665         return ret;
666     }
667
668     if (!private_output->regist_vblank_cb)
669     {
670         private_output->regist_vblank_cb = 1;
671         ret = func_display->output_set_vblank_handler(private_output->output_backend,
672                                                       _tdm_output_cb_vblank);
673     }
674
675     pthread_mutex_unlock(&private_display->lock);
676
677     return ret;
678 }
679
680 EXTERN tdm_error
681 tdm_output_commit(tdm_output *output, int sync, tdm_output_commit_handler func, void *user_data)
682 {
683     tdm_func_display *func_display;
684     tdm_private_commit_handler *commit_handler;
685     OUTPUT_FUNC_ENTRY();
686
687     pthread_mutex_lock(&private_display->lock);
688
689     func_display = &private_display->func_display;
690
691     if (!func_display->output_commit)
692     {
693         pthread_mutex_unlock(&private_display->lock);
694         return TDM_ERROR_NONE;
695     }
696
697     commit_handler = calloc(1, sizeof(tdm_private_commit_handler));
698     if (!commit_handler)
699     {
700         TDM_ERR("failed: alloc memory");
701         pthread_mutex_unlock(&private_display->lock);
702         return TDM_ERROR_OUT_OF_MEMORY;
703     }
704
705     LIST_ADD(&commit_handler->link, &private_output->commit_handler_list);
706     commit_handler->private_output = private_output;
707     commit_handler->func = func;
708     commit_handler->user_data = user_data;
709
710     ret = func_display->output_commit(private_output->output_backend, sync, commit_handler);
711     if (ret != TDM_ERROR_NONE)
712     {
713         pthread_mutex_unlock(&private_display->lock);
714         return ret;
715     }
716
717     if (!private_output->regist_commit_cb)
718     {
719         private_output->regist_commit_cb = 1;
720         ret = func_display->output_set_commit_handler(private_output->output_backend,
721                                                       _tdm_output_cb_commit);
722     }
723
724     pthread_mutex_unlock(&private_display->lock);
725
726     return ret;
727 }
728
729 EXTERN tdm_error
730 tdm_output_set_mode(tdm_output *output, tdm_output_mode *mode)
731 {
732     tdm_func_display *func_display;
733     OUTPUT_FUNC_ENTRY();
734
735     TDM_RETURN_VAL_IF_FAIL(mode != NULL, TDM_ERROR_INVALID_PARAMETER);
736
737     pthread_mutex_lock(&private_display->lock);
738
739     func_display = &private_display->func_display;
740
741     if (!func_display->output_set_mode)
742     {
743         pthread_mutex_unlock(&private_display->lock);
744         return TDM_ERROR_NONE;
745     }
746
747     ret = func_display->output_set_mode(private_output->output_backend, mode);
748
749     pthread_mutex_unlock(&private_display->lock);
750
751     return ret;
752 }
753
754 EXTERN tdm_error
755 tdm_output_get_mode(tdm_output *output, const tdm_output_mode **mode)
756 {
757     tdm_func_display *func_display;
758     OUTPUT_FUNC_ENTRY();
759
760     TDM_RETURN_VAL_IF_FAIL(mode != NULL, TDM_ERROR_INVALID_PARAMETER);
761
762     pthread_mutex_lock(&private_display->lock);
763
764     func_display = &private_display->func_display;
765
766     if (!func_display->output_get_mode)
767     {
768         pthread_mutex_unlock(&private_display->lock);
769         return TDM_ERROR_NONE;
770     }
771
772     ret = func_display->output_get_mode(private_output->output_backend, mode);
773
774     pthread_mutex_unlock(&private_display->lock);
775
776     return ret;
777 }
778
779 EXTERN tdm_error
780 tdm_output_set_dpms(tdm_output *output, tdm_output_dpms dpms_value)
781 {
782     tdm_func_display *func_display;
783     OUTPUT_FUNC_ENTRY();
784
785     TDM_RETURN_VAL_IF_FAIL(dpms_value >= TDM_OUTPUT_DPMS_ON, TDM_ERROR_INVALID_PARAMETER);
786     TDM_RETURN_VAL_IF_FAIL(dpms_value < TDM_OUTPUT_DPMS_MAX, TDM_ERROR_INVALID_PARAMETER);
787
788     pthread_mutex_lock(&private_display->lock);
789
790     func_display = &private_display->func_display;
791
792     if (!func_display->output_set_dpms)
793     {
794         pthread_mutex_unlock(&private_display->lock);
795         return TDM_ERROR_NONE;
796     }
797
798     ret = func_display->output_set_dpms(private_output->output_backend, dpms_value);
799
800     pthread_mutex_unlock(&private_display->lock);
801
802     return ret;
803 }
804
805 EXTERN tdm_error
806 tdm_output_get_dpms(tdm_output *output, tdm_output_dpms *dpms_value)
807 {
808     tdm_func_display *func_display;
809     OUTPUT_FUNC_ENTRY();
810
811     TDM_RETURN_VAL_IF_FAIL(dpms_value != NULL, TDM_ERROR_INVALID_PARAMETER);
812
813     pthread_mutex_lock(&private_display->lock);
814
815     func_display = &private_display->func_display;
816
817     if (!func_display->output_get_dpms)
818     {
819         pthread_mutex_unlock(&private_display->lock);
820         return TDM_ERROR_NONE;
821     }
822
823     ret = func_display->output_get_dpms(private_output->output_backend, dpms_value);
824
825     pthread_mutex_unlock(&private_display->lock);
826
827     return ret;
828 }
829
830 EXTERN tdm_capture*
831 tdm_output_create_capture(tdm_output *output, tdm_error *error)
832 {
833     tdm_capture *capture = NULL;
834
835     OUTPUT_FUNC_ENTRY_ERROR();
836
837     pthread_mutex_lock(&private_display->lock);
838
839     capture = (tdm_capture*)tdm_capture_create_output_internal(private_output, error);
840
841     pthread_mutex_unlock(&private_display->lock);
842
843     return capture;
844 }
845
846 EXTERN tdm_error
847 tdm_layer_get_capabilities(tdm_layer *layer, tdm_layer_capability *capabilities)
848 {
849     LAYER_FUNC_ENTRY();
850
851     TDM_RETURN_VAL_IF_FAIL(capabilities != NULL, TDM_ERROR_INVALID_PARAMETER);
852
853     pthread_mutex_lock(&private_display->lock);
854
855     *capabilities = private_layer->caps.capabilities;
856
857     pthread_mutex_unlock(&private_display->lock);
858
859     return ret;
860 }
861
862 EXTERN tdm_error
863 tdm_layer_get_available_formats(tdm_layer *layer, const tbm_format **formats, int *count)
864 {
865     LAYER_FUNC_ENTRY();
866
867     TDM_RETURN_VAL_IF_FAIL(formats != NULL, TDM_ERROR_INVALID_PARAMETER);
868     TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
869
870     pthread_mutex_lock(&private_display->lock);
871
872     *formats = (const tbm_format*)private_layer->caps.formats;
873     *count = private_layer->caps.format_count;
874
875     pthread_mutex_unlock(&private_display->lock);
876
877     return ret;
878 }
879
880 EXTERN tdm_error
881 tdm_layer_get_available_properties(tdm_layer *layer, const tdm_prop **props, int *count)
882 {
883     LAYER_FUNC_ENTRY();
884
885     TDM_RETURN_VAL_IF_FAIL(props != NULL, TDM_ERROR_INVALID_PARAMETER);
886     TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
887
888     pthread_mutex_lock(&private_display->lock);
889
890     *props = (const tdm_prop*)private_layer->caps.props;
891     *count = private_layer->caps.prop_count;
892
893     pthread_mutex_unlock(&private_display->lock);
894
895     return ret;
896 }
897
898 EXTERN tdm_error
899 tdm_layer_get_zpos(tdm_layer *layer, unsigned int *zpos)
900 {
901     LAYER_FUNC_ENTRY();
902
903     TDM_RETURN_VAL_IF_FAIL(zpos != NULL, TDM_ERROR_INVALID_PARAMETER);
904
905     pthread_mutex_lock(&private_display->lock);
906
907     *zpos = private_layer->caps.zpos;
908
909     pthread_mutex_unlock(&private_display->lock);
910
911     return ret;
912 }
913
914 EXTERN tdm_error
915 tdm_layer_set_property(tdm_layer *layer, unsigned int id, tdm_value value)
916 {
917     tdm_func_display *func_display;
918     LAYER_FUNC_ENTRY();
919
920     pthread_mutex_lock(&private_display->lock);
921
922     func_display = &private_display->func_display;
923
924     if (!func_display->layer_set_property)
925     {
926         pthread_mutex_unlock(&private_display->lock);
927         return TDM_ERROR_NONE;
928     }
929
930     ret = func_display->layer_set_property(private_layer->layer_backend, id, value);
931
932     pthread_mutex_unlock(&private_display->lock);
933
934     return ret;
935 }
936
937 EXTERN tdm_error
938 tdm_layer_get_property(tdm_layer *layer, unsigned int id, tdm_value *value)
939 {
940     tdm_func_display *func_display;
941     LAYER_FUNC_ENTRY();
942
943     TDM_RETURN_VAL_IF_FAIL(value != NULL, TDM_ERROR_INVALID_PARAMETER);
944
945     pthread_mutex_lock(&private_display->lock);
946
947     func_display = &private_display->func_display;
948
949     if (!func_display->layer_get_property)
950     {
951         pthread_mutex_unlock(&private_display->lock);
952         return TDM_ERROR_NONE;
953     }
954
955     ret = func_display->layer_get_property(private_layer->layer_backend, id, value);
956
957     pthread_mutex_unlock(&private_display->lock);
958
959     return ret;
960 }
961
962 EXTERN tdm_error
963 tdm_layer_set_info(tdm_layer *layer, tdm_info_layer *info)
964 {
965     tdm_func_display *func_display;
966     LAYER_FUNC_ENTRY();
967
968     TDM_RETURN_VAL_IF_FAIL(info != NULL, TDM_ERROR_INVALID_PARAMETER);
969
970     pthread_mutex_lock(&private_display->lock);
971
972     func_display = &private_display->func_display;
973
974     private_layer->usable = 0;
975
976     if (!func_display->layer_set_info)
977     {
978         pthread_mutex_unlock(&private_display->lock);
979         return TDM_ERROR_NONE;
980     }
981
982     ret = func_display->layer_set_info(private_layer->layer_backend, info);
983
984     pthread_mutex_unlock(&private_display->lock);
985
986     return ret;
987 }
988
989 EXTERN tdm_error
990 tdm_layer_get_info(tdm_layer *layer, tdm_info_layer *info)
991 {
992     tdm_func_display *func_display;
993     LAYER_FUNC_ENTRY();
994
995     TDM_RETURN_VAL_IF_FAIL(info != NULL, TDM_ERROR_INVALID_PARAMETER);
996
997     pthread_mutex_lock(&private_display->lock);
998
999     func_display = &private_display->func_display;
1000
1001     if (!func_display->layer_get_info)
1002     {
1003         pthread_mutex_unlock(&private_display->lock);
1004         return TDM_ERROR_NONE;
1005     }
1006
1007     ret = func_display->layer_get_info(private_layer->layer_backend, info);
1008
1009     pthread_mutex_unlock(&private_display->lock);
1010
1011     return ret;
1012 }
1013
1014 EXTERN tdm_error
1015 tdm_layer_set_buffer(tdm_layer *layer, tdm_buffer *buffer)
1016 {
1017     tdm_func_display *func_display;
1018     LAYER_FUNC_ENTRY();
1019
1020     TDM_RETURN_VAL_IF_FAIL(buffer != NULL, TDM_ERROR_INVALID_PARAMETER);
1021
1022     pthread_mutex_lock(&private_display->lock);
1023
1024     func_display = &private_display->func_display;
1025
1026     private_layer->usable = 0;
1027
1028     if (!func_display->layer_set_buffer)
1029     {
1030         pthread_mutex_unlock(&private_display->lock);
1031         return TDM_ERROR_NONE;
1032     }
1033
1034     if (private_layer->waiting_buffer)
1035     {
1036         pthread_mutex_unlock(&private_display->lock);
1037         tdm_buffer_unref_backend(private_layer->waiting_buffer);
1038         pthread_mutex_lock(&private_display->lock);
1039     }
1040
1041     private_layer->waiting_buffer = 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->waiting_buffer)
1062     {
1063         pthread_mutex_unlock(&private_display->lock);
1064         tdm_buffer_unref_backend(private_layer->waiting_buffer);
1065         pthread_mutex_lock(&private_display->lock);
1066         private_layer->waiting_buffer = NULL;
1067     }
1068
1069     if (private_layer->showing_buffer)
1070     {
1071         pthread_mutex_unlock(&private_display->lock);
1072         tdm_buffer_unref_backend(private_layer->showing_buffer);
1073         pthread_mutex_lock(&private_display->lock);
1074         private_layer->showing_buffer = NULL;
1075     }
1076
1077     private_layer->usable = 1;
1078
1079     if (!func_display->layer_unset_buffer)
1080     {
1081         pthread_mutex_unlock(&private_display->lock);
1082         return TDM_ERROR_NONE;
1083     }
1084
1085     ret = func_display->layer_unset_buffer(private_layer->layer_backend);
1086
1087     pthread_mutex_unlock(&private_display->lock);
1088
1089     return ret;
1090 }
1091
1092 EXTERN tdm_error
1093 tdm_layer_is_usable(tdm_layer *layer, unsigned int *usable)
1094 {
1095     LAYER_FUNC_ENTRY();
1096
1097     TDM_RETURN_VAL_IF_FAIL(usable != NULL, TDM_ERROR_INVALID_PARAMETER);
1098
1099     pthread_mutex_lock(&private_display->lock);
1100
1101     *usable = private_layer->usable;
1102
1103     pthread_mutex_unlock(&private_display->lock);
1104
1105     return ret;
1106 }
1107
1108
1109 EXTERN tdm_capture*
1110 tdm_layer_create_capture(tdm_layer *layer, tdm_error *error)
1111 {
1112     tdm_capture *capture = NULL;
1113
1114     LAYER_FUNC_ENTRY_ERROR();
1115
1116     pthread_mutex_lock(&private_display->lock);
1117
1118     capture = (tdm_capture*)tdm_capture_create_layer_internal(private_layer, error);
1119
1120     pthread_mutex_unlock(&private_display->lock);
1121
1122     return capture;
1123 }