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