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