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