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