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