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