display: correct fps count
[platform/core/uifw/libtdm.git] / src / tdm_display.c
1 /**************************************************************************
2  *
3  * libtdm
4  *
5  * Copyright 2015 Samsung Electronics co., Ltd. All Rights Reserved.
6  *
7  * Contact: Eunchul Kim <chulspro.kim@samsung.com>,
8  *          JinYoung Jeon <jy0.jeon@samsung.com>,
9  *          Taeheon Kim <th908.kim@samsung.com>,
10  *          YoungJun Cho <yj44.cho@samsung.com>,
11  *          SooChan Lim <sc1.lim@samsung.com>,
12  *          Boram Park <sc1.lim@samsung.com>
13  *
14  * Permission is hereby granted, free of charge, to any person obtaining a
15  * copy of this software and associated documentation files (the
16  * "Software"), to deal in the Software without restriction, including
17  * without limitation the rights to use, copy, modify, merge, publish,
18  * distribute, sub license, and/or sell copies of the Software, and to
19  * permit persons to whom the Software is furnished to do so, subject to
20  * the following conditions:
21  *
22  * The above copyright notice and this permission notice (including the
23  * next paragraph) shall be included in all copies or substantial portions
24  * of the Software.
25  *
26  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
27  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
28  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
29  * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
30  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
31  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
32  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
33  *
34 **************************************************************************/
35
36 #ifdef HAVE_CONFIG_H
37 #include "config.h"
38 #endif
39
40 #include "tdm.h"
41 #include "tdm_backend.h"
42 #include "tdm_private.h"
43 #include "tdm_helper.h"
44
45 #define COUNT_MAX   10
46
47 #define DISPLAY_FUNC_ENTRY() \
48         tdm_private_display *private_display; \
49         tdm_error ret = TDM_ERROR_NONE; /* default TDM_ERROR_NONE */\
50         TDM_RETURN_VAL_IF_FAIL(dpy != NULL, TDM_ERROR_INVALID_PARAMETER); \
51         private_display = (tdm_private_display*)dpy;
52
53 #define DISPLAY_FUNC_ENTRY_ERROR() \
54         tdm_private_display *private_display; \
55         tdm_error ret = TDM_ERROR_NONE; /* default TDM_ERROR_NONE */\
56         TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(dpy != NULL, TDM_ERROR_INVALID_PARAMETER, NULL); \
57         private_display = (tdm_private_display*)dpy;
58
59 #define OUTPUT_FUNC_ENTRY() \
60         tdm_private_display *private_display; \
61         tdm_private_output *private_output; \
62         tdm_error ret = TDM_ERROR_NONE; /* default TDM_ERROR_NONE */\
63         TDM_RETURN_VAL_IF_FAIL(output != NULL, TDM_ERROR_INVALID_PARAMETER); \
64         private_output = (tdm_private_output*)output; \
65         private_display = private_output->private_display
66
67 #define OUTPUT_FUNC_ENTRY_ERROR() \
68         tdm_private_display *private_display; \
69         tdm_private_output *private_output; \
70         tdm_error ret = TDM_ERROR_NONE; /* default TDM_ERROR_NONE */\
71         TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(output != NULL, TDM_ERROR_INVALID_PARAMETER, NULL); \
72         private_output = (tdm_private_output*)output; \
73         private_display = private_output->private_display
74
75 #define LAYER_FUNC_ENTRY() \
76         tdm_private_display *private_display; \
77         tdm_private_output *private_output; \
78         tdm_private_layer *private_layer; \
79         tdm_error ret = TDM_ERROR_NONE; /* default TDM_ERROR_NONE */\
80         TDM_RETURN_VAL_IF_FAIL(layer != NULL, TDM_ERROR_INVALID_PARAMETER); \
81         private_layer = (tdm_private_layer*)layer; \
82         private_output = private_layer->private_output; \
83         private_display = private_output->private_display
84
85 #define LAYER_FUNC_ENTRY_ERROR() \
86         tdm_private_display *private_display; \
87         tdm_private_output *private_output; \
88         tdm_private_layer *private_layer; \
89         tdm_error ret = TDM_ERROR_NONE; /* default TDM_ERROR_NONE */\
90         TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(layer != NULL, TDM_ERROR_INVALID_PARAMETER, NULL); \
91         private_layer = (tdm_private_layer*)layer; \
92         private_output = private_layer->private_output; \
93         private_display = private_output->private_display
94
95 #define LAYER_FUNC_ENTRY_VOID_RETURN() \
96         tdm_private_display *private_display; \
97         tdm_private_output *private_output; \
98         tdm_private_layer *private_layer; \
99         tdm_error ret = TDM_ERROR_NONE; /* default TDM_ERROR_NONE */\
100         TDM_RETURN_IF_FAIL(layer != NULL); \
101         private_layer = (tdm_private_layer*)layer; \
102         private_output = private_layer->private_output; \
103         private_display = private_output->private_display
104
105 static void _tdm_layer_committed(tdm_private_layer *private_layer);
106 static void _tdm_layer_cb_wait_vblank(tdm_vblank *vblank, tdm_error error, unsigned int sequence,
107                                                                           unsigned int tv_sec, unsigned int tv_usec, void *user_data);
108
109 EXTERN tdm_error
110 tdm_display_get_capabilities(tdm_display *dpy,
111                                                          tdm_display_capability *capabilities)
112 {
113         DISPLAY_FUNC_ENTRY();
114
115         TDM_RETURN_VAL_IF_FAIL(capabilities != NULL, TDM_ERROR_INVALID_PARAMETER);
116
117         _pthread_mutex_lock(&private_display->lock);
118
119         *capabilities = private_display->capabilities;
120
121         _pthread_mutex_unlock(&private_display->lock);
122
123         return ret;
124 }
125
126 EXTERN tdm_error
127 tdm_display_get_pp_capabilities(tdm_display *dpy,
128                                                                 tdm_pp_capability *capabilities)
129 {
130         DISPLAY_FUNC_ENTRY();
131
132         TDM_RETURN_VAL_IF_FAIL(capabilities != NULL, TDM_ERROR_INVALID_PARAMETER);
133
134         _pthread_mutex_lock(&private_display->lock);
135
136         if (!(private_display->capabilities & TDM_DISPLAY_CAPABILITY_PP)) {
137                 TDM_ERR("no pp capability");
138                 _pthread_mutex_unlock(&private_display->lock);
139                 return TDM_ERROR_NO_CAPABILITY;
140         }
141
142         *capabilities = private_display->caps_pp.capabilities;
143
144         _pthread_mutex_unlock(&private_display->lock);
145
146         return ret;
147 }
148
149 EXTERN tdm_error
150 tdm_display_get_pp_available_formats(tdm_display *dpy,
151                                                                          const tbm_format **formats, int *count)
152 {
153         DISPLAY_FUNC_ENTRY();
154
155         TDM_RETURN_VAL_IF_FAIL(formats != NULL, TDM_ERROR_INVALID_PARAMETER);
156         TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
157
158         _pthread_mutex_lock(&private_display->lock);
159
160         if (!(private_display->capabilities & TDM_DISPLAY_CAPABILITY_PP)) {
161                 TDM_ERR("no pp capability");
162                 _pthread_mutex_unlock(&private_display->lock);
163                 return TDM_ERROR_NO_CAPABILITY;
164         }
165
166         *formats = (const tbm_format *)private_display->caps_pp.formats;
167         *count = private_display->caps_pp.format_count;
168
169         _pthread_mutex_unlock(&private_display->lock);
170
171         return ret;
172 }
173
174 EXTERN tdm_error
175 tdm_display_get_pp_available_size(tdm_display *dpy, int *min_w, int *min_h,
176                                                                   int *max_w, int *max_h, int *preferred_align)
177 {
178         DISPLAY_FUNC_ENTRY();
179
180         _pthread_mutex_lock(&private_display->lock);
181
182         if (!(private_display->capabilities & TDM_DISPLAY_CAPABILITY_PP)) {
183                 TDM_ERR("no pp capability");
184                 _pthread_mutex_unlock(&private_display->lock);
185                 return TDM_ERROR_NO_CAPABILITY;
186         }
187
188         if (min_w)
189                 *min_w = TDM_FRONT_VALUE(private_display->caps_pp.min_w);
190         if (min_h)
191                 *min_h = TDM_FRONT_VALUE(private_display->caps_pp.min_h);
192         if (max_w)
193                 *max_w = TDM_FRONT_VALUE(private_display->caps_pp.max_w);
194         if (max_h)
195                 *max_h = TDM_FRONT_VALUE(private_display->caps_pp.max_h);
196         if (preferred_align)
197                 *preferred_align = TDM_FRONT_VALUE(private_display->caps_pp.preferred_align);
198
199         _pthread_mutex_unlock(&private_display->lock);
200
201         return ret;
202 }
203
204 EXTERN tdm_error
205 tdm_display_get_capture_capabilities(tdm_display *dpy,
206                                                                          tdm_capture_capability *capabilities)
207 {
208         DISPLAY_FUNC_ENTRY();
209
210         TDM_RETURN_VAL_IF_FAIL(capabilities != NULL, TDM_ERROR_INVALID_PARAMETER);
211
212         _pthread_mutex_lock(&private_display->lock);
213
214         if (!(private_display->capabilities & TDM_DISPLAY_CAPABILITY_CAPTURE)) {
215                 TDM_ERR("no capture capability");
216                 _pthread_mutex_unlock(&private_display->lock);
217                 return TDM_ERROR_NO_CAPABILITY;
218         }
219
220         *capabilities = private_display->caps_capture.capabilities;
221
222         _pthread_mutex_unlock(&private_display->lock);
223
224         return ret;
225 }
226
227 EXTERN tdm_error
228 tdm_display_get_catpure_available_formats(tdm_display *dpy,
229                 const tbm_format **formats, int *count)
230 {
231         DISPLAY_FUNC_ENTRY();
232
233         TDM_RETURN_VAL_IF_FAIL(formats != NULL, TDM_ERROR_INVALID_PARAMETER);
234         TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
235
236         _pthread_mutex_lock(&private_display->lock);
237
238         if (!(private_display->capabilities & TDM_DISPLAY_CAPABILITY_CAPTURE)) {
239                 TDM_ERR("no capture capability");
240                 _pthread_mutex_unlock(&private_display->lock);
241                 return TDM_ERROR_NO_CAPABILITY;
242         }
243
244         *formats = (const tbm_format *)private_display->caps_capture.formats;
245         *count = private_display->caps_capture.format_count;
246
247         _pthread_mutex_unlock(&private_display->lock);
248
249         return ret;
250 }
251
252 EXTERN tdm_error
253 tdm_display_get_capture_available_size(tdm_display *dpy, int *min_w, int *min_h,
254                                                                            int *max_w, int *max_h, int *preferred_align)
255 {
256         DISPLAY_FUNC_ENTRY();
257
258         _pthread_mutex_lock(&private_display->lock);
259
260         if (!(private_display->capabilities & TDM_DISPLAY_CAPABILITY_CAPTURE)) {
261                 TDM_ERR("no capture capability");
262                 _pthread_mutex_unlock(&private_display->lock);
263                 return TDM_ERROR_NO_CAPABILITY;
264         }
265
266         if (min_w)
267                 *min_w = TDM_FRONT_VALUE(private_display->caps_capture.min_w);
268         if (min_h)
269                 *min_h = TDM_FRONT_VALUE(private_display->caps_capture.min_h);
270         if (max_w)
271                 *max_w = TDM_FRONT_VALUE(private_display->caps_capture.max_w);
272         if (max_h)
273                 *max_h = TDM_FRONT_VALUE(private_display->caps_capture.max_h);
274         if (preferred_align)
275                 *preferred_align = TDM_FRONT_VALUE(private_display->caps_capture.preferred_align);
276
277         _pthread_mutex_unlock(&private_display->lock);
278
279         return ret;
280 }
281
282 EXTERN tdm_error
283 tdm_display_get_max_layer_count(tdm_display *dpy, int *max_count)
284 {
285         DISPLAY_FUNC_ENTRY();
286
287         TDM_RETURN_VAL_IF_FAIL(max_count != NULL, TDM_ERROR_INVALID_PARAMETER);
288
289         _pthread_mutex_lock(&private_display->lock);
290
291         *max_count = TDM_FRONT_VALUE(private_display->caps_display.max_layer_count);
292
293         _pthread_mutex_unlock(&private_display->lock);
294
295         return ret;
296 }
297
298 EXTERN tdm_error
299 tdm_display_get_output_count(tdm_display *dpy, int *count)
300 {
301         tdm_private_output *private_output = NULL;
302
303         DISPLAY_FUNC_ENTRY();
304
305         TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
306
307         _pthread_mutex_lock(&private_display->lock);
308
309         *count = 0;
310         LIST_FOR_EACH_ENTRY(private_output, &private_display->output_list, link)
311         (*count)++;
312
313         if (*count == 0) {
314                 _pthread_mutex_unlock(&private_display->lock);
315                 return TDM_ERROR_NONE;
316         }
317
318         _pthread_mutex_unlock(&private_display->lock);
319
320         return ret;
321 }
322
323
324 EXTERN tdm_output *
325 tdm_display_get_output(tdm_display *dpy, int index, tdm_error *error)
326 {
327         tdm_private_output *private_output = NULL;
328
329         DISPLAY_FUNC_ENTRY_ERROR();
330
331         _pthread_mutex_lock(&private_display->lock);
332
333         if (error)
334                 *error = TDM_ERROR_NONE;
335
336         LIST_FOR_EACH_ENTRY(private_output, &private_display->output_list, link) {
337                 if (private_output->index == index) {
338                         _pthread_mutex_unlock(&private_display->lock);
339                         return private_output;
340                 }
341         }
342
343         _pthread_mutex_unlock(&private_display->lock);
344
345         return NULL;
346 }
347
348 EXTERN tdm_error
349 tdm_display_get_fd(tdm_display *dpy, int *fd)
350 {
351         DISPLAY_FUNC_ENTRY();
352
353         TDM_RETURN_VAL_IF_FAIL(fd != NULL, TDM_ERROR_INVALID_PARAMETER);
354
355         _pthread_mutex_lock(&private_display->lock);
356
357         if (tdm_thread_is_running())
358                 *fd = tdm_thread_get_fd(private_display->private_loop);
359         else
360                 *fd = tdm_event_loop_get_fd(private_display);
361
362         _pthread_mutex_unlock(&private_display->lock);
363
364         return ret;
365 }
366
367 EXTERN tdm_error
368 tdm_display_handle_events(tdm_display *dpy)
369 {
370         struct pollfd fds;
371         int fd = -1;
372
373         DISPLAY_FUNC_ENTRY();
374
375         ret = tdm_display_get_fd(dpy, &fd);
376         TDM_RETURN_VAL_IF_FAIL(fd >= 0, ret);
377
378         fds.events = POLLIN;
379         fds.fd = fd;
380         fds.revents = 0;
381
382         if (tdm_debug_module & TDM_DEBUG_THREAD)
383                 TDM_INFO("fd(%d) polling in", fd);
384
385         while (poll(&fds, 1, -1) < 0) {
386                 if (errno == EINTR || errno == EAGAIN)  /* normal case */
387                         continue;
388                 else {
389                         TDM_ERR("poll failed: %m");
390                         return TDM_ERROR_OPERATION_FAILED;
391                 }
392         }
393
394         if (tdm_debug_module & TDM_DEBUG_THREAD)
395                 TDM_INFO("fd(%d) polling out", fd);
396
397         if (tdm_thread_is_running())
398                 ret = tdm_thread_handle_cb(private_display->private_loop);
399         else
400                 ret = tdm_event_loop_dispatch(private_display);
401
402         return ret;
403 }
404
405 EXTERN tdm_error
406 tdm_display_get_backend_info(tdm_display *dpy, const char **name,
407                                                          const char **vendor, int *major, int *minor)
408 {
409         tdm_backend_module *module_data;
410
411         DISPLAY_FUNC_ENTRY();
412
413         _pthread_mutex_lock(&private_display->lock);
414
415         module_data = private_display->module_data;
416
417         if (name)
418                 *name = module_data->name;
419         if (vendor)
420                 *vendor = module_data->vendor;
421         if (major)
422                 *major = TDM_BACKEND_GET_ABI_MAJOR(module_data->abi_version);
423         if (minor)
424                 *minor = TDM_BACKEND_GET_ABI_MINOR(module_data->abi_version);
425
426         _pthread_mutex_unlock(&private_display->lock);
427
428         return ret;
429 }
430
431 EXTERN tdm_pp *
432 tdm_display_create_pp(tdm_display *dpy, tdm_error *error)
433 {
434         tdm_pp *pp;
435
436         DISPLAY_FUNC_ENTRY_ERROR();
437
438         _pthread_mutex_lock(&private_display->lock);
439
440         pp = (tdm_pp *)tdm_pp_create_internal(private_display, error);
441
442         _pthread_mutex_unlock(&private_display->lock);
443
444         return pp;
445 }
446
447 EXTERN tdm_error
448 tdm_output_get_model_info(tdm_output *output, const char **maker,
449                                                   const char **model, const char **name)
450 {
451         OUTPUT_FUNC_ENTRY();
452
453         _pthread_mutex_lock(&private_display->lock);
454
455         if (maker)
456                 *maker = private_output->caps.maker;
457         if (model)
458                 *model = private_output->caps.model;
459         if (name)
460                 *name = private_output->caps.name;
461
462         _pthread_mutex_unlock(&private_display->lock);
463
464         return ret;
465 }
466
467 EXTERN tdm_error
468 tdm_output_get_capabilities(tdm_output *output, tdm_output_capability *capabilities)
469 {
470         OUTPUT_FUNC_ENTRY();
471
472         TDM_RETURN_VAL_IF_FAIL(capabilities != NULL, TDM_ERROR_INVALID_PARAMETER);
473
474         _pthread_mutex_lock(&private_display->lock);
475
476         *capabilities = private_output->caps.capabilities;
477
478         _pthread_mutex_unlock(&private_display->lock);
479
480         return ret;
481 }
482
483 EXTERN tdm_error
484 tdm_output_get_conn_status(tdm_output *output, tdm_output_conn_status *status)
485 {
486         OUTPUT_FUNC_ENTRY();
487
488         TDM_RETURN_VAL_IF_FAIL(status != NULL, TDM_ERROR_INVALID_PARAMETER);
489
490         _pthread_mutex_lock(&private_display->lock);
491
492         *status = private_output->caps.status;
493
494         _pthread_mutex_unlock(&private_display->lock);
495
496         return ret;
497 }
498
499 static unsigned int
500 _tdm_output_used_layer_count(tdm_private_output *private_output)
501 {
502         tdm_private_layer *private_layer = NULL;
503         unsigned int count = 0;
504
505         LIST_FOR_EACH_ENTRY(private_layer, &private_output->layer_list, link) {
506                 if (!private_layer->usable)
507                         count++;
508         }
509
510         return count;
511 }
512
513 static void
514 _tdm_output_update(tdm_output *output_backend, void *user_data)
515 {
516         tdm_private_display *private_display;
517         tdm_private_output *private_output = user_data;
518         tdm_error ret;
519
520         TDM_RETURN_IF_FAIL(private_output);
521
522         private_display = private_output->private_display;
523
524         ret = tdm_display_update_output(private_display, output_backend, private_output->pipe);
525         TDM_RETURN_IF_FAIL(ret == TDM_ERROR_NONE);
526 }
527
528 INTERN void
529 tdm_output_cb_status(tdm_output *output_backend, tdm_output_conn_status status,
530                                          void *user_data)
531 {
532         tdm_private_display *private_display;
533         tdm_private_output *private_output = user_data;
534         tdm_value value;
535
536         TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED());
537         TDM_RETURN_IF_FAIL(private_output);
538
539         private_display = private_output->private_display;
540
541         if (!tdm_thread_in_display_thread(syscall(SYS_gettid))) {
542                 tdm_thread_cb_output_status output_status;
543                 tdm_error ret;
544
545                 _tdm_output_update(output_backend, user_data);
546
547                 output_status.base.type = TDM_THREAD_CB_OUTPUT_STATUS;
548                 output_status.base.length = sizeof output_status;
549                 output_status.output_stamp = private_output->stamp;
550                 output_status.status = status;
551                 output_status.user_data = user_data;
552
553                 value.u32 = status;
554                 tdm_output_call_change_handler_internal(private_output,
555                                                                                                 &private_output->change_handler_list_sub,
556                                                                                                 TDM_OUTPUT_CHANGE_CONNECTION,
557                                                                                                 value, 0);
558
559                 ret = tdm_thread_send_cb(private_display->private_loop, &output_status.base);
560                 TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
561
562                 return;
563         }
564
565         if (!tdm_thread_is_running())
566                 _tdm_output_update(output_backend, user_data);
567
568         value.u32 = status;
569         tdm_output_call_change_handler_internal(private_output,
570                                                                                         &private_output->change_handler_list_main,
571                                                                                         TDM_OUTPUT_CHANGE_CONNECTION,
572                                                                                         value, 0);
573 }
574
575 EXTERN tdm_error
576 tdm_output_add_change_handler(tdm_output *output,
577                                                           tdm_output_change_handler func,
578                                                           void *user_data)
579 {
580         tdm_private_change_handler *change_handler;
581         OUTPUT_FUNC_ENTRY();
582
583         TDM_RETURN_VAL_IF_FAIL(func != NULL, TDM_ERROR_INVALID_PARAMETER);
584
585         pthread_mutex_lock(&private_display->lock);
586
587         change_handler = calloc(1, sizeof(tdm_private_change_handler));
588         if (!change_handler) {
589                 TDM_ERR("failed: alloc memory");
590                 _pthread_mutex_unlock(&private_display->lock);
591                 return TDM_ERROR_OUT_OF_MEMORY;
592         }
593
594         change_handler->private_output = private_output;
595         change_handler->func = func;
596         change_handler->user_data = user_data;
597         change_handler->owner_tid = syscall(SYS_gettid);
598
599         if (!tdm_thread_in_display_thread(change_handler->owner_tid))
600                 LIST_ADDTAIL(&change_handler->link, &private_output->change_handler_list_sub);
601         else
602                 LIST_ADDTAIL(&change_handler->link, &private_output->change_handler_list_main);
603
604         _pthread_mutex_unlock(&private_display->lock);
605
606         return ret;
607 }
608
609 EXTERN void
610 tdm_output_remove_change_handler(tdm_output *output,
611                                                                  tdm_output_change_handler func,
612                                                                  void *user_data)
613 {
614         tdm_private_display *private_display;
615         tdm_private_output *private_output;
616         tdm_private_change_handler *h = NULL, *hh = NULL;
617
618         TDM_RETURN_IF_FAIL(output != NULL);
619         TDM_RETURN_IF_FAIL(func != NULL);
620
621         private_output = (tdm_private_output*)output;
622         private_display = private_output->private_display;
623
624         _pthread_mutex_lock(&private_display->lock);
625
626         LIST_FOR_EACH_ENTRY_SAFE(h, hh, &private_output->change_handler_list_main, link) {
627                 if (h->func != func || h->user_data != user_data)
628                         continue;
629
630                 LIST_DEL(&h->link);
631                 free(h);
632
633                 _pthread_mutex_unlock(&private_display->lock);
634
635                 return;
636         }
637
638         LIST_FOR_EACH_ENTRY_SAFE(h, hh, &private_output->change_handler_list_sub, link) {
639                 if (h->func != func || h->user_data != user_data)
640                         continue;
641
642                 LIST_DEL(&h->link);
643                 free(h);
644
645                 _pthread_mutex_unlock(&private_display->lock);
646
647                 return;
648         }
649
650         _pthread_mutex_unlock(&private_display->lock);
651 }
652
653 EXTERN tdm_error
654 tdm_output_get_output_type(tdm_output *output, tdm_output_type *type)
655 {
656         OUTPUT_FUNC_ENTRY();
657
658         TDM_RETURN_VAL_IF_FAIL(type != NULL, TDM_ERROR_INVALID_PARAMETER);
659
660         _pthread_mutex_lock(&private_display->lock);
661
662         *type = private_output->caps.type;
663
664         _pthread_mutex_unlock(&private_display->lock);
665
666         return ret;
667 }
668
669 EXTERN tdm_error
670 tdm_output_get_layer_count(tdm_output *output, int *count)
671 {
672         tdm_private_layer *private_layer = NULL;
673
674         OUTPUT_FUNC_ENTRY();
675
676         TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
677
678         _pthread_mutex_lock(&private_display->lock);
679
680         *count = 0;
681         LIST_FOR_EACH_ENTRY(private_layer, &private_output->layer_list, link)
682         (*count)++;
683         if (*count == 0) {
684                 _pthread_mutex_unlock(&private_display->lock);
685                 return TDM_ERROR_NONE;
686         }
687
688         _pthread_mutex_unlock(&private_display->lock);
689
690         return ret;
691 }
692
693
694 EXTERN tdm_layer *
695 tdm_output_get_layer(tdm_output *output, int index, tdm_error *error)
696 {
697         tdm_private_layer *private_layer = NULL;
698
699         OUTPUT_FUNC_ENTRY_ERROR();
700
701         _pthread_mutex_lock(&private_display->lock);
702
703         if (error)
704                 *error = TDM_ERROR_NONE;
705
706         LIST_FOR_EACH_ENTRY(private_layer, &private_output->layer_list, link) {
707                 if (private_layer->index == index) {
708                         _pthread_mutex_unlock(&private_display->lock);
709                         return private_layer;
710                 }
711         }
712
713         _pthread_mutex_unlock(&private_display->lock);
714
715         return NULL;
716 }
717
718 EXTERN tdm_error
719 tdm_output_get_available_properties(tdm_output *output, const tdm_prop **props,
720                                                                         int *count)
721 {
722         OUTPUT_FUNC_ENTRY();
723
724         TDM_RETURN_VAL_IF_FAIL(props != NULL, TDM_ERROR_INVALID_PARAMETER);
725         TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
726
727         _pthread_mutex_lock(&private_display->lock);
728
729         *props = (const tdm_prop *)private_output->caps.props;
730         *count = private_output->caps.prop_count;
731
732         _pthread_mutex_unlock(&private_display->lock);
733
734         return ret;
735 }
736
737 EXTERN tdm_error
738 tdm_output_get_available_modes(tdm_output *output,
739                                                            const tdm_output_mode **modes, int *count)
740 {
741         OUTPUT_FUNC_ENTRY();
742
743         TDM_RETURN_VAL_IF_FAIL(modes != NULL, TDM_ERROR_INVALID_PARAMETER);
744         TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
745
746         _pthread_mutex_lock(&private_display->lock);
747
748         *modes = (const tdm_output_mode *)private_output->caps.modes;
749         *count = private_output->caps.mode_count;
750
751         _pthread_mutex_unlock(&private_display->lock);
752
753         return ret;
754 }
755
756 EXTERN tdm_error
757 tdm_output_get_available_size(tdm_output *output, int *min_w, int *min_h,
758                                                           int *max_w, int *max_h, int *preferred_align)
759 {
760         OUTPUT_FUNC_ENTRY();
761
762         _pthread_mutex_lock(&private_display->lock);
763
764         if (min_w)
765                 *min_w = TDM_FRONT_VALUE(private_output->caps.min_w);
766         if (min_h)
767                 *min_h = TDM_FRONT_VALUE(private_output->caps.min_h);
768         if (max_w)
769                 *max_w = TDM_FRONT_VALUE(private_output->caps.max_w);
770         if (max_h)
771                 *max_h = TDM_FRONT_VALUE(private_output->caps.max_h);
772         if (preferred_align)
773                 *preferred_align = TDM_FRONT_VALUE(private_output->caps.preferred_align);
774
775         _pthread_mutex_unlock(&private_display->lock);
776
777         return ret;
778 }
779
780 EXTERN tdm_error
781 tdm_output_get_cursor_available_size(tdm_output *output, int *min_w, int *min_h,
782                                                                          int *max_w, int *max_h, int *preferred_align)
783 {
784         OUTPUT_FUNC_ENTRY();
785
786         _pthread_mutex_lock(&private_display->lock);
787
788         if (!tdm_display_check_module_abi(private_display, 1, 5)) {
789
790                 if (min_w)
791                         *min_w = -1;
792                 if (min_h)
793                         *min_h = -1;
794                 if (max_w)
795                         *max_w = -1;
796                 if (max_h)
797                         *max_h = -1;
798                 if (preferred_align)
799                         *preferred_align = -1;
800
801                 _pthread_mutex_unlock(&private_display->lock);
802
803                 return TDM_ERROR_BAD_MODULE;
804         }
805
806         if (min_w)
807                 *min_w = TDM_FRONT_VALUE(private_output->caps.cursor_min_w);
808         if (min_h)
809                 *min_h = TDM_FRONT_VALUE(private_output->caps.cursor_min_h);
810         if (max_w)
811                 *max_w = TDM_FRONT_VALUE(private_output->caps.cursor_max_w);
812         if (max_h)
813                 *max_h = TDM_FRONT_VALUE(private_output->caps.cursor_max_h);
814         if (preferred_align)
815                 *preferred_align = TDM_FRONT_VALUE(private_output->caps.cursor_preferred_align);
816
817         _pthread_mutex_unlock(&private_display->lock);
818
819         return ret;
820 }
821
822 EXTERN tdm_error
823 tdm_output_get_physical_size(tdm_output *output, unsigned int *mmWidth,
824                                                          unsigned int *mmHeight)
825 {
826         OUTPUT_FUNC_ENTRY();
827
828         _pthread_mutex_lock(&private_display->lock);
829
830         if (mmWidth)
831                 *mmWidth = private_output->caps.mmWidth;
832         if (mmHeight)
833                 *mmHeight = private_output->caps.mmHeight;
834
835         _pthread_mutex_unlock(&private_display->lock);
836
837         return ret;
838 }
839
840 EXTERN tdm_error
841 tdm_output_get_subpixel(tdm_output *output, unsigned int *subpixel)
842 {
843         OUTPUT_FUNC_ENTRY();
844         TDM_RETURN_VAL_IF_FAIL(subpixel != NULL, TDM_ERROR_INVALID_PARAMETER);
845
846         _pthread_mutex_lock(&private_display->lock);
847
848         *subpixel = private_output->caps.subpixel;
849
850         _pthread_mutex_unlock(&private_display->lock);
851
852         return ret;
853 }
854
855 EXTERN tdm_error
856 tdm_output_get_pipe(tdm_output *output, unsigned int *pipe)
857 {
858         OUTPUT_FUNC_ENTRY();
859         TDM_RETURN_VAL_IF_FAIL(pipe != NULL, TDM_ERROR_INVALID_PARAMETER);
860
861         _pthread_mutex_lock(&private_display->lock);
862
863         *pipe = private_output->pipe;
864
865         _pthread_mutex_unlock(&private_display->lock);
866
867         return ret;
868 }
869
870 EXTERN tdm_error
871 tdm_output_get_primary_index(tdm_output *output, int *index)
872 {
873         tdm_private_layer *private_layer = NULL;
874
875         OUTPUT_FUNC_ENTRY();
876         TDM_RETURN_VAL_IF_FAIL(index != NULL, TDM_ERROR_INVALID_PARAMETER);
877
878         _pthread_mutex_lock(&private_display->lock);
879
880         LIST_FOR_EACH_ENTRY(private_layer, &private_output->layer_list, link) {
881                 if (private_layer->caps.capabilities & TDM_LAYER_CAPABILITY_PRIMARY) {
882                         *index = private_layer->index;
883                         break;
884                 }
885         }
886
887         _pthread_mutex_unlock(&private_display->lock);
888
889         return ret;
890 }
891
892 EXTERN tdm_error
893 tdm_output_set_property(tdm_output *output, unsigned int id, tdm_value value)
894 {
895         tdm_func_output *func_output;
896         OUTPUT_FUNC_ENTRY();
897
898         _pthread_mutex_lock(&private_display->lock);
899
900         func_output = &private_display->func_output;
901
902         if (!func_output->output_set_property) {
903                 _pthread_mutex_unlock(&private_display->lock);
904                 TDM_ERR("not implemented!!");
905                 return TDM_ERROR_NOT_IMPLEMENTED;
906         }
907
908         ret = func_output->output_set_property(private_output->output_backend, id,
909                                                                                    value);
910
911         _pthread_mutex_unlock(&private_display->lock);
912
913         return ret;
914 }
915
916 EXTERN tdm_error
917 tdm_output_get_property(tdm_output *output, unsigned int id, tdm_value *value)
918 {
919         tdm_func_output *func_output;
920         OUTPUT_FUNC_ENTRY();
921
922         TDM_RETURN_VAL_IF_FAIL(value != NULL, TDM_ERROR_INVALID_PARAMETER);
923
924         _pthread_mutex_lock(&private_display->lock);
925
926         func_output = &private_display->func_output;
927
928         if (!func_output->output_get_property) {
929                 _pthread_mutex_unlock(&private_display->lock);
930                 TDM_ERR("not implemented!!");
931                 return TDM_ERROR_NOT_IMPLEMENTED;
932         }
933
934         ret = func_output->output_get_property(private_output->output_backend, id,
935                                                                                    value);
936
937         _pthread_mutex_unlock(&private_display->lock);
938
939         return ret;
940 }
941
942 INTERN void
943 tdm_output_cb_vblank(tdm_output *output_backend, unsigned int sequence,
944                                          unsigned int tv_sec, unsigned int tv_usec, void *user_data)
945 {
946         tdm_private_vblank_handler *vblank_handler = user_data;
947         tdm_private_vblank_handler *v = NULL, *vv = NULL;
948         tdm_private_output *private_output;
949         tdm_private_display *private_display;
950         struct list_head clone_list;
951         int interval, sync;
952         pid_t tid = syscall(SYS_gettid);
953
954         TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED());
955         TDM_RETURN_IF_FAIL(vblank_handler);
956
957         private_output = vblank_handler->private_output;
958         private_display = private_output->private_display;
959
960         if (vblank_handler->owner_tid != tid) {
961                 tdm_thread_cb_output_vblank output_vblank;
962                 tdm_error ret;
963
964                 output_vblank.base.type = TDM_THREAD_CB_OUTPUT_VBLANK;
965                 output_vblank.base.length = sizeof output_vblank;
966                 output_vblank.output_stamp = vblank_handler->private_output->stamp;
967                 output_vblank.sequence = sequence;
968                 output_vblank.tv_sec = tv_sec;
969                 output_vblank.tv_usec = tv_usec;
970                 output_vblank.user_data = user_data;
971
972                 ret = tdm_thread_send_cb(private_display->private_loop, &output_vblank.base);
973                 TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
974
975                 return;
976         }
977
978         if (vblank_handler->owner_tid != tid)
979                 TDM_NEVER_GET_HERE();
980
981         interval = vblank_handler->interval;
982         sync = vblank_handler->sync;
983
984         LIST_INITHEAD(&clone_list);
985
986         LIST_FOR_EACH_ENTRY_SAFE(v, vv, &private_output->vblank_handler_list, link) {
987                 if (v->interval != interval || v->sync != sync || v->owner_tid != tid)
988                         continue;
989
990                 LIST_DEL(&v->link);
991                 LIST_ADDTAIL(&v->link, &clone_list);
992         }
993
994         if (tdm_debug_module & TDM_DEBUG_COMMIT)
995                 TDM_INFO("-----------------------------------------");
996
997         _pthread_mutex_unlock(&private_display->lock);
998         LIST_FOR_EACH_ENTRY_SAFE(v, vv, &clone_list, link) {
999                 if (tdm_debug_module & TDM_DEBUG_COMMIT)
1000                         TDM_INFO("output(%d) got vblank: handler(%p)", private_output->pipe, v);
1001
1002                 if (v->func)
1003                         v->func(v->private_output, sequence, tv_sec, tv_usec, v->user_data);
1004                 LIST_DEL(&v->link);
1005                 free(v);
1006         }
1007         _pthread_mutex_lock(&private_display->lock);
1008
1009         if (tdm_debug_module & TDM_DEBUG_COMMIT)
1010                 TDM_INFO("-----------------------------------------...");
1011 }
1012
1013 INTERN void
1014 tdm_output_cb_commit(tdm_output *output_backend, unsigned int sequence,
1015                                          unsigned int tv_sec, unsigned int tv_usec, void *user_data)
1016 {
1017         tdm_private_output_commit_handler *output_commit_handler = user_data;
1018         tdm_private_display *private_display;
1019         tdm_private_output *private_output;
1020         tdm_private_layer *private_layer = NULL;
1021
1022         TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED());
1023
1024         if (!output_commit_handler)
1025                 return;
1026
1027         private_output = output_commit_handler->private_output;
1028         private_display = private_output->private_display;
1029
1030         if (output_commit_handler->owner_tid != syscall(SYS_gettid)) {
1031                 tdm_thread_cb_output_commit output_commit;
1032                 tdm_error ret;
1033
1034                 output_commit.base.type = TDM_THREAD_CB_OUTPUT_COMMIT;
1035                 output_commit.base.length = sizeof output_commit;
1036                 output_commit.output_stamp = private_output->stamp;
1037                 output_commit.sequence = sequence;
1038                 output_commit.tv_sec = tv_sec;
1039                 output_commit.tv_usec = tv_usec;
1040                 output_commit.user_data = user_data;
1041
1042                 ret = tdm_thread_send_cb(private_display->private_loop, &output_commit.base);
1043                 TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
1044
1045                 return;
1046         }
1047
1048         if (private_display->commit_type == TDM_COMMIT_TYPE_OUTPUT) {
1049                 /* In case of layer commit, the below will be handled in the layer commit callback */
1050                 LIST_FOR_EACH_ENTRY(private_layer, &private_output->layer_list, link) {
1051                         _tdm_layer_committed(private_layer);
1052                 }
1053         }
1054
1055         if (output_commit_handler->func) {
1056                 _pthread_mutex_unlock(&private_display->lock);
1057                 output_commit_handler->func(private_output, sequence,
1058                                                                         tv_sec, tv_usec, output_commit_handler->user_data);
1059                 _pthread_mutex_lock(&private_display->lock);
1060         }
1061
1062         LIST_DEL(&output_commit_handler->link);
1063         free(output_commit_handler);
1064 }
1065
1066 /* add_front: To distinguish between the user vblank handlers and the layer
1067  *            commit vblank handlers. The layer commit handlers will be called
1068  *            before calling the user vblank handlers.
1069  */
1070 static tdm_error
1071 _tdm_output_wait_vblank(tdm_output *output, int interval, int sync,
1072                                                 tdm_output_vblank_handler func, void *user_data,
1073                                                 unsigned int add_front)
1074 {
1075         tdm_func_output *func_output;
1076         tdm_private_vblank_handler *vblank_handler = NULL, *v = NULL;
1077         unsigned int skip_request = 0;
1078         pid_t tid = syscall(SYS_gettid);
1079
1080         OUTPUT_FUNC_ENTRY();
1081
1082         func_output = &private_display->func_output;
1083
1084         /* interval SHOULD be at least 1 */
1085         if (interval <= 0)
1086                 interval = 1;
1087
1088         if (!func_output->output_wait_vblank) {
1089                 TDM_ERR("not implemented!!");
1090                 return TDM_ERROR_NOT_IMPLEMENTED;
1091         }
1092
1093         if (!private_output->regist_vblank_cb) {
1094                 private_output->regist_vblank_cb = 1;
1095                 ret = func_output->output_set_vblank_handler(private_output->output_backend,
1096                                 tdm_output_cb_vblank);
1097         }
1098
1099         vblank_handler = calloc(1, sizeof(tdm_private_vblank_handler));
1100         if (!vblank_handler) {
1101                 TDM_ERR("failed: alloc memory");
1102                 return TDM_ERROR_OUT_OF_MEMORY;
1103         }
1104
1105         if (tdm_debug_module & TDM_DEBUG_COMMIT)
1106                 TDM_INFO("output(%d) wait_vblank: handler(%p)", private_output->pipe, vblank_handler);
1107
1108         LIST_FOR_EACH_ENTRY(v, &private_output->vblank_handler_list, link) {
1109                 if (v->interval == interval && v->sync == sync && v->owner_tid == tid) {
1110                         skip_request = 1;
1111                         break;
1112                 }
1113         }
1114
1115         if (add_front)
1116                 LIST_ADD(&vblank_handler->link, &private_output->vblank_handler_list);
1117         else
1118                 LIST_ADDTAIL(&vblank_handler->link, &private_output->vblank_handler_list);
1119
1120         vblank_handler->private_output = private_output;
1121         vblank_handler->interval = interval;
1122         vblank_handler->sync = sync;
1123         vblank_handler->func = func;
1124         vblank_handler->user_data = user_data;
1125         vblank_handler->owner_tid = tid;
1126
1127         /* If there is the previous request, we can skip to call output_wait_vblank() */
1128         if (!skip_request) {
1129                 ret = func_output->output_wait_vblank(private_output->output_backend, interval,
1130                                                                                           sync, vblank_handler);
1131                 TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, wait_failed);
1132
1133                 if (tdm_debug_module & TDM_DEBUG_COMMIT)
1134                         TDM_INFO("output(%d) backend wait_vblank", private_output->pipe);
1135         }
1136
1137         return ret;
1138
1139 wait_failed:
1140         if (vblank_handler) {
1141                 LIST_DEL(&vblank_handler->link);
1142                 free(vblank_handler);
1143         }
1144         return ret;
1145 }
1146
1147 EXTERN tdm_error
1148 tdm_output_wait_vblank(tdm_output *output, int interval, int sync,
1149                                            tdm_output_vblank_handler func, void *user_data)
1150 {
1151         OUTPUT_FUNC_ENTRY();
1152
1153         _pthread_mutex_lock(&private_display->lock);
1154
1155         if (private_output->current_dpms_value > TDM_OUTPUT_DPMS_ON) {
1156                 TDM_WRN("output(%d) dpms: %s", private_output->pipe,
1157                                 tdm_dpms_str(private_output->current_dpms_value));
1158                 _pthread_mutex_unlock(&private_display->lock);
1159                 return TDM_ERROR_DPMS_OFF;
1160         }
1161
1162         ret = _tdm_output_wait_vblank(output, interval, sync, func, user_data, 0);
1163
1164         _pthread_mutex_unlock(&private_display->lock);
1165
1166         return ret;
1167 }
1168
1169 EXTERN tdm_error
1170 tdm_output_wait_vblank_add_front(tdm_output *output, int interval, int sync,
1171                                                                  tdm_output_vblank_handler func, void *user_data)
1172 {
1173         OUTPUT_FUNC_ENTRY();
1174
1175         _pthread_mutex_lock(&private_display->lock);
1176
1177         if (private_output->current_dpms_value > TDM_OUTPUT_DPMS_ON) {
1178                 TDM_WRN("output(%d) dpms: %s", private_output->pipe,
1179                                 tdm_dpms_str(private_output->current_dpms_value));
1180                 _pthread_mutex_unlock(&private_display->lock);
1181                 return TDM_ERROR_DPMS_OFF;
1182         }
1183
1184         ret = _tdm_output_wait_vblank(output, interval, sync, func, user_data, 1);
1185
1186         _pthread_mutex_unlock(&private_display->lock);
1187
1188         return ret;
1189 }
1190
1191 static tdm_error
1192 _tdm_output_commit(tdm_output *output, int sync, tdm_output_commit_handler func,
1193                                    void *user_data)
1194 {
1195         tdm_func_output *func_output;
1196         tdm_private_output_commit_handler *output_commit_handler = NULL;
1197         OUTPUT_FUNC_ENTRY();
1198
1199         func_output = &private_display->func_output;
1200
1201         if (!func_output->output_commit) {
1202                 TDM_ERR("not implemented!!");
1203                 return TDM_ERROR_NOT_IMPLEMENTED;
1204         }
1205
1206         if (func) {
1207                 if (!private_output->regist_commit_cb) {
1208                         private_output->regist_commit_cb = 1;
1209                         ret = func_output->output_set_commit_handler(private_output->output_backend,
1210                                         tdm_output_cb_commit);
1211                         TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, commit_failed);
1212                 }
1213
1214                 output_commit_handler = calloc(1, sizeof(tdm_private_output_commit_handler));
1215                 if (!output_commit_handler) {
1216                         TDM_ERR("failed: alloc memory");
1217                         return TDM_ERROR_OUT_OF_MEMORY;
1218                 }
1219
1220                 LIST_ADDTAIL(&output_commit_handler->link, &private_output->output_commit_handler_list);
1221                 output_commit_handler->private_output = private_output;
1222                 output_commit_handler->func = func;
1223                 output_commit_handler->user_data = user_data;
1224                 output_commit_handler->owner_tid = syscall(SYS_gettid);
1225         }
1226
1227         ret = func_output->output_commit(private_output->output_backend, sync,
1228                                                                          output_commit_handler);
1229         TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, commit_failed);
1230
1231         if (tdm_debug_module & TDM_DEBUG_COMMIT)
1232                 TDM_INFO("output(%d) backend commit", private_output->pipe);
1233
1234         return ret;
1235
1236 commit_failed:
1237         if (output_commit_handler) {
1238                 LIST_DEL(&output_commit_handler->link);
1239                 free(output_commit_handler);
1240         }
1241         return ret;
1242 }
1243
1244 EXTERN tdm_error
1245 tdm_output_commit(tdm_output *output, int sync, tdm_output_commit_handler func,
1246                                   void *user_data)
1247 {
1248         OUTPUT_FUNC_ENTRY();
1249
1250         _pthread_mutex_lock(&private_display->lock);
1251
1252         if (private_display->commit_type == TDM_COMMIT_TYPE_NONE)
1253                 private_display->commit_type = TDM_COMMIT_TYPE_OUTPUT;
1254         else if (private_display->commit_type == TDM_COMMIT_TYPE_LAYER) {
1255                 TDM_ERR("Can't supported. Use tdm_layer_commit");
1256                 _pthread_mutex_unlock(&private_display->lock);
1257                 return TDM_ERROR_BAD_REQUEST;
1258         }
1259
1260         if (private_display->commit_per_vblank) {
1261                 TDM_ERR("Use tdm_layer_commit");
1262                 _pthread_mutex_unlock(&private_display->lock);
1263                 return TDM_ERROR_BAD_REQUEST;
1264         }
1265
1266         if (private_output->current_dpms_value > TDM_OUTPUT_DPMS_ON) {
1267                 TDM_ERR("output(%d) dpms: %s", private_output->pipe,
1268                                 tdm_dpms_str(private_output->current_dpms_value));
1269                 _pthread_mutex_unlock(&private_display->lock);
1270                 return TDM_ERROR_DPMS_OFF;
1271         }
1272
1273         if (tdm_debug_module & TDM_DEBUG_COMMIT)
1274                 TDM_INFO("output(%d) commit", private_output->pipe);
1275
1276         ret = _tdm_output_commit(output, sync, func, user_data);
1277
1278         _pthread_mutex_unlock(&private_display->lock);
1279
1280         return ret;
1281 }
1282
1283 EXTERN tdm_error
1284 tdm_output_set_mode(tdm_output *output, const tdm_output_mode *mode)
1285 {
1286         tdm_func_output *func_output;
1287         OUTPUT_FUNC_ENTRY();
1288
1289         TDM_RETURN_VAL_IF_FAIL(mode != NULL, TDM_ERROR_INVALID_PARAMETER);
1290
1291         _pthread_mutex_lock(&private_display->lock);
1292
1293         func_output = &private_display->func_output;
1294
1295         if (!func_output->output_set_mode) {
1296                 _pthread_mutex_unlock(&private_display->lock);
1297                 TDM_ERR("not implemented!!");
1298                 return TDM_ERROR_NOT_IMPLEMENTED;
1299         }
1300
1301         ret = func_output->output_set_mode(private_output->output_backend, mode);
1302         if (ret == TDM_ERROR_NONE)
1303                 private_output->current_mode = mode;
1304         _pthread_mutex_unlock(&private_display->lock);
1305
1306         return ret;
1307 }
1308
1309 EXTERN tdm_error
1310 tdm_output_get_mode(tdm_output *output, const tdm_output_mode **mode)
1311 {
1312         OUTPUT_FUNC_ENTRY();
1313
1314         TDM_RETURN_VAL_IF_FAIL(mode != NULL, TDM_ERROR_INVALID_PARAMETER);
1315
1316         _pthread_mutex_lock(&private_display->lock);
1317
1318         *mode = private_output->current_mode;
1319
1320         _pthread_mutex_unlock(&private_display->lock);
1321
1322         return ret;
1323 }
1324
1325 static tdm_error
1326 _tdm_output_dpms_changed_timeout(void *user_data)
1327 {
1328         tdm_private_output *private_output = user_data;
1329         tdm_value value;
1330
1331         value.u32 = private_output->current_dpms_value;
1332         tdm_output_call_change_handler_internal(private_output,
1333                                                                                         &private_output->change_handler_list_sub,
1334                                                                                         TDM_OUTPUT_CHANGE_DPMS,
1335                                                                                         value, 0);
1336
1337         return TDM_ERROR_NONE;
1338 }
1339
1340 INTERN void
1341 tdm_output_cb_dpms(tdm_output *output_backend, tdm_output_dpms dpms, void *user_data)
1342 {
1343         tdm_private_display *private_display;
1344         tdm_private_output *private_output = user_data;
1345         tdm_value value;
1346
1347         TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED());
1348         TDM_RETURN_IF_FAIL(private_output);
1349
1350         private_display = private_output->private_display;
1351
1352         if (!tdm_thread_in_display_thread(syscall(SYS_gettid))) {
1353                 tdm_thread_cb_output_dpms output_dpms;
1354                 tdm_error ret;
1355
1356                 _tdm_output_update(output_backend, user_data);
1357
1358                 output_dpms.base.type = TDM_THREAD_CB_OUTPUT_DPMS;
1359                 output_dpms.base.length = sizeof output_dpms;
1360                 output_dpms.output_stamp = private_output->stamp;
1361                 output_dpms.dpms = dpms;
1362                 output_dpms.user_data = user_data;
1363
1364                 value.u32 = dpms;
1365                 tdm_output_call_change_handler_internal(private_output,
1366                                                                                                 &private_output->change_handler_list_sub,
1367                                                                                                 TDM_OUTPUT_CHANGE_DPMS,
1368                                                                                                 value, 0);
1369
1370                 ret = tdm_thread_send_cb(private_display->private_loop, &output_dpms.base);
1371                 TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
1372
1373                 return;
1374         }
1375
1376         private_output->current_dpms_value = dpms;
1377
1378         value.u32 = dpms;
1379         tdm_output_call_change_handler_internal(private_output,
1380                                                                                         &private_output->change_handler_list_main,
1381                                                                                         TDM_OUTPUT_CHANGE_DPMS,
1382                                                                                         value, 0);
1383 }
1384
1385 EXTERN tdm_error
1386 tdm_output_set_dpms(tdm_output *output, tdm_output_dpms dpms_value)
1387 {
1388         tdm_func_output *func_output;
1389         OUTPUT_FUNC_ENTRY();
1390
1391         if (dpms_value > TDM_OUTPUT_DPMS_OFF)
1392                 dpms_value = TDM_OUTPUT_DPMS_OFF;
1393
1394         _pthread_mutex_lock(&private_display->lock);
1395
1396         if (private_output->current_dpms_value == dpms_value) {
1397                 _pthread_mutex_unlock(&private_display->lock);
1398                 return TDM_ERROR_NONE;
1399         }
1400
1401         /** Use timer to call the output change callback of the sub-thread.
1402          * The output change callback of tdm_server and tdm_vblank was called
1403          * in the main thread. And it made the multi thread issue. If we use
1404          * the timer, we can call the sub-thread's output change callback in
1405          * sub-thread.
1406          */
1407         if (!private_output->dpms_changed_timer) {
1408                 private_output->dpms_changed_timer =
1409                         tdm_event_loop_add_timer_handler(private_output->private_display,
1410                                                                                          _tdm_output_dpms_changed_timeout, private_output, NULL);
1411                 if (!private_output->dpms_changed_timer) {
1412                         TDM_ERR("can't create dpms timer!!");
1413                         _pthread_mutex_unlock(&private_display->lock);
1414                         return TDM_ERROR_OUT_OF_MEMORY;
1415                 }
1416         }
1417
1418         func_output = &private_display->func_output;
1419
1420         if (!func_output->output_set_dpms) {
1421                 _pthread_mutex_unlock(&private_display->lock);
1422                 private_output->current_dpms_value = dpms_value;
1423                 TDM_WRN("not implemented!!");
1424                 return TDM_ERROR_NONE;
1425         }
1426
1427         if (func_output->output_set_dpms_handler) {
1428                 if (!private_output->regist_dpms_cb) {
1429                         private_output->regist_dpms_cb = 1;
1430                         ret = func_output->output_set_dpms_handler(private_output->output_backend,
1431                                         tdm_output_cb_dpms, private_output);
1432                         if (ret != TDM_ERROR_NONE) {
1433                                 _pthread_mutex_unlock(&private_display->lock);
1434                                 TDM_ERR("Can't set the dpms handler!!");
1435                                 return ret;
1436                         }
1437                 }
1438         }
1439
1440         ret = func_output->output_set_dpms(private_output->output_backend, dpms_value);
1441
1442         if (ret == TDM_ERROR_NONE && !func_output->output_set_dpms_handler) {
1443                 tdm_value value;
1444
1445                 private_output->current_dpms_value = dpms_value;
1446
1447                 value.u32 = dpms_value;
1448                 tdm_output_call_change_handler_internal(private_output,
1449                                                                                                 &private_output->change_handler_list_main,
1450                                                                                                 TDM_OUTPUT_CHANGE_DPMS,
1451                                                                                                 value, 0);
1452
1453                 if (!LIST_IS_EMPTY(&private_output->change_handler_list_sub)) {
1454                         ret = tdm_event_loop_source_timer_update(private_output->dpms_changed_timer, 1);
1455                         if (ret != TDM_ERROR_NONE)
1456                                 TDM_NEVER_GET_HERE();
1457                 }
1458         }
1459
1460         _pthread_mutex_unlock(&private_display->lock);
1461
1462         return ret;
1463 }
1464
1465 EXTERN tdm_error
1466 tdm_output_get_dpms(tdm_output *output, tdm_output_dpms *dpms_value)
1467 {
1468         tdm_func_output *func_output;
1469         OUTPUT_FUNC_ENTRY();
1470
1471         TDM_RETURN_VAL_IF_FAIL(dpms_value != NULL, TDM_ERROR_INVALID_PARAMETER);
1472
1473         _pthread_mutex_lock(&private_display->lock);
1474
1475         func_output = &private_display->func_output;
1476
1477         if (!func_output->output_get_dpms) {
1478                 *dpms_value = private_output->current_dpms_value;
1479                 _pthread_mutex_unlock(&private_display->lock);
1480                 TDM_WRN("not implemented!!");
1481                 return TDM_ERROR_NONE;
1482         }
1483
1484         ret = func_output->output_get_dpms(private_output->output_backend, dpms_value);
1485
1486         _pthread_mutex_unlock(&private_display->lock);
1487
1488         return ret;
1489 }
1490
1491 EXTERN tdm_capture *
1492 tdm_output_create_capture(tdm_output *output, tdm_error *error)
1493 {
1494         tdm_capture *capture = NULL;
1495
1496         OUTPUT_FUNC_ENTRY_ERROR();
1497
1498         _pthread_mutex_lock(&private_display->lock);
1499
1500         capture = (tdm_capture *)tdm_capture_create_output_internal(private_output, error);
1501
1502         _pthread_mutex_unlock(&private_display->lock);
1503
1504         return capture;
1505 }
1506
1507 INTERN void
1508 tdm_output_call_change_handler_internal(tdm_private_output *private_output,
1509                                                                                 struct list_head *change_handler_list,
1510                                                                                 tdm_output_change_type type,
1511                                                                                 tdm_value value,
1512                                                                                 int no_check_thread_id)
1513 {
1514         tdm_private_display *private_display;
1515         tdm_private_change_handler *change_handler = NULL;
1516
1517         TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED());
1518         TDM_RETURN_IF_FAIL(private_output);
1519
1520         private_display = private_output->private_display;
1521         if (!tdm_thread_in_display_thread(syscall(SYS_gettid))) {
1522                 if (type & TDM_OUTPUT_CHANGE_CONNECTION)
1523                         TDM_INFO("output(%d) changed: %s (%d)",
1524                                          private_output->pipe, tdm_status_str(value.u32), value.u32);
1525                 if (type & TDM_OUTPUT_CHANGE_DPMS)
1526                         TDM_INFO("output(%d) changed: dpms %s (%d)",
1527                                          private_output->pipe, tdm_dpms_str(value.u32), value.u32);
1528         }
1529
1530         if (LIST_IS_EMPTY(change_handler_list))
1531                 return;
1532
1533         LIST_FOR_EACH_ENTRY(change_handler, change_handler_list, link) {
1534                 if (!no_check_thread_id && change_handler->owner_tid != syscall(SYS_gettid))
1535                         TDM_NEVER_GET_HERE();
1536
1537                 _pthread_mutex_unlock(&private_display->lock);
1538                 change_handler->func(private_output, type,
1539                                                          value, change_handler->user_data);
1540                 _pthread_mutex_lock(&private_display->lock);
1541         }
1542 }
1543
1544 EXTERN tdm_error
1545 tdm_layer_get_capabilities(tdm_layer *layer, tdm_layer_capability *capabilities)
1546 {
1547         LAYER_FUNC_ENTRY();
1548
1549         TDM_RETURN_VAL_IF_FAIL(capabilities != NULL, TDM_ERROR_INVALID_PARAMETER);
1550
1551         _pthread_mutex_lock(&private_display->lock);
1552
1553         *capabilities = private_layer->caps.capabilities;
1554
1555         _pthread_mutex_unlock(&private_display->lock);
1556
1557         return ret;
1558 }
1559
1560 EXTERN tdm_error
1561 tdm_layer_get_available_formats(tdm_layer *layer, const tbm_format **formats, int *count)
1562 {
1563         LAYER_FUNC_ENTRY();
1564
1565         TDM_RETURN_VAL_IF_FAIL(formats != NULL, TDM_ERROR_INVALID_PARAMETER);
1566         TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
1567
1568         _pthread_mutex_lock(&private_display->lock);
1569
1570         *formats = (const tbm_format *)private_layer->caps.formats;
1571         *count = private_layer->caps.format_count;
1572
1573         _pthread_mutex_unlock(&private_display->lock);
1574
1575         return ret;
1576 }
1577
1578 EXTERN tdm_error
1579 tdm_layer_get_available_properties(tdm_layer *layer, const tdm_prop **props, int *count)
1580 {
1581         LAYER_FUNC_ENTRY();
1582
1583         TDM_RETURN_VAL_IF_FAIL(props != NULL, TDM_ERROR_INVALID_PARAMETER);
1584         TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
1585
1586         _pthread_mutex_lock(&private_display->lock);
1587
1588         *props = (const tdm_prop *)private_layer->caps.props;
1589         *count = private_layer->caps.prop_count;
1590
1591         _pthread_mutex_unlock(&private_display->lock);
1592
1593         return ret;
1594 }
1595
1596 EXTERN tdm_error
1597 tdm_layer_get_zpos(tdm_layer *layer, int *zpos)
1598 {
1599         LAYER_FUNC_ENTRY();
1600
1601         TDM_RETURN_VAL_IF_FAIL(zpos != NULL, TDM_ERROR_INVALID_PARAMETER);
1602
1603         _pthread_mutex_lock(&private_display->lock);
1604
1605         *zpos = private_layer->caps.zpos;
1606
1607         _pthread_mutex_unlock(&private_display->lock);
1608
1609         return ret;
1610 }
1611
1612 EXTERN tdm_error
1613 tdm_layer_set_property(tdm_layer *layer, unsigned int id, tdm_value value)
1614 {
1615         tdm_func_layer *func_layer;
1616         LAYER_FUNC_ENTRY();
1617
1618         _pthread_mutex_lock(&private_display->lock);
1619
1620         func_layer = &private_display->func_layer;
1621
1622         if (private_layer->usable)
1623                 TDM_INFO("layer(%d) not usable", private_layer->index);
1624
1625         private_layer->usable = 0;
1626
1627         if (!func_layer->layer_set_property) {
1628                 _pthread_mutex_unlock(&private_display->lock);
1629                 TDM_ERR("not implemented!!");
1630                 return TDM_ERROR_NOT_IMPLEMENTED;
1631         }
1632
1633         ret = func_layer->layer_set_property(private_layer->layer_backend, id, value);
1634
1635         _pthread_mutex_unlock(&private_display->lock);
1636
1637         return ret;
1638 }
1639
1640 EXTERN tdm_error
1641 tdm_layer_get_property(tdm_layer *layer, unsigned int id, tdm_value *value)
1642 {
1643         tdm_func_layer *func_layer;
1644         LAYER_FUNC_ENTRY();
1645
1646         TDM_RETURN_VAL_IF_FAIL(value != NULL, TDM_ERROR_INVALID_PARAMETER);
1647
1648         _pthread_mutex_lock(&private_display->lock);
1649
1650         func_layer = &private_display->func_layer;
1651
1652         if (!func_layer->layer_get_property) {
1653                 _pthread_mutex_unlock(&private_display->lock);
1654                 TDM_ERR("not implemented!!");
1655                 return TDM_ERROR_NOT_IMPLEMENTED;
1656         }
1657
1658         ret = func_layer->layer_get_property(private_layer->layer_backend, id, value);
1659
1660         _pthread_mutex_unlock(&private_display->lock);
1661
1662         return ret;
1663 }
1664
1665 EXTERN tdm_error
1666 tdm_layer_set_info(tdm_layer *layer, tdm_info_layer *info)
1667 {
1668         tdm_func_layer *func_layer;
1669         char fmtstr[128];
1670
1671         LAYER_FUNC_ENTRY();
1672
1673         TDM_RETURN_VAL_IF_FAIL(info != NULL, TDM_ERROR_INVALID_PARAMETER);
1674
1675         _pthread_mutex_lock(&private_display->lock);
1676
1677         func_layer = &private_display->func_layer;
1678
1679         if (private_layer->usable)
1680                 TDM_INFO("layer(%p) not usable", private_layer);
1681
1682         private_layer->usable = 0;
1683
1684         if (!func_layer->layer_set_info) {
1685                 _pthread_mutex_unlock(&private_display->lock);
1686                 TDM_ERR("not implemented!!");
1687                 return TDM_ERROR_NOT_IMPLEMENTED;
1688         }
1689
1690         if (info->src_config.format)
1691                 snprintf(fmtstr, 128, "%c%c%c%c", FOURCC_STR(info->src_config.format));
1692         else
1693                 snprintf(fmtstr, 128, "NONE");
1694
1695         TDM_INFO("layer(%p) info: src(%dx%d %d,%d %dx%d %s) dst(%d,%d %dx%d) trans(%d)",
1696                          private_layer, info->src_config.size.h, info->src_config.size.v,
1697                          info->src_config.pos.x, info->src_config.pos.y,
1698                          info->src_config.pos.w, info->src_config.pos.h,
1699                          fmtstr,
1700                          info->dst_pos.x, info->dst_pos.y,
1701                          info->dst_pos.w, info->dst_pos.h,
1702                          info->transform);
1703
1704         ret = func_layer->layer_set_info(private_layer->layer_backend, info);
1705         TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
1706
1707         _pthread_mutex_unlock(&private_display->lock);
1708
1709         return ret;
1710 }
1711
1712 EXTERN tdm_error
1713 tdm_layer_get_info(tdm_layer *layer, tdm_info_layer *info)
1714 {
1715         tdm_func_layer *func_layer;
1716         LAYER_FUNC_ENTRY();
1717
1718         TDM_RETURN_VAL_IF_FAIL(info != NULL, TDM_ERROR_INVALID_PARAMETER);
1719
1720         _pthread_mutex_lock(&private_display->lock);
1721
1722         func_layer = &private_display->func_layer;
1723
1724         if (!func_layer->layer_get_info) {
1725                 _pthread_mutex_unlock(&private_display->lock);
1726                 TDM_ERR("not implemented!!");
1727                 return TDM_ERROR_NOT_IMPLEMENTED;
1728         }
1729
1730         ret = func_layer->layer_get_info(private_layer->layer_backend, info);
1731
1732         _pthread_mutex_unlock(&private_display->lock);
1733
1734         return ret;
1735 }
1736
1737 static void
1738 _tdm_layer_dump_buffer(tdm_layer *layer, tbm_surface_h buffer)
1739 {
1740         tdm_private_layer *private_layer = (tdm_private_layer*)layer;
1741         tdm_private_output *private_output = private_layer->private_output;
1742         unsigned int pipe;
1743         int zpos;
1744         char fname[PATH_MAX];
1745
1746         pipe = private_output->pipe;
1747         zpos = private_layer->caps.zpos;
1748
1749         snprintf(fname, sizeof(fname), "tdm_%d_lyr_%d", pipe, zpos);
1750
1751         tbm_surface_internal_dump_buffer(buffer, fname);
1752         TDM_DBG("%s dump excute", fname);
1753
1754         return;
1755 }
1756
1757 EXTERN tdm_error
1758 tdm_layer_set_buffer(tdm_layer *layer, tbm_surface_h buffer)
1759 {
1760         tdm_func_layer *func_layer;
1761
1762         LAYER_FUNC_ENTRY();
1763
1764         TDM_RETURN_VAL_IF_FAIL(buffer != NULL, TDM_ERROR_INVALID_PARAMETER);
1765
1766         _pthread_mutex_lock(&private_display->lock);
1767
1768         if (tdm_debug_dump & TDM_DUMP_FLAG_LAYER &&
1769                 !(private_layer->caps.capabilities & TDM_LAYER_CAPABILITY_VIDEO)) {
1770                 char str[TDM_PATH_LEN];
1771                 static int i;
1772                 snprintf(str, TDM_PATH_LEN, "layer_%d_%d_%03d",
1773                                  private_output->index, private_layer->index, i++);
1774                 tdm_helper_dump_buffer_str(buffer, tdm_debug_dump_dir, str);
1775         }
1776
1777         func_layer = &private_display->func_layer;
1778
1779         if (private_layer->usable)
1780                 TDM_INFO("layer(%p) not usable", private_layer);
1781
1782         private_layer->usable = 0;
1783
1784         if (!func_layer->layer_set_buffer) {
1785                 _pthread_mutex_unlock(&private_display->lock);
1786                 TDM_ERR("not implemented!!");
1787                 return TDM_ERROR_NOT_IMPLEMENTED;
1788         }
1789
1790         ret = func_layer->layer_set_buffer(private_layer->layer_backend, buffer);
1791         TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
1792
1793         /* dump buffer */
1794         if (tdm_dump_enable && !(private_layer->caps.capabilities & TDM_LAYER_CAPABILITY_VIDEO))
1795                 _tdm_layer_dump_buffer(layer, buffer);
1796
1797         if (ret == TDM_ERROR_NONE) {
1798                 /* FIXME: should save to pending_buffer first. And after committing
1799                  * successfully, need to move to waiting_buffer.
1800                  */
1801                 if (private_layer->waiting_buffer) {
1802                         _pthread_mutex_unlock(&private_display->lock);
1803                         tdm_buffer_unref_backend(private_layer->waiting_buffer);
1804                         _pthread_mutex_lock(&private_display->lock);
1805                 }
1806
1807                 private_layer->waiting_buffer = tdm_buffer_ref_backend(buffer);
1808                 if (tdm_debug_module & TDM_DEBUG_BUFFER)
1809                         TDM_INFO("layer(%p) waiting_buffer(%p)",
1810                                          private_layer, private_layer->waiting_buffer);
1811         }
1812
1813         _pthread_mutex_unlock(&private_display->lock);
1814
1815         return ret;
1816 }
1817
1818 EXTERN tdm_error
1819 tdm_layer_unset_buffer(tdm_layer *layer)
1820 {
1821         tdm_private_layer_commit_handler *lm = NULL, *lmm = NULL;
1822         tdm_func_layer *func_layer;
1823         LAYER_FUNC_ENTRY();
1824
1825         _pthread_mutex_lock(&private_display->lock);
1826
1827         func_layer = &private_display->func_layer;
1828
1829         if (private_layer->waiting_buffer) {
1830                 _pthread_mutex_unlock(&private_display->lock);
1831                 tdm_buffer_unref_backend(private_layer->waiting_buffer);
1832                 _pthread_mutex_lock(&private_display->lock);
1833                 private_layer->waiting_buffer = NULL;
1834
1835                 if (tdm_debug_module & TDM_DEBUG_BUFFER)
1836                         TDM_INFO("layer(%p) waiting_buffer(%p)",
1837                                          private_layer, private_layer->waiting_buffer);
1838         }
1839
1840         if (private_layer->showing_buffer) {
1841                 _pthread_mutex_unlock(&private_display->lock);
1842                 tdm_buffer_unref_backend(private_layer->showing_buffer);
1843                 _pthread_mutex_lock(&private_display->lock);
1844                 private_layer->showing_buffer = NULL;
1845
1846                 if (tdm_debug_module & TDM_DEBUG_BUFFER)
1847                         TDM_INFO("layer(%p) showing_buffer(%p)",
1848                                          private_layer, private_layer->showing_buffer);
1849         }
1850
1851         LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &private_output->layer_commit_handler_list, link) {
1852                 if (lm->private_layer != private_layer)
1853                         continue;
1854                 LIST_DEL(&lm->link);
1855                 free(lm);
1856         }
1857
1858         LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &private_output->pending_commit_handler_list, link) {
1859                 if (lm->private_layer != private_layer)
1860                         continue;
1861                 LIST_DEL(&lm->link);
1862                 free(lm);
1863         }
1864
1865         private_layer->usable = 1;
1866
1867         if (private_layer->usable)
1868                 TDM_INFO("layer(%p) now usable", private_layer);
1869
1870         if (!func_layer->layer_unset_buffer) {
1871                 _pthread_mutex_unlock(&private_display->lock);
1872                 TDM_ERR("not implemented!!");
1873                 return TDM_ERROR_NOT_IMPLEMENTED;
1874         }
1875
1876         ret = func_layer->layer_unset_buffer(private_layer->layer_backend);
1877         TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
1878
1879         _pthread_mutex_unlock(&private_display->lock);
1880
1881         return ret;
1882 }
1883
1884 static void
1885 _tdm_layer_committed(tdm_private_layer *private_layer)
1886 {
1887         tdm_private_output *private_output = private_layer->private_output;
1888         tdm_private_display *private_display = private_output->private_display;
1889
1890         if (!private_layer->waiting_buffer)
1891                 return;
1892
1893         if (private_display->print_fps) {
1894                 double curr = tdm_helper_get_time();
1895                 if (private_layer->fps_stamp == 0) {
1896                         private_layer->fps_stamp = curr;
1897                 } else if ((curr - private_layer->fps_stamp) > 1.0) {
1898                         TDM_INFO("output(%d) layer(%d) fps: %d", private_output->index, private_layer->index, private_layer->fps_count);
1899                         private_layer->fps_count = 0;
1900                         private_layer->fps_stamp = curr;
1901                 } else
1902                         private_layer->fps_count++;
1903         } else if (private_layer->fps_stamp != 0) {
1904                 private_layer->fps_stamp = 0;
1905                 private_layer->fps_count = 0;
1906         }
1907
1908         if (private_layer->showing_buffer) {
1909                 _pthread_mutex_unlock(&private_display->lock);
1910                 tdm_buffer_unref_backend(private_layer->showing_buffer);
1911                 _pthread_mutex_lock(&private_display->lock);
1912
1913                 if (private_layer->buffer_queue) {
1914                         _pthread_mutex_unlock(&private_display->lock);
1915                         tbm_surface_queue_release(private_layer->buffer_queue,
1916                                                                           private_layer->showing_buffer);
1917                         _pthread_mutex_lock(&private_display->lock);
1918                 }
1919         }
1920
1921         private_layer->showing_buffer = private_layer->waiting_buffer;
1922         private_layer->waiting_buffer = NULL;
1923
1924         if (tdm_debug_module & TDM_DEBUG_BUFFER)
1925                 TDM_INFO("layer(%p) waiting_buffer(%p) showing_buffer(%p)",
1926                                  private_layer, private_layer->waiting_buffer,
1927                                  private_layer->showing_buffer);
1928 }
1929
1930 static void
1931 _tdm_layer_got_output_vblank(tdm_private_output *private_output, unsigned int sequence,
1932                                                          unsigned int tv_sec, unsigned int tv_usec)
1933 {
1934         tdm_private_layer_commit_handler *lm = NULL, *lmm = NULL;
1935         tdm_private_display *private_display;
1936         struct list_head clone_list, pending_clone_list;
1937         tdm_error ret;
1938
1939         private_display = private_output->private_display;
1940
1941         private_output->layer_waiting_vblank = 0;
1942
1943         LIST_INITHEAD(&clone_list);
1944         LIST_INITHEAD(&pending_clone_list);
1945
1946         LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &private_output->layer_commit_handler_list, link) {
1947                 LIST_DEL(&lm->link);
1948                 lm->private_layer->committing = 0;
1949                 LIST_ADDTAIL(&lm->link, &clone_list);
1950         }
1951
1952         LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &private_output->pending_commit_handler_list, link) {
1953                 LIST_DEL(&lm->link);
1954                 lm->private_layer->committing = 0;
1955                 LIST_ADDTAIL(&lm->link, &pending_clone_list);
1956         }
1957
1958         LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &clone_list, link) {
1959                 if (tdm_debug_module & TDM_DEBUG_COMMIT)
1960                         TDM_INFO("layer(%p) committed. handle(%p)", lm->private_layer, (lm)?:NULL);
1961
1962                 _tdm_layer_committed(lm->private_layer);
1963                 _pthread_mutex_unlock(&private_display->lock);
1964                 if (lm->func)
1965                         lm->func(lm->private_layer, sequence, tv_sec, tv_usec, lm->user_data);
1966                 _pthread_mutex_lock(&private_display->lock);
1967                 LIST_DEL(&lm->link);
1968                 free(lm);
1969         }
1970
1971         if (LIST_IS_EMPTY(&pending_clone_list))
1972                 return;
1973
1974         TDM_GOTO_IF_FAIL(private_output->vblank != NULL, wait_failed);
1975
1976         ret = _tdm_output_commit(private_output, 0, NULL, NULL);
1977         TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, wait_failed);
1978
1979         if (tdm_debug_module & TDM_DEBUG_COMMIT)
1980                 TDM_INFO("layer commit: output(%d) commit", private_output->pipe);
1981
1982         /* tdm_vblank APIs is for server. it should be called in unlock status*/
1983         if (!private_output->layer_waiting_vblank) {
1984                 _pthread_mutex_unlock(&private_display->lock);
1985                 ret = tdm_vblank_wait(private_output->vblank, 0, 0, 1, _tdm_layer_cb_wait_vblank, private_output);
1986                 _pthread_mutex_lock(&private_display->lock);
1987                 TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, wait_failed);
1988                 private_output->layer_waiting_vblank = 1;
1989         }
1990
1991         if (tdm_debug_module & TDM_DEBUG_COMMIT)
1992                 TDM_INFO("layer commit: output(%d) wait vblank", private_output->pipe);
1993
1994         LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &pending_clone_list, link) {
1995                 LIST_DEL(&lm->link);
1996                 LIST_ADDTAIL(&lm->link, &private_output->layer_commit_handler_list);
1997         }
1998
1999         return;
2000 wait_failed:
2001         LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &pending_clone_list, link) {
2002                 LIST_DEL(&lm->link);
2003                 free(lm);
2004         }
2005         return;
2006 }
2007
2008 static void
2009 _tdm_layer_cb_output_commit(tdm_output *output, unsigned int sequence,
2010                                                         unsigned int tv_sec, unsigned int tv_usec, void *user_data)
2011 {
2012         tdm_private_layer_commit_handler *layer_commit_handler = user_data;
2013         tdm_private_layer_commit_handler *lm = NULL;
2014         tdm_private_display *private_display;
2015         tdm_private_output *private_output = output;
2016         tdm_private_layer *private_layer;
2017         int found = 0;
2018
2019         TDM_RETURN_IF_FAIL(layer_commit_handler != NULL);
2020
2021         private_display = private_output->private_display;
2022
2023         LIST_FOR_EACH_ENTRY(lm, &private_output->layer_commit_handler_list, link) {
2024                 if (layer_commit_handler == lm) {
2025                         found = 1;
2026                         break;
2027                 }
2028         }
2029
2030         if (!found)
2031                 return;
2032
2033         private_layer = layer_commit_handler->private_layer;
2034
2035         if (tdm_debug_module & TDM_DEBUG_COMMIT)
2036                 TDM_INFO("layer(%p) commit: output(%d) committed. handle(%p)",
2037                                  private_layer, private_output->pipe, (layer_commit_handler)?:NULL);
2038
2039         _pthread_mutex_lock(&private_display->lock);
2040
2041         _tdm_layer_committed(private_layer);
2042
2043         if (layer_commit_handler->func) {
2044                 _pthread_mutex_unlock(&private_display->lock);
2045                 layer_commit_handler->func(private_output, sequence,
2046                                                                    tv_sec, tv_usec, layer_commit_handler->user_data);
2047                 _pthread_mutex_lock(&private_display->lock);
2048         }
2049
2050         LIST_DEL(&layer_commit_handler->link);
2051         free(layer_commit_handler);
2052
2053         _pthread_mutex_unlock(&private_display->lock);
2054 }
2055
2056 static void
2057 _tdm_layer_cb_wait_vblank(tdm_vblank *vblank, tdm_error error, unsigned int sequence,
2058                                                   unsigned int tv_sec, unsigned int tv_usec, void *user_data)
2059 {
2060         tdm_private_output *private_output = user_data;
2061         tdm_private_display *private_display;
2062
2063         TDM_RETURN_IF_FAIL(private_output != NULL);
2064
2065         private_display = private_output->private_display;
2066
2067         _pthread_mutex_lock(&private_display->lock);
2068
2069         if (tdm_debug_module & TDM_DEBUG_COMMIT)
2070                 TDM_INFO("layer commit: output(%d) got vblank", private_output->pipe);
2071
2072         _tdm_layer_got_output_vblank(private_output, sequence, tv_sec, tv_usec);
2073
2074         _pthread_mutex_unlock(&private_display->lock);
2075 }
2076
2077 static int
2078 _tdm_layer_commit_possible(tdm_private_layer *private_layer)
2079 {
2080         tdm_private_output *private_output = private_layer->private_output;
2081         tdm_private_display *private_display = private_output->private_display;
2082
2083         if (private_display->commit_per_vblank == 1 && _tdm_output_used_layer_count(private_output) == 1) {
2084                 if (tdm_debug_module & TDM_DEBUG_COMMIT)
2085                         TDM_INFO("layer(%p) commit: 1 layer", private_layer);
2086                 return 1;
2087         }
2088
2089         if (private_display->commit_per_vblank == 2 && LIST_IS_EMPTY(&private_output->layer_commit_handler_list)) {
2090                 if (tdm_debug_module & TDM_DEBUG_COMMIT)
2091                         TDM_INFO("layer(%p) commit: non previous commit", private_layer);
2092                 return 1;
2093         }
2094
2095         return 0;
2096 }
2097
2098 static tdm_error
2099 _tdm_layer_commit(tdm_layer *layer, tdm_layer_commit_handler func, void *user_data)
2100 {
2101         tdm_private_layer_commit_handler *layer_commit_handler;
2102         LAYER_FUNC_ENTRY();
2103
2104         layer_commit_handler = calloc(1, sizeof(tdm_private_layer_commit_handler));
2105         if (!layer_commit_handler) {
2106                 TDM_ERR("failed: alloc memory");
2107                 return TDM_ERROR_OUT_OF_MEMORY;
2108         }
2109
2110         if (tdm_debug_module & TDM_DEBUG_COMMIT)
2111                 TDM_INFO("layer(%p) commit: handle(%p)", private_layer, layer_commit_handler);
2112
2113         LIST_INITHEAD(&layer_commit_handler->link);
2114         layer_commit_handler->private_layer = private_layer;
2115         layer_commit_handler->func = func;
2116         layer_commit_handler->user_data = user_data;
2117
2118         if (!private_display->commit_per_vblank) {
2119                 TDM_GOTO_IF_FAIL(private_display->commit_type == TDM_COMMIT_TYPE_OUTPUT, commit_failed);
2120
2121                 LIST_ADDTAIL(&layer_commit_handler->link, &private_output->layer_commit_handler_list);
2122                 ret = _tdm_output_commit(private_layer->private_output, 0, _tdm_layer_cb_output_commit, layer_commit_handler);
2123                 TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, commit_failed);
2124
2125                 if (tdm_debug_module & TDM_DEBUG_COMMIT)
2126                         TDM_INFO("layer(%p) commit: no commit-per-vblank", private_layer);
2127         } else {
2128                 TDM_GOTO_IF_FAIL(private_display->commit_type == TDM_COMMIT_TYPE_LAYER, commit_failed);
2129
2130                 if (private_layer->committing)
2131                         TDM_WRN("layer(%d) too many commit", private_layer->index);
2132                 else
2133                         private_layer->committing = 1;
2134
2135                 if (_tdm_layer_commit_possible(private_layer)) {
2136                         /* add to layer_commit_handler_list */
2137                         LIST_ADDTAIL(&layer_commit_handler->link, &private_output->layer_commit_handler_list);
2138
2139                         ret = _tdm_output_commit(private_layer->private_output, 0, NULL, NULL);
2140                         TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, commit_failed);
2141
2142                         if (tdm_debug_module & TDM_DEBUG_COMMIT)
2143                                 TDM_INFO("layer(%p) commit: output", private_layer);
2144                 } else {
2145                         /* add to pending_commit_handler_list. It will be commited when a vblank occurs */
2146                         LIST_ADDTAIL(&layer_commit_handler->link, &private_output->pending_commit_handler_list);
2147
2148                         if (tdm_debug_module & TDM_DEBUG_COMMIT)
2149                                 TDM_INFO("layer(%p) commit: pending", private_layer);
2150                 }
2151
2152                 if (!private_output->vblank) {
2153                         /* tdm_vblank APIs is for server. it should be called in unlock status*/
2154                         _pthread_mutex_unlock(&private_display->lock);
2155                         private_output->vblank = tdm_vblank_create(private_display, private_output, NULL);
2156                         _pthread_mutex_lock(&private_display->lock);
2157                         TDM_GOTO_IF_FAIL(private_output->vblank != NULL, commit_failed);
2158                 }
2159
2160                 if (!private_output->layer_waiting_vblank) {
2161                         /* tdm_vblank APIs is for server. it should be called in unlock status*/
2162                         _pthread_mutex_unlock(&private_display->lock);
2163                         ret = tdm_vblank_wait(private_output->vblank, 0, 0, 1, _tdm_layer_cb_wait_vblank, private_output);
2164                         _pthread_mutex_lock(&private_display->lock);
2165                         TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, commit_failed);
2166                         private_output->layer_waiting_vblank = 1;
2167
2168                         if (tdm_debug_module & TDM_DEBUG_COMMIT)
2169                                 TDM_INFO("layer(%p) commit: wait vblank", private_layer);
2170                 }
2171         }
2172
2173         return ret;
2174
2175 commit_failed:
2176         if (layer_commit_handler) {
2177                 LIST_DEL(&layer_commit_handler->link);
2178                 free(layer_commit_handler);
2179         }
2180         return ret;
2181 }
2182
2183 EXTERN tdm_error
2184 tdm_layer_commit(tdm_layer *layer, tdm_layer_commit_handler func, void *user_data)
2185 {
2186         LAYER_FUNC_ENTRY();
2187
2188         _pthread_mutex_lock(&private_display->lock);
2189
2190         if (private_display->commit_type == TDM_COMMIT_TYPE_NONE) {
2191                 if (!private_display->commit_per_vblank)
2192                         private_display->commit_type = TDM_COMMIT_TYPE_OUTPUT;
2193                 else
2194                         private_display->commit_type = TDM_COMMIT_TYPE_LAYER;
2195         }
2196
2197         if (private_output->current_dpms_value > TDM_OUTPUT_DPMS_ON) {
2198                 TDM_ERR("layer(%p)'s output(%d) dpms: %s", layer, private_output->pipe,
2199                                 tdm_dpms_str(private_output->current_dpms_value));
2200                 _pthread_mutex_unlock(&private_display->lock);
2201                 return TDM_ERROR_DPMS_OFF;
2202         }
2203
2204         ret = _tdm_layer_commit(private_layer, func, user_data);
2205
2206         _pthread_mutex_unlock(&private_display->lock);
2207
2208         return ret;
2209 }
2210
2211 EXTERN tdm_error
2212 tdm_layer_is_committing(tdm_layer *layer, unsigned int *committing)
2213 {
2214         LAYER_FUNC_ENTRY();
2215
2216         TDM_RETURN_VAL_IF_FAIL(committing != NULL, TDM_ERROR_INVALID_PARAMETER);
2217
2218         _pthread_mutex_lock(&private_display->lock);
2219
2220         *committing = private_layer->committing;
2221
2222         _pthread_mutex_unlock(&private_display->lock);
2223
2224         return ret;
2225 }
2226
2227 EXTERN tbm_surface_h
2228 tdm_layer_get_displaying_buffer(tdm_layer *layer, tdm_error *error)
2229 {
2230         tbm_surface_h buffer;
2231         LAYER_FUNC_ENTRY_ERROR();
2232
2233         _pthread_mutex_lock(&private_display->lock);
2234
2235         if (error)
2236                 *error = TDM_ERROR_NONE;
2237
2238         if (private_layer->showing_buffer) {
2239                 buffer = private_layer->showing_buffer;
2240         } else {
2241                 if (error)
2242                         *error = TDM_ERROR_OPERATION_FAILED;
2243                 _pthread_mutex_unlock(&private_display->lock);
2244                 TDM_DBG("layer(%p) showing_buffer is null", private_layer);
2245                 return NULL;
2246         }
2247         _pthread_mutex_unlock(&private_display->lock);
2248
2249         return buffer;
2250 }
2251
2252 static void
2253 _tbm_layer_queue_acquirable_cb(tbm_surface_queue_h surface_queue, void *data)
2254 {
2255         TDM_RETURN_IF_FAIL(data != NULL);
2256         tdm_layer *layer = data;
2257         tdm_func_layer *func_layer;
2258         tbm_surface_h surface = NULL;
2259         LAYER_FUNC_ENTRY_VOID_RETURN();
2260
2261         _pthread_mutex_lock(&private_display->lock);
2262
2263         func_layer = &private_display->func_layer;
2264         if (!func_layer->layer_set_buffer) {
2265                 _pthread_mutex_unlock(&private_display->lock);
2266                 return;
2267         }
2268
2269         if (TBM_SURFACE_QUEUE_ERROR_NONE != tbm_surface_queue_acquire(private_layer->buffer_queue, &surface) ||
2270                 surface == NULL) {
2271                 TDM_ERR("layer(%p) tbm_surface_queue_acquire() failed surface:%p",
2272                                 private_layer, surface);
2273                 _pthread_mutex_unlock(&private_display->lock);
2274                 return;
2275         }
2276
2277         ret = func_layer->layer_set_buffer(private_layer->layer_backend, surface);
2278         TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
2279
2280         if (ret == TDM_ERROR_NONE) {
2281                 if (private_layer->waiting_buffer) {
2282                         TDM_DBG("layer(%p) drop waiting_buffer(%p)", private_layer, private_layer->waiting_buffer);
2283                         _pthread_mutex_unlock(&private_display->lock);
2284                         tdm_buffer_unref_backend(private_layer->waiting_buffer);
2285                         tbm_surface_queue_release(private_layer->buffer_queue,
2286                                                                           private_layer->waiting_buffer);
2287                         _pthread_mutex_lock(&private_display->lock);
2288                 }
2289
2290                 private_layer->waiting_buffer = tdm_buffer_ref_backend(surface);
2291
2292                 if (tdm_debug_module & TDM_DEBUG_BUFFER)
2293                         TDM_INFO("layer(%p) waiting_buffer(%p)",
2294                                          private_layer, private_layer->waiting_buffer);
2295
2296                 if (private_display->commit_type == TDM_COMMIT_TYPE_OUTPUT) {
2297                         ret = _tdm_output_commit(private_layer->private_output, 0, NULL, NULL);
2298                         if (ret != TDM_ERROR_NONE)
2299                                 TDM_ERR("_tdm_output_commit() is fail");
2300                 } else if (private_display->commit_type == TDM_COMMIT_TYPE_LAYER) {
2301                         ret = _tdm_layer_commit(private_layer, NULL, NULL);
2302                         if (ret != TDM_ERROR_NONE)
2303                                 TDM_ERR("layer(%p) _tdm_layer_commit() is fail", private_layer);
2304                 } else {
2305                         TDM_NEVER_GET_HERE();
2306                 }
2307         }
2308
2309         _pthread_mutex_unlock(&private_display->lock);
2310 }
2311
2312 static void
2313 _tbm_layer_queue_destroy_cb(tbm_surface_queue_h surface_queue, void *data)
2314 {
2315         TDM_RETURN_IF_FAIL(data != NULL);
2316         tdm_layer *layer = data;
2317         LAYER_FUNC_ENTRY_VOID_RETURN();
2318         TDM_RETURN_IF_FAIL(ret == TDM_ERROR_NONE);
2319
2320         _pthread_mutex_lock(&private_display->lock);
2321
2322         if (private_layer->waiting_buffer) {
2323                 _pthread_mutex_unlock(&private_display->lock);
2324                 tdm_buffer_unref_backend(private_layer->waiting_buffer);
2325                 tbm_surface_queue_release(private_layer->buffer_queue,
2326                                                                   private_layer->waiting_buffer);
2327                 _pthread_mutex_lock(&private_display->lock);
2328         }
2329
2330         private_layer->buffer_queue = NULL;
2331
2332         _pthread_mutex_unlock(&private_display->lock);
2333 }
2334
2335 EXTERN tdm_error
2336 tdm_layer_set_buffer_queue(tdm_layer *layer, tbm_surface_queue_h buffer_queue)
2337 {
2338         tdm_func_layer *func_layer;
2339         LAYER_FUNC_ENTRY();
2340
2341         TDM_RETURN_VAL_IF_FAIL(buffer_queue != NULL, TDM_ERROR_INVALID_PARAMETER);
2342
2343         _pthread_mutex_lock(&private_display->lock);
2344
2345         func_layer = &private_display->func_layer;
2346
2347         if (private_layer->usable)
2348                 TDM_INFO("layer(%p) not usable", private_layer);
2349
2350         private_layer->usable = 0;
2351
2352         if (!func_layer->layer_set_buffer) {
2353                 _pthread_mutex_unlock(&private_display->lock);
2354                 TDM_ERR("not implemented!!");
2355                 return TDM_ERROR_NOT_IMPLEMENTED;
2356         }
2357
2358         if (buffer_queue == private_layer->buffer_queue) {
2359                 _pthread_mutex_unlock(&private_display->lock);
2360                 return TDM_ERROR_NONE;
2361         }
2362
2363         if (private_layer->waiting_buffer) {
2364                 _pthread_mutex_unlock(&private_display->lock);
2365                 tdm_buffer_unref_backend(private_layer->waiting_buffer);
2366                 tbm_surface_queue_release(private_layer->buffer_queue,
2367                                                                   private_layer->waiting_buffer);
2368                 private_layer->waiting_buffer = NULL;
2369                 _pthread_mutex_lock(&private_display->lock);
2370
2371                 if (tdm_debug_module & TDM_DEBUG_BUFFER)
2372                         TDM_INFO("layer(%p) waiting_buffer(%p)",
2373                                          private_layer, private_layer->waiting_buffer);
2374         }
2375
2376         private_layer->buffer_queue = buffer_queue;
2377         tbm_surface_queue_add_acquirable_cb(private_layer->buffer_queue,
2378                                                                                 _tbm_layer_queue_acquirable_cb,
2379                                                                                 layer);
2380         tbm_surface_queue_add_destroy_cb(private_layer->buffer_queue,
2381                                                                          _tbm_layer_queue_destroy_cb,
2382                                                                          layer);
2383         _pthread_mutex_unlock(&private_display->lock);
2384
2385         return ret;
2386 }
2387
2388 EXTERN tdm_error
2389 tdm_layer_unset_buffer_queue(tdm_layer *layer)
2390 {
2391         tdm_func_layer *func_layer;
2392         LAYER_FUNC_ENTRY();
2393
2394         _pthread_mutex_lock(&private_display->lock);
2395
2396         func_layer = &private_display->func_layer;
2397
2398         if (private_layer->waiting_buffer) {
2399                 _pthread_mutex_unlock(&private_display->lock);
2400                 tdm_buffer_unref_backend(private_layer->waiting_buffer);
2401                 tbm_surface_queue_release(private_layer->buffer_queue,
2402                                                                   private_layer->waiting_buffer);
2403                 private_layer->waiting_buffer = NULL;
2404                 _pthread_mutex_lock(&private_display->lock);
2405
2406                 if (tdm_debug_module & TDM_DEBUG_BUFFER)
2407                         TDM_INFO("layer(%p) waiting_buffer(%p)",
2408                                          private_layer, private_layer->waiting_buffer);
2409         }
2410
2411         if (private_layer->showing_buffer) {
2412                 _pthread_mutex_unlock(&private_display->lock);
2413                 tdm_buffer_unref_backend(private_layer->showing_buffer);
2414                 tbm_surface_queue_release(private_layer->buffer_queue,
2415                                                                   private_layer->showing_buffer);
2416                 _pthread_mutex_lock(&private_display->lock);
2417                 private_layer->showing_buffer = NULL;
2418
2419                 if (tdm_debug_module & TDM_DEBUG_BUFFER)
2420                         TDM_INFO("layer(%p) showing_buffer(%p)",
2421                                          private_layer, private_layer->showing_buffer);
2422         }
2423
2424         tbm_surface_queue_remove_acquirable_cb(private_layer->buffer_queue, _tbm_layer_queue_acquirable_cb, layer);
2425         tbm_surface_queue_remove_destroy_cb(private_layer->buffer_queue, _tbm_layer_queue_destroy_cb, layer);
2426         private_layer->buffer_queue = NULL;
2427         private_layer->usable = 1;
2428
2429         if (private_layer->usable)
2430                 TDM_INFO("layer(%p) now usable", private_layer);
2431
2432         if (!func_layer->layer_unset_buffer) {
2433                 _pthread_mutex_unlock(&private_display->lock);
2434                 TDM_ERR("not implemented!!");
2435                 return TDM_ERROR_NOT_IMPLEMENTED;
2436         }
2437
2438         ret = func_layer->layer_unset_buffer(private_layer->layer_backend);
2439
2440         _pthread_mutex_unlock(&private_display->lock);
2441
2442         return ret;
2443 }
2444
2445 EXTERN tdm_error
2446 tdm_layer_is_usable(tdm_layer *layer, unsigned int *usable)
2447 {
2448         LAYER_FUNC_ENTRY();
2449
2450         TDM_RETURN_VAL_IF_FAIL(usable != NULL, TDM_ERROR_INVALID_PARAMETER);
2451
2452         _pthread_mutex_lock(&private_display->lock);
2453
2454         *usable = private_layer->usable;
2455
2456         _pthread_mutex_unlock(&private_display->lock);
2457
2458         return ret;
2459 }
2460
2461 EXTERN tdm_error
2462 tdm_layer_set_video_pos(tdm_layer *layer, int zpos)
2463 {
2464         tdm_func_layer *func_layer;
2465         LAYER_FUNC_ENTRY();
2466
2467         _pthread_mutex_lock(&private_display->lock);
2468
2469         func_layer = &private_display->func_layer;
2470
2471         if (!(private_layer->caps.capabilities & TDM_LAYER_CAPABILITY_VIDEO)) {
2472                 TDM_ERR("layer(%p) is not video layer", private_layer);
2473                 _pthread_mutex_unlock(&private_display->lock);
2474                 return TDM_ERROR_INVALID_PARAMETER;
2475         }
2476
2477         if (!func_layer->layer_set_video_pos) {
2478                 _pthread_mutex_unlock(&private_display->lock);
2479                 TDM_ERR("not implemented!!");
2480                 return TDM_ERROR_NOT_IMPLEMENTED;
2481         }
2482
2483         ret = func_layer->layer_set_video_pos(private_layer->layer_backend, zpos);
2484
2485         _pthread_mutex_unlock(&private_display->lock);
2486
2487         return ret;
2488 }
2489
2490 EXTERN tdm_capture *
2491 tdm_layer_create_capture(tdm_layer *layer, tdm_error *error)
2492 {
2493         tdm_capture *capture = NULL;
2494
2495         LAYER_FUNC_ENTRY_ERROR();
2496
2497         _pthread_mutex_lock(&private_display->lock);
2498
2499         capture = (tdm_capture *)tdm_capture_create_layer_internal(private_layer, error);
2500
2501         _pthread_mutex_unlock(&private_display->lock);
2502
2503         return capture;
2504 }
2505
2506 EXTERN tdm_error
2507 tdm_layer_get_buffer_flags(tdm_layer *layer, unsigned int *flags)
2508 {
2509         tdm_func_layer *func_layer;
2510         LAYER_FUNC_ENTRY();
2511
2512         _pthread_mutex_lock(&private_display->lock);
2513
2514         func_layer = &private_display->func_layer;
2515
2516         if (!func_layer->layer_get_buffer_flags) {
2517                 _pthread_mutex_unlock(&private_display->lock);
2518                 TDM_ERR("not implemented!!");
2519                 return TDM_ERROR_NOT_IMPLEMENTED;
2520         }
2521
2522         ret = func_layer->layer_get_buffer_flags(private_layer->layer_backend, flags);
2523
2524         _pthread_mutex_unlock(&private_display->lock);
2525
2526         return ret;
2527 }