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