support the output change handler
[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 #define LAYER_FUNC_ENTRY_VOID_RETURN() \
95     tdm_private_display *private_display; \
96     tdm_private_output *private_output; \
97     tdm_private_layer *private_layer; \
98     tdm_error ret = TDM_ERROR_NONE; /* default TDM_ERROR_NONE */\
99     TDM_RETURN_IF_FAIL(layer != NULL); \
100     private_layer = (tdm_private_layer*)layer; \
101     private_output = private_layer->private_output; \
102     private_display = private_output->private_display
103
104 #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
105
106 struct type_name {
107         int type;
108         const char *name;
109 };
110
111 #define type_name_fn(res) \
112 const char * res##_str(int type) {                      \
113         unsigned int i;                                 \
114         for (i = 0; i < ARRAY_SIZE(res##_names); i++) { \
115                 if (res##_names[i].type == type)        \
116                         return res##_names[i].name;     \
117         }                                               \
118         return "(invalid)";                             \
119 }
120
121 struct type_name dpms_names[] = {
122         { TDM_OUTPUT_DPMS_ON, "on" },
123         { TDM_OUTPUT_DPMS_STANDBY, "standby" },
124         { TDM_OUTPUT_DPMS_SUSPEND, "suspend" },
125         { TDM_OUTPUT_DPMS_OFF, "off" },
126 };
127
128 static type_name_fn(dpms)
129
130 struct type_name status_names[] = {
131         { TDM_OUTPUT_CONN_STATUS_DISCONNECTED, "disconnected" },
132         { TDM_OUTPUT_CONN_STATUS_CONNECTED, "connected" },
133         { TDM_OUTPUT_CONN_STATUS_MODE_SETTED, "mode_setted" },
134 };
135
136 static type_name_fn(status)
137
138 EXTERN tdm_error
139 tdm_display_get_capabilities(tdm_display *dpy,
140                              tdm_display_capability *capabilities)
141 {
142         DISPLAY_FUNC_ENTRY();
143
144         TDM_RETURN_VAL_IF_FAIL(capabilities != NULL, TDM_ERROR_INVALID_PARAMETER);
145
146         _pthread_mutex_lock(&private_display->lock);
147
148         *capabilities = private_display->capabilities;
149
150         _pthread_mutex_unlock(&private_display->lock);
151
152         return ret;
153 }
154
155 EXTERN tdm_error
156 tdm_display_get_pp_capabilities(tdm_display *dpy,
157                                 tdm_pp_capability *capabilities)
158 {
159         DISPLAY_FUNC_ENTRY();
160
161         TDM_RETURN_VAL_IF_FAIL(capabilities != NULL, TDM_ERROR_INVALID_PARAMETER);
162
163         _pthread_mutex_lock(&private_display->lock);
164
165         if (!(private_display->capabilities & TDM_DISPLAY_CAPABILITY_PP)) {
166                 TDM_ERR("no pp capability");
167                 _pthread_mutex_unlock(&private_display->lock);
168                 return TDM_ERROR_NO_CAPABILITY;
169         }
170
171         *capabilities = private_display->caps_pp.capabilities;
172
173         _pthread_mutex_unlock(&private_display->lock);
174
175         return ret;
176 }
177
178 EXTERN tdm_error
179 tdm_display_get_pp_available_formats(tdm_display *dpy,
180                                      const tbm_format **formats, int *count)
181 {
182         DISPLAY_FUNC_ENTRY();
183
184         TDM_RETURN_VAL_IF_FAIL(formats != NULL, TDM_ERROR_INVALID_PARAMETER);
185         TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
186
187         _pthread_mutex_lock(&private_display->lock);
188
189         if (!(private_display->capabilities & TDM_DISPLAY_CAPABILITY_PP)) {
190                 TDM_ERR("no pp capability");
191                 _pthread_mutex_unlock(&private_display->lock);
192                 return TDM_ERROR_NO_CAPABILITY;
193         }
194
195         *formats = (const tbm_format *)private_display->caps_pp.formats;
196         *count = private_display->caps_pp.format_count;
197
198         _pthread_mutex_unlock(&private_display->lock);
199
200         return ret;
201 }
202
203 EXTERN tdm_error
204 tdm_display_get_pp_available_size(tdm_display *dpy, int *min_w, int *min_h,
205                                   int *max_w, int *max_h, int *preferred_align)
206 {
207         DISPLAY_FUNC_ENTRY();
208
209         _pthread_mutex_lock(&private_display->lock);
210
211         if (!(private_display->capabilities & TDM_DISPLAY_CAPABILITY_PP)) {
212                 TDM_ERR("no pp capability");
213                 _pthread_mutex_unlock(&private_display->lock);
214                 return TDM_ERROR_NO_CAPABILITY;
215         }
216
217         if (min_w)
218                 *min_w = private_display->caps_pp.min_w;
219         if (min_h)
220                 *min_h = private_display->caps_pp.min_h;
221         if (max_w)
222                 *max_w = private_display->caps_pp.max_w;
223         if (max_h)
224                 *max_h = private_display->caps_pp.max_h;
225         if (preferred_align)
226                 *preferred_align = private_display->caps_pp.preferred_align;
227
228         _pthread_mutex_unlock(&private_display->lock);
229
230         return ret;
231 }
232
233 EXTERN tdm_error
234 tdm_display_get_capture_capabilities(tdm_display *dpy,
235                                      tdm_capture_capability *capabilities)
236 {
237         DISPLAY_FUNC_ENTRY();
238
239         TDM_RETURN_VAL_IF_FAIL(capabilities != NULL, TDM_ERROR_INVALID_PARAMETER);
240
241         _pthread_mutex_lock(&private_display->lock);
242
243         if (!(private_display->capabilities & TDM_DISPLAY_CAPABILITY_CAPTURE)) {
244                 TDM_ERR("no capture capability");
245                 _pthread_mutex_unlock(&private_display->lock);
246                 return TDM_ERROR_NO_CAPABILITY;
247         }
248
249         *capabilities = private_display->caps_capture.capabilities;
250
251         _pthread_mutex_unlock(&private_display->lock);
252
253         return ret;
254 }
255
256 EXTERN tdm_error
257 tdm_display_get_catpure_available_formats(tdm_display *dpy,
258                 const tbm_format **formats, int *count)
259 {
260         DISPLAY_FUNC_ENTRY();
261
262         TDM_RETURN_VAL_IF_FAIL(formats != NULL, TDM_ERROR_INVALID_PARAMETER);
263         TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
264
265         _pthread_mutex_lock(&private_display->lock);
266
267         if (!(private_display->capabilities & TDM_DISPLAY_CAPABILITY_CAPTURE)) {
268                 TDM_ERR("no capture capability");
269                 _pthread_mutex_unlock(&private_display->lock);
270                 return TDM_ERROR_NO_CAPABILITY;
271         }
272
273         *formats = (const tbm_format *)private_display->caps_capture.formats;
274         *count = private_display->caps_capture.format_count;
275
276         _pthread_mutex_unlock(&private_display->lock);
277
278         return ret;
279 }
280
281 EXTERN tdm_error
282 tdm_display_get_output_count(tdm_display *dpy, int *count)
283 {
284         tdm_private_output *private_output = NULL;
285
286         DISPLAY_FUNC_ENTRY();
287
288         TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
289
290         _pthread_mutex_lock(&private_display->lock);
291
292         *count = 0;
293         LIST_FOR_EACH_ENTRY(private_output, &private_display->output_list, link)
294         (*count)++;
295
296         if (*count == 0) {
297                 _pthread_mutex_unlock(&private_display->lock);
298                 return TDM_ERROR_NONE;
299         }
300
301         _pthread_mutex_unlock(&private_display->lock);
302
303         return ret;
304 }
305
306
307 EXTERN tdm_output *
308 tdm_display_get_output(tdm_display *dpy, int index, tdm_error *error)
309 {
310         tdm_private_output *private_output = NULL;
311         int i = 0;
312
313         DISPLAY_FUNC_ENTRY_ERROR();
314
315         _pthread_mutex_lock(&private_display->lock);
316
317         if (error)
318                 *error = TDM_ERROR_NONE;
319
320         i = 0;
321         LIST_FOR_EACH_ENTRY(private_output, &private_display->output_list, link) {
322                 if (i == index) {
323                         _pthread_mutex_unlock(&private_display->lock);
324                         return private_output;
325                 }
326                 i++;
327         }
328
329         _pthread_mutex_unlock(&private_display->lock);
330
331         return NULL;
332 }
333
334 EXTERN tdm_error
335 tdm_display_get_fd(tdm_display *dpy, int *fd)
336 {
337         DISPLAY_FUNC_ENTRY();
338
339         TDM_RETURN_VAL_IF_FAIL(fd != NULL, TDM_ERROR_INVALID_PARAMETER);
340
341         _pthread_mutex_lock(&private_display->lock);
342
343         *fd = tdm_event_get_fd(private_display);
344
345         _pthread_mutex_unlock(&private_display->lock);
346
347         return ret;
348 }
349
350 EXTERN tdm_error
351 tdm_display_handle_events(tdm_display *dpy)
352 {
353         DISPLAY_FUNC_ENTRY();
354
355         _pthread_mutex_lock(&private_display->lock);
356
357         ret = tdm_event_dispatch(private_display);
358
359         _pthread_mutex_unlock(&private_display->lock);
360
361         return ret;
362 }
363
364 EXTERN tdm_pp *
365 tdm_display_create_pp(tdm_display *dpy, tdm_error *error)
366 {
367         tdm_pp *pp;
368
369         DISPLAY_FUNC_ENTRY_ERROR();
370
371         _pthread_mutex_lock(&private_display->lock);
372
373         pp = (tdm_pp *)tdm_pp_create_internal(private_display, error);
374
375         _pthread_mutex_unlock(&private_display->lock);
376
377         return pp;
378 }
379
380 EXTERN tdm_error
381 tdm_output_get_model_info(tdm_output *output, const char **maker,
382                           const char **model, const char **name)
383 {
384         OUTPUT_FUNC_ENTRY();
385
386         _pthread_mutex_lock(&private_display->lock);
387
388         if (maker)
389                 *maker = private_output->caps.maker;
390         if (model)
391                 *model = private_output->caps.model;
392         if (name)
393                 *name = private_output->caps.name;
394
395         _pthread_mutex_unlock(&private_display->lock);
396
397         return ret;
398 }
399
400 EXTERN tdm_error
401 tdm_output_get_conn_status(tdm_output *output, tdm_output_conn_status *status)
402 {
403         OUTPUT_FUNC_ENTRY();
404
405         TDM_RETURN_VAL_IF_FAIL(status != NULL, TDM_ERROR_INVALID_PARAMETER);
406
407         _pthread_mutex_lock(&private_display->lock);
408
409         *status = private_output->caps.status;
410
411         _pthread_mutex_unlock(&private_display->lock);
412
413         return ret;
414 }
415
416 EXTERN tdm_error
417 tdm_output_add_change_handler(tdm_output *output,
418                               tdm_output_change_handler func,
419                               void *user_data)
420 {
421         tdm_private_change_handler *change_handler;
422         OUTPUT_FUNC_ENTRY();
423
424         TDM_RETURN_VAL_IF_FAIL(func != NULL, TDM_ERROR_INVALID_PARAMETER);
425
426         pthread_mutex_lock(&private_display->lock);
427
428         if (!private_output->regist_change_cb) {
429                 _pthread_mutex_unlock(&private_display->lock);
430                 TDM_DBG("failed: not implemented!!");
431                 return TDM_ERROR_NOT_IMPLEMENTED;
432         }
433
434         change_handler = calloc(1, sizeof(tdm_private_change_handler));
435         if (!change_handler) {
436                 TDM_ERR("failed: alloc memory");
437                 _pthread_mutex_unlock(&private_display->lock);
438                 return TDM_ERROR_OUT_OF_MEMORY;
439         }
440
441         LIST_ADD(&change_handler->link, &private_output->change_handler_list);
442         change_handler->private_output = private_output;
443         change_handler->func = func;
444         change_handler->user_data = user_data;
445
446         _pthread_mutex_unlock(&private_display->lock);
447
448         return ret;
449 }
450
451 EXTERN void
452 tdm_output_remove_change_handler(tdm_output *output,
453                                  tdm_output_change_handler func,
454                                  void *user_data)
455 {
456         tdm_private_display *private_display;
457         tdm_private_output *private_output;
458         tdm_private_change_handler *h = NULL, *hh = NULL;
459
460         TDM_RETURN_IF_FAIL(output != NULL);
461         TDM_RETURN_IF_FAIL(func != NULL);
462
463         private_output = (tdm_private_output*)output;
464         private_display = private_output->private_display;
465
466         _pthread_mutex_lock(&private_display->lock);
467
468         LIST_FOR_EACH_ENTRY_SAFE(h, hh, &private_output->change_handler_list, link) {
469                 if (h->func != func || h->user_data != user_data)
470                         continue;
471
472                 LIST_DEL(&h->link);
473                 free(h);
474
475                 _pthread_mutex_unlock(&private_display->lock);
476
477                 return;
478         }
479
480         _pthread_mutex_unlock(&private_display->lock);
481 }
482
483 EXTERN tdm_error
484 tdm_output_get_output_type(tdm_output *output, tdm_output_type *type)
485 {
486         OUTPUT_FUNC_ENTRY();
487
488         TDM_RETURN_VAL_IF_FAIL(type != NULL, TDM_ERROR_INVALID_PARAMETER);
489
490         _pthread_mutex_lock(&private_display->lock);
491
492         *type = private_output->caps.type;
493
494         _pthread_mutex_unlock(&private_display->lock);
495
496         return ret;
497 }
498
499 EXTERN tdm_error
500 tdm_output_get_layer_count(tdm_output *output, int *count)
501 {
502         tdm_private_layer *private_layer = NULL;
503
504         OUTPUT_FUNC_ENTRY();
505
506         TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
507
508         _pthread_mutex_lock(&private_display->lock);
509
510         *count = 0;
511         LIST_FOR_EACH_ENTRY(private_layer, &private_output->layer_list, link)
512         (*count)++;
513         if (*count == 0) {
514                 _pthread_mutex_unlock(&private_display->lock);
515                 return TDM_ERROR_NONE;
516         }
517
518         _pthread_mutex_unlock(&private_display->lock);
519
520         return ret;
521 }
522
523
524 EXTERN tdm_layer *
525 tdm_output_get_layer(tdm_output *output, int index, tdm_error *error)
526 {
527         tdm_private_layer *private_layer = NULL;
528         int i = 0;
529
530         OUTPUT_FUNC_ENTRY_ERROR();
531
532         _pthread_mutex_lock(&private_display->lock);
533
534         if (error)
535                 *error = TDM_ERROR_NONE;
536
537         LIST_FOR_EACH_ENTRY(private_layer, &private_output->layer_list, link) {
538                 if (i == index) {
539                         _pthread_mutex_unlock(&private_display->lock);
540                         return private_layer;
541                 }
542                 i++;
543         }
544
545         _pthread_mutex_unlock(&private_display->lock);
546
547         return NULL;
548 }
549
550 EXTERN tdm_error
551 tdm_output_get_available_properties(tdm_output *output, const tdm_prop **props,
552                                     int *count)
553 {
554         OUTPUT_FUNC_ENTRY();
555
556         TDM_RETURN_VAL_IF_FAIL(props != NULL, TDM_ERROR_INVALID_PARAMETER);
557         TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
558
559         _pthread_mutex_lock(&private_display->lock);
560
561         *props = (const tdm_prop *)private_output->caps.props;
562         *count = private_output->caps.prop_count;
563
564         _pthread_mutex_unlock(&private_display->lock);
565
566         return ret;
567 }
568
569 EXTERN tdm_error
570 tdm_output_get_available_modes(tdm_output *output,
571                                const tdm_output_mode **modes, int *count)
572 {
573         OUTPUT_FUNC_ENTRY();
574
575         TDM_RETURN_VAL_IF_FAIL(modes != NULL, TDM_ERROR_INVALID_PARAMETER);
576         TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
577
578         _pthread_mutex_lock(&private_display->lock);
579
580         *modes = (const tdm_output_mode *)private_output->caps.modes;
581         *count = private_output->caps.mode_count;
582
583         _pthread_mutex_unlock(&private_display->lock);
584
585         return ret;
586 }
587
588 EXTERN tdm_error
589 tdm_output_get_available_size(tdm_output *output, int *min_w, int *min_h,
590                               int *max_w, int *max_h, int *preferred_align)
591 {
592         OUTPUT_FUNC_ENTRY();
593
594         _pthread_mutex_lock(&private_display->lock);
595
596         if (min_w)
597                 *min_w = private_output->caps.min_w;
598         if (min_h)
599                 *min_h = private_output->caps.min_h;
600         if (max_w)
601                 *max_w = private_output->caps.max_w;
602         if (max_h)
603                 *max_h = private_output->caps.max_h;
604         if (preferred_align)
605                 *preferred_align = private_output->caps.preferred_align;
606
607         _pthread_mutex_unlock(&private_display->lock);
608
609         return ret;
610 }
611
612 EXTERN tdm_error
613 tdm_output_get_physical_size(tdm_output *output, unsigned int *mmWidth,
614                              unsigned int *mmHeight)
615 {
616         OUTPUT_FUNC_ENTRY();
617
618         _pthread_mutex_lock(&private_display->lock);
619
620         if (mmWidth)
621                 *mmWidth = private_output->caps.mmWidth;
622         if (mmHeight)
623                 *mmHeight = private_output->caps.mmHeight;
624
625         _pthread_mutex_unlock(&private_display->lock);
626
627         return ret;
628 }
629
630 EXTERN tdm_error
631 tdm_output_get_subpixel(tdm_output *output, unsigned int *subpixel)
632 {
633         OUTPUT_FUNC_ENTRY();
634         TDM_RETURN_VAL_IF_FAIL(subpixel != NULL, TDM_ERROR_INVALID_PARAMETER);
635
636         _pthread_mutex_lock(&private_display->lock);
637
638         *subpixel = private_output->caps.subpixel;
639
640         _pthread_mutex_unlock(&private_display->lock);
641
642         return ret;
643 }
644
645 EXTERN tdm_error
646 tdm_output_get_pipe(tdm_output *output, unsigned int *pipe)
647 {
648         OUTPUT_FUNC_ENTRY();
649         TDM_RETURN_VAL_IF_FAIL(pipe != NULL, TDM_ERROR_INVALID_PARAMETER);
650
651         _pthread_mutex_lock(&private_display->lock);
652
653         *pipe = private_output->pipe;
654
655         _pthread_mutex_unlock(&private_display->lock);
656
657         return ret;
658 }
659
660
661 EXTERN tdm_error
662 tdm_output_set_property(tdm_output *output, unsigned int id, tdm_value value)
663 {
664         tdm_func_output *func_output;
665         OUTPUT_FUNC_ENTRY();
666
667         _pthread_mutex_lock(&private_display->lock);
668
669         func_output = &private_display->func_output;
670
671         if (!func_output->output_set_property) {
672                 _pthread_mutex_unlock(&private_display->lock);
673                 TDM_DBG("failed: not implemented!!");
674                 return TDM_ERROR_NOT_IMPLEMENTED;
675         }
676
677         ret = func_output->output_set_property(private_output->output_backend, id,
678                                                value);
679
680         _pthread_mutex_unlock(&private_display->lock);
681
682         return ret;
683 }
684
685 EXTERN tdm_error
686 tdm_output_get_property(tdm_output *output, unsigned int id, tdm_value *value)
687 {
688         tdm_func_output *func_output;
689         OUTPUT_FUNC_ENTRY();
690
691         TDM_RETURN_VAL_IF_FAIL(value != NULL, TDM_ERROR_INVALID_PARAMETER);
692
693         _pthread_mutex_lock(&private_display->lock);
694
695         func_output = &private_display->func_output;
696
697         if (!func_output->output_get_property) {
698                 _pthread_mutex_unlock(&private_display->lock);
699                 TDM_DBG("failed: not implemented!!");
700                 return TDM_ERROR_NOT_IMPLEMENTED;
701         }
702
703         ret = func_output->output_get_property(private_output->output_backend, id,
704                                                value);
705
706         _pthread_mutex_unlock(&private_display->lock);
707
708         return ret;
709 }
710
711 static void
712 _tdm_output_cb_vblank(tdm_output *output_backend, unsigned int sequence,
713                       unsigned int tv_sec, unsigned int tv_usec, void *user_data)
714 {
715         tdm_private_vblank_handler *vblank_handler = user_data;
716         tdm_private_display *private_display;
717
718         TDM_RETURN_IF_FAIL(vblank_handler);
719
720         private_display = vblank_handler->private_output->private_display;
721
722         if (vblank_handler->func) {
723                 _pthread_mutex_unlock(&private_display->lock);
724                 vblank_handler->func(vblank_handler->private_output, sequence,
725                                      tv_sec, tv_usec, vblank_handler->user_data);
726                 _pthread_mutex_lock(&private_display->lock);
727         }
728
729         LIST_DEL(&vblank_handler->link);
730         free(vblank_handler);
731 }
732
733 static void
734 _tdm_output_cb_commit(tdm_output *output_backend, unsigned int sequence,
735                       unsigned int tv_sec, unsigned int tv_usec, void *user_data)
736 {
737         tdm_private_commit_handler *commit_handler = user_data;
738         tdm_private_display *private_display;
739         tdm_private_output *private_output;
740         tdm_private_layer *private_layer = NULL;
741
742         TDM_RETURN_IF_FAIL(commit_handler);
743
744         private_output = commit_handler->private_output;
745         private_display = private_output->private_display;
746
747         LIST_FOR_EACH_ENTRY(private_layer, &private_output->layer_list, link) {
748                 if (!private_layer->waiting_buffer)
749                         continue;
750
751                 if (private_layer->showing_buffer) {
752                         _pthread_mutex_unlock(&private_display->lock);
753                         tdm_buffer_unref_backend(private_layer->showing_buffer);
754                         _pthread_mutex_lock(&private_display->lock);
755
756                         if (private_layer->buffer_queue) {
757                                 _pthread_mutex_unlock(&private_display->lock);
758                                 tbm_surface_queue_release(private_layer->buffer_queue,
759                                                           private_layer->showing_buffer);
760                                 _pthread_mutex_lock(&private_display->lock);
761                         }
762                 }
763
764                 private_layer->showing_buffer = private_layer->waiting_buffer;
765                 private_layer->waiting_buffer = NULL;
766
767                 if (tdm_debug_buffer)
768                         TDM_INFO("layer(%p) waiting_buffer(%p) showing_buffer(%p)",
769                                  private_layer, private_layer->waiting_buffer,
770                                  private_layer->showing_buffer);
771         }
772
773         if (commit_handler->func) {
774                 _pthread_mutex_unlock(&private_display->lock);
775                 commit_handler->func(private_output, sequence,
776                                      tv_sec, tv_usec, commit_handler->user_data);
777                 _pthread_mutex_lock(&private_display->lock);
778         }
779
780         LIST_DEL(&commit_handler->link);
781         free(commit_handler);
782 }
783
784 EXTERN tdm_error
785 tdm_output_wait_vblank(tdm_output *output, int interval, int sync,
786                        tdm_output_vblank_handler func, void *user_data)
787 {
788         tdm_func_output *func_output;
789         tdm_private_vblank_handler *vblank_handler;
790         OUTPUT_FUNC_ENTRY();
791
792         _pthread_mutex_lock(&private_display->lock);
793
794         func_output = &private_display->func_output;
795
796         if (!func_output->output_wait_vblank) {
797                 _pthread_mutex_unlock(&private_display->lock);
798                 TDM_DBG("failed: not implemented!!");
799                 return TDM_ERROR_NOT_IMPLEMENTED;
800         }
801
802         vblank_handler = calloc(1, sizeof(tdm_private_vblank_handler));
803         if (!vblank_handler) {
804                 TDM_ERR("failed: alloc memory");
805                 _pthread_mutex_unlock(&private_display->lock);
806                 return TDM_ERROR_OUT_OF_MEMORY;
807         }
808
809         LIST_ADD(&vblank_handler->link, &private_output->vblank_handler_list);
810         vblank_handler->private_output = private_output;
811         vblank_handler->func = func;
812         vblank_handler->user_data = user_data;
813
814         ret = func_output->output_wait_vblank(private_output->output_backend, interval,
815                                               sync, vblank_handler);
816         if (ret != TDM_ERROR_NONE) {
817                 _pthread_mutex_unlock(&private_display->lock);
818                 return ret;
819         }
820
821         if (!private_output->regist_vblank_cb) {
822                 private_output->regist_vblank_cb = 1;
823                 ret = func_output->output_set_vblank_handler(private_output->output_backend,
824                                 _tdm_output_cb_vblank);
825         }
826
827         _pthread_mutex_unlock(&private_display->lock);
828
829         return ret;
830 }
831
832 static tdm_error
833 _tdm_output_commit(tdm_output *output, int sync, tdm_output_commit_handler func,
834                    void *user_data)
835 {
836         tdm_func_output *func_output;
837         tdm_private_commit_handler *commit_handler;
838         OUTPUT_FUNC_ENTRY();
839
840         func_output = &private_display->func_output;
841
842         if (!func_output->output_commit) {
843                 TDM_DBG("failed: not implemented!!");
844                 return TDM_ERROR_NOT_IMPLEMENTED;
845         }
846
847         commit_handler = calloc(1, sizeof(tdm_private_commit_handler));
848         if (!commit_handler) {
849                 TDM_ERR("failed: alloc memory");
850                 return TDM_ERROR_OUT_OF_MEMORY;
851         }
852
853         LIST_ADD(&commit_handler->link, &private_output->commit_handler_list);
854         commit_handler->private_output = private_output;
855         commit_handler->func = func;
856         commit_handler->user_data = user_data;
857
858         ret = func_output->output_commit(private_output->output_backend, sync,
859                                          commit_handler);
860         TDM_RETURN_VAL_IF_FAIL(ret == TDM_ERROR_NONE, ret);
861
862         if (!private_output->regist_commit_cb) {
863                 private_output->regist_commit_cb = 1;
864                 ret = func_output->output_set_commit_handler(private_output->output_backend,
865                                 _tdm_output_cb_commit);
866         }
867
868         return ret;
869 }
870
871 EXTERN tdm_error
872 tdm_output_commit(tdm_output *output, int sync, tdm_output_commit_handler func,
873                   void *user_data)
874 {
875         OUTPUT_FUNC_ENTRY();
876
877         _pthread_mutex_lock(&private_display->lock);
878
879         ret = _tdm_output_commit(output, sync, func, user_data);
880
881         _pthread_mutex_unlock(&private_display->lock);
882
883         return ret;
884 }
885
886 EXTERN tdm_error
887 tdm_output_set_mode(tdm_output *output, const tdm_output_mode *mode)
888 {
889         tdm_func_output *func_output;
890         OUTPUT_FUNC_ENTRY();
891
892         TDM_RETURN_VAL_IF_FAIL(mode != NULL, TDM_ERROR_INVALID_PARAMETER);
893
894         _pthread_mutex_lock(&private_display->lock);
895
896         func_output = &private_display->func_output;
897
898         if (!func_output->output_set_mode) {
899                 _pthread_mutex_unlock(&private_display->lock);
900                 TDM_DBG("failed: not implemented!!");
901                 return TDM_ERROR_NOT_IMPLEMENTED;
902         }
903
904         ret = func_output->output_set_mode(private_output->output_backend, mode);
905
906         _pthread_mutex_unlock(&private_display->lock);
907
908         return ret;
909 }
910
911 EXTERN tdm_error
912 tdm_output_get_mode(tdm_output *output, const tdm_output_mode **mode)
913 {
914         tdm_func_output *func_output;
915         OUTPUT_FUNC_ENTRY();
916
917         TDM_RETURN_VAL_IF_FAIL(mode != NULL, TDM_ERROR_INVALID_PARAMETER);
918
919         _pthread_mutex_lock(&private_display->lock);
920
921         func_output = &private_display->func_output;
922
923         if (!func_output->output_get_mode) {
924                 _pthread_mutex_unlock(&private_display->lock);
925                 TDM_DBG("failed: not implemented!!");
926                 return TDM_ERROR_NOT_IMPLEMENTED;
927         }
928
929         ret = func_output->output_get_mode(private_output->output_backend, mode);
930
931         _pthread_mutex_unlock(&private_display->lock);
932
933         return ret;
934 }
935
936 EXTERN tdm_error
937 tdm_output_set_dpms(tdm_output *output, tdm_output_dpms dpms_value)
938 {
939         tdm_func_output *func_output;
940         OUTPUT_FUNC_ENTRY();
941
942         if (dpms_value < TDM_OUTPUT_DPMS_ON)
943                 dpms_value = TDM_OUTPUT_DPMS_ON;
944         else if (dpms_value > TDM_OUTPUT_DPMS_OFF)
945                 dpms_value = TDM_OUTPUT_DPMS_OFF;
946
947         _pthread_mutex_lock(&private_display->lock);
948
949         func_output = &private_display->func_output;
950
951         if (!func_output->output_set_dpms) {
952                 _pthread_mutex_unlock(&private_display->lock);
953                 TDM_DBG("failed: not implemented!!");
954                 return TDM_ERROR_NOT_IMPLEMENTED;
955         }
956
957         ret = func_output->output_set_dpms(private_output->output_backend, dpms_value);
958
959         _pthread_mutex_unlock(&private_display->lock);
960
961         return ret;
962 }
963
964 EXTERN tdm_error
965 tdm_output_get_dpms(tdm_output *output, tdm_output_dpms *dpms_value)
966 {
967         tdm_func_output *func_output;
968         OUTPUT_FUNC_ENTRY();
969
970         TDM_RETURN_VAL_IF_FAIL(dpms_value != NULL, TDM_ERROR_INVALID_PARAMETER);
971
972         _pthread_mutex_lock(&private_display->lock);
973
974         func_output = &private_display->func_output;
975
976         if (!func_output->output_get_dpms) {
977                 _pthread_mutex_unlock(&private_display->lock);
978                 TDM_DBG("failed: not implemented!!");
979                 return TDM_ERROR_NOT_IMPLEMENTED;
980         }
981
982         ret = func_output->output_get_dpms(private_output->output_backend, dpms_value);
983
984         _pthread_mutex_unlock(&private_display->lock);
985
986         return ret;
987 }
988
989 EXTERN tdm_capture *
990 tdm_output_create_capture(tdm_output *output, tdm_error *error)
991 {
992         tdm_capture *capture = NULL;
993
994         OUTPUT_FUNC_ENTRY_ERROR();
995
996         _pthread_mutex_lock(&private_display->lock);
997
998         capture = (tdm_capture *)tdm_capture_create_output_internal(private_output,
999                         error);
1000
1001         _pthread_mutex_unlock(&private_display->lock);
1002
1003         return capture;
1004 }
1005
1006 INTERN void
1007 tdm_output_call_change_handler_internal(tdm_private_output *private_output,
1008                                         tdm_output_change_type type,
1009                                         tdm_value value)
1010 {
1011         tdm_private_change_handler *change_handler;
1012         tdm_private_display *private_display;
1013
1014         TDM_RETURN_IF_FAIL(private_output);
1015
1016         private_display = private_output->private_display;
1017
1018         if (type & TDM_OUTPUT_CHANGE_CONNECTION)
1019                 TDM_INFO("output(%d) changed: %s",
1020                          private_output->pipe, status_str(value.u32));
1021         if (type & TDM_OUTPUT_CHANGE_DPMS)
1022                 TDM_INFO("output(%d) changed: dpms %s",
1023                          private_output->pipe, dpms_str(value.u32));
1024
1025         _pthread_mutex_unlock(&private_display->lock);
1026
1027         LIST_FOR_EACH_ENTRY(change_handler, &private_output->change_handler_list, link) {
1028                 change_handler->func(private_output, type,
1029                                      value, change_handler->user_data);
1030         }
1031
1032         _pthread_mutex_lock(&private_display->lock);
1033 }
1034
1035 EXTERN tdm_error
1036 tdm_layer_get_capabilities(tdm_layer *layer, tdm_layer_capability *capabilities)
1037 {
1038         LAYER_FUNC_ENTRY();
1039
1040         TDM_RETURN_VAL_IF_FAIL(capabilities != NULL, TDM_ERROR_INVALID_PARAMETER);
1041
1042         _pthread_mutex_lock(&private_display->lock);
1043
1044         *capabilities = private_layer->caps.capabilities;
1045
1046         _pthread_mutex_unlock(&private_display->lock);
1047
1048         return ret;
1049 }
1050
1051 EXTERN tdm_error
1052 tdm_layer_get_available_formats(tdm_layer *layer, const tbm_format **formats,
1053                                 int *count)
1054 {
1055         LAYER_FUNC_ENTRY();
1056
1057         TDM_RETURN_VAL_IF_FAIL(formats != NULL, TDM_ERROR_INVALID_PARAMETER);
1058         TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
1059
1060         _pthread_mutex_lock(&private_display->lock);
1061
1062         *formats = (const tbm_format *)private_layer->caps.formats;
1063         *count = private_layer->caps.format_count;
1064
1065         _pthread_mutex_unlock(&private_display->lock);
1066
1067         return ret;
1068 }
1069
1070 EXTERN tdm_error
1071 tdm_layer_get_available_properties(tdm_layer *layer, const tdm_prop **props,
1072                                    int *count)
1073 {
1074         LAYER_FUNC_ENTRY();
1075
1076         TDM_RETURN_VAL_IF_FAIL(props != NULL, TDM_ERROR_INVALID_PARAMETER);
1077         TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
1078
1079         _pthread_mutex_lock(&private_display->lock);
1080
1081         *props = (const tdm_prop *)private_layer->caps.props;
1082         *count = private_layer->caps.prop_count;
1083
1084         _pthread_mutex_unlock(&private_display->lock);
1085
1086         return ret;
1087 }
1088
1089 EXTERN tdm_error
1090 tdm_layer_get_zpos(tdm_layer *layer, unsigned int *zpos)
1091 {
1092         LAYER_FUNC_ENTRY();
1093
1094         TDM_RETURN_VAL_IF_FAIL(zpos != NULL, TDM_ERROR_INVALID_PARAMETER);
1095
1096         _pthread_mutex_lock(&private_display->lock);
1097
1098         *zpos = private_layer->caps.zpos;
1099
1100         _pthread_mutex_unlock(&private_display->lock);
1101
1102         return ret;
1103 }
1104
1105 EXTERN tdm_error
1106 tdm_layer_set_property(tdm_layer *layer, unsigned int id, tdm_value value)
1107 {
1108         tdm_func_layer *func_layer;
1109         LAYER_FUNC_ENTRY();
1110
1111         _pthread_mutex_lock(&private_display->lock);
1112
1113         func_layer = &private_display->func_layer;
1114
1115         if (!func_layer->layer_set_property) {
1116                 _pthread_mutex_unlock(&private_display->lock);
1117                 TDM_DBG("failed: not implemented!!");
1118                 return TDM_ERROR_NOT_IMPLEMENTED;
1119         }
1120
1121         ret = func_layer->layer_set_property(private_layer->layer_backend, id, value);
1122
1123         _pthread_mutex_unlock(&private_display->lock);
1124
1125         return ret;
1126 }
1127
1128 EXTERN tdm_error
1129 tdm_layer_get_property(tdm_layer *layer, unsigned int id, tdm_value *value)
1130 {
1131         tdm_func_layer *func_layer;
1132         LAYER_FUNC_ENTRY();
1133
1134         TDM_RETURN_VAL_IF_FAIL(value != NULL, TDM_ERROR_INVALID_PARAMETER);
1135
1136         _pthread_mutex_lock(&private_display->lock);
1137
1138         func_layer = &private_display->func_layer;
1139
1140         if (!func_layer->layer_get_property) {
1141                 _pthread_mutex_unlock(&private_display->lock);
1142                 TDM_DBG("failed: not implemented!!");
1143                 return TDM_ERROR_NOT_IMPLEMENTED;
1144         }
1145
1146         ret = func_layer->layer_get_property(private_layer->layer_backend, id, value);
1147
1148         _pthread_mutex_unlock(&private_display->lock);
1149
1150         return ret;
1151 }
1152
1153 EXTERN tdm_error
1154 tdm_layer_set_info(tdm_layer *layer, tdm_info_layer *info)
1155 {
1156         tdm_func_layer *func_layer;
1157         LAYER_FUNC_ENTRY();
1158
1159         TDM_RETURN_VAL_IF_FAIL(info != NULL, TDM_ERROR_INVALID_PARAMETER);
1160
1161         _pthread_mutex_lock(&private_display->lock);
1162
1163         func_layer = &private_display->func_layer;
1164
1165         private_layer->usable = 0;
1166
1167         if (!func_layer->layer_set_info) {
1168                 _pthread_mutex_unlock(&private_display->lock);
1169                 TDM_DBG("failed: not implemented!!");
1170                 return TDM_ERROR_NOT_IMPLEMENTED;
1171         }
1172
1173         TDM_INFO("layer(%p) info: src(%dx%d %d,%d %dx%d %c%c%c%c) dst(%d,%d %dx%d) trans(%d)",
1174                  private_layer, info->src_config.size.h, info->src_config.size.v,
1175                  info->src_config.pos.x, info->src_config.pos.y,
1176                  info->src_config.pos.w, info->src_config.pos.h,
1177                  FOURCC_STR(info->src_config.format),
1178                  info->dst_pos.x, info->dst_pos.y,
1179                  info->dst_pos.w, info->dst_pos.h,
1180                  info->transform);
1181
1182         ret = func_layer->layer_set_info(private_layer->layer_backend, info);
1183         TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
1184
1185         _pthread_mutex_unlock(&private_display->lock);
1186
1187         return ret;
1188 }
1189
1190 EXTERN tdm_error
1191 tdm_layer_get_info(tdm_layer *layer, tdm_info_layer *info)
1192 {
1193         tdm_func_layer *func_layer;
1194         LAYER_FUNC_ENTRY();
1195
1196         TDM_RETURN_VAL_IF_FAIL(info != NULL, TDM_ERROR_INVALID_PARAMETER);
1197
1198         _pthread_mutex_lock(&private_display->lock);
1199
1200         func_layer = &private_display->func_layer;
1201
1202         if (!func_layer->layer_get_info) {
1203                 _pthread_mutex_unlock(&private_display->lock);
1204                 TDM_DBG("failed: not implemented!!");
1205                 return TDM_ERROR_NOT_IMPLEMENTED;
1206         }
1207
1208         ret = func_layer->layer_get_info(private_layer->layer_backend, info);
1209
1210         _pthread_mutex_unlock(&private_display->lock);
1211
1212         return ret;
1213 }
1214
1215 EXTERN tdm_error
1216 tdm_layer_set_buffer(tdm_layer *layer, tbm_surface_h buffer)
1217 {
1218         tdm_func_layer *func_layer;
1219
1220         LAYER_FUNC_ENTRY();
1221
1222         TDM_RETURN_VAL_IF_FAIL(buffer != NULL, TDM_ERROR_INVALID_PARAMETER);
1223
1224         _pthread_mutex_lock(&private_display->lock);
1225
1226         func_layer = &private_display->func_layer;
1227
1228         private_layer->usable = 0;
1229
1230         if (!func_layer->layer_set_buffer) {
1231                 _pthread_mutex_unlock(&private_display->lock);
1232                 TDM_DBG("failed: not implemented!!");
1233                 return TDM_ERROR_NOT_IMPLEMENTED;
1234         }
1235
1236         ret = func_layer->layer_set_buffer(private_layer->layer_backend, buffer);
1237         TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
1238
1239         if (ret == TDM_ERROR_NONE) {
1240                 /* FIXME: should save to pending_buffer first. And after committing
1241                  * successfully, need to move to waiting_buffer.
1242                  */
1243                 if (private_layer->waiting_buffer) {
1244                         _pthread_mutex_unlock(&private_display->lock);
1245                         tdm_buffer_unref_backend(private_layer->waiting_buffer);
1246                         _pthread_mutex_lock(&private_display->lock);
1247                 }
1248
1249                 private_layer->waiting_buffer = tdm_buffer_ref_backend(buffer);
1250                 if (tdm_debug_buffer)
1251                         TDM_INFO("layer(%p) waiting_buffer(%p)",
1252                                  private_layer, private_layer->waiting_buffer);
1253         }
1254
1255         _pthread_mutex_unlock(&private_display->lock);
1256
1257         return ret;
1258 }
1259
1260 EXTERN tdm_error
1261 tdm_layer_unset_buffer(tdm_layer *layer)
1262 {
1263         tdm_func_layer *func_layer;
1264         LAYER_FUNC_ENTRY();
1265
1266         _pthread_mutex_lock(&private_display->lock);
1267
1268         func_layer = &private_display->func_layer;
1269
1270         if (private_layer->waiting_buffer) {
1271                 _pthread_mutex_unlock(&private_display->lock);
1272                 tdm_buffer_unref_backend(private_layer->waiting_buffer);
1273                 _pthread_mutex_lock(&private_display->lock);
1274                 private_layer->waiting_buffer = NULL;
1275
1276                 if (tdm_debug_buffer)
1277                         TDM_INFO("layer(%p) waiting_buffer(%p)",
1278                                  private_layer, private_layer->waiting_buffer);
1279         }
1280
1281         if (private_layer->showing_buffer) {
1282                 _pthread_mutex_unlock(&private_display->lock);
1283                 tdm_buffer_unref_backend(private_layer->showing_buffer);
1284                 _pthread_mutex_lock(&private_display->lock);
1285                 private_layer->showing_buffer = NULL;
1286
1287                 if (tdm_debug_buffer)
1288                         TDM_INFO("layer(%p) showing_buffer(%p)",
1289                                  private_layer, private_layer->showing_buffer);
1290         }
1291
1292         private_layer->usable = 1;
1293
1294         if (!func_layer->layer_unset_buffer) {
1295                 _pthread_mutex_unlock(&private_display->lock);
1296                 TDM_DBG("failed: not implemented!!");
1297                 return TDM_ERROR_NOT_IMPLEMENTED;
1298         }
1299
1300         ret = func_layer->layer_unset_buffer(private_layer->layer_backend);
1301         TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
1302
1303         _pthread_mutex_unlock(&private_display->lock);
1304
1305         return ret;
1306 }
1307
1308 static void
1309 _tbm_layer_queue_acquirable_cb(tbm_surface_queue_h surface_queue, void *data)
1310 {
1311         TDM_RETURN_IF_FAIL(data != NULL);
1312         tdm_layer *layer = data;
1313         tdm_func_layer *func_layer;
1314         tbm_surface_h surface = NULL;
1315         LAYER_FUNC_ENTRY_VOID_RETURN();
1316
1317         _pthread_mutex_lock(&private_display->lock);
1318
1319         func_layer = &private_display->func_layer;
1320         if (!func_layer->layer_set_buffer) {
1321                 _pthread_mutex_unlock(&private_display->lock);
1322                 return;
1323         }
1324
1325         if (TBM_SURFACE_QUEUE_ERROR_NONE != tbm_surface_queue_acquire(
1326                     private_layer->buffer_queue, &surface) ||
1327             surface == NULL) {
1328                 TDM_ERR("layer(%p) tbm_surface_queue_acquire() failed surface:%p",
1329                         private_layer, surface);
1330                 _pthread_mutex_unlock(&private_display->lock);
1331                 return;
1332         }
1333
1334         ret = func_layer->layer_set_buffer(private_layer->layer_backend, surface);
1335         TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
1336
1337         if (ret == TDM_ERROR_NONE) {
1338                 if (private_layer->waiting_buffer) {
1339                         _pthread_mutex_unlock(&private_display->lock);
1340                         tdm_buffer_unref_backend(private_layer->waiting_buffer);
1341                         tbm_surface_queue_release(private_layer->buffer_queue,
1342                                                   private_layer->waiting_buffer);
1343                         _pthread_mutex_lock(&private_display->lock);
1344                 }
1345
1346                 private_layer->waiting_buffer = tdm_buffer_ref_backend(surface);
1347
1348                 if (tdm_debug_buffer)
1349                         TDM_INFO("layer(%p) waiting_buffer(%p)",
1350                                  private_layer, private_layer->waiting_buffer);
1351
1352                 ret = _tdm_output_commit(private_layer->private_output, 0, NULL, NULL);
1353                 if (ret != TDM_ERROR_NONE)
1354                         TDM_ERR("layer(%p) _tdm_output_commit() is fail", private_layer);
1355         }
1356
1357         _pthread_mutex_unlock(&private_display->lock);
1358 }
1359
1360 static void
1361 _tbm_layer_queue_destroy_cb(tbm_surface_queue_h surface_queue, void *data)
1362 {
1363         TDM_RETURN_IF_FAIL(data != NULL);
1364         tdm_layer *layer = data;
1365         LAYER_FUNC_ENTRY_VOID_RETURN();
1366         TDM_RETURN_IF_FAIL(ret == TDM_ERROR_NONE);
1367
1368         _pthread_mutex_lock(&private_display->lock);
1369
1370         if (private_layer->waiting_buffer) {
1371                 _pthread_mutex_unlock(&private_display->lock);
1372                 tdm_buffer_unref_backend(private_layer->waiting_buffer);
1373                 tbm_surface_queue_release(private_layer->buffer_queue,
1374                                           private_layer->waiting_buffer);
1375                 _pthread_mutex_lock(&private_display->lock);
1376         }
1377
1378         private_layer->buffer_queue = NULL;
1379
1380         _pthread_mutex_unlock(&private_display->lock);
1381 }
1382
1383 EXTERN tdm_error
1384 tdm_layer_set_buffer_queue(tdm_layer *layer, tbm_surface_queue_h buffer_queue)
1385 {
1386         tdm_func_layer *func_layer;
1387         LAYER_FUNC_ENTRY();
1388
1389         TDM_RETURN_VAL_IF_FAIL(buffer_queue != NULL, TDM_ERROR_INVALID_PARAMETER);
1390
1391         _pthread_mutex_lock(&private_display->lock);
1392
1393         func_layer = &private_display->func_layer;
1394
1395         private_layer->usable = 0;
1396
1397         if (!func_layer->layer_set_buffer) {
1398                 _pthread_mutex_unlock(&private_display->lock);
1399                 TDM_DBG("failed: not implemented!!");
1400                 return TDM_ERROR_NOT_IMPLEMENTED;
1401         }
1402
1403         if (buffer_queue == private_layer->buffer_queue) {
1404                 _pthread_mutex_unlock(&private_display->lock);
1405                 return TDM_ERROR_NONE;
1406         }
1407
1408         if (private_layer->waiting_buffer) {
1409                 _pthread_mutex_unlock(&private_display->lock);
1410                 tdm_buffer_unref_backend(private_layer->waiting_buffer);
1411                 tbm_surface_queue_release(private_layer->buffer_queue,
1412                                           private_layer->waiting_buffer);
1413                 private_layer->waiting_buffer = NULL;
1414                 _pthread_mutex_lock(&private_display->lock);
1415
1416                 if (tdm_debug_buffer)
1417                         TDM_INFO("layer(%p) waiting_buffer(%p)",
1418                                  private_layer, private_layer->waiting_buffer);
1419         }
1420
1421         private_layer->buffer_queue = buffer_queue;
1422         tbm_surface_queue_add_acquirable_cb(private_layer->buffer_queue,
1423                                             _tbm_layer_queue_acquirable_cb,
1424                                             layer);
1425         tbm_surface_queue_add_destroy_cb(private_layer->buffer_queue,
1426                                          _tbm_layer_queue_destroy_cb,
1427                                          layer);
1428         _pthread_mutex_unlock(&private_display->lock);
1429
1430         return ret;
1431 }
1432
1433 EXTERN tdm_error
1434 tdm_layer_unset_buffer_queue(tdm_layer *layer)
1435 {
1436         tdm_func_layer *func_layer;
1437         LAYER_FUNC_ENTRY();
1438
1439         _pthread_mutex_lock(&private_display->lock);
1440
1441         func_layer = &private_display->func_layer;
1442
1443         if (private_layer->waiting_buffer) {
1444                 _pthread_mutex_unlock(&private_display->lock);
1445                 tdm_buffer_unref_backend(private_layer->waiting_buffer);
1446                 tbm_surface_queue_release(private_layer->buffer_queue,
1447                                           private_layer->waiting_buffer);
1448                 private_layer->waiting_buffer = NULL;
1449                 _pthread_mutex_lock(&private_display->lock);
1450
1451                 if (tdm_debug_buffer)
1452                         TDM_INFO("layer(%p) waiting_buffer(%p)",
1453                                  private_layer, private_layer->waiting_buffer);
1454         }
1455
1456         if (private_layer->showing_buffer) {
1457                 _pthread_mutex_unlock(&private_display->lock);
1458                 tdm_buffer_unref_backend(private_layer->showing_buffer);
1459                 tbm_surface_queue_release(private_layer->buffer_queue,
1460                                           private_layer->showing_buffer);
1461                 _pthread_mutex_lock(&private_display->lock);
1462                 private_layer->showing_buffer = NULL;
1463
1464                 if (tdm_debug_buffer)
1465                         TDM_INFO("layer(%p) showing_buffer(%p)",
1466                                  private_layer, private_layer->showing_buffer);
1467         }
1468
1469         tbm_surface_queue_remove_acquirable_cb(private_layer->buffer_queue, _tbm_layer_queue_acquirable_cb, layer);
1470         tbm_surface_queue_remove_destroy_cb(private_layer->buffer_queue, _tbm_layer_queue_destroy_cb, layer);
1471         private_layer->buffer_queue = NULL;
1472         private_layer->usable = 1;
1473
1474         if (!func_layer->layer_unset_buffer) {
1475                 _pthread_mutex_unlock(&private_display->lock);
1476                 TDM_DBG("failed: not implemented!!");
1477                 return TDM_ERROR_NOT_IMPLEMENTED;
1478         }
1479
1480         ret = func_layer->layer_unset_buffer(private_layer->layer_backend);
1481
1482         _pthread_mutex_unlock(&private_display->lock);
1483
1484         return ret;
1485 }
1486
1487 EXTERN tdm_error
1488 tdm_layer_is_usable(tdm_layer *layer, unsigned int *usable)
1489 {
1490         LAYER_FUNC_ENTRY();
1491
1492         TDM_RETURN_VAL_IF_FAIL(usable != NULL, TDM_ERROR_INVALID_PARAMETER);
1493
1494         _pthread_mutex_lock(&private_display->lock);
1495
1496         *usable = private_layer->usable;
1497
1498         _pthread_mutex_unlock(&private_display->lock);
1499
1500         return ret;
1501 }
1502
1503 EXTERN tdm_error
1504 tdm_layer_set_video_pos(tdm_layer *layer, int zpos)
1505 {
1506         tdm_func_layer *func_layer;
1507         LAYER_FUNC_ENTRY();
1508
1509         _pthread_mutex_lock(&private_display->lock);
1510
1511         func_layer = &private_display->func_layer;
1512
1513         if (!(private_layer->caps.capabilities & TDM_LAYER_CAPABILITY_VIDEO)) {
1514                 TDM_ERR("layer(%p) is not video layer", private_layer);
1515                 _pthread_mutex_unlock(&private_display->lock);
1516                 return TDM_ERROR_INVALID_PARAMETER;
1517         }
1518
1519         if (!func_layer->layer_set_video_pos) {
1520                 _pthread_mutex_unlock(&private_display->lock);
1521                 TDM_DBG("failed: not implemented!!");
1522                 return TDM_ERROR_NOT_IMPLEMENTED;
1523         }
1524
1525         ret = func_layer->layer_set_video_pos(private_layer->layer_backend, zpos);
1526
1527         _pthread_mutex_unlock(&private_display->lock);
1528
1529         return ret;
1530 }
1531
1532 EXTERN tdm_capture *
1533 tdm_layer_create_capture(tdm_layer *layer, tdm_error *error)
1534 {
1535         tdm_capture *capture = NULL;
1536
1537         LAYER_FUNC_ENTRY_ERROR();
1538
1539         _pthread_mutex_lock(&private_display->lock);
1540
1541         capture = (tdm_capture *)tdm_capture_create_layer_internal(private_layer,
1542                         error);
1543
1544         _pthread_mutex_unlock(&private_display->lock);
1545
1546         return capture;
1547 }