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