Add return value check.
[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                         TDM_RETURN_VAL_IF_FAIL(ret == TDM_ERROR_NONE, ret);
1381                 }
1382         }
1383
1384         ret = func_output->output_set_dpms(private_output->output_backend, dpms_value);
1385
1386         if (ret == TDM_ERROR_NONE && !func_output->output_set_dpms_handler) {
1387                 tdm_value value;
1388
1389                 private_output->current_dpms_value = dpms_value;
1390
1391                 value.u32 = dpms_value;
1392                 tdm_output_call_change_handler_internal(private_output,
1393                                                                                                 &private_output->change_handler_list_main,
1394                                                                                                 TDM_OUTPUT_CHANGE_DPMS,
1395                                                                                                 value, 0);
1396
1397                 if (!LIST_IS_EMPTY(&private_output->change_handler_list_sub)) {
1398                         ret = tdm_event_loop_source_timer_update(private_output->dpms_changed_timer, 1);
1399                         if (ret != TDM_ERROR_NONE)
1400                                 TDM_NEVER_GET_HERE();
1401                 }
1402         }
1403
1404         _pthread_mutex_unlock(&private_display->lock);
1405
1406         return ret;
1407 }
1408
1409 EXTERN tdm_error
1410 tdm_output_get_dpms(tdm_output *output, tdm_output_dpms *dpms_value)
1411 {
1412         tdm_func_output *func_output;
1413         OUTPUT_FUNC_ENTRY();
1414
1415         TDM_RETURN_VAL_IF_FAIL(dpms_value != NULL, TDM_ERROR_INVALID_PARAMETER);
1416
1417         _pthread_mutex_lock(&private_display->lock);
1418
1419         func_output = &private_display->func_output;
1420
1421         if (!func_output->output_get_dpms) {
1422                 *dpms_value = private_output->current_dpms_value;
1423                 _pthread_mutex_unlock(&private_display->lock);
1424                 TDM_WRN("not implemented!!");
1425                 return TDM_ERROR_NONE;
1426         }
1427
1428         ret = func_output->output_get_dpms(private_output->output_backend, dpms_value);
1429
1430         _pthread_mutex_unlock(&private_display->lock);
1431
1432         return ret;
1433 }
1434
1435 EXTERN tdm_capture *
1436 tdm_output_create_capture(tdm_output *output, tdm_error *error)
1437 {
1438         tdm_capture *capture = NULL;
1439
1440         OUTPUT_FUNC_ENTRY_ERROR();
1441
1442         _pthread_mutex_lock(&private_display->lock);
1443
1444         capture = (tdm_capture *)tdm_capture_create_output_internal(private_output, error);
1445
1446         _pthread_mutex_unlock(&private_display->lock);
1447
1448         return capture;
1449 }
1450
1451 INTERN void
1452 tdm_output_call_change_handler_internal(tdm_private_output *private_output,
1453                                                                                 struct list_head *change_handler_list,
1454                                                                                 tdm_output_change_type type,
1455                                                                                 tdm_value value,
1456                                                                                 int no_check_thread_id)
1457 {
1458         tdm_private_display *private_display;
1459         tdm_private_change_handler *change_handler = NULL;
1460
1461         TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED());
1462         TDM_RETURN_IF_FAIL(private_output);
1463
1464         private_display = private_output->private_display;
1465         if (!tdm_thread_in_display_thread(syscall(SYS_gettid))) {
1466                 if (type & TDM_OUTPUT_CHANGE_CONNECTION)
1467                         TDM_INFO("output(%d) changed: %s (%d)",
1468                                          private_output->pipe, tdm_status_str(value.u32), value.u32);
1469                 if (type & TDM_OUTPUT_CHANGE_DPMS)
1470                         TDM_INFO("output(%d) changed: dpms %s (%d)",
1471                                          private_output->pipe, tdm_dpms_str(value.u32), value.u32);
1472         }
1473
1474         if (LIST_IS_EMPTY(change_handler_list))
1475                 return;
1476
1477         LIST_FOR_EACH_ENTRY(change_handler, change_handler_list, link) {
1478                 if (!no_check_thread_id && change_handler->owner_tid != syscall(SYS_gettid))
1479                         TDM_NEVER_GET_HERE();
1480
1481                 _pthread_mutex_unlock(&private_display->lock);
1482                 change_handler->func(private_output, type,
1483                                                          value, change_handler->user_data);
1484                 _pthread_mutex_lock(&private_display->lock);
1485         }
1486 }
1487
1488 EXTERN tdm_error
1489 tdm_layer_get_capabilities(tdm_layer *layer, tdm_layer_capability *capabilities)
1490 {
1491         LAYER_FUNC_ENTRY();
1492
1493         TDM_RETURN_VAL_IF_FAIL(capabilities != NULL, TDM_ERROR_INVALID_PARAMETER);
1494
1495         _pthread_mutex_lock(&private_display->lock);
1496
1497         *capabilities = private_layer->caps.capabilities;
1498
1499         _pthread_mutex_unlock(&private_display->lock);
1500
1501         return ret;
1502 }
1503
1504 EXTERN tdm_error
1505 tdm_layer_get_available_formats(tdm_layer *layer, const tbm_format **formats, int *count)
1506 {
1507         LAYER_FUNC_ENTRY();
1508
1509         TDM_RETURN_VAL_IF_FAIL(formats != NULL, TDM_ERROR_INVALID_PARAMETER);
1510         TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
1511
1512         _pthread_mutex_lock(&private_display->lock);
1513
1514         *formats = (const tbm_format *)private_layer->caps.formats;
1515         *count = private_layer->caps.format_count;
1516
1517         _pthread_mutex_unlock(&private_display->lock);
1518
1519         return ret;
1520 }
1521
1522 EXTERN tdm_error
1523 tdm_layer_get_available_properties(tdm_layer *layer, const tdm_prop **props, int *count)
1524 {
1525         LAYER_FUNC_ENTRY();
1526
1527         TDM_RETURN_VAL_IF_FAIL(props != NULL, TDM_ERROR_INVALID_PARAMETER);
1528         TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
1529
1530         _pthread_mutex_lock(&private_display->lock);
1531
1532         *props = (const tdm_prop *)private_layer->caps.props;
1533         *count = private_layer->caps.prop_count;
1534
1535         _pthread_mutex_unlock(&private_display->lock);
1536
1537         return ret;
1538 }
1539
1540 EXTERN tdm_error
1541 tdm_layer_get_zpos(tdm_layer *layer, int *zpos)
1542 {
1543         LAYER_FUNC_ENTRY();
1544
1545         TDM_RETURN_VAL_IF_FAIL(zpos != NULL, TDM_ERROR_INVALID_PARAMETER);
1546
1547         _pthread_mutex_lock(&private_display->lock);
1548
1549         *zpos = private_layer->caps.zpos;
1550
1551         _pthread_mutex_unlock(&private_display->lock);
1552
1553         return ret;
1554 }
1555
1556 EXTERN tdm_error
1557 tdm_layer_set_property(tdm_layer *layer, unsigned int id, tdm_value value)
1558 {
1559         tdm_func_layer *func_layer;
1560         LAYER_FUNC_ENTRY();
1561
1562         _pthread_mutex_lock(&private_display->lock);
1563
1564         func_layer = &private_display->func_layer;
1565
1566         if (private_layer->usable)
1567                 TDM_INFO("layer(%d) not usable", private_layer->index);
1568
1569         private_layer->usable = 0;
1570
1571         if (!func_layer->layer_set_property) {
1572                 _pthread_mutex_unlock(&private_display->lock);
1573                 TDM_ERR("not implemented!!");
1574                 return TDM_ERROR_NOT_IMPLEMENTED;
1575         }
1576
1577         ret = func_layer->layer_set_property(private_layer->layer_backend, id, value);
1578
1579         _pthread_mutex_unlock(&private_display->lock);
1580
1581         return ret;
1582 }
1583
1584 EXTERN tdm_error
1585 tdm_layer_get_property(tdm_layer *layer, unsigned int id, tdm_value *value)
1586 {
1587         tdm_func_layer *func_layer;
1588         LAYER_FUNC_ENTRY();
1589
1590         TDM_RETURN_VAL_IF_FAIL(value != NULL, TDM_ERROR_INVALID_PARAMETER);
1591
1592         _pthread_mutex_lock(&private_display->lock);
1593
1594         func_layer = &private_display->func_layer;
1595
1596         if (!func_layer->layer_get_property) {
1597                 _pthread_mutex_unlock(&private_display->lock);
1598                 TDM_ERR("not implemented!!");
1599                 return TDM_ERROR_NOT_IMPLEMENTED;
1600         }
1601
1602         ret = func_layer->layer_get_property(private_layer->layer_backend, id, value);
1603
1604         _pthread_mutex_unlock(&private_display->lock);
1605
1606         return ret;
1607 }
1608
1609 EXTERN tdm_error
1610 tdm_layer_set_info(tdm_layer *layer, tdm_info_layer *info)
1611 {
1612         tdm_func_layer *func_layer;
1613         char fmtstr[128];
1614
1615         LAYER_FUNC_ENTRY();
1616
1617         TDM_RETURN_VAL_IF_FAIL(info != NULL, TDM_ERROR_INVALID_PARAMETER);
1618
1619         _pthread_mutex_lock(&private_display->lock);
1620
1621         func_layer = &private_display->func_layer;
1622
1623         if (private_layer->usable)
1624                 TDM_INFO("layer(%p) not usable", private_layer);
1625
1626         private_layer->usable = 0;
1627
1628         if (!func_layer->layer_set_info) {
1629                 _pthread_mutex_unlock(&private_display->lock);
1630                 TDM_ERR("not implemented!!");
1631                 return TDM_ERROR_NOT_IMPLEMENTED;
1632         }
1633
1634         if (info->src_config.format)
1635                 snprintf(fmtstr, 128, "%c%c%c%c", FOURCC_STR(info->src_config.format));
1636         else
1637                 snprintf(fmtstr, 128, "NONE");
1638
1639         TDM_INFO("layer(%p) info: src(%dx%d %d,%d %dx%d %s) dst(%d,%d %dx%d) trans(%d)",
1640                          private_layer, info->src_config.size.h, info->src_config.size.v,
1641                          info->src_config.pos.x, info->src_config.pos.y,
1642                          info->src_config.pos.w, info->src_config.pos.h,
1643                          fmtstr,
1644                          info->dst_pos.x, info->dst_pos.y,
1645                          info->dst_pos.w, info->dst_pos.h,
1646                          info->transform);
1647
1648         ret = func_layer->layer_set_info(private_layer->layer_backend, info);
1649         TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
1650
1651         _pthread_mutex_unlock(&private_display->lock);
1652
1653         return ret;
1654 }
1655
1656 EXTERN tdm_error
1657 tdm_layer_get_info(tdm_layer *layer, tdm_info_layer *info)
1658 {
1659         tdm_func_layer *func_layer;
1660         LAYER_FUNC_ENTRY();
1661
1662         TDM_RETURN_VAL_IF_FAIL(info != NULL, TDM_ERROR_INVALID_PARAMETER);
1663
1664         _pthread_mutex_lock(&private_display->lock);
1665
1666         func_layer = &private_display->func_layer;
1667
1668         if (!func_layer->layer_get_info) {
1669                 _pthread_mutex_unlock(&private_display->lock);
1670                 TDM_ERR("not implemented!!");
1671                 return TDM_ERROR_NOT_IMPLEMENTED;
1672         }
1673
1674         ret = func_layer->layer_get_info(private_layer->layer_backend, info);
1675
1676         _pthread_mutex_unlock(&private_display->lock);
1677
1678         return ret;
1679 }
1680
1681 static void
1682 _tdm_layer_dump_buffer(tdm_layer *layer, tbm_surface_h buffer)
1683 {
1684         tdm_private_layer *private_layer = (tdm_private_layer*)layer;
1685         tdm_private_output *private_output = private_layer->private_output;
1686         unsigned int pipe;
1687         int zpos;
1688         char fname[PATH_MAX];
1689
1690         pipe = private_output->pipe;
1691         zpos = private_layer->caps.zpos;
1692
1693         snprintf(fname, sizeof(fname), "tdm_%d_lyr_%d", pipe, zpos);
1694
1695         tbm_surface_internal_dump_buffer(buffer, fname);
1696         TDM_DBG("%s dump excute", fname);
1697
1698         return;
1699 }
1700
1701 EXTERN tdm_error
1702 tdm_layer_set_buffer(tdm_layer *layer, tbm_surface_h buffer)
1703 {
1704         tdm_func_layer *func_layer;
1705
1706         LAYER_FUNC_ENTRY();
1707
1708         TDM_RETURN_VAL_IF_FAIL(buffer != NULL, TDM_ERROR_INVALID_PARAMETER);
1709
1710         _pthread_mutex_lock(&private_display->lock);
1711
1712         if (tdm_debug_dump & TDM_DUMP_FLAG_LAYER &&
1713                 !(private_layer->caps.capabilities & TDM_LAYER_CAPABILITY_VIDEO)) {
1714                 char str[TDM_PATH_LEN];
1715                 static int i;
1716                 snprintf(str, TDM_PATH_LEN, "layer_%d_%d_%03d",
1717                                  private_output->index, private_layer->index, i++);
1718                 tdm_helper_dump_buffer_str(buffer, tdm_debug_dump_dir, str);
1719         }
1720
1721         func_layer = &private_display->func_layer;
1722
1723         if (private_layer->usable)
1724                 TDM_INFO("layer(%p) not usable", private_layer);
1725
1726         private_layer->usable = 0;
1727
1728         if (!func_layer->layer_set_buffer) {
1729                 _pthread_mutex_unlock(&private_display->lock);
1730                 TDM_ERR("not implemented!!");
1731                 return TDM_ERROR_NOT_IMPLEMENTED;
1732         }
1733
1734         ret = func_layer->layer_set_buffer(private_layer->layer_backend, buffer);
1735         TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
1736
1737         /* dump buffer */
1738         if (tdm_dump_enable && !(private_layer->caps.capabilities & TDM_LAYER_CAPABILITY_VIDEO))
1739                 _tdm_layer_dump_buffer(layer, buffer);
1740
1741         if (ret == TDM_ERROR_NONE) {
1742                 /* FIXME: should save to pending_buffer first. And after committing
1743                  * successfully, need to move to waiting_buffer.
1744                  */
1745                 if (private_layer->waiting_buffer) {
1746                         _pthread_mutex_unlock(&private_display->lock);
1747                         tdm_buffer_unref_backend(private_layer->waiting_buffer);
1748                         _pthread_mutex_lock(&private_display->lock);
1749                 }
1750
1751                 private_layer->waiting_buffer = tdm_buffer_ref_backend(buffer);
1752                 if (tdm_debug_module & TDM_DEBUG_BUFFER)
1753                         TDM_INFO("layer(%p) waiting_buffer(%p)",
1754                                          private_layer, private_layer->waiting_buffer);
1755         }
1756
1757         _pthread_mutex_unlock(&private_display->lock);
1758
1759         return ret;
1760 }
1761
1762 EXTERN tdm_error
1763 tdm_layer_unset_buffer(tdm_layer *layer)
1764 {
1765         tdm_private_layer_commit_handler *lm = NULL, *lmm = NULL;
1766         tdm_func_layer *func_layer;
1767         LAYER_FUNC_ENTRY();
1768
1769         _pthread_mutex_lock(&private_display->lock);
1770
1771         func_layer = &private_display->func_layer;
1772
1773         if (private_layer->waiting_buffer) {
1774                 _pthread_mutex_unlock(&private_display->lock);
1775                 tdm_buffer_unref_backend(private_layer->waiting_buffer);
1776                 _pthread_mutex_lock(&private_display->lock);
1777                 private_layer->waiting_buffer = NULL;
1778
1779                 if (tdm_debug_module & TDM_DEBUG_BUFFER)
1780                         TDM_INFO("layer(%p) waiting_buffer(%p)",
1781                                          private_layer, private_layer->waiting_buffer);
1782         }
1783
1784         if (private_layer->showing_buffer) {
1785                 _pthread_mutex_unlock(&private_display->lock);
1786                 tdm_buffer_unref_backend(private_layer->showing_buffer);
1787                 _pthread_mutex_lock(&private_display->lock);
1788                 private_layer->showing_buffer = NULL;
1789
1790                 if (tdm_debug_module & TDM_DEBUG_BUFFER)
1791                         TDM_INFO("layer(%p) showing_buffer(%p)",
1792                                          private_layer, private_layer->showing_buffer);
1793         }
1794
1795         LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &private_output->layer_commit_handler_list, link) {
1796                 if (lm->private_layer != private_layer)
1797                         continue;
1798                 LIST_DEL(&lm->link);
1799                 free(lm);
1800         }
1801
1802         LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &private_output->pending_commit_handler_list, link) {
1803                 if (lm->private_layer != private_layer)
1804                         continue;
1805                 LIST_DEL(&lm->link);
1806                 free(lm);
1807         }
1808
1809         private_layer->usable = 1;
1810
1811         if (private_layer->usable)
1812                 TDM_INFO("layer(%p) now usable", private_layer);
1813
1814         if (!func_layer->layer_unset_buffer) {
1815                 _pthread_mutex_unlock(&private_display->lock);
1816                 TDM_ERR("not implemented!!");
1817                 return TDM_ERROR_NOT_IMPLEMENTED;
1818         }
1819
1820         ret = func_layer->layer_unset_buffer(private_layer->layer_backend);
1821         TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
1822
1823         _pthread_mutex_unlock(&private_display->lock);
1824
1825         return ret;
1826 }
1827
1828 static void
1829 _tdm_layer_committed(tdm_private_layer *private_layer)
1830 {
1831         tdm_private_output *private_output = private_layer->private_output;
1832         tdm_private_display *private_display = private_output->private_display;
1833
1834         private_layer->committing = 0;
1835
1836         if (private_display->print_fps) {
1837                 double curr = tdm_helper_get_time();
1838                 private_layer->fps_count++;
1839                 if (private_layer->fps_stamp == 0) {
1840                         private_layer->fps_stamp = curr;
1841                 } else if ((curr - private_layer->fps_stamp) > 1.0) {
1842                         TDM_INFO("output(%d) layer(%d) fps: %d", private_output->index, private_layer->index, private_layer->fps_count - 1);
1843                         private_layer->fps_count = 1;
1844                         private_layer->fps_stamp = curr;
1845                 }
1846         } else if (private_layer->fps_stamp != 0) {
1847                 private_layer->fps_stamp = 0;
1848                 private_layer->fps_count = 0;
1849         }
1850
1851         if (!private_layer->waiting_buffer)
1852                 return;
1853
1854         if (private_layer->showing_buffer) {
1855                 _pthread_mutex_unlock(&private_display->lock);
1856                 tdm_buffer_unref_backend(private_layer->showing_buffer);
1857                 _pthread_mutex_lock(&private_display->lock);
1858
1859                 if (private_layer->buffer_queue) {
1860                         _pthread_mutex_unlock(&private_display->lock);
1861                         tbm_surface_queue_release(private_layer->buffer_queue,
1862                                                                           private_layer->showing_buffer);
1863                         _pthread_mutex_lock(&private_display->lock);
1864                 }
1865         }
1866
1867         private_layer->showing_buffer = private_layer->waiting_buffer;
1868         private_layer->waiting_buffer = NULL;
1869
1870         if (tdm_debug_module & TDM_DEBUG_BUFFER)
1871                 TDM_INFO("layer(%p) waiting_buffer(%p) showing_buffer(%p)",
1872                                  private_layer, private_layer->waiting_buffer,
1873                                  private_layer->showing_buffer);
1874 }
1875
1876 static void
1877 _tdm_layer_got_output_vblank(tdm_private_output *private_output, unsigned int sequence,
1878                                                          unsigned int tv_sec, unsigned int tv_usec)
1879 {
1880         tdm_private_layer_commit_handler *lm = NULL, *lmm = NULL;
1881         tdm_private_display *private_display;
1882         tdm_error ret;
1883
1884         private_display = private_output->private_display;
1885
1886         private_output->waiting_vblank = 0;
1887
1888         LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &private_output->layer_commit_handler_list, link) {
1889                 _tdm_layer_committed(lm->private_layer);
1890
1891                 if (lm->func) {
1892                         _pthread_mutex_unlock(&private_display->lock);
1893                         lm->func(lm->private_layer, sequence, tv_sec, tv_usec, lm->user_data);
1894                         _pthread_mutex_lock(&private_display->lock);
1895                 }
1896
1897                 LIST_DEL(&lm->link);
1898                 free(lm);
1899         }
1900
1901         if (LIST_IS_EMPTY(&private_output->pending_commit_handler_list))
1902                 return;
1903
1904 #if 1
1905         ret = _tdm_output_commit(private_output, 0, _tdm_layer_cb_output_commit, NULL);
1906         TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, wait_failed);
1907
1908         if (tdm_debug_module & TDM_DEBUG_COMMIT)
1909                 TDM_INFO("layer commit: output(%d) commit", private_output->pipe);
1910
1911         private_output->waiting_vblank = 1;
1912 #else
1913         ret = _tdm_output_commit(private_output, 0, NULL, NULL);
1914         TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, wait_failed);
1915
1916         if (tdm_debug_module & TDM_DEBUG_COMMIT)
1917                 TDM_INFO("layer commit: output(%d) commit", private_output->pipe);
1918
1919         TDM_RETURN_IF_FAIL(private_output->vblank != NULL);
1920
1921         /* tdm_vblank APIs is for server. it should be called in unlock status*/
1922         _pthread_mutex_unlock(&private_display->lock);
1923         ret = tdm_vblank_wait(private_output->vblank, 0, 0, 1, _tdm_layer_cb_wait_vblank, private_output);
1924         _pthread_mutex_lock(&private_display->lock);
1925         TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, wait_failed);
1926         private_output->waiting_vblank = 1;
1927
1928         if (tdm_debug_module & TDM_DEBUG_COMMIT)
1929                 TDM_INFO("layer commit: output(%d) wait vblank", private_output->pipe);
1930 #endif
1931
1932         LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &private_output->pending_commit_handler_list, link) {
1933                 LIST_DEL(&lm->link);
1934                 LIST_ADD(&lm->link, &private_output->layer_commit_handler_list);
1935         }
1936
1937         return;
1938 wait_failed:
1939         LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &private_output->pending_commit_handler_list, link) {
1940                 LIST_DEL(&lm->link);
1941                 free(lm);
1942         }
1943         return;
1944 }
1945
1946 static void
1947 _tdm_layer_cb_output_commit(tdm_output *output, unsigned int sequence,
1948                                                         unsigned int tv_sec, unsigned int tv_usec, void *user_data)
1949 {
1950         tdm_private_layer_commit_handler *layer_commit_handler = user_data;
1951         tdm_private_display *private_display;
1952         tdm_private_output *private_output = output;
1953         tdm_private_layer *private_layer;
1954
1955         private_display = private_output->private_display;
1956
1957         _pthread_mutex_lock(&private_display->lock);
1958
1959         if (layer_commit_handler) {
1960                 tdm_private_layer_commit_handler *lm = NULL;
1961                 int found = 0;
1962
1963                 LIST_FOR_EACH_ENTRY(lm, &private_output->layer_commit_handler_list, link) {
1964                         if (layer_commit_handler == lm) {
1965                                 found = 1;
1966                                 break;
1967                         }
1968                 }
1969
1970                 if (found) {
1971                         private_layer = layer_commit_handler->private_layer;
1972
1973                         if (tdm_debug_module & TDM_DEBUG_COMMIT)
1974                                 TDM_INFO("layer(%p) commit: output(%d) committed", private_layer, private_output->pipe);
1975
1976                         _tdm_layer_committed(private_layer);
1977
1978                         if (layer_commit_handler->func) {
1979                                 _pthread_mutex_unlock(&private_display->lock);
1980                                 layer_commit_handler->func(private_output, sequence,
1981                                                                                    tv_sec, tv_usec, layer_commit_handler->user_data);
1982                                 _pthread_mutex_lock(&private_display->lock);
1983                         }
1984
1985                         LIST_DEL(&layer_commit_handler->link);
1986                         free(layer_commit_handler);
1987                 }
1988         } else {
1989                 if (tdm_debug_module & TDM_DEBUG_COMMIT)
1990                         TDM_INFO("layer commit: output(%d) committed", private_output->pipe);
1991
1992                 _tdm_layer_got_output_vblank(private_output, sequence, tv_sec, tv_usec);
1993         }
1994
1995         _pthread_mutex_unlock(&private_display->lock);
1996 }
1997
1998 static void
1999 _tdm_layer_cb_wait_vblank(tdm_vblank *vblank, tdm_error error, unsigned int sequence,
2000                                                   unsigned int tv_sec, unsigned int tv_usec, void *user_data)
2001 {
2002         tdm_private_output *private_output = user_data;
2003         tdm_private_display *private_display;
2004
2005         TDM_RETURN_IF_FAIL(private_output != NULL);
2006
2007         private_display = private_output->private_display;
2008
2009         _pthread_mutex_lock(&private_display->lock);
2010
2011         if (tdm_debug_module & TDM_DEBUG_COMMIT)
2012                 TDM_INFO("layer commit: output(%d) got vblank", private_output->pipe);
2013
2014         _tdm_layer_got_output_vblank(private_output, sequence, tv_sec, tv_usec);
2015
2016         _pthread_mutex_unlock(&private_display->lock);
2017 }
2018
2019 static int
2020 _tdm_layer_commit_possible(tdm_private_layer *private_layer)
2021 {
2022         tdm_private_output *private_output = private_layer->private_output;
2023         tdm_private_display *private_display = private_output->private_display;
2024
2025         if (!private_display->commit_per_vblank) {
2026                 if (tdm_debug_module & TDM_DEBUG_COMMIT)
2027                         TDM_INFO("layer(%p) commit: commit_per_vblank false", private_layer);
2028                 return 1;
2029         }
2030
2031         if (private_display->commit_per_vblank == 1 && _tdm_output_used_layer_count(private_output) == 1) {
2032                 if (tdm_debug_module & TDM_DEBUG_COMMIT)
2033                         TDM_INFO("layer(%p) commit: 1 layer", private_layer);
2034                 return 1;
2035         }
2036
2037         if (private_display->commit_per_vblank == 2 && LIST_IS_EMPTY(&private_output->layer_commit_handler_list)) {
2038                 if (tdm_debug_module & TDM_DEBUG_COMMIT)
2039                         TDM_INFO("layer(%p) commit: non previous commit", private_layer);
2040                 return 1;
2041         }
2042
2043         return 0;
2044 }
2045
2046 static tdm_error
2047 _tdm_layer_commit(tdm_layer *layer, tdm_layer_commit_handler func, void *user_data)
2048 {
2049         tdm_private_layer_commit_handler *layer_commit_handler;
2050         LAYER_FUNC_ENTRY();
2051
2052         layer_commit_handler = calloc(1, sizeof(tdm_private_layer_commit_handler));
2053         if (!layer_commit_handler) {
2054                 TDM_ERR("failed: alloc memory");
2055                 return TDM_ERROR_OUT_OF_MEMORY;
2056         }
2057
2058         LIST_INITHEAD(&layer_commit_handler->link);
2059         layer_commit_handler->private_layer = private_layer;
2060         layer_commit_handler->func = func;
2061         layer_commit_handler->user_data = user_data;
2062
2063         if (_tdm_layer_commit_possible(private_layer)) {
2064                 if (private_layer->committing)
2065                         TDM_WRN("layer(%d) too many commit", private_layer->index);
2066                 else
2067                         private_layer->committing = 1;
2068
2069                 LIST_ADD(&layer_commit_handler->link, &private_output->layer_commit_handler_list);
2070                 ret = _tdm_output_commit(private_layer->private_output, 0, _tdm_layer_cb_output_commit, layer_commit_handler);
2071                 TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, commit_failed);
2072
2073                 if (tdm_debug_module & TDM_DEBUG_COMMIT)
2074                         TDM_INFO("layer(%p) commit: output", private_layer);
2075         } else {
2076                 if (private_layer->committing)
2077                         TDM_WRN("layer(%d) too many commit", private_layer->index);
2078                 else
2079                         private_layer->committing = 1;
2080
2081                 LIST_ADD(&layer_commit_handler->link, &private_output->pending_commit_handler_list);
2082
2083                 if (tdm_debug_module & TDM_DEBUG_COMMIT)
2084                         TDM_INFO("layer(%p) commit: pending", private_layer);
2085
2086                 if (!private_output->vblank) {
2087                         /* tdm_vblank APIs is for server. it should be called in unlock status*/
2088                         _pthread_mutex_unlock(&private_display->lock);
2089                         private_output->vblank = tdm_vblank_create(private_display, private_output, NULL);
2090                         _pthread_mutex_lock(&private_display->lock);
2091                         TDM_GOTO_IF_FAIL(private_output->vblank != NULL, commit_failed);
2092                 }
2093
2094                 if (!private_output->waiting_vblank) {
2095                         /* tdm_vblank APIs is for server. it should be called in unlock status*/
2096                         _pthread_mutex_unlock(&private_display->lock);
2097                         ret = tdm_vblank_wait(private_output->vblank, 0, 0, 1, _tdm_layer_cb_wait_vblank, private_output);
2098                         _pthread_mutex_lock(&private_display->lock);
2099                         TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, commit_failed);
2100                         private_output->waiting_vblank = 1;
2101
2102                         if (tdm_debug_module & TDM_DEBUG_COMMIT)
2103                                 TDM_INFO("layer(%p) commit: wait vblank", private_layer);
2104                 }
2105         }
2106
2107         return ret;
2108
2109 commit_failed:
2110         if (layer_commit_handler) {
2111                 LIST_DEL(&layer_commit_handler->link);
2112                 free(layer_commit_handler);
2113         }
2114         return ret;
2115 }
2116
2117 EXTERN tdm_error
2118 tdm_layer_commit(tdm_layer *layer, tdm_layer_commit_handler func, void *user_data)
2119 {
2120         LAYER_FUNC_ENTRY();
2121
2122         _pthread_mutex_lock(&private_display->lock);
2123
2124         if (private_display->commit_type == TDM_COMMIT_TYPE_NONE)
2125                 private_display->commit_type = TDM_COMMIT_TYPE_LAYER;
2126         else if (private_display->commit_type == TDM_COMMIT_TYPE_OUTPUT) {
2127                 TDM_ERR("Can't supported. Use tdm_output_commit");
2128                 _pthread_mutex_unlock(&private_display->lock);
2129                 return TDM_ERROR_BAD_REQUEST;
2130         }
2131
2132         if (private_output->current_dpms_value > TDM_OUTPUT_DPMS_ON) {
2133                 TDM_ERR("layer(%p)'s output(%d) dpms: %s", layer, private_output->pipe,
2134                                 tdm_dpms_str(private_output->current_dpms_value));
2135                 _pthread_mutex_unlock(&private_display->lock);
2136                 return TDM_ERROR_DPMS_OFF;
2137         }
2138
2139         if (tdm_debug_module & TDM_DEBUG_COMMIT)
2140                 TDM_INFO("layer(%p) commit", private_layer);
2141
2142         ret = _tdm_layer_commit(private_layer, func, user_data);
2143
2144         _pthread_mutex_unlock(&private_display->lock);
2145
2146         return ret;
2147 }
2148
2149 EXTERN tdm_error
2150 tdm_layer_is_committing(tdm_layer *layer, unsigned int *committing)
2151 {
2152         LAYER_FUNC_ENTRY();
2153
2154         TDM_RETURN_VAL_IF_FAIL(committing != NULL, TDM_ERROR_INVALID_PARAMETER);
2155
2156         _pthread_mutex_lock(&private_display->lock);
2157
2158         *committing = private_layer->committing;
2159
2160         _pthread_mutex_unlock(&private_display->lock);
2161
2162         return ret;
2163 }
2164
2165 EXTERN tbm_surface_h
2166 tdm_layer_get_displaying_buffer(tdm_layer *layer, tdm_error *error)
2167 {
2168         tbm_surface_h buffer;
2169         LAYER_FUNC_ENTRY_ERROR();
2170
2171         _pthread_mutex_lock(&private_display->lock);
2172
2173         if (error)
2174                 *error = TDM_ERROR_NONE;
2175
2176         if (private_layer->showing_buffer) {
2177                 buffer = private_layer->showing_buffer;
2178         } else {
2179                 if (error)
2180                         *error = TDM_ERROR_OPERATION_FAILED;
2181                 _pthread_mutex_unlock(&private_display->lock);
2182                 TDM_DBG("layer(%p) showing_buffer is null", private_layer);
2183                 return NULL;
2184         }
2185         _pthread_mutex_unlock(&private_display->lock);
2186
2187         return buffer;
2188 }
2189
2190 static void
2191 _tbm_layer_queue_acquirable_cb(tbm_surface_queue_h surface_queue, void *data)
2192 {
2193         TDM_RETURN_IF_FAIL(data != NULL);
2194         tdm_layer *layer = data;
2195         tdm_func_layer *func_layer;
2196         tbm_surface_h surface = NULL;
2197         LAYER_FUNC_ENTRY_VOID_RETURN();
2198
2199         _pthread_mutex_lock(&private_display->lock);
2200
2201         func_layer = &private_display->func_layer;
2202         if (!func_layer->layer_set_buffer) {
2203                 _pthread_mutex_unlock(&private_display->lock);
2204                 return;
2205         }
2206
2207         if (TBM_SURFACE_QUEUE_ERROR_NONE != tbm_surface_queue_acquire(private_layer->buffer_queue, &surface) ||
2208                 surface == NULL) {
2209                 TDM_ERR("layer(%p) tbm_surface_queue_acquire() failed surface:%p",
2210                                 private_layer, surface);
2211                 _pthread_mutex_unlock(&private_display->lock);
2212                 return;
2213         }
2214
2215         ret = func_layer->layer_set_buffer(private_layer->layer_backend, surface);
2216         TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
2217
2218         if (ret == TDM_ERROR_NONE) {
2219                 if (private_layer->waiting_buffer) {
2220                         TDM_DBG("layer(%p) drop waiting_buffer(%p)", private_layer, private_layer->waiting_buffer);
2221                         _pthread_mutex_unlock(&private_display->lock);
2222                         tdm_buffer_unref_backend(private_layer->waiting_buffer);
2223                         tbm_surface_queue_release(private_layer->buffer_queue,
2224                                                                           private_layer->waiting_buffer);
2225                         _pthread_mutex_lock(&private_display->lock);
2226                 }
2227
2228                 private_layer->waiting_buffer = tdm_buffer_ref_backend(surface);
2229
2230                 if (tdm_debug_module & TDM_DEBUG_BUFFER)
2231                         TDM_INFO("layer(%p) waiting_buffer(%p)",
2232                                          private_layer, private_layer->waiting_buffer);
2233
2234                 if (private_display->commit_type == TDM_COMMIT_TYPE_OUTPUT) {
2235                         ret = _tdm_output_commit(private_layer->private_output, 0, NULL, NULL);
2236                         if (ret != TDM_ERROR_NONE)
2237                                 TDM_ERR("_tdm_output_commit() is fail");
2238                 } else if (private_display->commit_type == TDM_COMMIT_TYPE_LAYER) {
2239                         ret = _tdm_layer_commit(private_layer, NULL, NULL);
2240                         if (ret != TDM_ERROR_NONE)
2241                                 TDM_ERR("layer(%p) _tdm_layer_commit() is fail", private_layer);
2242                 } else {
2243                         TDM_NEVER_GET_HERE();
2244                 }
2245         }
2246
2247         _pthread_mutex_unlock(&private_display->lock);
2248 }
2249
2250 static void
2251 _tbm_layer_queue_destroy_cb(tbm_surface_queue_h surface_queue, void *data)
2252 {
2253         TDM_RETURN_IF_FAIL(data != NULL);
2254         tdm_layer *layer = data;
2255         LAYER_FUNC_ENTRY_VOID_RETURN();
2256         TDM_RETURN_IF_FAIL(ret == TDM_ERROR_NONE);
2257
2258         _pthread_mutex_lock(&private_display->lock);
2259
2260         if (private_layer->waiting_buffer) {
2261                 _pthread_mutex_unlock(&private_display->lock);
2262                 tdm_buffer_unref_backend(private_layer->waiting_buffer);
2263                 tbm_surface_queue_release(private_layer->buffer_queue,
2264                                                                   private_layer->waiting_buffer);
2265                 _pthread_mutex_lock(&private_display->lock);
2266         }
2267
2268         private_layer->buffer_queue = NULL;
2269
2270         _pthread_mutex_unlock(&private_display->lock);
2271 }
2272
2273 EXTERN tdm_error
2274 tdm_layer_set_buffer_queue(tdm_layer *layer, tbm_surface_queue_h buffer_queue)
2275 {
2276         tdm_func_layer *func_layer;
2277         LAYER_FUNC_ENTRY();
2278
2279         TDM_RETURN_VAL_IF_FAIL(buffer_queue != NULL, TDM_ERROR_INVALID_PARAMETER);
2280
2281         _pthread_mutex_lock(&private_display->lock);
2282
2283         func_layer = &private_display->func_layer;
2284
2285         if (private_layer->usable)
2286                 TDM_INFO("layer(%p) not usable", private_layer);
2287
2288         private_layer->usable = 0;
2289
2290         if (!func_layer->layer_set_buffer) {
2291                 _pthread_mutex_unlock(&private_display->lock);
2292                 TDM_ERR("not implemented!!");
2293                 return TDM_ERROR_NOT_IMPLEMENTED;
2294         }
2295
2296         if (buffer_queue == private_layer->buffer_queue) {
2297                 _pthread_mutex_unlock(&private_display->lock);
2298                 return TDM_ERROR_NONE;
2299         }
2300
2301         if (private_layer->waiting_buffer) {
2302                 _pthread_mutex_unlock(&private_display->lock);
2303                 tdm_buffer_unref_backend(private_layer->waiting_buffer);
2304                 tbm_surface_queue_release(private_layer->buffer_queue,
2305                                                                   private_layer->waiting_buffer);
2306                 private_layer->waiting_buffer = NULL;
2307                 _pthread_mutex_lock(&private_display->lock);
2308
2309                 if (tdm_debug_module & TDM_DEBUG_BUFFER)
2310                         TDM_INFO("layer(%p) waiting_buffer(%p)",
2311                                          private_layer, private_layer->waiting_buffer);
2312         }
2313
2314         private_layer->buffer_queue = buffer_queue;
2315         tbm_surface_queue_add_acquirable_cb(private_layer->buffer_queue,
2316                                                                                 _tbm_layer_queue_acquirable_cb,
2317                                                                                 layer);
2318         tbm_surface_queue_add_destroy_cb(private_layer->buffer_queue,
2319                                                                          _tbm_layer_queue_destroy_cb,
2320                                                                          layer);
2321         _pthread_mutex_unlock(&private_display->lock);
2322
2323         return ret;
2324 }
2325
2326 EXTERN tdm_error
2327 tdm_layer_unset_buffer_queue(tdm_layer *layer)
2328 {
2329         tdm_func_layer *func_layer;
2330         LAYER_FUNC_ENTRY();
2331
2332         _pthread_mutex_lock(&private_display->lock);
2333
2334         func_layer = &private_display->func_layer;
2335
2336         if (private_layer->waiting_buffer) {
2337                 _pthread_mutex_unlock(&private_display->lock);
2338                 tdm_buffer_unref_backend(private_layer->waiting_buffer);
2339                 tbm_surface_queue_release(private_layer->buffer_queue,
2340                                                                   private_layer->waiting_buffer);
2341                 private_layer->waiting_buffer = NULL;
2342                 _pthread_mutex_lock(&private_display->lock);
2343
2344                 if (tdm_debug_module & TDM_DEBUG_BUFFER)
2345                         TDM_INFO("layer(%p) waiting_buffer(%p)",
2346                                          private_layer, private_layer->waiting_buffer);
2347         }
2348
2349         if (private_layer->showing_buffer) {
2350                 _pthread_mutex_unlock(&private_display->lock);
2351                 tdm_buffer_unref_backend(private_layer->showing_buffer);
2352                 tbm_surface_queue_release(private_layer->buffer_queue,
2353                                                                   private_layer->showing_buffer);
2354                 _pthread_mutex_lock(&private_display->lock);
2355                 private_layer->showing_buffer = NULL;
2356
2357                 if (tdm_debug_module & TDM_DEBUG_BUFFER)
2358                         TDM_INFO("layer(%p) showing_buffer(%p)",
2359                                          private_layer, private_layer->showing_buffer);
2360         }
2361
2362         tbm_surface_queue_remove_acquirable_cb(private_layer->buffer_queue, _tbm_layer_queue_acquirable_cb, layer);
2363         tbm_surface_queue_remove_destroy_cb(private_layer->buffer_queue, _tbm_layer_queue_destroy_cb, layer);
2364         private_layer->buffer_queue = NULL;
2365         private_layer->usable = 1;
2366
2367         if (private_layer->usable)
2368                 TDM_INFO("layer(%p) now usable", private_layer);
2369
2370         if (!func_layer->layer_unset_buffer) {
2371                 _pthread_mutex_unlock(&private_display->lock);
2372                 TDM_ERR("not implemented!!");
2373                 return TDM_ERROR_NOT_IMPLEMENTED;
2374         }
2375
2376         ret = func_layer->layer_unset_buffer(private_layer->layer_backend);
2377
2378         _pthread_mutex_unlock(&private_display->lock);
2379
2380         return ret;
2381 }
2382
2383 EXTERN tdm_error
2384 tdm_layer_is_usable(tdm_layer *layer, unsigned int *usable)
2385 {
2386         LAYER_FUNC_ENTRY();
2387
2388         TDM_RETURN_VAL_IF_FAIL(usable != NULL, TDM_ERROR_INVALID_PARAMETER);
2389
2390         _pthread_mutex_lock(&private_display->lock);
2391
2392         *usable = private_layer->usable;
2393
2394         _pthread_mutex_unlock(&private_display->lock);
2395
2396         return ret;
2397 }
2398
2399 EXTERN tdm_error
2400 tdm_layer_set_video_pos(tdm_layer *layer, int zpos)
2401 {
2402         tdm_func_layer *func_layer;
2403         LAYER_FUNC_ENTRY();
2404
2405         _pthread_mutex_lock(&private_display->lock);
2406
2407         func_layer = &private_display->func_layer;
2408
2409         if (!(private_layer->caps.capabilities & TDM_LAYER_CAPABILITY_VIDEO)) {
2410                 TDM_ERR("layer(%p) is not video layer", private_layer);
2411                 _pthread_mutex_unlock(&private_display->lock);
2412                 return TDM_ERROR_INVALID_PARAMETER;
2413         }
2414
2415         if (!func_layer->layer_set_video_pos) {
2416                 _pthread_mutex_unlock(&private_display->lock);
2417                 TDM_ERR("not implemented!!");
2418                 return TDM_ERROR_NOT_IMPLEMENTED;
2419         }
2420
2421         ret = func_layer->layer_set_video_pos(private_layer->layer_backend, zpos);
2422
2423         _pthread_mutex_unlock(&private_display->lock);
2424
2425         return ret;
2426 }
2427
2428 EXTERN tdm_capture *
2429 tdm_layer_create_capture(tdm_layer *layer, tdm_error *error)
2430 {
2431         tdm_capture *capture = NULL;
2432
2433         LAYER_FUNC_ENTRY_ERROR();
2434
2435         _pthread_mutex_lock(&private_display->lock);
2436
2437         capture = (tdm_capture *)tdm_capture_create_layer_internal(private_layer, error);
2438
2439         _pthread_mutex_unlock(&private_display->lock);
2440
2441         return capture;
2442 }
2443
2444 EXTERN tdm_error
2445 tdm_layer_get_buffer_flags(tdm_layer *layer, unsigned int *flags)
2446 {
2447         tdm_func_layer *func_layer;
2448         LAYER_FUNC_ENTRY();
2449
2450         _pthread_mutex_lock(&private_display->lock);
2451
2452         func_layer = &private_display->func_layer;
2453
2454         if (!func_layer->layer_get_buffer_flags) {
2455                 _pthread_mutex_unlock(&private_display->lock);
2456                 TDM_ERR("not implemented!!");
2457                 return TDM_ERROR_NOT_IMPLEMENTED;
2458         }
2459
2460         ret = func_layer->layer_get_buffer_flags(private_layer->layer_backend, flags);
2461
2462         _pthread_mutex_unlock(&private_display->lock);
2463
2464         return ret;
2465 }