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