commit: enhance debug log
[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_ADD(&change_handler->link, &private_output->change_handler_list_sub);
601         else
602                 LIST_ADD(&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         _pthread_mutex_unlock(&private_display->lock);
995         LIST_FOR_EACH_ENTRY_SAFE(v, vv, &clone_list, link) {
996                 if (tdm_debug_module & TDM_DEBUG_COMMIT)
997                         TDM_INFO("output(%d) got vblank: handler(%p)", private_output->pipe, v);
998
999                 if (v->func)
1000                         v->func(v->private_output, sequence, tv_sec, tv_usec, v->user_data);
1001                 LIST_DEL(&v->link);
1002                 free(v);
1003         }
1004         _pthread_mutex_lock(&private_display->lock);
1005 }
1006
1007 INTERN void
1008 tdm_output_cb_commit(tdm_output *output_backend, unsigned int sequence,
1009                                          unsigned int tv_sec, unsigned int tv_usec, void *user_data)
1010 {
1011         tdm_private_output_commit_handler *output_commit_handler = user_data;
1012         tdm_private_display *private_display;
1013         tdm_private_output *private_output;
1014         tdm_private_layer *private_layer = NULL;
1015
1016         TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED());
1017
1018         if (!output_commit_handler)
1019                 return;
1020
1021         private_output = output_commit_handler->private_output;
1022         private_display = private_output->private_display;
1023
1024         if (output_commit_handler->owner_tid != syscall(SYS_gettid)) {
1025                 tdm_thread_cb_output_commit output_commit;
1026                 tdm_error ret;
1027
1028                 output_commit.base.type = TDM_THREAD_CB_OUTPUT_COMMIT;
1029                 output_commit.base.length = sizeof output_commit;
1030                 output_commit.output_stamp = private_output->stamp;
1031                 output_commit.sequence = sequence;
1032                 output_commit.tv_sec = tv_sec;
1033                 output_commit.tv_usec = tv_usec;
1034                 output_commit.user_data = user_data;
1035
1036                 ret = tdm_thread_send_cb(private_display->private_loop, &output_commit.base);
1037                 TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
1038
1039                 return;
1040         }
1041
1042         if (private_display->commit_type == TDM_COMMIT_TYPE_OUTPUT) {
1043                 /* In case of layer commit, the below will be handled in the layer commit callback */
1044                 LIST_FOR_EACH_ENTRY(private_layer, &private_output->layer_list, link) {
1045                         _tdm_layer_committed(private_layer);
1046                 }
1047         }
1048
1049         if (output_commit_handler->func) {
1050                 _pthread_mutex_unlock(&private_display->lock);
1051                 output_commit_handler->func(private_output, sequence,
1052                                                                         tv_sec, tv_usec, output_commit_handler->user_data);
1053                 _pthread_mutex_lock(&private_display->lock);
1054         }
1055
1056         LIST_DEL(&output_commit_handler->link);
1057         free(output_commit_handler);
1058 }
1059
1060 /* add_front: To distinguish between the user vblank handlers and the layer
1061  *            commit vblank handlers. The layer commit handlers will be called
1062  *            before calling the user vblank handlers.
1063  */
1064 static tdm_error
1065 _tdm_output_wait_vblank(tdm_output *output, int interval, int sync,
1066                                                 tdm_output_vblank_handler func, void *user_data,
1067                                                 unsigned int add_front)
1068 {
1069         tdm_func_output *func_output;
1070         tdm_private_vblank_handler *vblank_handler = NULL, *v = NULL;
1071         unsigned int skip_request = 0;
1072         pid_t tid = syscall(SYS_gettid);
1073
1074         OUTPUT_FUNC_ENTRY();
1075
1076         func_output = &private_display->func_output;
1077
1078         /* interval SHOULD be at least 1 */
1079         if (interval <= 0)
1080                 interval = 1;
1081
1082         if (!func_output->output_wait_vblank) {
1083                 TDM_ERR("not implemented!!");
1084                 return TDM_ERROR_NOT_IMPLEMENTED;
1085         }
1086
1087         if (!private_output->regist_vblank_cb) {
1088                 private_output->regist_vblank_cb = 1;
1089                 ret = func_output->output_set_vblank_handler(private_output->output_backend,
1090                                 tdm_output_cb_vblank);
1091         }
1092
1093         vblank_handler = calloc(1, sizeof(tdm_private_vblank_handler));
1094         if (!vblank_handler) {
1095                 TDM_ERR("failed: alloc memory");
1096                 return TDM_ERROR_OUT_OF_MEMORY;
1097         }
1098
1099         if (tdm_debug_module & TDM_DEBUG_COMMIT)
1100                 TDM_INFO("output(%d) wait_vblank: handler(%p)", private_output->pipe, vblank_handler);
1101
1102         LIST_FOR_EACH_ENTRY(v, &private_output->vblank_handler_list, link) {
1103                 if (v->interval == interval && v->sync == sync && v->owner_tid == tid) {
1104                         skip_request = 1;
1105                         break;
1106                 }
1107         }
1108
1109         if (add_front)
1110                 LIST_ADD(&vblank_handler->link, &private_output->vblank_handler_list);
1111         else
1112                 LIST_ADDTAIL(&vblank_handler->link, &private_output->vblank_handler_list);
1113
1114         vblank_handler->private_output = private_output;
1115         vblank_handler->interval = interval;
1116         vblank_handler->sync = sync;
1117         vblank_handler->func = func;
1118         vblank_handler->user_data = user_data;
1119         vblank_handler->owner_tid = tid;
1120
1121         /* If there is the previous request, we can skip to call output_wait_vblank() */
1122         if (!skip_request) {
1123                 ret = func_output->output_wait_vblank(private_output->output_backend, interval,
1124                                                                                           sync, vblank_handler);
1125                 TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, wait_failed);
1126
1127                 if (tdm_debug_module & TDM_DEBUG_COMMIT)
1128                         TDM_INFO("output(%d) backend wait_vblank", private_output->pipe);
1129         }
1130
1131         return ret;
1132
1133 wait_failed:
1134         if (vblank_handler) {
1135                 LIST_DEL(&vblank_handler->link);
1136                 free(vblank_handler);
1137         }
1138         return ret;
1139 }
1140
1141 EXTERN tdm_error
1142 tdm_output_wait_vblank(tdm_output *output, int interval, int sync,
1143                                            tdm_output_vblank_handler func, void *user_data)
1144 {
1145         OUTPUT_FUNC_ENTRY();
1146
1147         _pthread_mutex_lock(&private_display->lock);
1148
1149         if (private_output->current_dpms_value > TDM_OUTPUT_DPMS_ON) {
1150                 TDM_WRN("output(%d) dpms: %s", private_output->pipe,
1151                                 tdm_dpms_str(private_output->current_dpms_value));
1152                 _pthread_mutex_unlock(&private_display->lock);
1153                 return TDM_ERROR_DPMS_OFF;
1154         }
1155
1156         ret = _tdm_output_wait_vblank(output, interval, sync, func, user_data, 0);
1157
1158         _pthread_mutex_unlock(&private_display->lock);
1159
1160         return ret;
1161 }
1162
1163 EXTERN tdm_error
1164 tdm_output_wait_vblank_add_front(tdm_output *output, int interval, int sync,
1165                                                                  tdm_output_vblank_handler func, void *user_data)
1166 {
1167         OUTPUT_FUNC_ENTRY();
1168
1169         _pthread_mutex_lock(&private_display->lock);
1170
1171         if (private_output->current_dpms_value > TDM_OUTPUT_DPMS_ON) {
1172                 TDM_WRN("output(%d) dpms: %s", private_output->pipe,
1173                                 tdm_dpms_str(private_output->current_dpms_value));
1174                 _pthread_mutex_unlock(&private_display->lock);
1175                 return TDM_ERROR_DPMS_OFF;
1176         }
1177
1178         ret = _tdm_output_wait_vblank(output, interval, sync, func, user_data, 1);
1179
1180         _pthread_mutex_unlock(&private_display->lock);
1181
1182         return ret;
1183 }
1184
1185 static tdm_error
1186 _tdm_output_commit(tdm_output *output, int sync, tdm_output_commit_handler func,
1187                                    void *user_data)
1188 {
1189         tdm_func_output *func_output;
1190         tdm_private_output_commit_handler *output_commit_handler = NULL;
1191         OUTPUT_FUNC_ENTRY();
1192
1193         func_output = &private_display->func_output;
1194
1195         if (!func_output->output_commit) {
1196                 TDM_ERR("not implemented!!");
1197                 return TDM_ERROR_NOT_IMPLEMENTED;
1198         }
1199
1200         if (func) {
1201                 if (!private_output->regist_commit_cb) {
1202                         private_output->regist_commit_cb = 1;
1203                         ret = func_output->output_set_commit_handler(private_output->output_backend,
1204                                         tdm_output_cb_commit);
1205                         TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, commit_failed);
1206                 }
1207
1208                 output_commit_handler = calloc(1, sizeof(tdm_private_output_commit_handler));
1209                 if (!output_commit_handler) {
1210                         TDM_ERR("failed: alloc memory");
1211                         return TDM_ERROR_OUT_OF_MEMORY;
1212                 }
1213
1214                 LIST_ADD(&output_commit_handler->link, &private_output->output_commit_handler_list);
1215                 output_commit_handler->private_output = private_output;
1216                 output_commit_handler->func = func;
1217                 output_commit_handler->user_data = user_data;
1218                 output_commit_handler->owner_tid = syscall(SYS_gettid);
1219         }
1220
1221         ret = func_output->output_commit(private_output->output_backend, sync,
1222                                                                          output_commit_handler);
1223         TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, commit_failed);
1224
1225         if (tdm_debug_module & TDM_DEBUG_COMMIT)
1226                 TDM_INFO("output(%d) backend commit", private_output->pipe);
1227
1228         return ret;
1229
1230 commit_failed:
1231         if (output_commit_handler) {
1232                 LIST_DEL(&output_commit_handler->link);
1233                 free(output_commit_handler);
1234         }
1235         return ret;
1236 }
1237
1238 EXTERN tdm_error
1239 tdm_output_commit(tdm_output *output, int sync, tdm_output_commit_handler func,
1240                                   void *user_data)
1241 {
1242         OUTPUT_FUNC_ENTRY();
1243
1244         _pthread_mutex_lock(&private_display->lock);
1245
1246         if (private_display->commit_type == TDM_COMMIT_TYPE_NONE)
1247                 private_display->commit_type = TDM_COMMIT_TYPE_OUTPUT;
1248         else if (private_display->commit_type == TDM_COMMIT_TYPE_LAYER) {
1249                 TDM_ERR("Can't supported. Use tdm_layer_commit");
1250                 _pthread_mutex_unlock(&private_display->lock);
1251                 return TDM_ERROR_BAD_REQUEST;
1252         }
1253
1254         if (private_display->commit_per_vblank) {
1255                 TDM_ERR("Use tdm_layer_commit");
1256                 _pthread_mutex_unlock(&private_display->lock);
1257                 return TDM_ERROR_BAD_REQUEST;
1258         }
1259
1260         if (private_output->current_dpms_value > TDM_OUTPUT_DPMS_ON) {
1261                 TDM_ERR("output(%d) dpms: %s", private_output->pipe,
1262                                 tdm_dpms_str(private_output->current_dpms_value));
1263                 _pthread_mutex_unlock(&private_display->lock);
1264                 return TDM_ERROR_DPMS_OFF;
1265         }
1266
1267         if (tdm_debug_module & TDM_DEBUG_COMMIT)
1268                 TDM_INFO("output(%d) commit", private_output->pipe);
1269
1270         ret = _tdm_output_commit(output, sync, func, user_data);
1271
1272         _pthread_mutex_unlock(&private_display->lock);
1273
1274         return ret;
1275 }
1276
1277 EXTERN tdm_error
1278 tdm_output_set_mode(tdm_output *output, const tdm_output_mode *mode)
1279 {
1280         tdm_func_output *func_output;
1281         OUTPUT_FUNC_ENTRY();
1282
1283         TDM_RETURN_VAL_IF_FAIL(mode != NULL, TDM_ERROR_INVALID_PARAMETER);
1284
1285         _pthread_mutex_lock(&private_display->lock);
1286
1287         func_output = &private_display->func_output;
1288
1289         if (!func_output->output_set_mode) {
1290                 _pthread_mutex_unlock(&private_display->lock);
1291                 TDM_ERR("not implemented!!");
1292                 return TDM_ERROR_NOT_IMPLEMENTED;
1293         }
1294
1295         ret = func_output->output_set_mode(private_output->output_backend, mode);
1296         if (ret == TDM_ERROR_NONE)
1297                 private_output->current_mode = mode;
1298         _pthread_mutex_unlock(&private_display->lock);
1299
1300         return ret;
1301 }
1302
1303 EXTERN tdm_error
1304 tdm_output_get_mode(tdm_output *output, const tdm_output_mode **mode)
1305 {
1306         OUTPUT_FUNC_ENTRY();
1307
1308         TDM_RETURN_VAL_IF_FAIL(mode != NULL, TDM_ERROR_INVALID_PARAMETER);
1309
1310         _pthread_mutex_lock(&private_display->lock);
1311
1312         *mode = private_output->current_mode;
1313
1314         _pthread_mutex_unlock(&private_display->lock);
1315
1316         return ret;
1317 }
1318
1319 static tdm_error
1320 _tdm_output_dpms_changed_timeout(void *user_data)
1321 {
1322         tdm_private_output *private_output = user_data;
1323         tdm_value value;
1324
1325         value.u32 = private_output->current_dpms_value;
1326         tdm_output_call_change_handler_internal(private_output,
1327                                                                                         &private_output->change_handler_list_sub,
1328                                                                                         TDM_OUTPUT_CHANGE_DPMS,
1329                                                                                         value, 0);
1330
1331         return TDM_ERROR_NONE;
1332 }
1333
1334 INTERN void
1335 tdm_output_cb_dpms(tdm_output *output_backend, tdm_output_dpms dpms, void *user_data)
1336 {
1337         tdm_private_display *private_display;
1338         tdm_private_output *private_output = user_data;
1339         tdm_value value;
1340
1341         TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED());
1342         TDM_RETURN_IF_FAIL(private_output);
1343
1344         private_display = private_output->private_display;
1345
1346         if (!tdm_thread_in_display_thread(syscall(SYS_gettid))) {
1347                 tdm_thread_cb_output_dpms output_dpms;
1348                 tdm_error ret;
1349
1350                 _tdm_output_update(output_backend, user_data);
1351
1352                 output_dpms.base.type = TDM_THREAD_CB_OUTPUT_DPMS;
1353                 output_dpms.base.length = sizeof output_dpms;
1354                 output_dpms.output_stamp = private_output->stamp;
1355                 output_dpms.dpms = dpms;
1356                 output_dpms.user_data = user_data;
1357
1358                 value.u32 = dpms;
1359                 tdm_output_call_change_handler_internal(private_output,
1360                                                                                                 &private_output->change_handler_list_sub,
1361                                                                                                 TDM_OUTPUT_CHANGE_DPMS,
1362                                                                                                 value, 0);
1363
1364                 ret = tdm_thread_send_cb(private_display->private_loop, &output_dpms.base);
1365                 TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
1366
1367                 return;
1368         }
1369
1370         private_output->current_dpms_value = dpms;
1371
1372         value.u32 = dpms;
1373         tdm_output_call_change_handler_internal(private_output,
1374                                                                                         &private_output->change_handler_list_main,
1375                                                                                         TDM_OUTPUT_CHANGE_DPMS,
1376                                                                                         value, 0);
1377 }
1378
1379 EXTERN tdm_error
1380 tdm_output_set_dpms(tdm_output *output, tdm_output_dpms dpms_value)
1381 {
1382         tdm_func_output *func_output;
1383         OUTPUT_FUNC_ENTRY();
1384
1385         if (dpms_value > TDM_OUTPUT_DPMS_OFF)
1386                 dpms_value = TDM_OUTPUT_DPMS_OFF;
1387
1388         _pthread_mutex_lock(&private_display->lock);
1389
1390         if (private_output->current_dpms_value == dpms_value) {
1391                 _pthread_mutex_unlock(&private_display->lock);
1392                 return TDM_ERROR_NONE;
1393         }
1394
1395         /** Use timer to call the output change callback of the sub-thread.
1396          * The output change callback of tdm_server and tdm_vblank was called
1397          * in the main thread. And it made the multi thread issue. If we use
1398          * the timer, we can call the sub-thread's output change callback in
1399          * sub-thread.
1400          */
1401         if (!private_output->dpms_changed_timer) {
1402                 private_output->dpms_changed_timer =
1403                         tdm_event_loop_add_timer_handler(private_output->private_display,
1404                                                                                          _tdm_output_dpms_changed_timeout, private_output, NULL);
1405                 if (!private_output->dpms_changed_timer) {
1406                         TDM_ERR("can't create dpms timer!!");
1407                         _pthread_mutex_unlock(&private_display->lock);
1408                         return TDM_ERROR_OUT_OF_MEMORY;
1409                 }
1410         }
1411
1412         func_output = &private_display->func_output;
1413
1414         if (!func_output->output_set_dpms) {
1415                 _pthread_mutex_unlock(&private_display->lock);
1416                 private_output->current_dpms_value = dpms_value;
1417                 TDM_WRN("not implemented!!");
1418                 return TDM_ERROR_NONE;
1419         }
1420
1421         if (func_output->output_set_dpms_handler) {
1422                 if (!private_output->regist_dpms_cb) {
1423                         private_output->regist_dpms_cb = 1;
1424                         ret = func_output->output_set_dpms_handler(private_output->output_backend,
1425                                         tdm_output_cb_dpms, private_output);
1426                         if (ret != TDM_ERROR_NONE) {
1427                                 _pthread_mutex_unlock(&private_display->lock);
1428                                 TDM_ERR("Can't set the dpms handler!!");
1429                                 return ret;
1430                         }
1431                 }
1432         }
1433
1434         ret = func_output->output_set_dpms(private_output->output_backend, dpms_value);
1435
1436         if (ret == TDM_ERROR_NONE && !func_output->output_set_dpms_handler) {
1437                 tdm_value value;
1438
1439                 private_output->current_dpms_value = dpms_value;
1440
1441                 value.u32 = dpms_value;
1442                 tdm_output_call_change_handler_internal(private_output,
1443                                                                                                 &private_output->change_handler_list_main,
1444                                                                                                 TDM_OUTPUT_CHANGE_DPMS,
1445                                                                                                 value, 0);
1446
1447                 if (!LIST_IS_EMPTY(&private_output->change_handler_list_sub)) {
1448                         ret = tdm_event_loop_source_timer_update(private_output->dpms_changed_timer, 1);
1449                         if (ret != TDM_ERROR_NONE)
1450                                 TDM_NEVER_GET_HERE();
1451                 }
1452         }
1453
1454         _pthread_mutex_unlock(&private_display->lock);
1455
1456         return ret;
1457 }
1458
1459 EXTERN tdm_error
1460 tdm_output_get_dpms(tdm_output *output, tdm_output_dpms *dpms_value)
1461 {
1462         tdm_func_output *func_output;
1463         OUTPUT_FUNC_ENTRY();
1464
1465         TDM_RETURN_VAL_IF_FAIL(dpms_value != NULL, TDM_ERROR_INVALID_PARAMETER);
1466
1467         _pthread_mutex_lock(&private_display->lock);
1468
1469         func_output = &private_display->func_output;
1470
1471         if (!func_output->output_get_dpms) {
1472                 *dpms_value = private_output->current_dpms_value;
1473                 _pthread_mutex_unlock(&private_display->lock);
1474                 TDM_WRN("not implemented!!");
1475                 return TDM_ERROR_NONE;
1476         }
1477
1478         ret = func_output->output_get_dpms(private_output->output_backend, dpms_value);
1479
1480         _pthread_mutex_unlock(&private_display->lock);
1481
1482         return ret;
1483 }
1484
1485 EXTERN tdm_capture *
1486 tdm_output_create_capture(tdm_output *output, tdm_error *error)
1487 {
1488         tdm_capture *capture = NULL;
1489
1490         OUTPUT_FUNC_ENTRY_ERROR();
1491
1492         _pthread_mutex_lock(&private_display->lock);
1493
1494         capture = (tdm_capture *)tdm_capture_create_output_internal(private_output, error);
1495
1496         _pthread_mutex_unlock(&private_display->lock);
1497
1498         return capture;
1499 }
1500
1501 INTERN void
1502 tdm_output_call_change_handler_internal(tdm_private_output *private_output,
1503                                                                                 struct list_head *change_handler_list,
1504                                                                                 tdm_output_change_type type,
1505                                                                                 tdm_value value,
1506                                                                                 int no_check_thread_id)
1507 {
1508         tdm_private_display *private_display;
1509         tdm_private_change_handler *change_handler = NULL;
1510
1511         TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED());
1512         TDM_RETURN_IF_FAIL(private_output);
1513
1514         private_display = private_output->private_display;
1515         if (!tdm_thread_in_display_thread(syscall(SYS_gettid))) {
1516                 if (type & TDM_OUTPUT_CHANGE_CONNECTION)
1517                         TDM_INFO("output(%d) changed: %s (%d)",
1518                                          private_output->pipe, tdm_status_str(value.u32), value.u32);
1519                 if (type & TDM_OUTPUT_CHANGE_DPMS)
1520                         TDM_INFO("output(%d) changed: dpms %s (%d)",
1521                                          private_output->pipe, tdm_dpms_str(value.u32), value.u32);
1522         }
1523
1524         if (LIST_IS_EMPTY(change_handler_list))
1525                 return;
1526
1527         LIST_FOR_EACH_ENTRY(change_handler, change_handler_list, link) {
1528                 if (!no_check_thread_id && change_handler->owner_tid != syscall(SYS_gettid))
1529                         TDM_NEVER_GET_HERE();
1530
1531                 _pthread_mutex_unlock(&private_display->lock);
1532                 change_handler->func(private_output, type,
1533                                                          value, change_handler->user_data);
1534                 _pthread_mutex_lock(&private_display->lock);
1535         }
1536 }
1537
1538 EXTERN tdm_error
1539 tdm_layer_get_capabilities(tdm_layer *layer, tdm_layer_capability *capabilities)
1540 {
1541         LAYER_FUNC_ENTRY();
1542
1543         TDM_RETURN_VAL_IF_FAIL(capabilities != NULL, TDM_ERROR_INVALID_PARAMETER);
1544
1545         _pthread_mutex_lock(&private_display->lock);
1546
1547         *capabilities = private_layer->caps.capabilities;
1548
1549         _pthread_mutex_unlock(&private_display->lock);
1550
1551         return ret;
1552 }
1553
1554 EXTERN tdm_error
1555 tdm_layer_get_available_formats(tdm_layer *layer, const tbm_format **formats, int *count)
1556 {
1557         LAYER_FUNC_ENTRY();
1558
1559         TDM_RETURN_VAL_IF_FAIL(formats != NULL, TDM_ERROR_INVALID_PARAMETER);
1560         TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
1561
1562         _pthread_mutex_lock(&private_display->lock);
1563
1564         *formats = (const tbm_format *)private_layer->caps.formats;
1565         *count = private_layer->caps.format_count;
1566
1567         _pthread_mutex_unlock(&private_display->lock);
1568
1569         return ret;
1570 }
1571
1572 EXTERN tdm_error
1573 tdm_layer_get_available_properties(tdm_layer *layer, const tdm_prop **props, int *count)
1574 {
1575         LAYER_FUNC_ENTRY();
1576
1577         TDM_RETURN_VAL_IF_FAIL(props != NULL, TDM_ERROR_INVALID_PARAMETER);
1578         TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
1579
1580         _pthread_mutex_lock(&private_display->lock);
1581
1582         *props = (const tdm_prop *)private_layer->caps.props;
1583         *count = private_layer->caps.prop_count;
1584
1585         _pthread_mutex_unlock(&private_display->lock);
1586
1587         return ret;
1588 }
1589
1590 EXTERN tdm_error
1591 tdm_layer_get_zpos(tdm_layer *layer, int *zpos)
1592 {
1593         LAYER_FUNC_ENTRY();
1594
1595         TDM_RETURN_VAL_IF_FAIL(zpos != NULL, TDM_ERROR_INVALID_PARAMETER);
1596
1597         _pthread_mutex_lock(&private_display->lock);
1598
1599         *zpos = private_layer->caps.zpos;
1600
1601         _pthread_mutex_unlock(&private_display->lock);
1602
1603         return ret;
1604 }
1605
1606 EXTERN tdm_error
1607 tdm_layer_set_property(tdm_layer *layer, unsigned int id, tdm_value value)
1608 {
1609         tdm_func_layer *func_layer;
1610         LAYER_FUNC_ENTRY();
1611
1612         _pthread_mutex_lock(&private_display->lock);
1613
1614         func_layer = &private_display->func_layer;
1615
1616         if (private_layer->usable)
1617                 TDM_INFO("layer(%d) not usable", private_layer->index);
1618
1619         private_layer->usable = 0;
1620
1621         if (!func_layer->layer_set_property) {
1622                 _pthread_mutex_unlock(&private_display->lock);
1623                 TDM_ERR("not implemented!!");
1624                 return TDM_ERROR_NOT_IMPLEMENTED;
1625         }
1626
1627         ret = func_layer->layer_set_property(private_layer->layer_backend, id, value);
1628
1629         _pthread_mutex_unlock(&private_display->lock);
1630
1631         return ret;
1632 }
1633
1634 EXTERN tdm_error
1635 tdm_layer_get_property(tdm_layer *layer, unsigned int id, tdm_value *value)
1636 {
1637         tdm_func_layer *func_layer;
1638         LAYER_FUNC_ENTRY();
1639
1640         TDM_RETURN_VAL_IF_FAIL(value != NULL, TDM_ERROR_INVALID_PARAMETER);
1641
1642         _pthread_mutex_lock(&private_display->lock);
1643
1644         func_layer = &private_display->func_layer;
1645
1646         if (!func_layer->layer_get_property) {
1647                 _pthread_mutex_unlock(&private_display->lock);
1648                 TDM_ERR("not implemented!!");
1649                 return TDM_ERROR_NOT_IMPLEMENTED;
1650         }
1651
1652         ret = func_layer->layer_get_property(private_layer->layer_backend, id, value);
1653
1654         _pthread_mutex_unlock(&private_display->lock);
1655
1656         return ret;
1657 }
1658
1659 EXTERN tdm_error
1660 tdm_layer_set_info(tdm_layer *layer, tdm_info_layer *info)
1661 {
1662         tdm_func_layer *func_layer;
1663         char fmtstr[128];
1664
1665         LAYER_FUNC_ENTRY();
1666
1667         TDM_RETURN_VAL_IF_FAIL(info != NULL, TDM_ERROR_INVALID_PARAMETER);
1668
1669         _pthread_mutex_lock(&private_display->lock);
1670
1671         func_layer = &private_display->func_layer;
1672
1673         if (private_layer->usable)
1674                 TDM_INFO("layer(%p) not usable", private_layer);
1675
1676         private_layer->usable = 0;
1677
1678         if (!func_layer->layer_set_info) {
1679                 _pthread_mutex_unlock(&private_display->lock);
1680                 TDM_ERR("not implemented!!");
1681                 return TDM_ERROR_NOT_IMPLEMENTED;
1682         }
1683
1684         if (info->src_config.format)
1685                 snprintf(fmtstr, 128, "%c%c%c%c", FOURCC_STR(info->src_config.format));
1686         else
1687                 snprintf(fmtstr, 128, "NONE");
1688
1689         TDM_INFO("layer(%p) info: src(%dx%d %d,%d %dx%d %s) dst(%d,%d %dx%d) trans(%d)",
1690                          private_layer, info->src_config.size.h, info->src_config.size.v,
1691                          info->src_config.pos.x, info->src_config.pos.y,
1692                          info->src_config.pos.w, info->src_config.pos.h,
1693                          fmtstr,
1694                          info->dst_pos.x, info->dst_pos.y,
1695                          info->dst_pos.w, info->dst_pos.h,
1696                          info->transform);
1697
1698         ret = func_layer->layer_set_info(private_layer->layer_backend, info);
1699         TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
1700
1701         _pthread_mutex_unlock(&private_display->lock);
1702
1703         return ret;
1704 }
1705
1706 EXTERN tdm_error
1707 tdm_layer_get_info(tdm_layer *layer, tdm_info_layer *info)
1708 {
1709         tdm_func_layer *func_layer;
1710         LAYER_FUNC_ENTRY();
1711
1712         TDM_RETURN_VAL_IF_FAIL(info != NULL, TDM_ERROR_INVALID_PARAMETER);
1713
1714         _pthread_mutex_lock(&private_display->lock);
1715
1716         func_layer = &private_display->func_layer;
1717
1718         if (!func_layer->layer_get_info) {
1719                 _pthread_mutex_unlock(&private_display->lock);
1720                 TDM_ERR("not implemented!!");
1721                 return TDM_ERROR_NOT_IMPLEMENTED;
1722         }
1723
1724         ret = func_layer->layer_get_info(private_layer->layer_backend, info);
1725
1726         _pthread_mutex_unlock(&private_display->lock);
1727
1728         return ret;
1729 }
1730
1731 static void
1732 _tdm_layer_dump_buffer(tdm_layer *layer, tbm_surface_h buffer)
1733 {
1734         tdm_private_layer *private_layer = (tdm_private_layer*)layer;
1735         tdm_private_output *private_output = private_layer->private_output;
1736         unsigned int pipe;
1737         int zpos;
1738         char fname[PATH_MAX];
1739
1740         pipe = private_output->pipe;
1741         zpos = private_layer->caps.zpos;
1742
1743         snprintf(fname, sizeof(fname), "tdm_%d_lyr_%d", pipe, zpos);
1744
1745         tbm_surface_internal_dump_buffer(buffer, fname);
1746         TDM_DBG("%s dump excute", fname);
1747
1748         return;
1749 }
1750
1751 EXTERN tdm_error
1752 tdm_layer_set_buffer(tdm_layer *layer, tbm_surface_h buffer)
1753 {
1754         tdm_func_layer *func_layer;
1755
1756         LAYER_FUNC_ENTRY();
1757
1758         TDM_RETURN_VAL_IF_FAIL(buffer != NULL, TDM_ERROR_INVALID_PARAMETER);
1759
1760         _pthread_mutex_lock(&private_display->lock);
1761
1762         if (tdm_debug_dump & TDM_DUMP_FLAG_LAYER &&
1763                 !(private_layer->caps.capabilities & TDM_LAYER_CAPABILITY_VIDEO)) {
1764                 char str[TDM_PATH_LEN];
1765                 static int i;
1766                 snprintf(str, TDM_PATH_LEN, "layer_%d_%d_%03d",
1767                                  private_output->index, private_layer->index, i++);
1768                 tdm_helper_dump_buffer_str(buffer, tdm_debug_dump_dir, str);
1769         }
1770
1771         func_layer = &private_display->func_layer;
1772
1773         if (private_layer->usable)
1774                 TDM_INFO("layer(%p) not usable", private_layer);
1775
1776         private_layer->usable = 0;
1777
1778         if (!func_layer->layer_set_buffer) {
1779                 _pthread_mutex_unlock(&private_display->lock);
1780                 TDM_ERR("not implemented!!");
1781                 return TDM_ERROR_NOT_IMPLEMENTED;
1782         }
1783
1784         ret = func_layer->layer_set_buffer(private_layer->layer_backend, buffer);
1785         TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
1786
1787         /* dump buffer */
1788         if (tdm_dump_enable && !(private_layer->caps.capabilities & TDM_LAYER_CAPABILITY_VIDEO))
1789                 _tdm_layer_dump_buffer(layer, buffer);
1790
1791         if (ret == TDM_ERROR_NONE) {
1792                 /* FIXME: should save to pending_buffer first. And after committing
1793                  * successfully, need to move to waiting_buffer.
1794                  */
1795                 if (private_layer->waiting_buffer) {
1796                         _pthread_mutex_unlock(&private_display->lock);
1797                         tdm_buffer_unref_backend(private_layer->waiting_buffer);
1798                         _pthread_mutex_lock(&private_display->lock);
1799                 }
1800
1801                 private_layer->waiting_buffer = tdm_buffer_ref_backend(buffer);
1802                 if (tdm_debug_module & TDM_DEBUG_BUFFER)
1803                         TDM_INFO("layer(%p) waiting_buffer(%p)",
1804                                          private_layer, private_layer->waiting_buffer);
1805         }
1806
1807         _pthread_mutex_unlock(&private_display->lock);
1808
1809         return ret;
1810 }
1811
1812 EXTERN tdm_error
1813 tdm_layer_unset_buffer(tdm_layer *layer)
1814 {
1815         tdm_private_layer_commit_handler *lm = NULL, *lmm = NULL;
1816         tdm_func_layer *func_layer;
1817         LAYER_FUNC_ENTRY();
1818
1819         _pthread_mutex_lock(&private_display->lock);
1820
1821         func_layer = &private_display->func_layer;
1822
1823         if (private_layer->waiting_buffer) {
1824                 _pthread_mutex_unlock(&private_display->lock);
1825                 tdm_buffer_unref_backend(private_layer->waiting_buffer);
1826                 _pthread_mutex_lock(&private_display->lock);
1827                 private_layer->waiting_buffer = NULL;
1828
1829                 if (tdm_debug_module & TDM_DEBUG_BUFFER)
1830                         TDM_INFO("layer(%p) waiting_buffer(%p)",
1831                                          private_layer, private_layer->waiting_buffer);
1832         }
1833
1834         if (private_layer->showing_buffer) {
1835                 _pthread_mutex_unlock(&private_display->lock);
1836                 tdm_buffer_unref_backend(private_layer->showing_buffer);
1837                 _pthread_mutex_lock(&private_display->lock);
1838                 private_layer->showing_buffer = NULL;
1839
1840                 if (tdm_debug_module & TDM_DEBUG_BUFFER)
1841                         TDM_INFO("layer(%p) showing_buffer(%p)",
1842                                          private_layer, private_layer->showing_buffer);
1843         }
1844
1845         LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &private_output->layer_commit_handler_list, link) {
1846                 if (lm->private_layer != private_layer)
1847                         continue;
1848                 LIST_DEL(&lm->link);
1849                 free(lm);
1850         }
1851
1852         LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &private_output->pending_commit_handler_list, link) {
1853                 if (lm->private_layer != private_layer)
1854                         continue;
1855                 LIST_DEL(&lm->link);
1856                 free(lm);
1857         }
1858
1859         private_layer->usable = 1;
1860
1861         if (private_layer->usable)
1862                 TDM_INFO("layer(%p) now usable", private_layer);
1863
1864         if (!func_layer->layer_unset_buffer) {
1865                 _pthread_mutex_unlock(&private_display->lock);
1866                 TDM_ERR("not implemented!!");
1867                 return TDM_ERROR_NOT_IMPLEMENTED;
1868         }
1869
1870         ret = func_layer->layer_unset_buffer(private_layer->layer_backend);
1871         TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
1872
1873         _pthread_mutex_unlock(&private_display->lock);
1874
1875         return ret;
1876 }
1877
1878 static void
1879 _tdm_layer_committed(tdm_private_layer *private_layer)
1880 {
1881         tdm_private_output *private_output = private_layer->private_output;
1882         tdm_private_display *private_display = private_output->private_display;
1883
1884         private_layer->committing = 0;
1885
1886         if (private_display->print_fps) {
1887                 double curr = tdm_helper_get_time();
1888                 private_layer->fps_count++;
1889                 if (private_layer->fps_stamp == 0) {
1890                         private_layer->fps_stamp = curr;
1891                 } else if ((curr - private_layer->fps_stamp) > 1.0) {
1892                         TDM_INFO("output(%d) layer(%d) fps: %d", private_output->index, private_layer->index, private_layer->fps_count - 1);
1893                         private_layer->fps_count = 1;
1894                         private_layer->fps_stamp = curr;
1895                 }
1896         } else if (private_layer->fps_stamp != 0) {
1897                 private_layer->fps_stamp = 0;
1898                 private_layer->fps_count = 0;
1899         }
1900
1901         if (!private_layer->waiting_buffer)
1902                 return;
1903
1904         if (private_layer->showing_buffer) {
1905                 _pthread_mutex_unlock(&private_display->lock);
1906                 tdm_buffer_unref_backend(private_layer->showing_buffer);
1907                 _pthread_mutex_lock(&private_display->lock);
1908
1909                 if (private_layer->buffer_queue) {
1910                         _pthread_mutex_unlock(&private_display->lock);
1911                         tbm_surface_queue_release(private_layer->buffer_queue,
1912                                                                           private_layer->showing_buffer);
1913                         _pthread_mutex_lock(&private_display->lock);
1914                 }
1915         }
1916
1917         private_layer->showing_buffer = private_layer->waiting_buffer;
1918         private_layer->waiting_buffer = NULL;
1919
1920         if (tdm_debug_module & TDM_DEBUG_BUFFER)
1921                 TDM_INFO("layer(%p) waiting_buffer(%p) showing_buffer(%p)",
1922                                  private_layer, private_layer->waiting_buffer,
1923                                  private_layer->showing_buffer);
1924 }
1925
1926 static void
1927 _tdm_layer_got_output_vblank(tdm_private_output *private_output, unsigned int sequence,
1928                                                          unsigned int tv_sec, unsigned int tv_usec)
1929 {
1930         tdm_private_layer_commit_handler *lm = NULL, *lmm = NULL;
1931         tdm_private_display *private_display;
1932         struct list_head clone_list, pending_clone_list;
1933         tdm_error ret;
1934
1935         private_display = private_output->private_display;
1936
1937         private_output->waiting_vblank = 0;
1938
1939         LIST_INITHEAD(&clone_list);
1940         LIST_INITHEAD(&pending_clone_list);
1941
1942         LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &private_output->layer_commit_handler_list, link) {
1943                 LIST_DEL(&lm->link);
1944                 LIST_ADDTAIL(&lm->link, &clone_list);
1945         }
1946
1947         LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &private_output->pending_commit_handler_list, link) {
1948                 LIST_DEL(&lm->link);
1949                 LIST_ADDTAIL(&lm->link, &pending_clone_list);
1950         }
1951
1952         LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &clone_list, link) {
1953                 if (tdm_debug_module & TDM_DEBUG_COMMIT)
1954                         TDM_INFO("layer(%p) committed. handle(%p)", lm->private_layer, (lm)?:NULL);
1955
1956                 _tdm_layer_committed(lm->private_layer);
1957                 _pthread_mutex_unlock(&private_display->lock);
1958                 if (lm->func)
1959                         lm->func(lm->private_layer, sequence, tv_sec, tv_usec, lm->user_data);
1960                 _pthread_mutex_lock(&private_display->lock);
1961                 LIST_DEL(&lm->link);
1962                 free(lm);
1963         }
1964
1965         if (LIST_IS_EMPTY(&pending_clone_list))
1966                 return;
1967
1968         TDM_GOTO_IF_FAIL(private_output->vblank != NULL, wait_failed);
1969
1970         ret = _tdm_output_commit(private_output, 0, NULL, NULL);
1971         TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, wait_failed);
1972
1973         if (tdm_debug_module & TDM_DEBUG_COMMIT)
1974                 TDM_INFO("layer commit: output(%d) commit", private_output->pipe);
1975
1976         /* tdm_vblank APIs is for server. it should be called in unlock status*/
1977         _pthread_mutex_unlock(&private_display->lock);
1978         ret = tdm_vblank_wait(private_output->vblank, 0, 0, 1, _tdm_layer_cb_wait_vblank, private_output);
1979         _pthread_mutex_lock(&private_display->lock);
1980         TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, wait_failed);
1981         private_output->waiting_vblank = 1;
1982
1983         if (tdm_debug_module & TDM_DEBUG_COMMIT)
1984                 TDM_INFO("layer commit: output(%d) wait vblank", private_output->pipe);
1985
1986         LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &pending_clone_list, link) {
1987                 LIST_DEL(&lm->link);
1988                 LIST_ADDTAIL(&lm->link, &private_output->layer_commit_handler_list);
1989         }
1990
1991         return;
1992 wait_failed:
1993         LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &pending_clone_list, link) {
1994                 LIST_DEL(&lm->link);
1995                 free(lm);
1996         }
1997         return;
1998 }
1999
2000 static void
2001 _tdm_layer_cb_output_commit(tdm_output *output, unsigned int sequence,
2002                                                         unsigned int tv_sec, unsigned int tv_usec, void *user_data)
2003 {
2004         tdm_private_layer_commit_handler *layer_commit_handler = user_data;
2005         tdm_private_layer_commit_handler *lm = NULL;
2006         tdm_private_display *private_display;
2007         tdm_private_output *private_output = output;
2008         tdm_private_layer *private_layer;
2009         int found = 0;
2010
2011         TDM_RETURN_IF_FAIL(layer_commit_handler != NULL);
2012
2013         private_display = private_output->private_display;
2014
2015         LIST_FOR_EACH_ENTRY(lm, &private_output->layer_commit_handler_list, link) {
2016                 if (layer_commit_handler == lm) {
2017                         found = 1;
2018                         break;
2019                 }
2020         }
2021
2022         if (!found)
2023                 return;
2024
2025         private_layer = layer_commit_handler->private_layer;
2026
2027         if (tdm_debug_module & TDM_DEBUG_COMMIT)
2028                 TDM_INFO("layer(%p) commit: output(%d) committed. handle(%p)",
2029                                  private_layer, private_output->pipe, (layer_commit_handler)?:NULL);
2030
2031         _pthread_mutex_lock(&private_display->lock);
2032
2033         _tdm_layer_committed(private_layer);
2034
2035         if (layer_commit_handler->func) {
2036                 _pthread_mutex_unlock(&private_display->lock);
2037                 layer_commit_handler->func(private_output, sequence,
2038                                                                    tv_sec, tv_usec, layer_commit_handler->user_data);
2039                 _pthread_mutex_lock(&private_display->lock);
2040         }
2041
2042         LIST_DEL(&layer_commit_handler->link);
2043         free(layer_commit_handler);
2044
2045         _pthread_mutex_unlock(&private_display->lock);
2046 }
2047
2048 static void
2049 _tdm_layer_cb_wait_vblank(tdm_vblank *vblank, tdm_error error, unsigned int sequence,
2050                                                   unsigned int tv_sec, unsigned int tv_usec, void *user_data)
2051 {
2052         tdm_private_output *private_output = user_data;
2053         tdm_private_display *private_display;
2054
2055         TDM_RETURN_IF_FAIL(private_output != NULL);
2056
2057         private_display = private_output->private_display;
2058
2059         _pthread_mutex_lock(&private_display->lock);
2060
2061         if (tdm_debug_module & TDM_DEBUG_COMMIT)
2062                 TDM_INFO("layer commit: output(%d) got vblank", private_output->pipe);
2063
2064         _tdm_layer_got_output_vblank(private_output, sequence, tv_sec, tv_usec);
2065
2066         _pthread_mutex_unlock(&private_display->lock);
2067 }
2068
2069 static int
2070 _tdm_layer_commit_possible(tdm_private_layer *private_layer)
2071 {
2072         tdm_private_output *private_output = private_layer->private_output;
2073         tdm_private_display *private_display = private_output->private_display;
2074
2075         if (private_display->commit_per_vblank == 1 && _tdm_output_used_layer_count(private_output) == 1) {
2076                 if (tdm_debug_module & TDM_DEBUG_COMMIT)
2077                         TDM_INFO("layer(%p) commit: 1 layer", private_layer);
2078                 return 1;
2079         }
2080
2081         if (private_display->commit_per_vblank == 2 && LIST_IS_EMPTY(&private_output->layer_commit_handler_list)) {
2082                 if (tdm_debug_module & TDM_DEBUG_COMMIT)
2083                         TDM_INFO("layer(%p) commit: non previous commit", private_layer);
2084                 return 1;
2085         }
2086
2087         return 0;
2088 }
2089
2090 static tdm_error
2091 _tdm_layer_commit(tdm_layer *layer, tdm_layer_commit_handler func, void *user_data)
2092 {
2093         tdm_private_layer_commit_handler *layer_commit_handler;
2094         LAYER_FUNC_ENTRY();
2095
2096         layer_commit_handler = calloc(1, sizeof(tdm_private_layer_commit_handler));
2097         if (!layer_commit_handler) {
2098                 TDM_ERR("failed: alloc memory");
2099                 return TDM_ERROR_OUT_OF_MEMORY;
2100         }
2101
2102         if (tdm_debug_module & TDM_DEBUG_COMMIT)
2103                 TDM_INFO("layer(%p) commit: handle(%p)", private_layer, layer_commit_handler);
2104
2105         LIST_INITHEAD(&layer_commit_handler->link);
2106         layer_commit_handler->private_layer = private_layer;
2107         layer_commit_handler->func = func;
2108         layer_commit_handler->user_data = user_data;
2109
2110         if (!private_display->commit_per_vblank) {
2111                 TDM_GOTO_IF_FAIL(private_display->commit_type == TDM_COMMIT_TYPE_OUTPUT, commit_failed);
2112
2113                 LIST_ADD(&layer_commit_handler->link, &private_output->layer_commit_handler_list);
2114                 ret = _tdm_output_commit(private_layer->private_output, 0, _tdm_layer_cb_output_commit, layer_commit_handler);
2115                 TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, commit_failed);
2116
2117                 if (tdm_debug_module & TDM_DEBUG_COMMIT)
2118                         TDM_INFO("layer(%p) commit: no commit-per-vblank", private_layer);
2119         } else {
2120                 TDM_GOTO_IF_FAIL(private_display->commit_type == TDM_COMMIT_TYPE_LAYER, commit_failed);
2121
2122                 if (private_layer->committing)
2123                         TDM_WRN("layer(%d) too many commit", private_layer->index);
2124                 else
2125                         private_layer->committing = 1;
2126
2127                 if (_tdm_layer_commit_possible(private_layer)) {
2128                         /* add to layer_commit_handler_list */
2129                         LIST_ADD(&layer_commit_handler->link, &private_output->layer_commit_handler_list);
2130
2131                         ret = _tdm_output_commit(private_layer->private_output, 0, NULL, NULL);
2132                         TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, commit_failed);
2133
2134                         if (tdm_debug_module & TDM_DEBUG_COMMIT)
2135                                 TDM_INFO("layer(%p) commit: output", private_layer);
2136                 } else {
2137                         /* add to pending_commit_handler_list. It will be commited when a vblank occurs */
2138                         LIST_ADD(&layer_commit_handler->link, &private_output->pending_commit_handler_list);
2139
2140                         if (tdm_debug_module & TDM_DEBUG_COMMIT)
2141                                 TDM_INFO("layer(%p) commit: pending", private_layer);
2142                 }
2143
2144                 if (!private_output->vblank) {
2145                         /* tdm_vblank APIs is for server. it should be called in unlock status*/
2146                         _pthread_mutex_unlock(&private_display->lock);
2147                         private_output->vblank = tdm_vblank_create(private_display, private_output, NULL);
2148                         _pthread_mutex_lock(&private_display->lock);
2149                         TDM_GOTO_IF_FAIL(private_output->vblank != NULL, commit_failed);
2150
2151                         /* to call the frontend's internal vblank handlers before the extern vblank handlers */
2152                         tdm_vblank_set_add_front(private_output->vblank, 1);
2153                 }
2154
2155                 if (!private_output->waiting_vblank) {
2156                         /* tdm_vblank APIs is for server. it should be called in unlock status*/
2157                         _pthread_mutex_unlock(&private_display->lock);
2158                         ret = tdm_vblank_wait(private_output->vblank, 0, 0, 1, _tdm_layer_cb_wait_vblank, private_output);
2159                         _pthread_mutex_lock(&private_display->lock);
2160                         TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, commit_failed);
2161                         private_output->waiting_vblank = 1;
2162
2163                         if (tdm_debug_module & TDM_DEBUG_COMMIT)
2164                                 TDM_INFO("layer(%p) commit: wait vblank", private_layer);
2165                 }
2166         }
2167
2168         return ret;
2169
2170 commit_failed:
2171         if (layer_commit_handler) {
2172                 LIST_DEL(&layer_commit_handler->link);
2173                 free(layer_commit_handler);
2174         }
2175         return ret;
2176 }
2177
2178 EXTERN tdm_error
2179 tdm_layer_commit(tdm_layer *layer, tdm_layer_commit_handler func, void *user_data)
2180 {
2181         LAYER_FUNC_ENTRY();
2182
2183         _pthread_mutex_lock(&private_display->lock);
2184
2185         if (private_display->commit_type == TDM_COMMIT_TYPE_NONE) {
2186                 if (!private_display->commit_per_vblank)
2187                         private_display->commit_type = TDM_COMMIT_TYPE_OUTPUT;
2188                 else
2189                         private_display->commit_type = TDM_COMMIT_TYPE_LAYER;
2190         }
2191
2192         if (private_output->current_dpms_value > TDM_OUTPUT_DPMS_ON) {
2193                 TDM_ERR("layer(%p)'s output(%d) dpms: %s", layer, private_output->pipe,
2194                                 tdm_dpms_str(private_output->current_dpms_value));
2195                 _pthread_mutex_unlock(&private_display->lock);
2196                 return TDM_ERROR_DPMS_OFF;
2197         }
2198
2199         ret = _tdm_layer_commit(private_layer, func, user_data);
2200
2201         _pthread_mutex_unlock(&private_display->lock);
2202
2203         return ret;
2204 }
2205
2206 EXTERN tdm_error
2207 tdm_layer_is_committing(tdm_layer *layer, unsigned int *committing)
2208 {
2209         LAYER_FUNC_ENTRY();
2210
2211         TDM_RETURN_VAL_IF_FAIL(committing != NULL, TDM_ERROR_INVALID_PARAMETER);
2212
2213         _pthread_mutex_lock(&private_display->lock);
2214
2215         *committing = private_layer->committing;
2216
2217         _pthread_mutex_unlock(&private_display->lock);
2218
2219         return ret;
2220 }
2221
2222 EXTERN tbm_surface_h
2223 tdm_layer_get_displaying_buffer(tdm_layer *layer, tdm_error *error)
2224 {
2225         tbm_surface_h buffer;
2226         LAYER_FUNC_ENTRY_ERROR();
2227
2228         _pthread_mutex_lock(&private_display->lock);
2229
2230         if (error)
2231                 *error = TDM_ERROR_NONE;
2232
2233         if (private_layer->showing_buffer) {
2234                 buffer = private_layer->showing_buffer;
2235         } else {
2236                 if (error)
2237                         *error = TDM_ERROR_OPERATION_FAILED;
2238                 _pthread_mutex_unlock(&private_display->lock);
2239                 TDM_DBG("layer(%p) showing_buffer is null", private_layer);
2240                 return NULL;
2241         }
2242         _pthread_mutex_unlock(&private_display->lock);
2243
2244         return buffer;
2245 }
2246
2247 static void
2248 _tbm_layer_queue_acquirable_cb(tbm_surface_queue_h surface_queue, void *data)
2249 {
2250         TDM_RETURN_IF_FAIL(data != NULL);
2251         tdm_layer *layer = data;
2252         tdm_func_layer *func_layer;
2253         tbm_surface_h surface = NULL;
2254         LAYER_FUNC_ENTRY_VOID_RETURN();
2255
2256         _pthread_mutex_lock(&private_display->lock);
2257
2258         func_layer = &private_display->func_layer;
2259         if (!func_layer->layer_set_buffer) {
2260                 _pthread_mutex_unlock(&private_display->lock);
2261                 return;
2262         }
2263
2264         if (TBM_SURFACE_QUEUE_ERROR_NONE != tbm_surface_queue_acquire(private_layer->buffer_queue, &surface) ||
2265                 surface == NULL) {
2266                 TDM_ERR("layer(%p) tbm_surface_queue_acquire() failed surface:%p",
2267                                 private_layer, surface);
2268                 _pthread_mutex_unlock(&private_display->lock);
2269                 return;
2270         }
2271
2272         ret = func_layer->layer_set_buffer(private_layer->layer_backend, surface);
2273         TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
2274
2275         if (ret == TDM_ERROR_NONE) {
2276                 if (private_layer->waiting_buffer) {
2277                         TDM_DBG("layer(%p) drop waiting_buffer(%p)", private_layer, private_layer->waiting_buffer);
2278                         _pthread_mutex_unlock(&private_display->lock);
2279                         tdm_buffer_unref_backend(private_layer->waiting_buffer);
2280                         tbm_surface_queue_release(private_layer->buffer_queue,
2281                                                                           private_layer->waiting_buffer);
2282                         _pthread_mutex_lock(&private_display->lock);
2283                 }
2284
2285                 private_layer->waiting_buffer = tdm_buffer_ref_backend(surface);
2286
2287                 if (tdm_debug_module & TDM_DEBUG_BUFFER)
2288                         TDM_INFO("layer(%p) waiting_buffer(%p)",
2289                                          private_layer, private_layer->waiting_buffer);
2290
2291                 if (private_display->commit_type == TDM_COMMIT_TYPE_OUTPUT) {
2292                         ret = _tdm_output_commit(private_layer->private_output, 0, NULL, NULL);
2293                         if (ret != TDM_ERROR_NONE)
2294                                 TDM_ERR("_tdm_output_commit() is fail");
2295                 } else if (private_display->commit_type == TDM_COMMIT_TYPE_LAYER) {
2296                         ret = _tdm_layer_commit(private_layer, NULL, NULL);
2297                         if (ret != TDM_ERROR_NONE)
2298                                 TDM_ERR("layer(%p) _tdm_layer_commit() is fail", private_layer);
2299                 } else {
2300                         TDM_NEVER_GET_HERE();
2301                 }
2302         }
2303
2304         _pthread_mutex_unlock(&private_display->lock);
2305 }
2306
2307 static void
2308 _tbm_layer_queue_destroy_cb(tbm_surface_queue_h surface_queue, void *data)
2309 {
2310         TDM_RETURN_IF_FAIL(data != NULL);
2311         tdm_layer *layer = data;
2312         LAYER_FUNC_ENTRY_VOID_RETURN();
2313         TDM_RETURN_IF_FAIL(ret == TDM_ERROR_NONE);
2314
2315         _pthread_mutex_lock(&private_display->lock);
2316
2317         if (private_layer->waiting_buffer) {
2318                 _pthread_mutex_unlock(&private_display->lock);
2319                 tdm_buffer_unref_backend(private_layer->waiting_buffer);
2320                 tbm_surface_queue_release(private_layer->buffer_queue,
2321                                                                   private_layer->waiting_buffer);
2322                 _pthread_mutex_lock(&private_display->lock);
2323         }
2324
2325         private_layer->buffer_queue = NULL;
2326
2327         _pthread_mutex_unlock(&private_display->lock);
2328 }
2329
2330 EXTERN tdm_error
2331 tdm_layer_set_buffer_queue(tdm_layer *layer, tbm_surface_queue_h buffer_queue)
2332 {
2333         tdm_func_layer *func_layer;
2334         LAYER_FUNC_ENTRY();
2335
2336         TDM_RETURN_VAL_IF_FAIL(buffer_queue != NULL, TDM_ERROR_INVALID_PARAMETER);
2337
2338         _pthread_mutex_lock(&private_display->lock);
2339
2340         func_layer = &private_display->func_layer;
2341
2342         if (private_layer->usable)
2343                 TDM_INFO("layer(%p) not usable", private_layer);
2344
2345         private_layer->usable = 0;
2346
2347         if (!func_layer->layer_set_buffer) {
2348                 _pthread_mutex_unlock(&private_display->lock);
2349                 TDM_ERR("not implemented!!");
2350                 return TDM_ERROR_NOT_IMPLEMENTED;
2351         }
2352
2353         if (buffer_queue == private_layer->buffer_queue) {
2354                 _pthread_mutex_unlock(&private_display->lock);
2355                 return TDM_ERROR_NONE;
2356         }
2357
2358         if (private_layer->waiting_buffer) {
2359                 _pthread_mutex_unlock(&private_display->lock);
2360                 tdm_buffer_unref_backend(private_layer->waiting_buffer);
2361                 tbm_surface_queue_release(private_layer->buffer_queue,
2362                                                                   private_layer->waiting_buffer);
2363                 private_layer->waiting_buffer = NULL;
2364                 _pthread_mutex_lock(&private_display->lock);
2365
2366                 if (tdm_debug_module & TDM_DEBUG_BUFFER)
2367                         TDM_INFO("layer(%p) waiting_buffer(%p)",
2368                                          private_layer, private_layer->waiting_buffer);
2369         }
2370
2371         private_layer->buffer_queue = buffer_queue;
2372         tbm_surface_queue_add_acquirable_cb(private_layer->buffer_queue,
2373                                                                                 _tbm_layer_queue_acquirable_cb,
2374                                                                                 layer);
2375         tbm_surface_queue_add_destroy_cb(private_layer->buffer_queue,
2376                                                                          _tbm_layer_queue_destroy_cb,
2377                                                                          layer);
2378         _pthread_mutex_unlock(&private_display->lock);
2379
2380         return ret;
2381 }
2382
2383 EXTERN tdm_error
2384 tdm_layer_unset_buffer_queue(tdm_layer *layer)
2385 {
2386         tdm_func_layer *func_layer;
2387         LAYER_FUNC_ENTRY();
2388
2389         _pthread_mutex_lock(&private_display->lock);
2390
2391         func_layer = &private_display->func_layer;
2392
2393         if (private_layer->waiting_buffer) {
2394                 _pthread_mutex_unlock(&private_display->lock);
2395                 tdm_buffer_unref_backend(private_layer->waiting_buffer);
2396                 tbm_surface_queue_release(private_layer->buffer_queue,
2397                                                                   private_layer->waiting_buffer);
2398                 private_layer->waiting_buffer = NULL;
2399                 _pthread_mutex_lock(&private_display->lock);
2400
2401                 if (tdm_debug_module & TDM_DEBUG_BUFFER)
2402                         TDM_INFO("layer(%p) waiting_buffer(%p)",
2403                                          private_layer, private_layer->waiting_buffer);
2404         }
2405
2406         if (private_layer->showing_buffer) {
2407                 _pthread_mutex_unlock(&private_display->lock);
2408                 tdm_buffer_unref_backend(private_layer->showing_buffer);
2409                 tbm_surface_queue_release(private_layer->buffer_queue,
2410                                                                   private_layer->showing_buffer);
2411                 _pthread_mutex_lock(&private_display->lock);
2412                 private_layer->showing_buffer = NULL;
2413
2414                 if (tdm_debug_module & TDM_DEBUG_BUFFER)
2415                         TDM_INFO("layer(%p) showing_buffer(%p)",
2416                                          private_layer, private_layer->showing_buffer);
2417         }
2418
2419         tbm_surface_queue_remove_acquirable_cb(private_layer->buffer_queue, _tbm_layer_queue_acquirable_cb, layer);
2420         tbm_surface_queue_remove_destroy_cb(private_layer->buffer_queue, _tbm_layer_queue_destroy_cb, layer);
2421         private_layer->buffer_queue = NULL;
2422         private_layer->usable = 1;
2423
2424         if (private_layer->usable)
2425                 TDM_INFO("layer(%p) now usable", private_layer);
2426
2427         if (!func_layer->layer_unset_buffer) {
2428                 _pthread_mutex_unlock(&private_display->lock);
2429                 TDM_ERR("not implemented!!");
2430                 return TDM_ERROR_NOT_IMPLEMENTED;
2431         }
2432
2433         ret = func_layer->layer_unset_buffer(private_layer->layer_backend);
2434
2435         _pthread_mutex_unlock(&private_display->lock);
2436
2437         return ret;
2438 }
2439
2440 EXTERN tdm_error
2441 tdm_layer_is_usable(tdm_layer *layer, unsigned int *usable)
2442 {
2443         LAYER_FUNC_ENTRY();
2444
2445         TDM_RETURN_VAL_IF_FAIL(usable != NULL, TDM_ERROR_INVALID_PARAMETER);
2446
2447         _pthread_mutex_lock(&private_display->lock);
2448
2449         *usable = private_layer->usable;
2450
2451         _pthread_mutex_unlock(&private_display->lock);
2452
2453         return ret;
2454 }
2455
2456 EXTERN tdm_error
2457 tdm_layer_set_video_pos(tdm_layer *layer, int zpos)
2458 {
2459         tdm_func_layer *func_layer;
2460         LAYER_FUNC_ENTRY();
2461
2462         _pthread_mutex_lock(&private_display->lock);
2463
2464         func_layer = &private_display->func_layer;
2465
2466         if (!(private_layer->caps.capabilities & TDM_LAYER_CAPABILITY_VIDEO)) {
2467                 TDM_ERR("layer(%p) is not video layer", private_layer);
2468                 _pthread_mutex_unlock(&private_display->lock);
2469                 return TDM_ERROR_INVALID_PARAMETER;
2470         }
2471
2472         if (!func_layer->layer_set_video_pos) {
2473                 _pthread_mutex_unlock(&private_display->lock);
2474                 TDM_ERR("not implemented!!");
2475                 return TDM_ERROR_NOT_IMPLEMENTED;
2476         }
2477
2478         ret = func_layer->layer_set_video_pos(private_layer->layer_backend, zpos);
2479
2480         _pthread_mutex_unlock(&private_display->lock);
2481
2482         return ret;
2483 }
2484
2485 EXTERN tdm_capture *
2486 tdm_layer_create_capture(tdm_layer *layer, tdm_error *error)
2487 {
2488         tdm_capture *capture = NULL;
2489
2490         LAYER_FUNC_ENTRY_ERROR();
2491
2492         _pthread_mutex_lock(&private_display->lock);
2493
2494         capture = (tdm_capture *)tdm_capture_create_layer_internal(private_layer, error);
2495
2496         _pthread_mutex_unlock(&private_display->lock);
2497
2498         return capture;
2499 }
2500
2501 EXTERN tdm_error
2502 tdm_layer_get_buffer_flags(tdm_layer *layer, unsigned int *flags)
2503 {
2504         tdm_func_layer *func_layer;
2505         LAYER_FUNC_ENTRY();
2506
2507         _pthread_mutex_lock(&private_display->lock);
2508
2509         func_layer = &private_display->func_layer;
2510
2511         if (!func_layer->layer_get_buffer_flags) {
2512                 _pthread_mutex_unlock(&private_display->lock);
2513                 TDM_ERR("not implemented!!");
2514                 return TDM_ERROR_NOT_IMPLEMENTED;
2515         }
2516
2517         ret = func_layer->layer_get_buffer_flags(private_layer->layer_backend, flags);
2518
2519         _pthread_mutex_unlock(&private_display->lock);
2520
2521         return ret;
2522 }