support thread
[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         if (private_display->private_thread)
344                 *fd = tdm_thread_get_fd(private_display);
345         else
346                 *fd = tdm_event_get_fd(private_display);
347
348         _pthread_mutex_unlock(&private_display->lock);
349
350         return ret;
351 }
352
353 EXTERN tdm_error
354 tdm_display_handle_events(tdm_display *dpy)
355 {
356         struct pollfd fds;
357         int fd = -1;
358
359         DISPLAY_FUNC_ENTRY();
360
361         ret = tdm_display_get_fd(dpy, &fd);
362         TDM_RETURN_VAL_IF_FAIL(fd >= 0, ret);
363
364         fds.events = POLLIN;
365         fds.fd = fd;
366         fds.revents = 0;
367
368         if (tdm_debug_thread)
369                 TDM_INFO("fd(%d) polling in", fd);
370
371         while (poll(&fds, 1, -1) < 0) {
372                 if (errno == EBUSY)  /* normal case */
373                         continue;
374                 else {
375                         TDM_ERR("poll failed: %m");
376                         return TDM_ERROR_OPERATION_FAILED;
377                 }
378         }
379
380         if (tdm_debug_thread)
381                 TDM_INFO("fd(%d) polling out", fd);
382
383         _pthread_mutex_lock(&private_display->lock);
384
385         if (private_display->private_thread)
386                 ret = tdm_thread_handle_cb(private_display);
387         else
388                 ret = tdm_event_dispatch(private_display);
389
390         _pthread_mutex_unlock(&private_display->lock);
391
392         return ret;
393 }
394
395 EXTERN tdm_pp *
396 tdm_display_create_pp(tdm_display *dpy, tdm_error *error)
397 {
398         tdm_pp *pp;
399
400         DISPLAY_FUNC_ENTRY_ERROR();
401
402         _pthread_mutex_lock(&private_display->lock);
403
404         pp = (tdm_pp *)tdm_pp_create_internal(private_display, error);
405
406         _pthread_mutex_unlock(&private_display->lock);
407
408         return pp;
409 }
410
411 EXTERN tdm_error
412 tdm_output_get_model_info(tdm_output *output, const char **maker,
413                           const char **model, const char **name)
414 {
415         OUTPUT_FUNC_ENTRY();
416
417         _pthread_mutex_lock(&private_display->lock);
418
419         if (maker)
420                 *maker = private_output->caps.maker;
421         if (model)
422                 *model = private_output->caps.model;
423         if (name)
424                 *name = private_output->caps.name;
425
426         _pthread_mutex_unlock(&private_display->lock);
427
428         return ret;
429 }
430
431 EXTERN tdm_error
432 tdm_output_get_conn_status(tdm_output *output, tdm_output_conn_status *status)
433 {
434         OUTPUT_FUNC_ENTRY();
435
436         TDM_RETURN_VAL_IF_FAIL(status != NULL, TDM_ERROR_INVALID_PARAMETER);
437
438         _pthread_mutex_lock(&private_display->lock);
439
440         *status = private_output->caps.status;
441
442         _pthread_mutex_unlock(&private_display->lock);
443
444         return ret;
445 }
446
447 EXTERN tdm_error
448 tdm_output_add_change_handler(tdm_output *output,
449                               tdm_output_change_handler func,
450                               void *user_data)
451 {
452         tdm_private_change_handler *change_handler;
453         OUTPUT_FUNC_ENTRY();
454
455         TDM_RETURN_VAL_IF_FAIL(func != NULL, TDM_ERROR_INVALID_PARAMETER);
456
457         pthread_mutex_lock(&private_display->lock);
458
459         if (!private_output->regist_change_cb) {
460                 _pthread_mutex_unlock(&private_display->lock);
461                 TDM_DBG("failed: not implemented!!");
462                 return TDM_ERROR_NOT_IMPLEMENTED;
463         }
464
465         change_handler = calloc(1, sizeof(tdm_private_change_handler));
466         if (!change_handler) {
467                 TDM_ERR("failed: alloc memory");
468                 _pthread_mutex_unlock(&private_display->lock);
469                 return TDM_ERROR_OUT_OF_MEMORY;
470         }
471
472         LIST_ADD(&change_handler->link, &private_output->change_handler_list);
473         change_handler->private_output = private_output;
474         change_handler->func = func;
475         change_handler->user_data = user_data;
476
477         _pthread_mutex_unlock(&private_display->lock);
478
479         return ret;
480 }
481
482 EXTERN void
483 tdm_output_remove_change_handler(tdm_output *output,
484                                  tdm_output_change_handler func,
485                                  void *user_data)
486 {
487         tdm_private_display *private_display;
488         tdm_private_output *private_output;
489         tdm_private_change_handler *h = NULL, *hh = NULL;
490
491         TDM_RETURN_IF_FAIL(output != NULL);
492         TDM_RETURN_IF_FAIL(func != NULL);
493
494         private_output = (tdm_private_output*)output;
495         private_display = private_output->private_display;
496
497         _pthread_mutex_lock(&private_display->lock);
498
499         LIST_FOR_EACH_ENTRY_SAFE(h, hh, &private_output->change_handler_list, link) {
500                 if (h->func != func || h->user_data != user_data)
501                         continue;
502
503                 LIST_DEL(&h->link);
504                 free(h);
505
506                 _pthread_mutex_unlock(&private_display->lock);
507
508                 return;
509         }
510
511         _pthread_mutex_unlock(&private_display->lock);
512 }
513
514 EXTERN tdm_error
515 tdm_output_get_output_type(tdm_output *output, tdm_output_type *type)
516 {
517         OUTPUT_FUNC_ENTRY();
518
519         TDM_RETURN_VAL_IF_FAIL(type != NULL, TDM_ERROR_INVALID_PARAMETER);
520
521         _pthread_mutex_lock(&private_display->lock);
522
523         *type = private_output->caps.type;
524
525         _pthread_mutex_unlock(&private_display->lock);
526
527         return ret;
528 }
529
530 EXTERN tdm_error
531 tdm_output_get_layer_count(tdm_output *output, int *count)
532 {
533         tdm_private_layer *private_layer = NULL;
534
535         OUTPUT_FUNC_ENTRY();
536
537         TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
538
539         _pthread_mutex_lock(&private_display->lock);
540
541         *count = 0;
542         LIST_FOR_EACH_ENTRY(private_layer, &private_output->layer_list, link)
543         (*count)++;
544         if (*count == 0) {
545                 _pthread_mutex_unlock(&private_display->lock);
546                 return TDM_ERROR_NONE;
547         }
548
549         _pthread_mutex_unlock(&private_display->lock);
550
551         return ret;
552 }
553
554
555 EXTERN tdm_layer *
556 tdm_output_get_layer(tdm_output *output, int index, tdm_error *error)
557 {
558         tdm_private_layer *private_layer = NULL;
559         int i = 0;
560
561         OUTPUT_FUNC_ENTRY_ERROR();
562
563         _pthread_mutex_lock(&private_display->lock);
564
565         if (error)
566                 *error = TDM_ERROR_NONE;
567
568         LIST_FOR_EACH_ENTRY(private_layer, &private_output->layer_list, link) {
569                 if (i == index) {
570                         _pthread_mutex_unlock(&private_display->lock);
571                         return private_layer;
572                 }
573                 i++;
574         }
575
576         _pthread_mutex_unlock(&private_display->lock);
577
578         return NULL;
579 }
580
581 EXTERN tdm_error
582 tdm_output_get_available_properties(tdm_output *output, const tdm_prop **props,
583                                     int *count)
584 {
585         OUTPUT_FUNC_ENTRY();
586
587         TDM_RETURN_VAL_IF_FAIL(props != NULL, TDM_ERROR_INVALID_PARAMETER);
588         TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
589
590         _pthread_mutex_lock(&private_display->lock);
591
592         *props = (const tdm_prop *)private_output->caps.props;
593         *count = private_output->caps.prop_count;
594
595         _pthread_mutex_unlock(&private_display->lock);
596
597         return ret;
598 }
599
600 EXTERN tdm_error
601 tdm_output_get_available_modes(tdm_output *output,
602                                const tdm_output_mode **modes, int *count)
603 {
604         OUTPUT_FUNC_ENTRY();
605
606         TDM_RETURN_VAL_IF_FAIL(modes != NULL, TDM_ERROR_INVALID_PARAMETER);
607         TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
608
609         _pthread_mutex_lock(&private_display->lock);
610
611         *modes = (const tdm_output_mode *)private_output->caps.modes;
612         *count = private_output->caps.mode_count;
613
614         _pthread_mutex_unlock(&private_display->lock);
615
616         return ret;
617 }
618
619 EXTERN tdm_error
620 tdm_output_get_available_size(tdm_output *output, int *min_w, int *min_h,
621                               int *max_w, int *max_h, int *preferred_align)
622 {
623         OUTPUT_FUNC_ENTRY();
624
625         _pthread_mutex_lock(&private_display->lock);
626
627         if (min_w)
628                 *min_w = private_output->caps.min_w;
629         if (min_h)
630                 *min_h = private_output->caps.min_h;
631         if (max_w)
632                 *max_w = private_output->caps.max_w;
633         if (max_h)
634                 *max_h = private_output->caps.max_h;
635         if (preferred_align)
636                 *preferred_align = private_output->caps.preferred_align;
637
638         _pthread_mutex_unlock(&private_display->lock);
639
640         return ret;
641 }
642
643 EXTERN tdm_error
644 tdm_output_get_physical_size(tdm_output *output, unsigned int *mmWidth,
645                              unsigned int *mmHeight)
646 {
647         OUTPUT_FUNC_ENTRY();
648
649         _pthread_mutex_lock(&private_display->lock);
650
651         if (mmWidth)
652                 *mmWidth = private_output->caps.mmWidth;
653         if (mmHeight)
654                 *mmHeight = private_output->caps.mmHeight;
655
656         _pthread_mutex_unlock(&private_display->lock);
657
658         return ret;
659 }
660
661 EXTERN tdm_error
662 tdm_output_get_subpixel(tdm_output *output, unsigned int *subpixel)
663 {
664         OUTPUT_FUNC_ENTRY();
665         TDM_RETURN_VAL_IF_FAIL(subpixel != NULL, TDM_ERROR_INVALID_PARAMETER);
666
667         _pthread_mutex_lock(&private_display->lock);
668
669         *subpixel = private_output->caps.subpixel;
670
671         _pthread_mutex_unlock(&private_display->lock);
672
673         return ret;
674 }
675
676 EXTERN tdm_error
677 tdm_output_get_pipe(tdm_output *output, unsigned int *pipe)
678 {
679         OUTPUT_FUNC_ENTRY();
680         TDM_RETURN_VAL_IF_FAIL(pipe != NULL, TDM_ERROR_INVALID_PARAMETER);
681
682         _pthread_mutex_lock(&private_display->lock);
683
684         *pipe = private_output->pipe;
685
686         _pthread_mutex_unlock(&private_display->lock);
687
688         return ret;
689 }
690
691
692 EXTERN tdm_error
693 tdm_output_set_property(tdm_output *output, unsigned int id, tdm_value value)
694 {
695         tdm_func_output *func_output;
696         OUTPUT_FUNC_ENTRY();
697
698         _pthread_mutex_lock(&private_display->lock);
699
700         func_output = &private_display->func_output;
701
702         if (!func_output->output_set_property) {
703                 _pthread_mutex_unlock(&private_display->lock);
704                 TDM_DBG("failed: not implemented!!");
705                 return TDM_ERROR_NOT_IMPLEMENTED;
706         }
707
708         ret = func_output->output_set_property(private_output->output_backend, id,
709                                                value);
710
711         _pthread_mutex_unlock(&private_display->lock);
712
713         return ret;
714 }
715
716 EXTERN tdm_error
717 tdm_output_get_property(tdm_output *output, unsigned int id, tdm_value *value)
718 {
719         tdm_func_output *func_output;
720         OUTPUT_FUNC_ENTRY();
721
722         TDM_RETURN_VAL_IF_FAIL(value != NULL, TDM_ERROR_INVALID_PARAMETER);
723
724         _pthread_mutex_lock(&private_display->lock);
725
726         func_output = &private_display->func_output;
727
728         if (!func_output->output_get_property) {
729                 _pthread_mutex_unlock(&private_display->lock);
730                 TDM_DBG("failed: not implemented!!");
731                 return TDM_ERROR_NOT_IMPLEMENTED;
732         }
733
734         ret = func_output->output_get_property(private_output->output_backend, id,
735                                                value);
736
737         _pthread_mutex_unlock(&private_display->lock);
738
739         return ret;
740 }
741
742 INTERN void
743 tdm_output_cb_vblank(tdm_output *output_backend, unsigned int sequence,
744                      unsigned int tv_sec, unsigned int tv_usec, void *user_data)
745 {
746         tdm_private_vblank_handler *vblank_handler = user_data;
747         tdm_private_display *private_display;
748
749         TDM_RETURN_IF_FAIL(vblank_handler);
750
751         private_display = vblank_handler->private_output->private_display;
752
753         if (!tdm_thread_in_display_thread(private_display)) {
754                 tdm_thread_cb_output_vblank output_vblank;
755                 tdm_error ret;
756
757                 output_vblank.base.type = TDM_THREAD_CB_OUTPUT_VBLANK;
758                 output_vblank.base.length = sizeof output_vblank;
759                 output_vblank.output_stamp = vblank_handler->private_output->stamp;
760                 output_vblank.sequence = sequence;
761                 output_vblank.tv_sec = tv_sec;
762                 output_vblank.tv_usec = tv_usec;
763                 output_vblank.user_data = user_data;
764
765                 ret = tdm_thread_send_cb(private_display, &output_vblank.base);
766                 TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
767
768                 return;
769         }
770
771         if (vblank_handler->func) {
772                 _pthread_mutex_unlock(&private_display->lock);
773                 vblank_handler->func(vblank_handler->private_output, sequence,
774                                      tv_sec, tv_usec, vblank_handler->user_data);
775                 _pthread_mutex_lock(&private_display->lock);
776         }
777
778         LIST_DEL(&vblank_handler->link);
779         free(vblank_handler);
780 }
781
782 INTERN void
783 tdm_output_cb_commit(tdm_output *output_backend, unsigned int sequence,
784                      unsigned int tv_sec, unsigned int tv_usec, void *user_data)
785 {
786         tdm_private_commit_handler *commit_handler = user_data;
787         tdm_private_display *private_display;
788         tdm_private_output *private_output;
789         tdm_private_layer *private_layer = NULL;
790
791         TDM_RETURN_IF_FAIL(commit_handler);
792
793         private_output = commit_handler->private_output;
794         private_display = private_output->private_display;
795
796         if (!tdm_thread_in_display_thread(private_display)) {
797                 tdm_thread_cb_output_commit output_commit;
798                 tdm_error ret;
799
800                 output_commit.base.type = TDM_THREAD_CB_OUTPUT_COMMIT;
801                 output_commit.base.length = sizeof output_commit;
802                 output_commit.output_stamp = private_output->stamp;
803                 output_commit.sequence = sequence;
804                 output_commit.tv_sec = tv_sec;
805                 output_commit.tv_usec = tv_usec;
806                 output_commit.user_data = user_data;
807
808                 ret = tdm_thread_send_cb(private_display, &output_commit.base);
809                 TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
810
811                 return;
812         }
813
814         LIST_FOR_EACH_ENTRY(private_layer, &private_output->layer_list, link) {
815                 if (!private_layer->waiting_buffer)
816                         continue;
817
818                 if (private_layer->showing_buffer) {
819                         _pthread_mutex_unlock(&private_display->lock);
820                         tdm_buffer_unref_backend(private_layer->showing_buffer);
821                         _pthread_mutex_lock(&private_display->lock);
822
823                         if (private_layer->buffer_queue) {
824                                 _pthread_mutex_unlock(&private_display->lock);
825                                 tbm_surface_queue_release(private_layer->buffer_queue,
826                                                           private_layer->showing_buffer);
827                                 _pthread_mutex_lock(&private_display->lock);
828                         }
829                 }
830
831                 private_layer->showing_buffer = private_layer->waiting_buffer;
832                 private_layer->waiting_buffer = NULL;
833
834                 if (tdm_debug_buffer)
835                         TDM_INFO("layer(%p) waiting_buffer(%p) showing_buffer(%p)",
836                                  private_layer, private_layer->waiting_buffer,
837                                  private_layer->showing_buffer);
838         }
839
840         if (commit_handler->func) {
841                 _pthread_mutex_unlock(&private_display->lock);
842                 commit_handler->func(private_output, sequence,
843                                      tv_sec, tv_usec, commit_handler->user_data);
844                 _pthread_mutex_lock(&private_display->lock);
845         }
846
847         LIST_DEL(&commit_handler->link);
848         free(commit_handler);
849 }
850
851 EXTERN tdm_error
852 tdm_output_wait_vblank(tdm_output *output, int interval, int sync,
853                        tdm_output_vblank_handler func, void *user_data)
854 {
855         tdm_func_output *func_output;
856         tdm_private_vblank_handler *vblank_handler;
857         OUTPUT_FUNC_ENTRY();
858
859         _pthread_mutex_lock(&private_display->lock);
860
861         func_output = &private_display->func_output;
862
863         if (!func_output->output_wait_vblank) {
864                 _pthread_mutex_unlock(&private_display->lock);
865                 TDM_DBG("failed: not implemented!!");
866                 return TDM_ERROR_NOT_IMPLEMENTED;
867         }
868
869         vblank_handler = calloc(1, sizeof(tdm_private_vblank_handler));
870         if (!vblank_handler) {
871                 TDM_ERR("failed: alloc memory");
872                 _pthread_mutex_unlock(&private_display->lock);
873                 return TDM_ERROR_OUT_OF_MEMORY;
874         }
875
876         LIST_ADD(&vblank_handler->link, &private_output->vblank_handler_list);
877         vblank_handler->private_output = private_output;
878         vblank_handler->func = func;
879         vblank_handler->user_data = user_data;
880
881         ret = func_output->output_wait_vblank(private_output->output_backend, interval,
882                                               sync, vblank_handler);
883         if (ret != TDM_ERROR_NONE) {
884                 _pthread_mutex_unlock(&private_display->lock);
885                 return ret;
886         }
887
888         if (!private_output->regist_vblank_cb) {
889                 private_output->regist_vblank_cb = 1;
890                 ret = func_output->output_set_vblank_handler(private_output->output_backend,
891                                 tdm_output_cb_vblank);
892         }
893
894         _pthread_mutex_unlock(&private_display->lock);
895
896         return ret;
897 }
898
899 static tdm_error
900 _tdm_output_commit(tdm_output *output, int sync, tdm_output_commit_handler func,
901                    void *user_data)
902 {
903         tdm_func_output *func_output;
904         tdm_private_commit_handler *commit_handler;
905         OUTPUT_FUNC_ENTRY();
906
907         func_output = &private_display->func_output;
908
909         if (!func_output->output_commit) {
910                 TDM_DBG("failed: not implemented!!");
911                 return TDM_ERROR_NOT_IMPLEMENTED;
912         }
913
914         commit_handler = calloc(1, sizeof(tdm_private_commit_handler));
915         if (!commit_handler) {
916                 TDM_ERR("failed: alloc memory");
917                 return TDM_ERROR_OUT_OF_MEMORY;
918         }
919
920         LIST_ADD(&commit_handler->link, &private_output->commit_handler_list);
921         commit_handler->private_output = private_output;
922         commit_handler->func = func;
923         commit_handler->user_data = user_data;
924
925         ret = func_output->output_commit(private_output->output_backend, sync,
926                                          commit_handler);
927         TDM_RETURN_VAL_IF_FAIL(ret == TDM_ERROR_NONE, ret);
928
929         if (!private_output->regist_commit_cb) {
930                 private_output->regist_commit_cb = 1;
931                 ret = func_output->output_set_commit_handler(private_output->output_backend,
932                                 tdm_output_cb_commit);
933         }
934
935         return ret;
936 }
937
938 EXTERN tdm_error
939 tdm_output_commit(tdm_output *output, int sync, tdm_output_commit_handler func,
940                   void *user_data)
941 {
942         OUTPUT_FUNC_ENTRY();
943
944         _pthread_mutex_lock(&private_display->lock);
945
946         ret = _tdm_output_commit(output, sync, func, user_data);
947
948         _pthread_mutex_unlock(&private_display->lock);
949
950         return ret;
951 }
952
953 EXTERN tdm_error
954 tdm_output_set_mode(tdm_output *output, const tdm_output_mode *mode)
955 {
956         tdm_func_output *func_output;
957         OUTPUT_FUNC_ENTRY();
958
959         TDM_RETURN_VAL_IF_FAIL(mode != NULL, TDM_ERROR_INVALID_PARAMETER);
960
961         _pthread_mutex_lock(&private_display->lock);
962
963         func_output = &private_display->func_output;
964
965         if (!func_output->output_set_mode) {
966                 _pthread_mutex_unlock(&private_display->lock);
967                 TDM_DBG("failed: not implemented!!");
968                 return TDM_ERROR_NOT_IMPLEMENTED;
969         }
970
971         ret = func_output->output_set_mode(private_output->output_backend, mode);
972
973         _pthread_mutex_unlock(&private_display->lock);
974
975         return ret;
976 }
977
978 EXTERN tdm_error
979 tdm_output_get_mode(tdm_output *output, const tdm_output_mode **mode)
980 {
981         tdm_func_output *func_output;
982         OUTPUT_FUNC_ENTRY();
983
984         TDM_RETURN_VAL_IF_FAIL(mode != NULL, TDM_ERROR_INVALID_PARAMETER);
985
986         _pthread_mutex_lock(&private_display->lock);
987
988         func_output = &private_display->func_output;
989
990         if (!func_output->output_get_mode) {
991                 _pthread_mutex_unlock(&private_display->lock);
992                 TDM_DBG("failed: not implemented!!");
993                 return TDM_ERROR_NOT_IMPLEMENTED;
994         }
995
996         ret = func_output->output_get_mode(private_output->output_backend, mode);
997
998         _pthread_mutex_unlock(&private_display->lock);
999
1000         return ret;
1001 }
1002
1003 EXTERN tdm_error
1004 tdm_output_set_dpms(tdm_output *output, tdm_output_dpms dpms_value)
1005 {
1006         tdm_func_output *func_output;
1007         OUTPUT_FUNC_ENTRY();
1008
1009         if (dpms_value < TDM_OUTPUT_DPMS_ON)
1010                 dpms_value = TDM_OUTPUT_DPMS_ON;
1011         else if (dpms_value > TDM_OUTPUT_DPMS_OFF)
1012                 dpms_value = TDM_OUTPUT_DPMS_OFF;
1013
1014         _pthread_mutex_lock(&private_display->lock);
1015
1016         func_output = &private_display->func_output;
1017
1018         if (!func_output->output_set_dpms) {
1019                 _pthread_mutex_unlock(&private_display->lock);
1020                 TDM_DBG("failed: not implemented!!");
1021                 return TDM_ERROR_NOT_IMPLEMENTED;
1022         }
1023
1024         ret = func_output->output_set_dpms(private_output->output_backend, dpms_value);
1025
1026         _pthread_mutex_unlock(&private_display->lock);
1027
1028         return ret;
1029 }
1030
1031 EXTERN tdm_error
1032 tdm_output_get_dpms(tdm_output *output, tdm_output_dpms *dpms_value)
1033 {
1034         tdm_func_output *func_output;
1035         OUTPUT_FUNC_ENTRY();
1036
1037         TDM_RETURN_VAL_IF_FAIL(dpms_value != NULL, TDM_ERROR_INVALID_PARAMETER);
1038
1039         _pthread_mutex_lock(&private_display->lock);
1040
1041         func_output = &private_display->func_output;
1042
1043         if (!func_output->output_get_dpms) {
1044                 _pthread_mutex_unlock(&private_display->lock);
1045                 TDM_DBG("failed: not implemented!!");
1046                 return TDM_ERROR_NOT_IMPLEMENTED;
1047         }
1048
1049         ret = func_output->output_get_dpms(private_output->output_backend, dpms_value);
1050
1051         _pthread_mutex_unlock(&private_display->lock);
1052
1053         return ret;
1054 }
1055
1056 EXTERN tdm_capture *
1057 tdm_output_create_capture(tdm_output *output, tdm_error *error)
1058 {
1059         tdm_capture *capture = NULL;
1060
1061         OUTPUT_FUNC_ENTRY_ERROR();
1062
1063         _pthread_mutex_lock(&private_display->lock);
1064
1065         capture = (tdm_capture *)tdm_capture_create_output_internal(private_output,
1066                         error);
1067
1068         _pthread_mutex_unlock(&private_display->lock);
1069
1070         return capture;
1071 }
1072
1073 INTERN void
1074 tdm_output_call_change_handler_internal(tdm_private_output *private_output,
1075                                         tdm_output_change_type type,
1076                                         tdm_value value)
1077 {
1078         tdm_private_change_handler *change_handler;
1079         tdm_private_display *private_display;
1080
1081         TDM_RETURN_IF_FAIL(private_output);
1082
1083         private_display = private_output->private_display;
1084
1085         if (type & TDM_OUTPUT_CHANGE_CONNECTION)
1086                 TDM_INFO("output(%d) changed: %s",
1087                          private_output->pipe, status_str(value.u32));
1088         if (type & TDM_OUTPUT_CHANGE_DPMS)
1089                 TDM_INFO("output(%d) changed: dpms %s",
1090                          private_output->pipe, dpms_str(value.u32));
1091
1092         _pthread_mutex_unlock(&private_display->lock);
1093
1094         LIST_FOR_EACH_ENTRY(change_handler, &private_output->change_handler_list, link) {
1095                 change_handler->func(private_output, type,
1096                                      value, change_handler->user_data);
1097         }
1098
1099         _pthread_mutex_lock(&private_display->lock);
1100 }
1101
1102 EXTERN tdm_error
1103 tdm_layer_get_capabilities(tdm_layer *layer, tdm_layer_capability *capabilities)
1104 {
1105         LAYER_FUNC_ENTRY();
1106
1107         TDM_RETURN_VAL_IF_FAIL(capabilities != NULL, TDM_ERROR_INVALID_PARAMETER);
1108
1109         _pthread_mutex_lock(&private_display->lock);
1110
1111         *capabilities = private_layer->caps.capabilities;
1112
1113         _pthread_mutex_unlock(&private_display->lock);
1114
1115         return ret;
1116 }
1117
1118 EXTERN tdm_error
1119 tdm_layer_get_available_formats(tdm_layer *layer, const tbm_format **formats,
1120                                 int *count)
1121 {
1122         LAYER_FUNC_ENTRY();
1123
1124         TDM_RETURN_VAL_IF_FAIL(formats != NULL, TDM_ERROR_INVALID_PARAMETER);
1125         TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
1126
1127         _pthread_mutex_lock(&private_display->lock);
1128
1129         *formats = (const tbm_format *)private_layer->caps.formats;
1130         *count = private_layer->caps.format_count;
1131
1132         _pthread_mutex_unlock(&private_display->lock);
1133
1134         return ret;
1135 }
1136
1137 EXTERN tdm_error
1138 tdm_layer_get_available_properties(tdm_layer *layer, const tdm_prop **props,
1139                                    int *count)
1140 {
1141         LAYER_FUNC_ENTRY();
1142
1143         TDM_RETURN_VAL_IF_FAIL(props != NULL, TDM_ERROR_INVALID_PARAMETER);
1144         TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
1145
1146         _pthread_mutex_lock(&private_display->lock);
1147
1148         *props = (const tdm_prop *)private_layer->caps.props;
1149         *count = private_layer->caps.prop_count;
1150
1151         _pthread_mutex_unlock(&private_display->lock);
1152
1153         return ret;
1154 }
1155
1156 EXTERN tdm_error
1157 tdm_layer_get_zpos(tdm_layer *layer, unsigned int *zpos)
1158 {
1159         LAYER_FUNC_ENTRY();
1160
1161         TDM_RETURN_VAL_IF_FAIL(zpos != NULL, TDM_ERROR_INVALID_PARAMETER);
1162
1163         _pthread_mutex_lock(&private_display->lock);
1164
1165         *zpos = private_layer->caps.zpos;
1166
1167         _pthread_mutex_unlock(&private_display->lock);
1168
1169         return ret;
1170 }
1171
1172 EXTERN tdm_error
1173 tdm_layer_set_property(tdm_layer *layer, unsigned int id, tdm_value value)
1174 {
1175         tdm_func_layer *func_layer;
1176         LAYER_FUNC_ENTRY();
1177
1178         _pthread_mutex_lock(&private_display->lock);
1179
1180         func_layer = &private_display->func_layer;
1181
1182         if (!func_layer->layer_set_property) {
1183                 _pthread_mutex_unlock(&private_display->lock);
1184                 TDM_DBG("failed: not implemented!!");
1185                 return TDM_ERROR_NOT_IMPLEMENTED;
1186         }
1187
1188         ret = func_layer->layer_set_property(private_layer->layer_backend, id, value);
1189
1190         _pthread_mutex_unlock(&private_display->lock);
1191
1192         return ret;
1193 }
1194
1195 EXTERN tdm_error
1196 tdm_layer_get_property(tdm_layer *layer, unsigned int id, tdm_value *value)
1197 {
1198         tdm_func_layer *func_layer;
1199         LAYER_FUNC_ENTRY();
1200
1201         TDM_RETURN_VAL_IF_FAIL(value != NULL, TDM_ERROR_INVALID_PARAMETER);
1202
1203         _pthread_mutex_lock(&private_display->lock);
1204
1205         func_layer = &private_display->func_layer;
1206
1207         if (!func_layer->layer_get_property) {
1208                 _pthread_mutex_unlock(&private_display->lock);
1209                 TDM_DBG("failed: not implemented!!");
1210                 return TDM_ERROR_NOT_IMPLEMENTED;
1211         }
1212
1213         ret = func_layer->layer_get_property(private_layer->layer_backend, id, value);
1214
1215         _pthread_mutex_unlock(&private_display->lock);
1216
1217         return ret;
1218 }
1219
1220 EXTERN tdm_error
1221 tdm_layer_set_info(tdm_layer *layer, tdm_info_layer *info)
1222 {
1223         tdm_func_layer *func_layer;
1224         LAYER_FUNC_ENTRY();
1225
1226         TDM_RETURN_VAL_IF_FAIL(info != NULL, TDM_ERROR_INVALID_PARAMETER);
1227
1228         _pthread_mutex_lock(&private_display->lock);
1229
1230         func_layer = &private_display->func_layer;
1231
1232         private_layer->usable = 0;
1233
1234         if (!func_layer->layer_set_info) {
1235                 _pthread_mutex_unlock(&private_display->lock);
1236                 TDM_DBG("failed: not implemented!!");
1237                 return TDM_ERROR_NOT_IMPLEMENTED;
1238         }
1239
1240         TDM_INFO("layer(%p) info: src(%dx%d %d,%d %dx%d %c%c%c%c) dst(%d,%d %dx%d) trans(%d)",
1241                  private_layer, info->src_config.size.h, info->src_config.size.v,
1242                  info->src_config.pos.x, info->src_config.pos.y,
1243                  info->src_config.pos.w, info->src_config.pos.h,
1244                  FOURCC_STR(info->src_config.format),
1245                  info->dst_pos.x, info->dst_pos.y,
1246                  info->dst_pos.w, info->dst_pos.h,
1247                  info->transform);
1248
1249         ret = func_layer->layer_set_info(private_layer->layer_backend, info);
1250         TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
1251
1252         _pthread_mutex_unlock(&private_display->lock);
1253
1254         return ret;
1255 }
1256
1257 EXTERN tdm_error
1258 tdm_layer_get_info(tdm_layer *layer, tdm_info_layer *info)
1259 {
1260         tdm_func_layer *func_layer;
1261         LAYER_FUNC_ENTRY();
1262
1263         TDM_RETURN_VAL_IF_FAIL(info != NULL, TDM_ERROR_INVALID_PARAMETER);
1264
1265         _pthread_mutex_lock(&private_display->lock);
1266
1267         func_layer = &private_display->func_layer;
1268
1269         if (!func_layer->layer_get_info) {
1270                 _pthread_mutex_unlock(&private_display->lock);
1271                 TDM_DBG("failed: not implemented!!");
1272                 return TDM_ERROR_NOT_IMPLEMENTED;
1273         }
1274
1275         ret = func_layer->layer_get_info(private_layer->layer_backend, info);
1276
1277         _pthread_mutex_unlock(&private_display->lock);
1278
1279         return ret;
1280 }
1281
1282 EXTERN tdm_error
1283 tdm_layer_set_buffer(tdm_layer *layer, tbm_surface_h buffer)
1284 {
1285         tdm_func_layer *func_layer;
1286
1287         LAYER_FUNC_ENTRY();
1288
1289         TDM_RETURN_VAL_IF_FAIL(buffer != NULL, TDM_ERROR_INVALID_PARAMETER);
1290
1291         _pthread_mutex_lock(&private_display->lock);
1292
1293         func_layer = &private_display->func_layer;
1294
1295         private_layer->usable = 0;
1296
1297         if (!func_layer->layer_set_buffer) {
1298                 _pthread_mutex_unlock(&private_display->lock);
1299                 TDM_DBG("failed: not implemented!!");
1300                 return TDM_ERROR_NOT_IMPLEMENTED;
1301         }
1302
1303         ret = func_layer->layer_set_buffer(private_layer->layer_backend, buffer);
1304         TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
1305
1306         if (ret == TDM_ERROR_NONE) {
1307                 /* FIXME: should save to pending_buffer first. And after committing
1308                  * successfully, need to move to waiting_buffer.
1309                  */
1310                 if (private_layer->waiting_buffer) {
1311                         _pthread_mutex_unlock(&private_display->lock);
1312                         tdm_buffer_unref_backend(private_layer->waiting_buffer);
1313                         _pthread_mutex_lock(&private_display->lock);
1314                 }
1315
1316                 private_layer->waiting_buffer = tdm_buffer_ref_backend(buffer);
1317                 if (tdm_debug_buffer)
1318                         TDM_INFO("layer(%p) waiting_buffer(%p)",
1319                                  private_layer, private_layer->waiting_buffer);
1320         }
1321
1322         _pthread_mutex_unlock(&private_display->lock);
1323
1324         return ret;
1325 }
1326
1327 EXTERN tdm_error
1328 tdm_layer_unset_buffer(tdm_layer *layer)
1329 {
1330         tdm_func_layer *func_layer;
1331         LAYER_FUNC_ENTRY();
1332
1333         _pthread_mutex_lock(&private_display->lock);
1334
1335         func_layer = &private_display->func_layer;
1336
1337         if (private_layer->waiting_buffer) {
1338                 _pthread_mutex_unlock(&private_display->lock);
1339                 tdm_buffer_unref_backend(private_layer->waiting_buffer);
1340                 _pthread_mutex_lock(&private_display->lock);
1341                 private_layer->waiting_buffer = NULL;
1342
1343                 if (tdm_debug_buffer)
1344                         TDM_INFO("layer(%p) waiting_buffer(%p)",
1345                                  private_layer, private_layer->waiting_buffer);
1346         }
1347
1348         if (private_layer->showing_buffer) {
1349                 _pthread_mutex_unlock(&private_display->lock);
1350                 tdm_buffer_unref_backend(private_layer->showing_buffer);
1351                 _pthread_mutex_lock(&private_display->lock);
1352                 private_layer->showing_buffer = NULL;
1353
1354                 if (tdm_debug_buffer)
1355                         TDM_INFO("layer(%p) showing_buffer(%p)",
1356                                  private_layer, private_layer->showing_buffer);
1357         }
1358
1359         private_layer->usable = 1;
1360
1361         if (!func_layer->layer_unset_buffer) {
1362                 _pthread_mutex_unlock(&private_display->lock);
1363                 TDM_DBG("failed: not implemented!!");
1364                 return TDM_ERROR_NOT_IMPLEMENTED;
1365         }
1366
1367         ret = func_layer->layer_unset_buffer(private_layer->layer_backend);
1368         TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
1369
1370         _pthread_mutex_unlock(&private_display->lock);
1371
1372         return ret;
1373 }
1374
1375 static void
1376 _tbm_layer_queue_acquirable_cb(tbm_surface_queue_h surface_queue, void *data)
1377 {
1378         TDM_RETURN_IF_FAIL(data != NULL);
1379         tdm_layer *layer = data;
1380         tdm_func_layer *func_layer;
1381         tbm_surface_h surface = NULL;
1382         LAYER_FUNC_ENTRY_VOID_RETURN();
1383
1384         _pthread_mutex_lock(&private_display->lock);
1385
1386         func_layer = &private_display->func_layer;
1387         if (!func_layer->layer_set_buffer) {
1388                 _pthread_mutex_unlock(&private_display->lock);
1389                 return;
1390         }
1391
1392         if (TBM_SURFACE_QUEUE_ERROR_NONE != tbm_surface_queue_acquire(
1393                     private_layer->buffer_queue, &surface) ||
1394             surface == NULL) {
1395                 TDM_ERR("layer(%p) tbm_surface_queue_acquire() failed surface:%p",
1396                         private_layer, surface);
1397                 _pthread_mutex_unlock(&private_display->lock);
1398                 return;
1399         }
1400
1401         ret = func_layer->layer_set_buffer(private_layer->layer_backend, surface);
1402         TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
1403
1404         if (ret == TDM_ERROR_NONE) {
1405                 if (private_layer->waiting_buffer) {
1406                         _pthread_mutex_unlock(&private_display->lock);
1407                         tdm_buffer_unref_backend(private_layer->waiting_buffer);
1408                         tbm_surface_queue_release(private_layer->buffer_queue,
1409                                                   private_layer->waiting_buffer);
1410                         _pthread_mutex_lock(&private_display->lock);
1411                 }
1412
1413                 private_layer->waiting_buffer = tdm_buffer_ref_backend(surface);
1414
1415                 if (tdm_debug_buffer)
1416                         TDM_INFO("layer(%p) waiting_buffer(%p)",
1417                                  private_layer, private_layer->waiting_buffer);
1418
1419                 ret = _tdm_output_commit(private_layer->private_output, 0, NULL, NULL);
1420                 if (ret != TDM_ERROR_NONE)
1421                         TDM_ERR("layer(%p) _tdm_output_commit() is fail", private_layer);
1422         }
1423
1424         _pthread_mutex_unlock(&private_display->lock);
1425 }
1426
1427 static void
1428 _tbm_layer_queue_destroy_cb(tbm_surface_queue_h surface_queue, void *data)
1429 {
1430         TDM_RETURN_IF_FAIL(data != NULL);
1431         tdm_layer *layer = data;
1432         LAYER_FUNC_ENTRY_VOID_RETURN();
1433         TDM_RETURN_IF_FAIL(ret == TDM_ERROR_NONE);
1434
1435         _pthread_mutex_lock(&private_display->lock);
1436
1437         if (private_layer->waiting_buffer) {
1438                 _pthread_mutex_unlock(&private_display->lock);
1439                 tdm_buffer_unref_backend(private_layer->waiting_buffer);
1440                 tbm_surface_queue_release(private_layer->buffer_queue,
1441                                           private_layer->waiting_buffer);
1442                 _pthread_mutex_lock(&private_display->lock);
1443         }
1444
1445         private_layer->buffer_queue = NULL;
1446
1447         _pthread_mutex_unlock(&private_display->lock);
1448 }
1449
1450 EXTERN tdm_error
1451 tdm_layer_set_buffer_queue(tdm_layer *layer, tbm_surface_queue_h buffer_queue)
1452 {
1453         tdm_func_layer *func_layer;
1454         LAYER_FUNC_ENTRY();
1455
1456         TDM_RETURN_VAL_IF_FAIL(buffer_queue != NULL, TDM_ERROR_INVALID_PARAMETER);
1457
1458         _pthread_mutex_lock(&private_display->lock);
1459
1460         func_layer = &private_display->func_layer;
1461
1462         private_layer->usable = 0;
1463
1464         if (!func_layer->layer_set_buffer) {
1465                 _pthread_mutex_unlock(&private_display->lock);
1466                 TDM_DBG("failed: not implemented!!");
1467                 return TDM_ERROR_NOT_IMPLEMENTED;
1468         }
1469
1470         if (buffer_queue == private_layer->buffer_queue) {
1471                 _pthread_mutex_unlock(&private_display->lock);
1472                 return TDM_ERROR_NONE;
1473         }
1474
1475         if (private_layer->waiting_buffer) {
1476                 _pthread_mutex_unlock(&private_display->lock);
1477                 tdm_buffer_unref_backend(private_layer->waiting_buffer);
1478                 tbm_surface_queue_release(private_layer->buffer_queue,
1479                                           private_layer->waiting_buffer);
1480                 private_layer->waiting_buffer = NULL;
1481                 _pthread_mutex_lock(&private_display->lock);
1482
1483                 if (tdm_debug_buffer)
1484                         TDM_INFO("layer(%p) waiting_buffer(%p)",
1485                                  private_layer, private_layer->waiting_buffer);
1486         }
1487
1488         private_layer->buffer_queue = buffer_queue;
1489         tbm_surface_queue_add_acquirable_cb(private_layer->buffer_queue,
1490                                             _tbm_layer_queue_acquirable_cb,
1491                                             layer);
1492         tbm_surface_queue_add_destroy_cb(private_layer->buffer_queue,
1493                                          _tbm_layer_queue_destroy_cb,
1494                                          layer);
1495         _pthread_mutex_unlock(&private_display->lock);
1496
1497         return ret;
1498 }
1499
1500 EXTERN tdm_error
1501 tdm_layer_unset_buffer_queue(tdm_layer *layer)
1502 {
1503         tdm_func_layer *func_layer;
1504         LAYER_FUNC_ENTRY();
1505
1506         _pthread_mutex_lock(&private_display->lock);
1507
1508         func_layer = &private_display->func_layer;
1509
1510         if (private_layer->waiting_buffer) {
1511                 _pthread_mutex_unlock(&private_display->lock);
1512                 tdm_buffer_unref_backend(private_layer->waiting_buffer);
1513                 tbm_surface_queue_release(private_layer->buffer_queue,
1514                                           private_layer->waiting_buffer);
1515                 private_layer->waiting_buffer = NULL;
1516                 _pthread_mutex_lock(&private_display->lock);
1517
1518                 if (tdm_debug_buffer)
1519                         TDM_INFO("layer(%p) waiting_buffer(%p)",
1520                                  private_layer, private_layer->waiting_buffer);
1521         }
1522
1523         if (private_layer->showing_buffer) {
1524                 _pthread_mutex_unlock(&private_display->lock);
1525                 tdm_buffer_unref_backend(private_layer->showing_buffer);
1526                 tbm_surface_queue_release(private_layer->buffer_queue,
1527                                           private_layer->showing_buffer);
1528                 _pthread_mutex_lock(&private_display->lock);
1529                 private_layer->showing_buffer = NULL;
1530
1531                 if (tdm_debug_buffer)
1532                         TDM_INFO("layer(%p) showing_buffer(%p)",
1533                                  private_layer, private_layer->showing_buffer);
1534         }
1535
1536         tbm_surface_queue_remove_acquirable_cb(private_layer->buffer_queue, _tbm_layer_queue_acquirable_cb, layer);
1537         tbm_surface_queue_remove_destroy_cb(private_layer->buffer_queue, _tbm_layer_queue_destroy_cb, layer);
1538         private_layer->buffer_queue = NULL;
1539         private_layer->usable = 1;
1540
1541         if (!func_layer->layer_unset_buffer) {
1542                 _pthread_mutex_unlock(&private_display->lock);
1543                 TDM_DBG("failed: not implemented!!");
1544                 return TDM_ERROR_NOT_IMPLEMENTED;
1545         }
1546
1547         ret = func_layer->layer_unset_buffer(private_layer->layer_backend);
1548
1549         _pthread_mutex_unlock(&private_display->lock);
1550
1551         return ret;
1552 }
1553
1554 EXTERN tdm_error
1555 tdm_layer_is_usable(tdm_layer *layer, unsigned int *usable)
1556 {
1557         LAYER_FUNC_ENTRY();
1558
1559         TDM_RETURN_VAL_IF_FAIL(usable != NULL, TDM_ERROR_INVALID_PARAMETER);
1560
1561         _pthread_mutex_lock(&private_display->lock);
1562
1563         *usable = private_layer->usable;
1564
1565         _pthread_mutex_unlock(&private_display->lock);
1566
1567         return ret;
1568 }
1569
1570 EXTERN tdm_error
1571 tdm_layer_set_video_pos(tdm_layer *layer, int zpos)
1572 {
1573         tdm_func_layer *func_layer;
1574         LAYER_FUNC_ENTRY();
1575
1576         _pthread_mutex_lock(&private_display->lock);
1577
1578         func_layer = &private_display->func_layer;
1579
1580         if (!(private_layer->caps.capabilities & TDM_LAYER_CAPABILITY_VIDEO)) {
1581                 TDM_ERR("layer(%p) is not video layer", private_layer);
1582                 _pthread_mutex_unlock(&private_display->lock);
1583                 return TDM_ERROR_INVALID_PARAMETER;
1584         }
1585
1586         if (!func_layer->layer_set_video_pos) {
1587                 _pthread_mutex_unlock(&private_display->lock);
1588                 TDM_DBG("failed: not implemented!!");
1589                 return TDM_ERROR_NOT_IMPLEMENTED;
1590         }
1591
1592         ret = func_layer->layer_set_video_pos(private_layer->layer_backend, zpos);
1593
1594         _pthread_mutex_unlock(&private_display->lock);
1595
1596         return ret;
1597 }
1598
1599 EXTERN tdm_capture *
1600 tdm_layer_create_capture(tdm_layer *layer, tdm_error *error)
1601 {
1602         tdm_capture *capture = NULL;
1603
1604         LAYER_FUNC_ENTRY_ERROR();
1605
1606         _pthread_mutex_lock(&private_display->lock);
1607
1608         capture = (tdm_capture *)tdm_capture_create_layer_internal(private_layer,
1609                         error);
1610
1611         _pthread_mutex_unlock(&private_display->lock);
1612
1613         return capture;
1614 }