remove unused helper function
[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 = TDM_FRONT_VALUE(private_display->caps_pp.min_w);
185         if (min_h)
186                 *min_h = TDM_FRONT_VALUE(private_display->caps_pp.min_h);
187         if (max_w)
188                 *max_w = TDM_FRONT_VALUE(private_display->caps_pp.max_w);
189         if (max_h)
190                 *max_h = TDM_FRONT_VALUE(private_display->caps_pp.max_h);
191         if (preferred_align)
192                 *preferred_align = TDM_FRONT_VALUE(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_capture_available_size(tdm_display *dpy, int *min_w, int *min_h,
249                                                                            int *max_w, int *max_h, int *preferred_align)
250 {
251         DISPLAY_FUNC_ENTRY();
252
253         _pthread_mutex_lock(&private_display->lock);
254
255         if (!(private_display->capabilities & TDM_DISPLAY_CAPABILITY_CAPTURE)) {
256                 TDM_ERR("no capture capability");
257                 _pthread_mutex_unlock(&private_display->lock);
258                 return TDM_ERROR_NO_CAPABILITY;
259         }
260
261         if (min_w)
262                 *min_w = TDM_FRONT_VALUE(private_display->caps_capture.min_w);
263         if (min_h)
264                 *min_h = TDM_FRONT_VALUE(private_display->caps_capture.min_h);
265         if (max_w)
266                 *max_w = TDM_FRONT_VALUE(private_display->caps_capture.max_w);
267         if (max_h)
268                 *max_h = TDM_FRONT_VALUE(private_display->caps_capture.max_h);
269         if (preferred_align)
270                 *preferred_align = TDM_FRONT_VALUE(private_display->caps_capture.preferred_align);
271
272         _pthread_mutex_unlock(&private_display->lock);
273
274         return ret;
275 }
276
277 EXTERN tdm_error
278 tdm_display_get_max_layer_count(tdm_display *dpy, int *max_count)
279 {
280         DISPLAY_FUNC_ENTRY();
281
282         TDM_RETURN_VAL_IF_FAIL(max_count != NULL, TDM_ERROR_INVALID_PARAMETER);
283
284         _pthread_mutex_lock(&private_display->lock);
285
286         *max_count = TDM_FRONT_VALUE(private_display->caps_display.max_layer_count);
287
288         _pthread_mutex_unlock(&private_display->lock);
289
290         return ret;
291 }
292
293 EXTERN tdm_error
294 tdm_display_get_output_count(tdm_display *dpy, int *count)
295 {
296         tdm_private_output *private_output = NULL;
297
298         DISPLAY_FUNC_ENTRY();
299
300         TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
301
302         _pthread_mutex_lock(&private_display->lock);
303
304         *count = 0;
305         LIST_FOR_EACH_ENTRY(private_output, &private_display->output_list, link)
306         (*count)++;
307
308         if (*count == 0) {
309                 _pthread_mutex_unlock(&private_display->lock);
310                 return TDM_ERROR_NONE;
311         }
312
313         _pthread_mutex_unlock(&private_display->lock);
314
315         return ret;
316 }
317
318
319 EXTERN tdm_output *
320 tdm_display_get_output(tdm_display *dpy, int index, tdm_error *error)
321 {
322         tdm_private_output *private_output = NULL;
323
324         DISPLAY_FUNC_ENTRY_ERROR();
325
326         _pthread_mutex_lock(&private_display->lock);
327
328         if (error)
329                 *error = TDM_ERROR_NONE;
330
331         LIST_FOR_EACH_ENTRY(private_output, &private_display->output_list, link) {
332                 if (private_output->index == index) {
333                         _pthread_mutex_unlock(&private_display->lock);
334                         return private_output;
335                 }
336         }
337
338         _pthread_mutex_unlock(&private_display->lock);
339
340         return NULL;
341 }
342
343 EXTERN tdm_error
344 tdm_display_get_fd(tdm_display *dpy, int *fd)
345 {
346         DISPLAY_FUNC_ENTRY();
347
348         TDM_RETURN_VAL_IF_FAIL(fd != NULL, TDM_ERROR_INVALID_PARAMETER);
349
350         _pthread_mutex_lock(&private_display->lock);
351
352         if (tdm_thread_is_running())
353                 *fd = tdm_thread_get_fd(private_display->private_loop);
354         else
355                 *fd = tdm_event_loop_get_fd(private_display);
356
357         _pthread_mutex_unlock(&private_display->lock);
358
359         return ret;
360 }
361
362 EXTERN tdm_error
363 tdm_display_handle_events(tdm_display *dpy)
364 {
365         struct pollfd fds;
366         int fd = -1;
367
368         DISPLAY_FUNC_ENTRY();
369
370         ret = tdm_display_get_fd(dpy, &fd);
371         TDM_RETURN_VAL_IF_FAIL(fd >= 0, ret);
372
373         fds.events = POLLIN;
374         fds.fd = fd;
375         fds.revents = 0;
376
377         if (tdm_debug_module & TDM_DEBUG_THREAD)
378                 TDM_INFO("fd(%d) polling in", fd);
379
380         while (poll(&fds, 1, -1) < 0) {
381                 if (errno == EINTR || errno == EAGAIN)  /* normal case */
382                         continue;
383                 else {
384                         TDM_ERR("poll failed: %m");
385                         return TDM_ERROR_OPERATION_FAILED;
386                 }
387         }
388
389         if (tdm_debug_module & TDM_DEBUG_THREAD)
390                 TDM_INFO("fd(%d) polling out", fd);
391
392         if (tdm_thread_is_running())
393                 ret = tdm_thread_handle_cb(private_display->private_loop);
394         else
395                 ret = tdm_event_loop_dispatch(private_display);
396
397         return ret;
398 }
399
400 EXTERN tdm_error
401 tdm_display_get_backend_info(tdm_display *dpy, const char **name,
402                                                          const char **vendor, int *major, int *minor)
403 {
404         tdm_backend_module *module_data;
405
406         DISPLAY_FUNC_ENTRY();
407
408         _pthread_mutex_lock(&private_display->lock);
409
410         module_data = private_display->module_data;
411
412         if (name)
413                 *name = module_data->name;
414         if (vendor)
415                 *vendor = module_data->vendor;
416         if (major)
417                 *major = TDM_BACKEND_GET_ABI_MAJOR(module_data->abi_version);
418         if (minor)
419                 *minor = TDM_BACKEND_GET_ABI_MINOR(module_data->abi_version);
420
421         _pthread_mutex_unlock(&private_display->lock);
422
423         return ret;
424 }
425
426 EXTERN tdm_pp *
427 tdm_display_create_pp(tdm_display *dpy, tdm_error *error)
428 {
429         tdm_pp *pp;
430
431         DISPLAY_FUNC_ENTRY_ERROR();
432
433         _pthread_mutex_lock(&private_display->lock);
434
435         pp = (tdm_pp *)tdm_pp_create_internal(private_display, error);
436
437         _pthread_mutex_unlock(&private_display->lock);
438
439         return pp;
440 }
441
442 EXTERN tdm_error
443 tdm_output_get_model_info(tdm_output *output, const char **maker,
444                                                   const char **model, const char **name)
445 {
446         OUTPUT_FUNC_ENTRY();
447
448         _pthread_mutex_lock(&private_display->lock);
449
450         if (maker)
451                 *maker = private_output->caps.maker;
452         if (model)
453                 *model = private_output->caps.model;
454         if (name)
455                 *name = private_output->caps.name;
456
457         _pthread_mutex_unlock(&private_display->lock);
458
459         return ret;
460 }
461
462 EXTERN tdm_error
463 tdm_output_get_capabilities(tdm_output *output, tdm_output_capability *capabilities)
464 {
465         OUTPUT_FUNC_ENTRY();
466
467         TDM_RETURN_VAL_IF_FAIL(capabilities != NULL, TDM_ERROR_INVALID_PARAMETER);
468
469         _pthread_mutex_lock(&private_display->lock);
470
471         *capabilities = private_output->caps.capabilities;
472
473         _pthread_mutex_unlock(&private_display->lock);
474
475         return ret;
476 }
477
478 EXTERN tdm_error
479 tdm_output_get_conn_status(tdm_output *output, tdm_output_conn_status *status)
480 {
481         OUTPUT_FUNC_ENTRY();
482
483         TDM_RETURN_VAL_IF_FAIL(status != NULL, TDM_ERROR_INVALID_PARAMETER);
484
485         _pthread_mutex_lock(&private_display->lock);
486
487         *status = private_output->caps.status;
488
489         _pthread_mutex_unlock(&private_display->lock);
490
491         return ret;
492 }
493
494 static void
495 _tdm_output_update(tdm_output *output_backend, void *user_data)
496 {
497         tdm_private_display *private_display;
498         tdm_private_output *private_output = user_data;
499         tdm_error ret;
500
501         TDM_RETURN_IF_FAIL(private_output);
502
503         private_display = private_output->private_display;
504
505         ret = tdm_display_update_output(private_display, output_backend, private_output->pipe);
506         TDM_RETURN_IF_FAIL(ret == TDM_ERROR_NONE);
507 }
508
509 INTERN void
510 tdm_output_cb_status(tdm_output *output_backend, tdm_output_conn_status status,
511                                          void *user_data)
512 {
513         tdm_private_display *private_display;
514         tdm_private_output *private_output = user_data;
515         tdm_value value;
516
517         TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED());
518         TDM_RETURN_IF_FAIL(private_output);
519
520         private_display = private_output->private_display;
521
522         if (!tdm_thread_in_display_thread(syscall(SYS_gettid))) {
523                 tdm_thread_cb_output_status output_status;
524                 tdm_error ret;
525
526                 _tdm_output_update(output_backend, user_data);
527
528                 output_status.base.type = TDM_THREAD_CB_OUTPUT_STATUS;
529                 output_status.base.length = sizeof output_status;
530                 output_status.output_stamp = private_output->stamp;
531                 output_status.status = status;
532                 output_status.user_data = user_data;
533
534                 value.u32 = status;
535                 tdm_output_call_change_handler_internal(private_output,
536                                                                                                 &private_output->change_handler_list_sub,
537                                                                                                 TDM_OUTPUT_CHANGE_CONNECTION,
538                                                                                                 value, 0);
539
540                 ret = tdm_thread_send_cb(private_display->private_loop, &output_status.base);
541                 TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
542
543                 return;
544         }
545
546         if (!tdm_thread_is_running())
547                 _tdm_output_update(output_backend, user_data);
548
549         value.u32 = status;
550         tdm_output_call_change_handler_internal(private_output,
551                                                                                         &private_output->change_handler_list_main,
552                                                                                         TDM_OUTPUT_CHANGE_CONNECTION,
553                                                                                         value, 0);
554 }
555
556 EXTERN tdm_error
557 tdm_output_add_change_handler(tdm_output *output,
558                                                           tdm_output_change_handler func,
559                                                           void *user_data)
560 {
561         tdm_private_change_handler *change_handler;
562         OUTPUT_FUNC_ENTRY();
563
564         TDM_RETURN_VAL_IF_FAIL(func != NULL, TDM_ERROR_INVALID_PARAMETER);
565
566         pthread_mutex_lock(&private_display->lock);
567
568         change_handler = calloc(1, sizeof(tdm_private_change_handler));
569         if (!change_handler) {
570                 TDM_ERR("failed: alloc memory");
571                 _pthread_mutex_unlock(&private_display->lock);
572                 return TDM_ERROR_OUT_OF_MEMORY;
573         }
574
575         change_handler->private_output = private_output;
576         change_handler->func = func;
577         change_handler->user_data = user_data;
578         change_handler->owner_tid = syscall(SYS_gettid);
579
580         if (!tdm_thread_in_display_thread(change_handler->owner_tid))
581                 LIST_ADD(&change_handler->link, &private_output->change_handler_list_sub);
582         else
583                 LIST_ADD(&change_handler->link, &private_output->change_handler_list_main);
584
585         _pthread_mutex_unlock(&private_display->lock);
586
587         return ret;
588 }
589
590 EXTERN void
591 tdm_output_remove_change_handler(tdm_output *output,
592                                                                  tdm_output_change_handler func,
593                                                                  void *user_data)
594 {
595         tdm_private_display *private_display;
596         tdm_private_output *private_output;
597         tdm_private_change_handler *h = NULL, *hh = NULL;
598
599         TDM_RETURN_IF_FAIL(output != NULL);
600         TDM_RETURN_IF_FAIL(func != NULL);
601
602         private_output = (tdm_private_output*)output;
603         private_display = private_output->private_display;
604
605         _pthread_mutex_lock(&private_display->lock);
606
607         LIST_FOR_EACH_ENTRY_SAFE(h, hh, &private_output->change_handler_list_main, link) {
608                 if (h->func != func || h->user_data != user_data)
609                         continue;
610
611                 LIST_DEL(&h->link);
612                 free(h);
613
614                 _pthread_mutex_unlock(&private_display->lock);
615
616                 return;
617         }
618
619         LIST_FOR_EACH_ENTRY_SAFE(h, hh, &private_output->change_handler_list_sub, link) {
620                 if (h->func != func || h->user_data != user_data)
621                         continue;
622
623                 LIST_DEL(&h->link);
624                 free(h);
625
626                 _pthread_mutex_unlock(&private_display->lock);
627
628                 return;
629         }
630
631         _pthread_mutex_unlock(&private_display->lock);
632 }
633
634 EXTERN tdm_error
635 tdm_output_get_output_type(tdm_output *output, tdm_output_type *type)
636 {
637         OUTPUT_FUNC_ENTRY();
638
639         TDM_RETURN_VAL_IF_FAIL(type != NULL, TDM_ERROR_INVALID_PARAMETER);
640
641         _pthread_mutex_lock(&private_display->lock);
642
643         *type = private_output->caps.type;
644
645         _pthread_mutex_unlock(&private_display->lock);
646
647         return ret;
648 }
649
650 EXTERN tdm_error
651 tdm_output_get_layer_count(tdm_output *output, int *count)
652 {
653         tdm_private_layer *private_layer = NULL;
654
655         OUTPUT_FUNC_ENTRY();
656
657         TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
658
659         _pthread_mutex_lock(&private_display->lock);
660
661         *count = 0;
662         LIST_FOR_EACH_ENTRY(private_layer, &private_output->layer_list, link)
663         (*count)++;
664         if (*count == 0) {
665                 _pthread_mutex_unlock(&private_display->lock);
666                 return TDM_ERROR_NONE;
667         }
668
669         _pthread_mutex_unlock(&private_display->lock);
670
671         return ret;
672 }
673
674
675 EXTERN tdm_layer *
676 tdm_output_get_layer(tdm_output *output, int index, tdm_error *error)
677 {
678         tdm_private_layer *private_layer = NULL;
679
680         OUTPUT_FUNC_ENTRY_ERROR();
681
682         _pthread_mutex_lock(&private_display->lock);
683
684         if (error)
685                 *error = TDM_ERROR_NONE;
686
687         LIST_FOR_EACH_ENTRY(private_layer, &private_output->layer_list, link) {
688                 if (private_layer->index == index) {
689                         _pthread_mutex_unlock(&private_display->lock);
690                         return private_layer;
691                 }
692         }
693
694         _pthread_mutex_unlock(&private_display->lock);
695
696         return NULL;
697 }
698
699 EXTERN tdm_error
700 tdm_output_get_available_properties(tdm_output *output, const tdm_prop **props,
701                                                                         int *count)
702 {
703         OUTPUT_FUNC_ENTRY();
704
705         TDM_RETURN_VAL_IF_FAIL(props != NULL, TDM_ERROR_INVALID_PARAMETER);
706         TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
707
708         _pthread_mutex_lock(&private_display->lock);
709
710         *props = (const tdm_prop *)private_output->caps.props;
711         *count = private_output->caps.prop_count;
712
713         _pthread_mutex_unlock(&private_display->lock);
714
715         return ret;
716 }
717
718 EXTERN tdm_error
719 tdm_output_get_available_modes(tdm_output *output,
720                                                            const tdm_output_mode **modes, int *count)
721 {
722         OUTPUT_FUNC_ENTRY();
723
724         TDM_RETURN_VAL_IF_FAIL(modes != NULL, TDM_ERROR_INVALID_PARAMETER);
725         TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
726
727         _pthread_mutex_lock(&private_display->lock);
728
729         *modes = (const tdm_output_mode *)private_output->caps.modes;
730         *count = private_output->caps.mode_count;
731
732         _pthread_mutex_unlock(&private_display->lock);
733
734         return ret;
735 }
736
737 EXTERN tdm_error
738 tdm_output_get_available_size(tdm_output *output, int *min_w, int *min_h,
739                                                           int *max_w, int *max_h, int *preferred_align)
740 {
741         OUTPUT_FUNC_ENTRY();
742
743         _pthread_mutex_lock(&private_display->lock);
744
745         if (min_w)
746                 *min_w = TDM_FRONT_VALUE(private_output->caps.min_w);
747         if (min_h)
748                 *min_h = TDM_FRONT_VALUE(private_output->caps.min_h);
749         if (max_w)
750                 *max_w = TDM_FRONT_VALUE(private_output->caps.max_w);
751         if (max_h)
752                 *max_h = TDM_FRONT_VALUE(private_output->caps.max_h);
753         if (preferred_align)
754                 *preferred_align = TDM_FRONT_VALUE(private_output->caps.preferred_align);
755
756         _pthread_mutex_unlock(&private_display->lock);
757
758         return ret;
759 }
760
761 EXTERN tdm_error
762 tdm_output_get_cursor_available_size(tdm_output *output, int *min_w, int *min_h,
763                                                                          int *max_w, int *max_h, int *preferred_align)
764 {
765         OUTPUT_FUNC_ENTRY();
766
767         _pthread_mutex_lock(&private_display->lock);
768
769         if (!tdm_display_check_module_abi(private_display, 1, 5)) {
770
771                 if (min_w)
772                         *min_w = -1;
773                 if (min_h)
774                         *min_h = -1;
775                 if (max_w)
776                         *max_w = -1;
777                 if (max_h)
778                         *max_h = -1;
779                 if (preferred_align)
780                         *preferred_align = -1;
781
782                 _pthread_mutex_unlock(&private_display->lock);
783
784                 return TDM_ERROR_BAD_MODULE;
785         }
786
787         if (min_w)
788                 *min_w = TDM_FRONT_VALUE(private_output->caps.cursor_min_w);
789         if (min_h)
790                 *min_h = TDM_FRONT_VALUE(private_output->caps.cursor_min_h);
791         if (max_w)
792                 *max_w = TDM_FRONT_VALUE(private_output->caps.cursor_max_w);
793         if (max_h)
794                 *max_h = TDM_FRONT_VALUE(private_output->caps.cursor_max_h);
795         if (preferred_align)
796                 *preferred_align = TDM_FRONT_VALUE(private_output->caps.cursor_preferred_align);
797
798         _pthread_mutex_unlock(&private_display->lock);
799
800         return ret;
801 }
802
803 EXTERN tdm_error
804 tdm_output_get_physical_size(tdm_output *output, unsigned int *mmWidth,
805                                                          unsigned int *mmHeight)
806 {
807         OUTPUT_FUNC_ENTRY();
808
809         _pthread_mutex_lock(&private_display->lock);
810
811         if (mmWidth)
812                 *mmWidth = private_output->caps.mmWidth;
813         if (mmHeight)
814                 *mmHeight = private_output->caps.mmHeight;
815
816         _pthread_mutex_unlock(&private_display->lock);
817
818         return ret;
819 }
820
821 EXTERN tdm_error
822 tdm_output_get_subpixel(tdm_output *output, unsigned int *subpixel)
823 {
824         OUTPUT_FUNC_ENTRY();
825         TDM_RETURN_VAL_IF_FAIL(subpixel != NULL, TDM_ERROR_INVALID_PARAMETER);
826
827         _pthread_mutex_lock(&private_display->lock);
828
829         *subpixel = private_output->caps.subpixel;
830
831         _pthread_mutex_unlock(&private_display->lock);
832
833         return ret;
834 }
835
836 EXTERN tdm_error
837 tdm_output_get_pipe(tdm_output *output, unsigned int *pipe)
838 {
839         OUTPUT_FUNC_ENTRY();
840         TDM_RETURN_VAL_IF_FAIL(pipe != NULL, TDM_ERROR_INVALID_PARAMETER);
841
842         _pthread_mutex_lock(&private_display->lock);
843
844         *pipe = private_output->pipe;
845
846         _pthread_mutex_unlock(&private_display->lock);
847
848         return ret;
849 }
850
851 EXTERN tdm_error
852 tdm_output_get_primary_index(tdm_output *output, int *index)
853 {
854         tdm_private_layer *private_layer = NULL;
855
856         OUTPUT_FUNC_ENTRY();
857         TDM_RETURN_VAL_IF_FAIL(index != NULL, TDM_ERROR_INVALID_PARAMETER);
858
859         _pthread_mutex_lock(&private_display->lock);
860
861         LIST_FOR_EACH_ENTRY(private_layer, &private_output->layer_list, link) {
862                 if (private_layer->caps.capabilities & TDM_LAYER_CAPABILITY_PRIMARY) {
863                         *index = private_layer->index;
864                         break;
865                 }
866         }
867
868         _pthread_mutex_unlock(&private_display->lock);
869
870         return ret;
871 }
872
873 EXTERN tdm_error
874 tdm_output_set_property(tdm_output *output, unsigned int id, tdm_value value)
875 {
876         tdm_func_output *func_output;
877         OUTPUT_FUNC_ENTRY();
878
879         _pthread_mutex_lock(&private_display->lock);
880
881         func_output = &private_display->func_output;
882
883         if (!func_output->output_set_property) {
884                 _pthread_mutex_unlock(&private_display->lock);
885                 TDM_ERR("not implemented!!");
886                 return TDM_ERROR_NOT_IMPLEMENTED;
887         }
888
889         ret = func_output->output_set_property(private_output->output_backend, id,
890                                                                                    value);
891
892         _pthread_mutex_unlock(&private_display->lock);
893
894         return ret;
895 }
896
897 EXTERN tdm_error
898 tdm_output_get_property(tdm_output *output, unsigned int id, tdm_value *value)
899 {
900         tdm_func_output *func_output;
901         OUTPUT_FUNC_ENTRY();
902
903         TDM_RETURN_VAL_IF_FAIL(value != NULL, TDM_ERROR_INVALID_PARAMETER);
904
905         _pthread_mutex_lock(&private_display->lock);
906
907         func_output = &private_display->func_output;
908
909         if (!func_output->output_get_property) {
910                 _pthread_mutex_unlock(&private_display->lock);
911                 TDM_ERR("not implemented!!");
912                 return TDM_ERROR_NOT_IMPLEMENTED;
913         }
914
915         ret = func_output->output_get_property(private_output->output_backend, id,
916                                                                                    value);
917
918         _pthread_mutex_unlock(&private_display->lock);
919
920         return ret;
921 }
922
923 INTERN void
924 tdm_output_cb_vblank(tdm_output *output_backend, unsigned int sequence,
925                                          unsigned int tv_sec, unsigned int tv_usec, void *user_data)
926 {
927         tdm_private_vblank_handler *vblank_handler = user_data;
928         tdm_private_display *private_display;
929
930         TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED());
931         TDM_RETURN_IF_FAIL(vblank_handler);
932
933         private_display = vblank_handler->private_output->private_display;
934
935         if (vblank_handler->owner_tid != syscall(SYS_gettid)) {
936                 tdm_thread_cb_output_vblank output_vblank;
937                 tdm_error ret;
938
939                 output_vblank.base.type = TDM_THREAD_CB_OUTPUT_VBLANK;
940                 output_vblank.base.length = sizeof output_vblank;
941                 output_vblank.output_stamp = vblank_handler->private_output->stamp;
942                 output_vblank.sequence = sequence;
943                 output_vblank.tv_sec = tv_sec;
944                 output_vblank.tv_usec = tv_usec;
945                 output_vblank.user_data = user_data;
946
947                 ret = tdm_thread_send_cb(private_display->private_loop, &output_vblank.base);
948                 TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
949
950                 return;
951         }
952
953         if (vblank_handler->owner_tid != syscall(SYS_gettid))
954                 TDM_NEVER_GET_HERE();
955
956         if (vblank_handler->func) {
957                 _pthread_mutex_unlock(&private_display->lock);
958                 vblank_handler->func(vblank_handler->private_output, sequence,
959                                                          tv_sec, tv_usec, vblank_handler->user_data);
960                 _pthread_mutex_lock(&private_display->lock);
961         }
962
963         LIST_DEL(&vblank_handler->link);
964         free(vblank_handler);
965 }
966
967 INTERN void
968 tdm_output_cb_commit(tdm_output *output_backend, unsigned int sequence,
969                                          unsigned int tv_sec, unsigned int tv_usec, void *user_data)
970 {
971         tdm_private_commit_handler *commit_handler = user_data;
972         tdm_private_display *private_display;
973         tdm_private_output *private_output;
974         tdm_private_layer *private_layer = NULL;
975
976         TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED());
977         TDM_RETURN_IF_FAIL(commit_handler);
978
979         private_output = commit_handler->private_output;
980         private_display = private_output->private_display;
981
982         if (commit_handler->owner_tid != syscall(SYS_gettid)) {
983                 tdm_thread_cb_output_commit output_commit;
984                 tdm_error ret;
985
986                 output_commit.base.type = TDM_THREAD_CB_OUTPUT_COMMIT;
987                 output_commit.base.length = sizeof output_commit;
988                 output_commit.output_stamp = private_output->stamp;
989                 output_commit.sequence = sequence;
990                 output_commit.tv_sec = tv_sec;
991                 output_commit.tv_usec = tv_usec;
992                 output_commit.user_data = user_data;
993
994                 ret = tdm_thread_send_cb(private_display->private_loop, &output_commit.base);
995                 TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
996
997                 return;
998         }
999
1000         LIST_FOR_EACH_ENTRY(private_layer, &private_output->layer_list, link) {
1001                 if (!private_layer->waiting_buffer)
1002                         continue;
1003
1004                 if (private_layer->showing_buffer) {
1005                         _pthread_mutex_unlock(&private_display->lock);
1006                         tdm_buffer_unref_backend(private_layer->showing_buffer);
1007                         _pthread_mutex_lock(&private_display->lock);
1008
1009                         if (private_layer->buffer_queue) {
1010                                 _pthread_mutex_unlock(&private_display->lock);
1011                                 tbm_surface_queue_release(private_layer->buffer_queue,
1012                                                                                   private_layer->showing_buffer);
1013                                 _pthread_mutex_lock(&private_display->lock);
1014                         }
1015                 }
1016
1017                 private_layer->showing_buffer = private_layer->waiting_buffer;
1018                 private_layer->waiting_buffer = NULL;
1019
1020                 if (tdm_debug_module & TDM_DEBUG_BUFFER)
1021                         TDM_INFO("layer(%p) waiting_buffer(%p) showing_buffer(%p)",
1022                                          private_layer, private_layer->waiting_buffer,
1023                                          private_layer->showing_buffer);
1024         }
1025
1026         if (commit_handler->func) {
1027                 _pthread_mutex_unlock(&private_display->lock);
1028                 commit_handler->func(private_output, sequence,
1029                                                          tv_sec, tv_usec, commit_handler->user_data);
1030                 _pthread_mutex_lock(&private_display->lock);
1031         }
1032
1033         LIST_DEL(&commit_handler->link);
1034         free(commit_handler);
1035 }
1036
1037 EXTERN tdm_error
1038 tdm_output_wait_vblank(tdm_output *output, int interval, int sync,
1039                                            tdm_output_vblank_handler func, void *user_data)
1040 {
1041         tdm_func_output *func_output;
1042         tdm_private_vblank_handler *vblank_handler;
1043         OUTPUT_FUNC_ENTRY();
1044
1045         _pthread_mutex_lock(&private_display->lock);
1046
1047         if (private_output->current_dpms_value > TDM_OUTPUT_DPMS_ON) {
1048                 TDM_WRN("output(%d) dpms: %s", private_output->pipe,
1049                                 tdm_dpms_str(private_output->current_dpms_value));
1050                 _pthread_mutex_unlock(&private_display->lock);
1051                 return TDM_ERROR_DPMS_OFF;
1052         }
1053
1054         func_output = &private_display->func_output;
1055
1056         if (!func_output->output_wait_vblank) {
1057                 _pthread_mutex_unlock(&private_display->lock);
1058                 TDM_ERR("not implemented!!");
1059                 return TDM_ERROR_NOT_IMPLEMENTED;
1060         }
1061
1062         vblank_handler = calloc(1, sizeof(tdm_private_vblank_handler));
1063         if (!vblank_handler) {
1064                 TDM_ERR("failed: alloc memory");
1065                 _pthread_mutex_unlock(&private_display->lock);
1066                 return TDM_ERROR_OUT_OF_MEMORY;
1067         }
1068
1069         LIST_ADD(&vblank_handler->link, &private_output->vblank_handler_list);
1070         vblank_handler->private_output = private_output;
1071         vblank_handler->func = func;
1072         vblank_handler->user_data = user_data;
1073         vblank_handler->owner_tid = syscall(SYS_gettid);
1074
1075         ret = func_output->output_wait_vblank(private_output->output_backend, interval,
1076                                                                                   sync, vblank_handler);
1077         if (ret != TDM_ERROR_NONE) {
1078                 _pthread_mutex_unlock(&private_display->lock);
1079                 return ret;
1080         }
1081
1082         if (!private_output->regist_vblank_cb) {
1083                 private_output->regist_vblank_cb = 1;
1084                 ret = func_output->output_set_vblank_handler(private_output->output_backend,
1085                                 tdm_output_cb_vblank);
1086         }
1087
1088         _pthread_mutex_unlock(&private_display->lock);
1089
1090         return ret;
1091 }
1092
1093 static tdm_error
1094 _tdm_output_commit(tdm_output *output, int sync, tdm_output_commit_handler func,
1095                                    void *user_data)
1096 {
1097         tdm_func_output *func_output;
1098         tdm_private_commit_handler *commit_handler;
1099         OUTPUT_FUNC_ENTRY();
1100
1101         func_output = &private_display->func_output;
1102
1103         if (!func_output->output_commit) {
1104                 TDM_ERR("not implemented!!");
1105                 return TDM_ERROR_NOT_IMPLEMENTED;
1106         }
1107
1108         commit_handler = calloc(1, sizeof(tdm_private_commit_handler));
1109         if (!commit_handler) {
1110                 TDM_ERR("failed: alloc memory");
1111                 return TDM_ERROR_OUT_OF_MEMORY;
1112         }
1113
1114         LIST_ADD(&commit_handler->link, &private_output->commit_handler_list);
1115         commit_handler->private_output = private_output;
1116         commit_handler->func = func;
1117         commit_handler->user_data = user_data;
1118         commit_handler->owner_tid = syscall(SYS_gettid);
1119
1120         if (!private_output->regist_commit_cb) {
1121                 private_output->regist_commit_cb = 1;
1122                 ret = func_output->output_set_commit_handler(private_output->output_backend,
1123                                 tdm_output_cb_commit);
1124         }
1125
1126         ret = func_output->output_commit(private_output->output_backend, sync,
1127                                                                          commit_handler);
1128         TDM_RETURN_VAL_IF_FAIL(ret == TDM_ERROR_NONE, ret);
1129
1130         return ret;
1131 }
1132
1133 EXTERN tdm_error
1134 tdm_output_commit(tdm_output *output, int sync, tdm_output_commit_handler func,
1135                                   void *user_data)
1136 {
1137         OUTPUT_FUNC_ENTRY();
1138
1139         _pthread_mutex_lock(&private_display->lock);
1140
1141         if (private_output->current_dpms_value > TDM_OUTPUT_DPMS_ON) {
1142                 TDM_ERR("output(%d) dpms: %s", private_output->pipe,
1143                                 tdm_dpms_str(private_output->current_dpms_value));
1144                 _pthread_mutex_unlock(&private_display->lock);
1145                 return TDM_ERROR_DPMS_OFF;
1146         }
1147
1148         ret = _tdm_output_commit(output, sync, func, user_data);
1149
1150         _pthread_mutex_unlock(&private_display->lock);
1151
1152         return ret;
1153 }
1154
1155 EXTERN tdm_error
1156 tdm_output_set_mode(tdm_output *output, const tdm_output_mode *mode)
1157 {
1158         tdm_func_output *func_output;
1159         OUTPUT_FUNC_ENTRY();
1160
1161         TDM_RETURN_VAL_IF_FAIL(mode != NULL, TDM_ERROR_INVALID_PARAMETER);
1162
1163         _pthread_mutex_lock(&private_display->lock);
1164
1165         func_output = &private_display->func_output;
1166
1167         if (!func_output->output_set_mode) {
1168                 _pthread_mutex_unlock(&private_display->lock);
1169                 TDM_ERR("not implemented!!");
1170                 return TDM_ERROR_NOT_IMPLEMENTED;
1171         }
1172
1173         ret = func_output->output_set_mode(private_output->output_backend, mode);
1174         if (ret == TDM_ERROR_NONE)
1175                 private_output->current_mode = mode;
1176         _pthread_mutex_unlock(&private_display->lock);
1177
1178         return ret;
1179 }
1180
1181 EXTERN tdm_error
1182 tdm_output_get_mode(tdm_output *output, const tdm_output_mode **mode)
1183 {
1184         OUTPUT_FUNC_ENTRY();
1185
1186         TDM_RETURN_VAL_IF_FAIL(mode != NULL, TDM_ERROR_INVALID_PARAMETER);
1187
1188         _pthread_mutex_lock(&private_display->lock);
1189
1190         *mode = private_output->current_mode;
1191
1192         _pthread_mutex_unlock(&private_display->lock);
1193
1194         return ret;
1195 }
1196
1197 static tdm_error
1198 _tdm_output_dpms_changed_timeout(void *user_data)
1199 {
1200         tdm_private_output *private_output = user_data;
1201         tdm_value value;
1202
1203         value.u32 = private_output->current_dpms_value;
1204         tdm_output_call_change_handler_internal(private_output,
1205                                                                                         &private_output->change_handler_list_sub,
1206                                                                                         TDM_OUTPUT_CHANGE_DPMS,
1207                                                                                         value, 0);
1208
1209         return TDM_ERROR_NONE;
1210 }
1211
1212 INTERN void
1213 tdm_output_cb_dpms(tdm_output *output_backend, tdm_output_dpms dpms, void *user_data)
1214 {
1215         tdm_private_display *private_display;
1216         tdm_private_output *private_output = user_data;
1217         tdm_value value;
1218
1219         TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED());
1220         TDM_RETURN_IF_FAIL(private_output);
1221
1222         private_display = private_output->private_display;
1223
1224         if (!tdm_thread_in_display_thread(syscall(SYS_gettid))) {
1225                 tdm_thread_cb_output_dpms output_dpms;
1226                 tdm_error ret;
1227
1228                 _tdm_output_update(output_backend, user_data);
1229
1230                 output_dpms.base.type = TDM_THREAD_CB_OUTPUT_DPMS;
1231                 output_dpms.base.length = sizeof output_dpms;
1232                 output_dpms.output_stamp = private_output->stamp;
1233                 output_dpms.dpms = dpms;
1234                 output_dpms.user_data = user_data;
1235
1236                 value.u32 = dpms;
1237                 tdm_output_call_change_handler_internal(private_output,
1238                                                                                                 &private_output->change_handler_list_sub,
1239                                                                                                 TDM_OUTPUT_CHANGE_DPMS,
1240                                                                                                 value, 0);
1241
1242                 ret = tdm_thread_send_cb(private_display->private_loop, &output_dpms.base);
1243                 TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
1244
1245                 return;
1246         }
1247
1248         private_output->current_dpms_value = dpms;
1249
1250         value.u32 = dpms;
1251         tdm_output_call_change_handler_internal(private_output,
1252                                                                                         &private_output->change_handler_list_main,
1253                                                                                         TDM_OUTPUT_CHANGE_DPMS,
1254                                                                                         value, 0);
1255 }
1256
1257 EXTERN tdm_error
1258 tdm_output_set_dpms(tdm_output *output, tdm_output_dpms dpms_value)
1259 {
1260         tdm_func_output *func_output;
1261         OUTPUT_FUNC_ENTRY();
1262
1263         if (dpms_value > TDM_OUTPUT_DPMS_OFF)
1264                 dpms_value = TDM_OUTPUT_DPMS_OFF;
1265
1266         _pthread_mutex_lock(&private_display->lock);
1267
1268         if (private_output->current_dpms_value == dpms_value) {
1269                 _pthread_mutex_unlock(&private_display->lock);
1270                 return TDM_ERROR_NONE;
1271         }
1272
1273         /** Use timer to call the output change callback of the sub-thread.
1274          * The output change callback of tdm_server and tdm_vblank was called
1275          * in the main thread. And it made the multi thread issue. If we use
1276          * the timer, we can call the sub-thread's output change callback in
1277          * sub-thread.
1278          */
1279         if (!private_output->dpms_changed_timer) {
1280                 private_output->dpms_changed_timer =
1281                         tdm_event_loop_add_timer_handler(private_output->private_display,
1282                                 _tdm_output_dpms_changed_timeout, private_output, NULL);
1283                 if (!private_output->dpms_changed_timer) {
1284                         TDM_ERR("can't create dpms timer!!");
1285                         _pthread_mutex_unlock(&private_display->lock);
1286                         return TDM_ERROR_OUT_OF_MEMORY;
1287                 }
1288         }
1289
1290         func_output = &private_display->func_output;
1291
1292         if (!func_output->output_set_dpms) {
1293                 _pthread_mutex_unlock(&private_display->lock);
1294                 private_output->current_dpms_value = dpms_value;
1295                 TDM_WRN("not implemented!!");
1296                 return TDM_ERROR_NONE;
1297         }
1298
1299         if (func_output->output_set_dpms_handler) {
1300                 if (!private_output->regist_dpms_cb) {
1301                         private_output->regist_dpms_cb = 1;
1302                         ret = func_output->output_set_dpms_handler(private_output->output_backend,
1303                                                                                                            tdm_output_cb_dpms, private_output);
1304                 }
1305         }
1306
1307         ret = func_output->output_set_dpms(private_output->output_backend, dpms_value);
1308
1309         if (ret == TDM_ERROR_NONE && !func_output->output_set_dpms_handler) {
1310                 tdm_value value;
1311
1312                 private_output->current_dpms_value = dpms_value;
1313
1314                 value.u32 = dpms_value;
1315                 tdm_output_call_change_handler_internal(private_output,
1316                                                                                                 &private_output->change_handler_list_main,
1317                                                                                                 TDM_OUTPUT_CHANGE_DPMS,
1318                                                                                                 value, 0);
1319
1320                 if (!LIST_IS_EMPTY(&private_output->change_handler_list_sub)) {
1321                         ret = tdm_event_loop_source_timer_update(private_output->dpms_changed_timer, 1);
1322                         if (ret != TDM_ERROR_NONE)
1323                                 TDM_NEVER_GET_HERE();
1324                 }
1325         }
1326
1327         _pthread_mutex_unlock(&private_display->lock);
1328
1329         return ret;
1330 }
1331
1332 EXTERN tdm_error
1333 tdm_output_get_dpms(tdm_output *output, tdm_output_dpms *dpms_value)
1334 {
1335         tdm_func_output *func_output;
1336         OUTPUT_FUNC_ENTRY();
1337
1338         TDM_RETURN_VAL_IF_FAIL(dpms_value != NULL, TDM_ERROR_INVALID_PARAMETER);
1339
1340         _pthread_mutex_lock(&private_display->lock);
1341
1342         func_output = &private_display->func_output;
1343
1344         if (!func_output->output_get_dpms) {
1345                 *dpms_value = private_output->current_dpms_value;
1346                 _pthread_mutex_unlock(&private_display->lock);
1347                 TDM_WRN("not implemented!!");
1348                 return TDM_ERROR_NONE;
1349         }
1350
1351         ret = func_output->output_get_dpms(private_output->output_backend, dpms_value);
1352
1353         _pthread_mutex_unlock(&private_display->lock);
1354
1355         return ret;
1356 }
1357
1358 EXTERN tdm_capture *
1359 tdm_output_create_capture(tdm_output *output, tdm_error *error)
1360 {
1361         tdm_capture *capture = NULL;
1362
1363         OUTPUT_FUNC_ENTRY_ERROR();
1364
1365         _pthread_mutex_lock(&private_display->lock);
1366
1367         capture = (tdm_capture *)tdm_capture_create_output_internal(private_output, error);
1368
1369         _pthread_mutex_unlock(&private_display->lock);
1370
1371         return capture;
1372 }
1373
1374 INTERN void
1375 tdm_output_call_change_handler_internal(tdm_private_output *private_output,
1376                                                                                 struct list_head *change_handler_list,
1377                                                                                 tdm_output_change_type type,
1378                                                                                 tdm_value value,
1379                                                                                 int no_check_thread_id)
1380 {
1381         tdm_private_display *private_display;
1382         tdm_private_change_handler *change_handler = NULL;
1383
1384         TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED());
1385         TDM_RETURN_IF_FAIL(private_output);
1386
1387         private_display = private_output->private_display;
1388         if (!tdm_thread_in_display_thread(syscall(SYS_gettid))) {
1389                 if (type & TDM_OUTPUT_CHANGE_CONNECTION)
1390                         TDM_INFO("output(%d) changed: %s (%d)",
1391                                          private_output->pipe, tdm_status_str(value.u32), value.u32);
1392                 if (type & TDM_OUTPUT_CHANGE_DPMS)
1393                         TDM_INFO("output(%d) changed: dpms %s (%d)",
1394                                          private_output->pipe, tdm_dpms_str(value.u32), value.u32);
1395         }
1396
1397         if (LIST_IS_EMPTY(change_handler_list))
1398                 return;
1399
1400         LIST_FOR_EACH_ENTRY(change_handler, change_handler_list, link) {
1401                 if (!no_check_thread_id && change_handler->owner_tid != syscall(SYS_gettid))
1402                         TDM_NEVER_GET_HERE();
1403
1404                 _pthread_mutex_unlock(&private_display->lock);
1405                 change_handler->func(private_output, type,
1406                                                          value, change_handler->user_data);
1407                 _pthread_mutex_lock(&private_display->lock);
1408         }
1409 }
1410
1411 EXTERN tdm_error
1412 tdm_layer_get_capabilities(tdm_layer *layer, tdm_layer_capability *capabilities)
1413 {
1414         LAYER_FUNC_ENTRY();
1415
1416         TDM_RETURN_VAL_IF_FAIL(capabilities != NULL, TDM_ERROR_INVALID_PARAMETER);
1417
1418         _pthread_mutex_lock(&private_display->lock);
1419
1420         *capabilities = private_layer->caps.capabilities;
1421
1422         _pthread_mutex_unlock(&private_display->lock);
1423
1424         return ret;
1425 }
1426
1427 EXTERN tdm_error
1428 tdm_layer_get_available_formats(tdm_layer *layer, const tbm_format **formats, int *count)
1429 {
1430         LAYER_FUNC_ENTRY();
1431
1432         TDM_RETURN_VAL_IF_FAIL(formats != NULL, TDM_ERROR_INVALID_PARAMETER);
1433         TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
1434
1435         _pthread_mutex_lock(&private_display->lock);
1436
1437         *formats = (const tbm_format *)private_layer->caps.formats;
1438         *count = private_layer->caps.format_count;
1439
1440         _pthread_mutex_unlock(&private_display->lock);
1441
1442         return ret;
1443 }
1444
1445 EXTERN tdm_error
1446 tdm_layer_get_available_properties(tdm_layer *layer, const tdm_prop **props, int *count)
1447 {
1448         LAYER_FUNC_ENTRY();
1449
1450         TDM_RETURN_VAL_IF_FAIL(props != NULL, TDM_ERROR_INVALID_PARAMETER);
1451         TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
1452
1453         _pthread_mutex_lock(&private_display->lock);
1454
1455         *props = (const tdm_prop *)private_layer->caps.props;
1456         *count = private_layer->caps.prop_count;
1457
1458         _pthread_mutex_unlock(&private_display->lock);
1459
1460         return ret;
1461 }
1462
1463 EXTERN tdm_error
1464 tdm_layer_get_zpos(tdm_layer *layer, int *zpos)
1465 {
1466         LAYER_FUNC_ENTRY();
1467
1468         TDM_RETURN_VAL_IF_FAIL(zpos != NULL, TDM_ERROR_INVALID_PARAMETER);
1469
1470         _pthread_mutex_lock(&private_display->lock);
1471
1472         *zpos = private_layer->caps.zpos;
1473
1474         _pthread_mutex_unlock(&private_display->lock);
1475
1476         return ret;
1477 }
1478
1479 EXTERN tdm_error
1480 tdm_layer_set_property(tdm_layer *layer, unsigned int id, tdm_value value)
1481 {
1482         tdm_func_layer *func_layer;
1483         LAYER_FUNC_ENTRY();
1484
1485         _pthread_mutex_lock(&private_display->lock);
1486
1487         func_layer = &private_display->func_layer;
1488
1489         if (!func_layer->layer_set_property) {
1490                 _pthread_mutex_unlock(&private_display->lock);
1491                 TDM_ERR("not implemented!!");
1492                 return TDM_ERROR_NOT_IMPLEMENTED;
1493         }
1494
1495         ret = func_layer->layer_set_property(private_layer->layer_backend, id, value);
1496
1497         _pthread_mutex_unlock(&private_display->lock);
1498
1499         return ret;
1500 }
1501
1502 EXTERN tdm_error
1503 tdm_layer_get_property(tdm_layer *layer, unsigned int id, tdm_value *value)
1504 {
1505         tdm_func_layer *func_layer;
1506         LAYER_FUNC_ENTRY();
1507
1508         TDM_RETURN_VAL_IF_FAIL(value != NULL, TDM_ERROR_INVALID_PARAMETER);
1509
1510         _pthread_mutex_lock(&private_display->lock);
1511
1512         func_layer = &private_display->func_layer;
1513
1514         if (!func_layer->layer_get_property) {
1515                 _pthread_mutex_unlock(&private_display->lock);
1516                 TDM_ERR("not implemented!!");
1517                 return TDM_ERROR_NOT_IMPLEMENTED;
1518         }
1519
1520         ret = func_layer->layer_get_property(private_layer->layer_backend, id, value);
1521
1522         _pthread_mutex_unlock(&private_display->lock);
1523
1524         return ret;
1525 }
1526
1527 EXTERN tdm_error
1528 tdm_layer_set_info(tdm_layer *layer, tdm_info_layer *info)
1529 {
1530         tdm_func_layer *func_layer;
1531         char fmtstr[128];
1532
1533         LAYER_FUNC_ENTRY();
1534
1535         TDM_RETURN_VAL_IF_FAIL(info != NULL, TDM_ERROR_INVALID_PARAMETER);
1536
1537         _pthread_mutex_lock(&private_display->lock);
1538
1539         func_layer = &private_display->func_layer;
1540
1541         if (private_layer->usable)
1542                 TDM_INFO("layer(%p) not usable", private_layer);
1543
1544         private_layer->usable = 0;
1545
1546         if (!func_layer->layer_set_info) {
1547                 _pthread_mutex_unlock(&private_display->lock);
1548                 TDM_ERR("not implemented!!");
1549                 return TDM_ERROR_NOT_IMPLEMENTED;
1550         }
1551
1552         if (info->src_config.format)
1553                 snprintf(fmtstr, 128, "%c%c%c%c", FOURCC_STR(info->src_config.format));
1554         else
1555                 snprintf(fmtstr, 128, "NONE");
1556
1557         TDM_INFO("layer(%p) info: src(%dx%d %d,%d %dx%d %s) dst(%d,%d %dx%d) trans(%d)",
1558                          private_layer, info->src_config.size.h, info->src_config.size.v,
1559                          info->src_config.pos.x, info->src_config.pos.y,
1560                          info->src_config.pos.w, info->src_config.pos.h,
1561                          fmtstr,
1562                          info->dst_pos.x, info->dst_pos.y,
1563                          info->dst_pos.w, info->dst_pos.h,
1564                          info->transform);
1565
1566         ret = func_layer->layer_set_info(private_layer->layer_backend, info);
1567         TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
1568
1569         _pthread_mutex_unlock(&private_display->lock);
1570
1571         return ret;
1572 }
1573
1574 EXTERN tdm_error
1575 tdm_layer_get_info(tdm_layer *layer, tdm_info_layer *info)
1576 {
1577         tdm_func_layer *func_layer;
1578         LAYER_FUNC_ENTRY();
1579
1580         TDM_RETURN_VAL_IF_FAIL(info != NULL, TDM_ERROR_INVALID_PARAMETER);
1581
1582         _pthread_mutex_lock(&private_display->lock);
1583
1584         func_layer = &private_display->func_layer;
1585
1586         if (!func_layer->layer_get_info) {
1587                 _pthread_mutex_unlock(&private_display->lock);
1588                 TDM_ERR("not implemented!!");
1589                 return TDM_ERROR_NOT_IMPLEMENTED;
1590         }
1591
1592         ret = func_layer->layer_get_info(private_layer->layer_backend, info);
1593
1594         _pthread_mutex_unlock(&private_display->lock);
1595
1596         return ret;
1597 }
1598
1599 EXTERN tdm_error
1600 tdm_layer_set_buffer(tdm_layer *layer, tbm_surface_h buffer)
1601 {
1602         tdm_func_layer *func_layer;
1603
1604         LAYER_FUNC_ENTRY();
1605
1606         TDM_RETURN_VAL_IF_FAIL(buffer != NULL, TDM_ERROR_INVALID_PARAMETER);
1607
1608         _pthread_mutex_lock(&private_display->lock);
1609
1610         if (tdm_debug_dump & TDM_DUMP_FLAG_LAYER &&
1611                 !(private_layer->caps.capabilities & TDM_LAYER_CAPABILITY_VIDEO)) {
1612                 char str[TDM_PATH_LEN];
1613                 static int i;
1614                 snprintf(str, TDM_PATH_LEN, "layer_%d_%d_%03d",
1615                                  private_output->index, private_layer->index, i++);
1616                 tdm_helper_dump_buffer_str(buffer, tdm_debug_dump_dir, str);
1617         }
1618
1619         func_layer = &private_display->func_layer;
1620
1621         if (private_layer->usable)
1622                 TDM_INFO("layer(%p) not usable", private_layer);
1623
1624         private_layer->usable = 0;
1625
1626         if (!func_layer->layer_set_buffer) {
1627                 _pthread_mutex_unlock(&private_display->lock);
1628                 TDM_ERR("not implemented!!");
1629                 return TDM_ERROR_NOT_IMPLEMENTED;
1630         }
1631
1632         ret = func_layer->layer_set_buffer(private_layer->layer_backend, buffer);
1633         TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
1634
1635         if (ret == TDM_ERROR_NONE) {
1636                 /* FIXME: should save to pending_buffer first. And after committing
1637                  * successfully, need to move to waiting_buffer.
1638                  */
1639                 if (private_layer->waiting_buffer) {
1640                         _pthread_mutex_unlock(&private_display->lock);
1641                         tdm_buffer_unref_backend(private_layer->waiting_buffer);
1642                         _pthread_mutex_lock(&private_display->lock);
1643                 }
1644
1645                 private_layer->waiting_buffer = tdm_buffer_ref_backend(buffer);
1646                 if (tdm_debug_module & TDM_DEBUG_BUFFER)
1647                         TDM_INFO("layer(%p) waiting_buffer(%p)",
1648                                          private_layer, private_layer->waiting_buffer);
1649         }
1650
1651         _pthread_mutex_unlock(&private_display->lock);
1652
1653         return ret;
1654 }
1655
1656 EXTERN tdm_error
1657 tdm_layer_unset_buffer(tdm_layer *layer)
1658 {
1659         tdm_func_layer *func_layer;
1660         LAYER_FUNC_ENTRY();
1661
1662         _pthread_mutex_lock(&private_display->lock);
1663
1664         func_layer = &private_display->func_layer;
1665
1666         if (private_layer->waiting_buffer) {
1667                 _pthread_mutex_unlock(&private_display->lock);
1668                 tdm_buffer_unref_backend(private_layer->waiting_buffer);
1669                 _pthread_mutex_lock(&private_display->lock);
1670                 private_layer->waiting_buffer = NULL;
1671
1672                 if (tdm_debug_module & TDM_DEBUG_BUFFER)
1673                         TDM_INFO("layer(%p) waiting_buffer(%p)",
1674                                          private_layer, private_layer->waiting_buffer);
1675         }
1676
1677         if (private_layer->showing_buffer) {
1678                 _pthread_mutex_unlock(&private_display->lock);
1679                 tdm_buffer_unref_backend(private_layer->showing_buffer);
1680                 _pthread_mutex_lock(&private_display->lock);
1681                 private_layer->showing_buffer = NULL;
1682
1683                 if (tdm_debug_module & TDM_DEBUG_BUFFER)
1684                         TDM_INFO("layer(%p) showing_buffer(%p)",
1685                                          private_layer, private_layer->showing_buffer);
1686         }
1687
1688         private_layer->usable = 1;
1689
1690         if (private_layer->usable)
1691                 TDM_INFO("layer(%p) now usable", private_layer);
1692
1693         if (!func_layer->layer_unset_buffer) {
1694                 _pthread_mutex_unlock(&private_display->lock);
1695                 TDM_ERR("not implemented!!");
1696                 return TDM_ERROR_NOT_IMPLEMENTED;
1697         }
1698
1699         ret = func_layer->layer_unset_buffer(private_layer->layer_backend);
1700         TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
1701
1702         _pthread_mutex_unlock(&private_display->lock);
1703
1704         return ret;
1705 }
1706
1707 EXTERN tbm_surface_h
1708 tdm_layer_get_displaying_buffer(tdm_layer *layer, tdm_error *error)
1709 {
1710         tbm_surface_h buffer;
1711         LAYER_FUNC_ENTRY_ERROR();
1712
1713         _pthread_mutex_lock(&private_display->lock);
1714
1715         if (error)
1716                 *error = TDM_ERROR_NONE;
1717
1718         if (private_layer->showing_buffer) {
1719                 buffer = private_layer->showing_buffer;
1720         } else {
1721                 if (error)
1722                         *error = TDM_ERROR_OPERATION_FAILED;
1723                 _pthread_mutex_unlock(&private_display->lock);
1724                 TDM_DBG("layer(%p) showing_buffer is null", private_layer);
1725                 return NULL;
1726         }
1727         _pthread_mutex_unlock(&private_display->lock);
1728
1729         return buffer;
1730 }
1731
1732 static void
1733 _tbm_layer_queue_acquirable_cb(tbm_surface_queue_h surface_queue, void *data)
1734 {
1735         TDM_RETURN_IF_FAIL(data != NULL);
1736         tdm_layer *layer = data;
1737         tdm_func_layer *func_layer;
1738         tbm_surface_h surface = NULL;
1739         LAYER_FUNC_ENTRY_VOID_RETURN();
1740
1741         _pthread_mutex_lock(&private_display->lock);
1742
1743         func_layer = &private_display->func_layer;
1744         if (!func_layer->layer_set_buffer) {
1745                 _pthread_mutex_unlock(&private_display->lock);
1746                 return;
1747         }
1748
1749         if (TBM_SURFACE_QUEUE_ERROR_NONE != tbm_surface_queue_acquire(private_layer->buffer_queue, &surface) ||
1750                 surface == NULL) {
1751                 TDM_ERR("layer(%p) tbm_surface_queue_acquire() failed surface:%p",
1752                                 private_layer, surface);
1753                 _pthread_mutex_unlock(&private_display->lock);
1754                 return;
1755         }
1756
1757         ret = func_layer->layer_set_buffer(private_layer->layer_backend, surface);
1758         TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
1759
1760         if (ret == TDM_ERROR_NONE) {
1761                 if (private_layer->waiting_buffer) {
1762                         TDM_DBG("layer(%p) drop waiting_buffer(%p)", private_layer, private_layer->waiting_buffer);
1763                         _pthread_mutex_unlock(&private_display->lock);
1764                         tdm_buffer_unref_backend(private_layer->waiting_buffer);
1765                         tbm_surface_queue_release(private_layer->buffer_queue,
1766                                                                           private_layer->waiting_buffer);
1767                         _pthread_mutex_lock(&private_display->lock);
1768                 }
1769
1770                 private_layer->waiting_buffer = tdm_buffer_ref_backend(surface);
1771
1772                 if (tdm_debug_module & TDM_DEBUG_BUFFER)
1773                         TDM_INFO("layer(%p) waiting_buffer(%p)",
1774                                          private_layer, private_layer->waiting_buffer);
1775
1776                 ret = _tdm_output_commit(private_layer->private_output, 0, NULL, NULL);
1777                 if (ret != TDM_ERROR_NONE)
1778                         TDM_ERR("layer(%p) _tdm_output_commit() is fail", private_layer);
1779         }
1780
1781         _pthread_mutex_unlock(&private_display->lock);
1782 }
1783
1784 static void
1785 _tbm_layer_queue_destroy_cb(tbm_surface_queue_h surface_queue, void *data)
1786 {
1787         TDM_RETURN_IF_FAIL(data != NULL);
1788         tdm_layer *layer = data;
1789         LAYER_FUNC_ENTRY_VOID_RETURN();
1790         TDM_RETURN_IF_FAIL(ret == TDM_ERROR_NONE);
1791
1792         _pthread_mutex_lock(&private_display->lock);
1793
1794         if (private_layer->waiting_buffer) {
1795                 _pthread_mutex_unlock(&private_display->lock);
1796                 tdm_buffer_unref_backend(private_layer->waiting_buffer);
1797                 tbm_surface_queue_release(private_layer->buffer_queue,
1798                                                                   private_layer->waiting_buffer);
1799                 _pthread_mutex_lock(&private_display->lock);
1800         }
1801
1802         private_layer->buffer_queue = NULL;
1803
1804         _pthread_mutex_unlock(&private_display->lock);
1805 }
1806
1807 EXTERN tdm_error
1808 tdm_layer_set_buffer_queue(tdm_layer *layer, tbm_surface_queue_h buffer_queue)
1809 {
1810         tdm_func_layer *func_layer;
1811         LAYER_FUNC_ENTRY();
1812
1813         TDM_RETURN_VAL_IF_FAIL(buffer_queue != NULL, TDM_ERROR_INVALID_PARAMETER);
1814
1815         _pthread_mutex_lock(&private_display->lock);
1816
1817         func_layer = &private_display->func_layer;
1818
1819         if (private_layer->usable)
1820                 TDM_INFO("layer(%p) not usable", private_layer);
1821
1822         private_layer->usable = 0;
1823
1824         if (!func_layer->layer_set_buffer) {
1825                 _pthread_mutex_unlock(&private_display->lock);
1826                 TDM_ERR("not implemented!!");
1827                 return TDM_ERROR_NOT_IMPLEMENTED;
1828         }
1829
1830         if (buffer_queue == private_layer->buffer_queue) {
1831                 _pthread_mutex_unlock(&private_display->lock);
1832                 return TDM_ERROR_NONE;
1833         }
1834
1835         if (private_layer->waiting_buffer) {
1836                 _pthread_mutex_unlock(&private_display->lock);
1837                 tdm_buffer_unref_backend(private_layer->waiting_buffer);
1838                 tbm_surface_queue_release(private_layer->buffer_queue,
1839                                                                   private_layer->waiting_buffer);
1840                 private_layer->waiting_buffer = NULL;
1841                 _pthread_mutex_lock(&private_display->lock);
1842
1843                 if (tdm_debug_module & TDM_DEBUG_BUFFER)
1844                         TDM_INFO("layer(%p) waiting_buffer(%p)",
1845                                          private_layer, private_layer->waiting_buffer);
1846         }
1847
1848         private_layer->buffer_queue = buffer_queue;
1849         tbm_surface_queue_add_acquirable_cb(private_layer->buffer_queue,
1850                                                                                 _tbm_layer_queue_acquirable_cb,
1851                                                                                 layer);
1852         tbm_surface_queue_add_destroy_cb(private_layer->buffer_queue,
1853                                                                          _tbm_layer_queue_destroy_cb,
1854                                                                          layer);
1855         _pthread_mutex_unlock(&private_display->lock);
1856
1857         return ret;
1858 }
1859
1860 EXTERN tdm_error
1861 tdm_layer_unset_buffer_queue(tdm_layer *layer)
1862 {
1863         tdm_func_layer *func_layer;
1864         LAYER_FUNC_ENTRY();
1865
1866         _pthread_mutex_lock(&private_display->lock);
1867
1868         func_layer = &private_display->func_layer;
1869
1870         if (private_layer->waiting_buffer) {
1871                 _pthread_mutex_unlock(&private_display->lock);
1872                 tdm_buffer_unref_backend(private_layer->waiting_buffer);
1873                 tbm_surface_queue_release(private_layer->buffer_queue,
1874                                                                   private_layer->waiting_buffer);
1875                 private_layer->waiting_buffer = NULL;
1876                 _pthread_mutex_lock(&private_display->lock);
1877
1878                 if (tdm_debug_module & TDM_DEBUG_BUFFER)
1879                         TDM_INFO("layer(%p) waiting_buffer(%p)",
1880                                          private_layer, private_layer->waiting_buffer);
1881         }
1882
1883         if (private_layer->showing_buffer) {
1884                 _pthread_mutex_unlock(&private_display->lock);
1885                 tdm_buffer_unref_backend(private_layer->showing_buffer);
1886                 tbm_surface_queue_release(private_layer->buffer_queue,
1887                                                                   private_layer->showing_buffer);
1888                 _pthread_mutex_lock(&private_display->lock);
1889                 private_layer->showing_buffer = NULL;
1890
1891                 if (tdm_debug_module & TDM_DEBUG_BUFFER)
1892                         TDM_INFO("layer(%p) showing_buffer(%p)",
1893                                          private_layer, private_layer->showing_buffer);
1894         }
1895
1896         tbm_surface_queue_remove_acquirable_cb(private_layer->buffer_queue, _tbm_layer_queue_acquirable_cb, layer);
1897         tbm_surface_queue_remove_destroy_cb(private_layer->buffer_queue, _tbm_layer_queue_destroy_cb, layer);
1898         private_layer->buffer_queue = NULL;
1899         private_layer->usable = 1;
1900
1901         if (private_layer->usable)
1902                 TDM_INFO("layer(%p) now usable", private_layer);
1903
1904         if (!func_layer->layer_unset_buffer) {
1905                 _pthread_mutex_unlock(&private_display->lock);
1906                 TDM_ERR("not implemented!!");
1907                 return TDM_ERROR_NOT_IMPLEMENTED;
1908         }
1909
1910         ret = func_layer->layer_unset_buffer(private_layer->layer_backend);
1911
1912         _pthread_mutex_unlock(&private_display->lock);
1913
1914         return ret;
1915 }
1916
1917 EXTERN tdm_error
1918 tdm_layer_is_usable(tdm_layer *layer, unsigned int *usable)
1919 {
1920         LAYER_FUNC_ENTRY();
1921
1922         TDM_RETURN_VAL_IF_FAIL(usable != NULL, TDM_ERROR_INVALID_PARAMETER);
1923
1924         _pthread_mutex_lock(&private_display->lock);
1925
1926         *usable = private_layer->usable;
1927
1928         _pthread_mutex_unlock(&private_display->lock);
1929
1930         return ret;
1931 }
1932
1933 EXTERN tdm_error
1934 tdm_layer_set_video_pos(tdm_layer *layer, int zpos)
1935 {
1936         tdm_func_layer *func_layer;
1937         LAYER_FUNC_ENTRY();
1938
1939         _pthread_mutex_lock(&private_display->lock);
1940
1941         func_layer = &private_display->func_layer;
1942
1943         if (!(private_layer->caps.capabilities & TDM_LAYER_CAPABILITY_VIDEO)) {
1944                 TDM_ERR("layer(%p) is not video layer", private_layer);
1945                 _pthread_mutex_unlock(&private_display->lock);
1946                 return TDM_ERROR_INVALID_PARAMETER;
1947         }
1948
1949         if (!func_layer->layer_set_video_pos) {
1950                 _pthread_mutex_unlock(&private_display->lock);
1951                 TDM_ERR("not implemented!!");
1952                 return TDM_ERROR_NOT_IMPLEMENTED;
1953         }
1954
1955         ret = func_layer->layer_set_video_pos(private_layer->layer_backend, zpos);
1956
1957         _pthread_mutex_unlock(&private_display->lock);
1958
1959         return ret;
1960 }
1961
1962 EXTERN tdm_capture *
1963 tdm_layer_create_capture(tdm_layer *layer, tdm_error *error)
1964 {
1965         tdm_capture *capture = NULL;
1966
1967         LAYER_FUNC_ENTRY_ERROR();
1968
1969         _pthread_mutex_lock(&private_display->lock);
1970
1971         capture = (tdm_capture *)tdm_capture_create_layer_internal(private_layer, error);
1972
1973         _pthread_mutex_unlock(&private_display->lock);
1974
1975         return capture;
1976 }
1977
1978 EXTERN tdm_error
1979 tdm_layer_get_buffer_flags(tdm_layer *layer, unsigned int *flags)
1980 {
1981         tdm_func_layer *func_layer;
1982         LAYER_FUNC_ENTRY();
1983
1984         _pthread_mutex_lock(&private_display->lock);
1985
1986         func_layer = &private_display->func_layer;
1987
1988         if (!func_layer->layer_get_buffer_flags) {
1989                 _pthread_mutex_unlock(&private_display->lock);
1990                 TDM_ERR("not implemented!!");
1991                 return TDM_ERROR_NOT_IMPLEMENTED;
1992         }
1993
1994         ret = func_layer->layer_get_buffer_flags(private_layer->layer_backend, flags);
1995
1996         _pthread_mutex_unlock(&private_display->lock);
1997
1998         return ret;
1999 }