set index to output, layer objects
[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 EXTERN tdm_error
106 tdm_display_get_capabilities(tdm_display *dpy,
107                                                          tdm_display_capability *capabilities)
108 {
109         DISPLAY_FUNC_ENTRY();
110
111         TDM_RETURN_VAL_IF_FAIL(capabilities != NULL, TDM_ERROR_INVALID_PARAMETER);
112
113         _pthread_mutex_lock(&private_display->lock);
114
115         *capabilities = private_display->capabilities;
116
117         _pthread_mutex_unlock(&private_display->lock);
118
119         return ret;
120 }
121
122 EXTERN tdm_error
123 tdm_display_get_pp_capabilities(tdm_display *dpy,
124                                                                 tdm_pp_capability *capabilities)
125 {
126         DISPLAY_FUNC_ENTRY();
127
128         TDM_RETURN_VAL_IF_FAIL(capabilities != NULL, TDM_ERROR_INVALID_PARAMETER);
129
130         _pthread_mutex_lock(&private_display->lock);
131
132         if (!(private_display->capabilities & TDM_DISPLAY_CAPABILITY_PP)) {
133                 TDM_ERR("no pp capability");
134                 _pthread_mutex_unlock(&private_display->lock);
135                 return TDM_ERROR_NO_CAPABILITY;
136         }
137
138         *capabilities = private_display->caps_pp.capabilities;
139
140         _pthread_mutex_unlock(&private_display->lock);
141
142         return ret;
143 }
144
145 EXTERN tdm_error
146 tdm_display_get_pp_available_formats(tdm_display *dpy,
147                                                                          const tbm_format **formats, int *count)
148 {
149         DISPLAY_FUNC_ENTRY();
150
151         TDM_RETURN_VAL_IF_FAIL(formats != NULL, TDM_ERROR_INVALID_PARAMETER);
152         TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
153
154         _pthread_mutex_lock(&private_display->lock);
155
156         if (!(private_display->capabilities & TDM_DISPLAY_CAPABILITY_PP)) {
157                 TDM_ERR("no pp capability");
158                 _pthread_mutex_unlock(&private_display->lock);
159                 return TDM_ERROR_NO_CAPABILITY;
160         }
161
162         *formats = (const tbm_format *)private_display->caps_pp.formats;
163         *count = private_display->caps_pp.format_count;
164
165         _pthread_mutex_unlock(&private_display->lock);
166
167         return ret;
168 }
169
170 EXTERN tdm_error
171 tdm_display_get_pp_available_size(tdm_display *dpy, int *min_w, int *min_h,
172                                                                   int *max_w, int *max_h, int *preferred_align)
173 {
174         DISPLAY_FUNC_ENTRY();
175
176         _pthread_mutex_lock(&private_display->lock);
177
178         if (!(private_display->capabilities & TDM_DISPLAY_CAPABILITY_PP)) {
179                 TDM_ERR("no pp capability");
180                 _pthread_mutex_unlock(&private_display->lock);
181                 return TDM_ERROR_NO_CAPABILITY;
182         }
183
184         if (min_w)
185                 *min_w = private_display->caps_pp.min_w;
186         if (min_h)
187                 *min_h = private_display->caps_pp.min_h;
188         if (max_w)
189                 *max_w = private_display->caps_pp.max_w;
190         if (max_h)
191                 *max_h = private_display->caps_pp.max_h;
192         if (preferred_align)
193                 *preferred_align = private_display->caps_pp.preferred_align;
194
195         _pthread_mutex_unlock(&private_display->lock);
196
197         return ret;
198 }
199
200 EXTERN tdm_error
201 tdm_display_get_capture_capabilities(tdm_display *dpy,
202                                                                          tdm_capture_capability *capabilities)
203 {
204         DISPLAY_FUNC_ENTRY();
205
206         TDM_RETURN_VAL_IF_FAIL(capabilities != NULL, TDM_ERROR_INVALID_PARAMETER);
207
208         _pthread_mutex_lock(&private_display->lock);
209
210         if (!(private_display->capabilities & TDM_DISPLAY_CAPABILITY_CAPTURE)) {
211                 TDM_ERR("no capture capability");
212                 _pthread_mutex_unlock(&private_display->lock);
213                 return TDM_ERROR_NO_CAPABILITY;
214         }
215
216         *capabilities = private_display->caps_capture.capabilities;
217
218         _pthread_mutex_unlock(&private_display->lock);
219
220         return ret;
221 }
222
223 EXTERN tdm_error
224 tdm_display_get_catpure_available_formats(tdm_display *dpy,
225                 const tbm_format **formats, int *count)
226 {
227         DISPLAY_FUNC_ENTRY();
228
229         TDM_RETURN_VAL_IF_FAIL(formats != NULL, TDM_ERROR_INVALID_PARAMETER);
230         TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
231
232         _pthread_mutex_lock(&private_display->lock);
233
234         if (!(private_display->capabilities & TDM_DISPLAY_CAPABILITY_CAPTURE)) {
235                 TDM_ERR("no capture capability");
236                 _pthread_mutex_unlock(&private_display->lock);
237                 return TDM_ERROR_NO_CAPABILITY;
238         }
239
240         *formats = (const tbm_format *)private_display->caps_capture.formats;
241         *count = private_display->caps_capture.format_count;
242
243         _pthread_mutex_unlock(&private_display->lock);
244
245         return ret;
246 }
247
248 EXTERN tdm_error
249 tdm_display_get_output_count(tdm_display *dpy, int *count)
250 {
251         tdm_private_output *private_output = NULL;
252
253         DISPLAY_FUNC_ENTRY();
254
255         TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
256
257         _pthread_mutex_lock(&private_display->lock);
258
259         *count = 0;
260         LIST_FOR_EACH_ENTRY(private_output, &private_display->output_list, link)
261         (*count)++;
262
263         if (*count == 0) {
264                 _pthread_mutex_unlock(&private_display->lock);
265                 return TDM_ERROR_NONE;
266         }
267
268         _pthread_mutex_unlock(&private_display->lock);
269
270         return ret;
271 }
272
273
274 EXTERN tdm_output *
275 tdm_display_get_output(tdm_display *dpy, int index, tdm_error *error)
276 {
277         tdm_private_output *private_output = NULL;
278
279         DISPLAY_FUNC_ENTRY_ERROR();
280
281         _pthread_mutex_lock(&private_display->lock);
282
283         if (error)
284                 *error = TDM_ERROR_NONE;
285
286         LIST_FOR_EACH_ENTRY(private_output, &private_display->output_list, link) {
287                 if (private_output->index == index) {
288                         _pthread_mutex_unlock(&private_display->lock);
289                         return private_output;
290                 }
291         }
292
293         _pthread_mutex_unlock(&private_display->lock);
294
295         return NULL;
296 }
297
298 EXTERN tdm_error
299 tdm_display_get_fd(tdm_display *dpy, int *fd)
300 {
301         DISPLAY_FUNC_ENTRY();
302
303         TDM_RETURN_VAL_IF_FAIL(fd != NULL, TDM_ERROR_INVALID_PARAMETER);
304
305         _pthread_mutex_lock(&private_display->lock);
306
307         if (tdm_thread_is_running())
308                 *fd = tdm_thread_get_fd(private_display->private_loop);
309         else
310                 *fd = tdm_event_loop_get_fd(private_display);
311
312         _pthread_mutex_unlock(&private_display->lock);
313
314         return ret;
315 }
316
317 EXTERN tdm_error
318 tdm_display_handle_events(tdm_display *dpy)
319 {
320         struct pollfd fds;
321         int fd = -1;
322
323         DISPLAY_FUNC_ENTRY();
324
325         ret = tdm_display_get_fd(dpy, &fd);
326         TDM_RETURN_VAL_IF_FAIL(fd >= 0, ret);
327
328         fds.events = POLLIN;
329         fds.fd = fd;
330         fds.revents = 0;
331
332         if (tdm_debug_module & TDM_DEBUG_THREAD)
333                 TDM_INFO("fd(%d) polling in", fd);
334
335         while (poll(&fds, 1, -1) < 0) {
336                 if (errno == EINTR || errno == EAGAIN)  /* normal case */
337                         continue;
338                 else {
339                         TDM_ERR("poll failed: %m");
340                         return TDM_ERROR_OPERATION_FAILED;
341                 }
342         }
343
344         if (tdm_debug_module & TDM_DEBUG_THREAD)
345                 TDM_INFO("fd(%d) polling out", fd);
346
347         if (tdm_thread_is_running())
348                 ret = tdm_thread_handle_cb(private_display->private_loop);
349         else
350                 ret = tdm_event_loop_dispatch(private_display);
351
352         return ret;
353 }
354
355 EXTERN tdm_error
356 tdm_display_get_backend_info(tdm_display *dpy, const char **name,
357                                                          const char **vendor, int *major, int *minor)
358 {
359         tdm_backend_module *module_data;
360
361         DISPLAY_FUNC_ENTRY();
362
363         _pthread_mutex_lock(&private_display->lock);
364
365         module_data = private_display->module_data;
366
367         if (name)
368                 *name = module_data->name;
369         if (vendor)
370                 *vendor = module_data->vendor;
371         if (major)
372                 *major = TDM_BACKEND_GET_ABI_MAJOR(module_data->abi_version);
373         if (minor)
374                 *minor = TDM_BACKEND_GET_ABI_MINOR(module_data->abi_version);
375
376         _pthread_mutex_unlock(&private_display->lock);
377
378         return ret;
379 }
380
381 EXTERN tdm_pp *
382 tdm_display_create_pp(tdm_display *dpy, tdm_error *error)
383 {
384         tdm_pp *pp;
385
386         DISPLAY_FUNC_ENTRY_ERROR();
387
388         _pthread_mutex_lock(&private_display->lock);
389
390         pp = (tdm_pp *)tdm_pp_create_internal(private_display, error);
391
392         _pthread_mutex_unlock(&private_display->lock);
393
394         return pp;
395 }
396
397 EXTERN tdm_error
398 tdm_output_get_model_info(tdm_output *output, const char **maker,
399                                                   const char **model, const char **name)
400 {
401         OUTPUT_FUNC_ENTRY();
402
403         _pthread_mutex_lock(&private_display->lock);
404
405         if (maker)
406                 *maker = private_output->caps.maker;
407         if (model)
408                 *model = private_output->caps.model;
409         if (name)
410                 *name = private_output->caps.name;
411
412         _pthread_mutex_unlock(&private_display->lock);
413
414         return ret;
415 }
416
417 EXTERN tdm_error
418 tdm_output_get_conn_status(tdm_output *output, tdm_output_conn_status *status)
419 {
420         OUTPUT_FUNC_ENTRY();
421
422         TDM_RETURN_VAL_IF_FAIL(status != NULL, TDM_ERROR_INVALID_PARAMETER);
423
424         _pthread_mutex_lock(&private_display->lock);
425
426         *status = private_output->caps.status;
427
428         _pthread_mutex_unlock(&private_display->lock);
429
430         return ret;
431 }
432
433 static void
434 _tdm_output_update(tdm_output *output_backend, void *user_data)
435 {
436         tdm_private_display *private_display;
437         tdm_private_output *private_output = user_data;
438         tdm_error ret;
439
440         TDM_RETURN_IF_FAIL(private_output);
441
442         private_display = private_output->private_display;
443
444         ret = tdm_display_update_output(private_display, output_backend, private_output->pipe);
445         TDM_RETURN_IF_FAIL(ret == TDM_ERROR_NONE);
446 }
447
448 INTERN void
449 tdm_output_cb_status(tdm_output *output_backend, tdm_output_conn_status status,
450                                          void *user_data)
451 {
452         tdm_private_display *private_display;
453         tdm_private_output *private_output = user_data;
454         tdm_value value;
455
456         TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED());
457         TDM_RETURN_IF_FAIL(private_output);
458
459         private_display = private_output->private_display;
460
461         if (!tdm_thread_in_display_thread(syscall(SYS_gettid))) {
462                 tdm_thread_cb_output_status output_status;
463                 tdm_error ret;
464
465                 _tdm_output_update(output_backend, user_data);
466
467                 output_status.base.type = TDM_THREAD_CB_OUTPUT_STATUS;
468                 output_status.base.length = sizeof output_status;
469                 output_status.output_stamp = private_output->stamp;
470                 output_status.status = status;
471                 output_status.user_data = user_data;
472
473                 value.u32 = status;
474                 tdm_output_call_change_handler_internal(private_output,
475                                                                                                 &private_output->change_handler_list_sub,
476                                                                                                 TDM_OUTPUT_CHANGE_CONNECTION,
477                                                                                                 value, 0);
478
479                 ret = tdm_thread_send_cb(private_display->private_loop, &output_status.base);
480                 TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
481
482                 return;
483         }
484
485         if (!tdm_thread_is_running())
486                 _tdm_output_update(output_backend, user_data);
487
488         value.u32 = status;
489         tdm_output_call_change_handler_internal(private_output,
490                                                                                         &private_output->change_handler_list_main,
491                                                                                         TDM_OUTPUT_CHANGE_CONNECTION,
492                                                                                         value, 0);
493 }
494
495 EXTERN tdm_error
496 tdm_output_add_change_handler(tdm_output *output,
497                                                           tdm_output_change_handler func,
498                                                           void *user_data)
499 {
500         tdm_private_change_handler *change_handler;
501         OUTPUT_FUNC_ENTRY();
502
503         TDM_RETURN_VAL_IF_FAIL(func != NULL, TDM_ERROR_INVALID_PARAMETER);
504
505         pthread_mutex_lock(&private_display->lock);
506
507         change_handler = calloc(1, sizeof(tdm_private_change_handler));
508         if (!change_handler) {
509                 TDM_ERR("failed: alloc memory");
510                 _pthread_mutex_unlock(&private_display->lock);
511                 return TDM_ERROR_OUT_OF_MEMORY;
512         }
513
514         change_handler->private_output = private_output;
515         change_handler->func = func;
516         change_handler->user_data = user_data;
517         change_handler->owner_tid = syscall(SYS_gettid);
518
519         if (!tdm_thread_in_display_thread(change_handler->owner_tid))
520                 LIST_ADD(&change_handler->link, &private_output->change_handler_list_sub);
521         else
522                 LIST_ADD(&change_handler->link, &private_output->change_handler_list_main);
523
524         _pthread_mutex_unlock(&private_display->lock);
525
526         return ret;
527 }
528
529 EXTERN void
530 tdm_output_remove_change_handler(tdm_output *output,
531                                                                  tdm_output_change_handler func,
532                                                                  void *user_data)
533 {
534         tdm_private_display *private_display;
535         tdm_private_output *private_output;
536         tdm_private_change_handler *h = NULL, *hh = NULL;
537
538         TDM_RETURN_IF_FAIL(output != NULL);
539         TDM_RETURN_IF_FAIL(func != NULL);
540
541         private_output = (tdm_private_output*)output;
542         private_display = private_output->private_display;
543
544         _pthread_mutex_lock(&private_display->lock);
545
546         LIST_FOR_EACH_ENTRY_SAFE(h, hh, &private_output->change_handler_list_main, link) {
547                 if (h->func != func || h->user_data != user_data)
548                         continue;
549
550                 LIST_DEL(&h->link);
551                 free(h);
552
553                 _pthread_mutex_unlock(&private_display->lock);
554
555                 return;
556         }
557
558         LIST_FOR_EACH_ENTRY_SAFE(h, hh, &private_output->change_handler_list_sub, link) {
559                 if (h->func != func || h->user_data != user_data)
560                         continue;
561
562                 LIST_DEL(&h->link);
563                 free(h);
564
565                 _pthread_mutex_unlock(&private_display->lock);
566
567                 return;
568         }
569
570         _pthread_mutex_unlock(&private_display->lock);
571 }
572
573 EXTERN tdm_error
574 tdm_output_get_output_type(tdm_output *output, tdm_output_type *type)
575 {
576         OUTPUT_FUNC_ENTRY();
577
578         TDM_RETURN_VAL_IF_FAIL(type != NULL, TDM_ERROR_INVALID_PARAMETER);
579
580         _pthread_mutex_lock(&private_display->lock);
581
582         *type = private_output->caps.type;
583
584         _pthread_mutex_unlock(&private_display->lock);
585
586         return ret;
587 }
588
589 EXTERN tdm_error
590 tdm_output_get_layer_count(tdm_output *output, int *count)
591 {
592         tdm_private_layer *private_layer = NULL;
593
594         OUTPUT_FUNC_ENTRY();
595
596         TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
597
598         _pthread_mutex_lock(&private_display->lock);
599
600         *count = 0;
601         LIST_FOR_EACH_ENTRY(private_layer, &private_output->layer_list, link)
602         (*count)++;
603         if (*count == 0) {
604                 _pthread_mutex_unlock(&private_display->lock);
605                 return TDM_ERROR_NONE;
606         }
607
608         _pthread_mutex_unlock(&private_display->lock);
609
610         return ret;
611 }
612
613
614 EXTERN tdm_layer *
615 tdm_output_get_layer(tdm_output *output, int index, tdm_error *error)
616 {
617         tdm_private_layer *private_layer = NULL;
618
619         OUTPUT_FUNC_ENTRY_ERROR();
620
621         _pthread_mutex_lock(&private_display->lock);
622
623         if (error)
624                 *error = TDM_ERROR_NONE;
625
626         LIST_FOR_EACH_ENTRY(private_layer, &private_output->layer_list, link) {
627                 if (private_layer->index == index) {
628                         _pthread_mutex_unlock(&private_display->lock);
629                         return private_layer;
630                 }
631         }
632
633         _pthread_mutex_unlock(&private_display->lock);
634
635         return NULL;
636 }
637
638 EXTERN tdm_error
639 tdm_output_get_available_properties(tdm_output *output, const tdm_prop **props,
640                                                                         int *count)
641 {
642         OUTPUT_FUNC_ENTRY();
643
644         TDM_RETURN_VAL_IF_FAIL(props != NULL, TDM_ERROR_INVALID_PARAMETER);
645         TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
646
647         _pthread_mutex_lock(&private_display->lock);
648
649         *props = (const tdm_prop *)private_output->caps.props;
650         *count = private_output->caps.prop_count;
651
652         _pthread_mutex_unlock(&private_display->lock);
653
654         return ret;
655 }
656
657 EXTERN tdm_error
658 tdm_output_get_available_modes(tdm_output *output,
659                                                            const tdm_output_mode **modes, int *count)
660 {
661         OUTPUT_FUNC_ENTRY();
662
663         TDM_RETURN_VAL_IF_FAIL(modes != NULL, TDM_ERROR_INVALID_PARAMETER);
664         TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
665
666         _pthread_mutex_lock(&private_display->lock);
667
668         *modes = (const tdm_output_mode *)private_output->caps.modes;
669         *count = private_output->caps.mode_count;
670
671         _pthread_mutex_unlock(&private_display->lock);
672
673         return ret;
674 }
675
676 EXTERN tdm_error
677 tdm_output_get_available_size(tdm_output *output, int *min_w, int *min_h,
678                                                           int *max_w, int *max_h, int *preferred_align)
679 {
680         OUTPUT_FUNC_ENTRY();
681
682         _pthread_mutex_lock(&private_display->lock);
683
684         if (min_w)
685                 *min_w = private_output->caps.min_w;
686         if (min_h)
687                 *min_h = private_output->caps.min_h;
688         if (max_w)
689                 *max_w = private_output->caps.max_w;
690         if (max_h)
691                 *max_h = private_output->caps.max_h;
692         if (preferred_align)
693                 *preferred_align = private_output->caps.preferred_align;
694
695         _pthread_mutex_unlock(&private_display->lock);
696
697         return ret;
698 }
699
700 EXTERN tdm_error
701 tdm_output_get_physical_size(tdm_output *output, unsigned int *mmWidth,
702                                                          unsigned int *mmHeight)
703 {
704         OUTPUT_FUNC_ENTRY();
705
706         _pthread_mutex_lock(&private_display->lock);
707
708         if (mmWidth)
709                 *mmWidth = private_output->caps.mmWidth;
710         if (mmHeight)
711                 *mmHeight = private_output->caps.mmHeight;
712
713         _pthread_mutex_unlock(&private_display->lock);
714
715         return ret;
716 }
717
718 EXTERN tdm_error
719 tdm_output_get_subpixel(tdm_output *output, unsigned int *subpixel)
720 {
721         OUTPUT_FUNC_ENTRY();
722         TDM_RETURN_VAL_IF_FAIL(subpixel != NULL, TDM_ERROR_INVALID_PARAMETER);
723
724         _pthread_mutex_lock(&private_display->lock);
725
726         *subpixel = private_output->caps.subpixel;
727
728         _pthread_mutex_unlock(&private_display->lock);
729
730         return ret;
731 }
732
733 EXTERN tdm_error
734 tdm_output_get_pipe(tdm_output *output, unsigned int *pipe)
735 {
736         OUTPUT_FUNC_ENTRY();
737         TDM_RETURN_VAL_IF_FAIL(pipe != NULL, TDM_ERROR_INVALID_PARAMETER);
738
739         _pthread_mutex_lock(&private_display->lock);
740
741         *pipe = private_output->pipe;
742
743         _pthread_mutex_unlock(&private_display->lock);
744
745         return ret;
746 }
747
748
749 EXTERN tdm_error
750 tdm_output_set_property(tdm_output *output, unsigned int id, tdm_value value)
751 {
752         tdm_func_output *func_output;
753         OUTPUT_FUNC_ENTRY();
754
755         _pthread_mutex_lock(&private_display->lock);
756
757         func_output = &private_display->func_output;
758
759         if (!func_output->output_set_property) {
760                 _pthread_mutex_unlock(&private_display->lock);
761                 TDM_ERR("not implemented!!");
762                 return TDM_ERROR_NOT_IMPLEMENTED;
763         }
764
765         ret = func_output->output_set_property(private_output->output_backend, id,
766                                                                                    value);
767
768         _pthread_mutex_unlock(&private_display->lock);
769
770         return ret;
771 }
772
773 EXTERN tdm_error
774 tdm_output_get_property(tdm_output *output, unsigned int id, tdm_value *value)
775 {
776         tdm_func_output *func_output;
777         OUTPUT_FUNC_ENTRY();
778
779         TDM_RETURN_VAL_IF_FAIL(value != NULL, TDM_ERROR_INVALID_PARAMETER);
780
781         _pthread_mutex_lock(&private_display->lock);
782
783         func_output = &private_display->func_output;
784
785         if (!func_output->output_get_property) {
786                 _pthread_mutex_unlock(&private_display->lock);
787                 TDM_ERR("not implemented!!");
788                 return TDM_ERROR_NOT_IMPLEMENTED;
789         }
790
791         ret = func_output->output_get_property(private_output->output_backend, id,
792                                                                                    value);
793
794         _pthread_mutex_unlock(&private_display->lock);
795
796         return ret;
797 }
798
799 INTERN void
800 tdm_output_cb_vblank(tdm_output *output_backend, unsigned int sequence,
801                                          unsigned int tv_sec, unsigned int tv_usec, void *user_data)
802 {
803         tdm_private_vblank_handler *vblank_handler = user_data;
804         tdm_private_display *private_display;
805
806         TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED());
807         TDM_RETURN_IF_FAIL(vblank_handler);
808
809         private_display = vblank_handler->private_output->private_display;
810
811         if (vblank_handler->owner_tid != syscall(SYS_gettid)) {
812                 tdm_thread_cb_output_vblank output_vblank;
813                 tdm_error ret;
814
815                 output_vblank.base.type = TDM_THREAD_CB_OUTPUT_VBLANK;
816                 output_vblank.base.length = sizeof output_vblank;
817                 output_vblank.output_stamp = vblank_handler->private_output->stamp;
818                 output_vblank.sequence = sequence;
819                 output_vblank.tv_sec = tv_sec;
820                 output_vblank.tv_usec = tv_usec;
821                 output_vblank.user_data = user_data;
822
823                 ret = tdm_thread_send_cb(private_display->private_loop, &output_vblank.base);
824                 TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
825
826                 return;
827         }
828
829         if (vblank_handler->owner_tid != syscall(SYS_gettid))
830                 TDM_NEVER_GET_HERE();
831
832         if (vblank_handler->func) {
833                 _pthread_mutex_unlock(&private_display->lock);
834                 vblank_handler->func(vblank_handler->private_output, sequence,
835                                                          tv_sec, tv_usec, vblank_handler->user_data);
836                 _pthread_mutex_lock(&private_display->lock);
837         }
838
839         LIST_DEL(&vblank_handler->link);
840         free(vblank_handler);
841 }
842
843 INTERN void
844 tdm_output_cb_commit(tdm_output *output_backend, unsigned int sequence,
845                                          unsigned int tv_sec, unsigned int tv_usec, void *user_data)
846 {
847         tdm_private_commit_handler *commit_handler = user_data;
848         tdm_private_display *private_display;
849         tdm_private_output *private_output;
850         tdm_private_layer *private_layer = NULL;
851
852         TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED());
853         TDM_RETURN_IF_FAIL(commit_handler);
854
855         private_output = commit_handler->private_output;
856         private_display = private_output->private_display;
857
858         if (commit_handler->owner_tid != syscall(SYS_gettid)) {
859                 tdm_thread_cb_output_commit output_commit;
860                 tdm_error ret;
861
862                 output_commit.base.type = TDM_THREAD_CB_OUTPUT_COMMIT;
863                 output_commit.base.length = sizeof output_commit;
864                 output_commit.output_stamp = private_output->stamp;
865                 output_commit.sequence = sequence;
866                 output_commit.tv_sec = tv_sec;
867                 output_commit.tv_usec = tv_usec;
868                 output_commit.user_data = user_data;
869
870                 ret = tdm_thread_send_cb(private_display->private_loop, &output_commit.base);
871                 TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
872
873                 return;
874         }
875
876         LIST_FOR_EACH_ENTRY(private_layer, &private_output->layer_list, link) {
877                 if (!private_layer->waiting_buffer)
878                         continue;
879
880                 if (private_layer->showing_buffer) {
881                         _pthread_mutex_unlock(&private_display->lock);
882                         tdm_buffer_unref_backend(private_layer->showing_buffer);
883                         _pthread_mutex_lock(&private_display->lock);
884
885                         if (private_layer->buffer_queue) {
886                                 _pthread_mutex_unlock(&private_display->lock);
887                                 tbm_surface_queue_release(private_layer->buffer_queue,
888                                                                                   private_layer->showing_buffer);
889                                 _pthread_mutex_lock(&private_display->lock);
890                         }
891                 }
892
893                 private_layer->showing_buffer = private_layer->waiting_buffer;
894                 private_layer->waiting_buffer = NULL;
895
896                 if (tdm_debug_module & TDM_DEBUG_BUFFER)
897                         TDM_INFO("layer(%p) waiting_buffer(%p) showing_buffer(%p)",
898                                          private_layer, private_layer->waiting_buffer,
899                                          private_layer->showing_buffer);
900         }
901
902         if (commit_handler->func) {
903                 _pthread_mutex_unlock(&private_display->lock);
904                 commit_handler->func(private_output, sequence,
905                                                          tv_sec, tv_usec, commit_handler->user_data);
906                 _pthread_mutex_lock(&private_display->lock);
907         }
908
909         LIST_DEL(&commit_handler->link);
910         free(commit_handler);
911 }
912
913 EXTERN tdm_error
914 tdm_output_wait_vblank(tdm_output *output, int interval, int sync,
915                                            tdm_output_vblank_handler func, void *user_data)
916 {
917         tdm_func_output *func_output;
918         tdm_private_vblank_handler *vblank_handler;
919         OUTPUT_FUNC_ENTRY();
920
921         _pthread_mutex_lock(&private_display->lock);
922
923         if (private_output->current_dpms_value > TDM_OUTPUT_DPMS_ON) {
924                 TDM_WRN("output(%d) dpms: %s", private_output->pipe,
925                                 tdm_dpms_str(private_output->current_dpms_value));
926                 _pthread_mutex_unlock(&private_display->lock);
927                 return TDM_ERROR_DPMS_OFF;
928         }
929
930         func_output = &private_display->func_output;
931
932         if (!func_output->output_wait_vblank) {
933                 _pthread_mutex_unlock(&private_display->lock);
934                 TDM_ERR("not implemented!!");
935                 return TDM_ERROR_NOT_IMPLEMENTED;
936         }
937
938         vblank_handler = calloc(1, sizeof(tdm_private_vblank_handler));
939         if (!vblank_handler) {
940                 TDM_ERR("failed: alloc memory");
941                 _pthread_mutex_unlock(&private_display->lock);
942                 return TDM_ERROR_OUT_OF_MEMORY;
943         }
944
945         LIST_ADD(&vblank_handler->link, &private_output->vblank_handler_list);
946         vblank_handler->private_output = private_output;
947         vblank_handler->func = func;
948         vblank_handler->user_data = user_data;
949         vblank_handler->owner_tid = syscall(SYS_gettid);
950
951         ret = func_output->output_wait_vblank(private_output->output_backend, interval,
952                                                                                   sync, vblank_handler);
953         if (ret != TDM_ERROR_NONE) {
954                 _pthread_mutex_unlock(&private_display->lock);
955                 return ret;
956         }
957
958         if (!private_output->regist_vblank_cb) {
959                 private_output->regist_vblank_cb = 1;
960                 ret = func_output->output_set_vblank_handler(private_output->output_backend,
961                                 tdm_output_cb_vblank);
962         }
963
964         _pthread_mutex_unlock(&private_display->lock);
965
966         return ret;
967 }
968
969 static tdm_error
970 _tdm_output_commit(tdm_output *output, int sync, tdm_output_commit_handler func,
971                                    void *user_data)
972 {
973         tdm_func_output *func_output;
974         tdm_private_commit_handler *commit_handler;
975         OUTPUT_FUNC_ENTRY();
976
977         func_output = &private_display->func_output;
978
979         if (!func_output->output_commit) {
980                 TDM_ERR("not implemented!!");
981                 return TDM_ERROR_NOT_IMPLEMENTED;
982         }
983
984         commit_handler = calloc(1, sizeof(tdm_private_commit_handler));
985         if (!commit_handler) {
986                 TDM_ERR("failed: alloc memory");
987                 return TDM_ERROR_OUT_OF_MEMORY;
988         }
989
990         LIST_ADD(&commit_handler->link, &private_output->commit_handler_list);
991         commit_handler->private_output = private_output;
992         commit_handler->func = func;
993         commit_handler->user_data = user_data;
994         commit_handler->owner_tid = syscall(SYS_gettid);
995
996         if (!private_output->regist_commit_cb) {
997                 private_output->regist_commit_cb = 1;
998                 ret = func_output->output_set_commit_handler(private_output->output_backend,
999                                 tdm_output_cb_commit);
1000         }
1001
1002         ret = func_output->output_commit(private_output->output_backend, sync,
1003                                                                          commit_handler);
1004         TDM_RETURN_VAL_IF_FAIL(ret == TDM_ERROR_NONE, ret);
1005
1006         return ret;
1007 }
1008
1009 EXTERN tdm_error
1010 tdm_output_commit(tdm_output *output, int sync, tdm_output_commit_handler func,
1011                                   void *user_data)
1012 {
1013         OUTPUT_FUNC_ENTRY();
1014
1015         _pthread_mutex_lock(&private_display->lock);
1016
1017         if (private_output->current_dpms_value > TDM_OUTPUT_DPMS_ON) {
1018                 TDM_ERR("output(%d) dpms: %s", private_output->pipe,
1019                                 tdm_dpms_str(private_output->current_dpms_value));
1020                 _pthread_mutex_unlock(&private_display->lock);
1021                 return TDM_ERROR_DPMS_OFF;
1022         }
1023
1024         ret = _tdm_output_commit(output, sync, func, user_data);
1025
1026         _pthread_mutex_unlock(&private_display->lock);
1027
1028         return ret;
1029 }
1030
1031 EXTERN tdm_error
1032 tdm_output_set_mode(tdm_output *output, const tdm_output_mode *mode)
1033 {
1034         tdm_func_output *func_output;
1035         OUTPUT_FUNC_ENTRY();
1036
1037         TDM_RETURN_VAL_IF_FAIL(mode != NULL, TDM_ERROR_INVALID_PARAMETER);
1038
1039         _pthread_mutex_lock(&private_display->lock);
1040
1041         func_output = &private_display->func_output;
1042
1043         if (!func_output->output_set_mode) {
1044                 _pthread_mutex_unlock(&private_display->lock);
1045                 TDM_ERR("not implemented!!");
1046                 return TDM_ERROR_NOT_IMPLEMENTED;
1047         }
1048
1049         ret = func_output->output_set_mode(private_output->output_backend, mode);
1050
1051         _pthread_mutex_unlock(&private_display->lock);
1052
1053         return ret;
1054 }
1055
1056 EXTERN tdm_error
1057 tdm_output_get_mode(tdm_output *output, const tdm_output_mode **mode)
1058 {
1059         tdm_func_output *func_output;
1060         OUTPUT_FUNC_ENTRY();
1061
1062         TDM_RETURN_VAL_IF_FAIL(mode != NULL, TDM_ERROR_INVALID_PARAMETER);
1063
1064         _pthread_mutex_lock(&private_display->lock);
1065
1066         func_output = &private_display->func_output;
1067
1068         if (!func_output->output_get_mode) {
1069                 _pthread_mutex_unlock(&private_display->lock);
1070                 TDM_ERR("not implemented!!");
1071                 return TDM_ERROR_NOT_IMPLEMENTED;
1072         }
1073
1074         ret = func_output->output_get_mode(private_output->output_backend, mode);
1075
1076         _pthread_mutex_unlock(&private_display->lock);
1077
1078         return ret;
1079 }
1080
1081 static tdm_error
1082 _tdm_output_dpms_changed_timeout(void *user_data)
1083 {
1084         tdm_private_output *private_output = user_data;
1085         tdm_value value;
1086
1087         value.u32 = private_output->current_dpms_value;
1088         tdm_output_call_change_handler_internal(private_output,
1089                                                                                         &private_output->change_handler_list_sub,
1090                                                                                         TDM_OUTPUT_CHANGE_DPMS,
1091                                                                                         value, 0);
1092
1093         return TDM_ERROR_NONE;
1094 }
1095
1096 EXTERN tdm_error
1097 tdm_output_set_dpms(tdm_output *output, tdm_output_dpms dpms_value)
1098 {
1099         tdm_func_output *func_output;
1100         OUTPUT_FUNC_ENTRY();
1101
1102         if (dpms_value > TDM_OUTPUT_DPMS_OFF)
1103                 dpms_value = TDM_OUTPUT_DPMS_OFF;
1104
1105         _pthread_mutex_lock(&private_display->lock);
1106
1107         if (private_output->current_dpms_value == dpms_value) {
1108                 _pthread_mutex_unlock(&private_display->lock);
1109                 return TDM_ERROR_NONE;
1110         }
1111
1112         if (!private_output->dpms_changed_timer) {
1113                 private_output->dpms_changed_timer =
1114                         tdm_event_loop_add_timer_handler(private_output->private_display,
1115                                 _tdm_output_dpms_changed_timeout, private_output, NULL);
1116                 if (!private_output->dpms_changed_timer) {
1117                         TDM_ERR("can't create dpms timer!!");
1118                         _pthread_mutex_unlock(&private_display->lock);
1119                         return TDM_ERROR_OUT_OF_MEMORY;
1120                 }
1121         }
1122
1123         func_output = &private_display->func_output;
1124
1125         if (!func_output->output_set_dpms) {
1126                 _pthread_mutex_unlock(&private_display->lock);
1127                 private_output->current_dpms_value = dpms_value;
1128                 TDM_WRN("not implemented!!");
1129                 return TDM_ERROR_NONE;
1130         }
1131
1132         ret = func_output->output_set_dpms(private_output->output_backend, dpms_value);
1133         if (ret == TDM_ERROR_NONE) {
1134                 tdm_value value;
1135
1136                 private_output->current_dpms_value = dpms_value;
1137
1138                 value.u32 = dpms_value;
1139                 tdm_output_call_change_handler_internal(private_output,
1140                                                                                                 &private_output->change_handler_list_main,
1141                                                                                                 TDM_OUTPUT_CHANGE_DPMS,
1142                                                                                                 value, 0);
1143
1144                 if (!LIST_IS_EMPTY(&private_output->change_handler_list_sub)) {
1145                         ret = tdm_event_loop_source_timer_update(private_output->dpms_changed_timer, 1);
1146                         if (ret != TDM_ERROR_NONE)
1147                                 TDM_NEVER_GET_HERE();
1148                 }
1149         }
1150
1151         _pthread_mutex_unlock(&private_display->lock);
1152
1153         return ret;
1154 }
1155
1156 EXTERN tdm_error
1157 tdm_output_get_dpms(tdm_output *output, tdm_output_dpms *dpms_value)
1158 {
1159         tdm_func_output *func_output;
1160         OUTPUT_FUNC_ENTRY();
1161
1162         TDM_RETURN_VAL_IF_FAIL(dpms_value != NULL, TDM_ERROR_INVALID_PARAMETER);
1163
1164         _pthread_mutex_lock(&private_display->lock);
1165
1166         func_output = &private_display->func_output;
1167
1168         if (!func_output->output_get_dpms) {
1169                 *dpms_value = private_output->current_dpms_value;
1170                 _pthread_mutex_unlock(&private_display->lock);
1171                 TDM_WRN("not implemented!!");
1172                 return TDM_ERROR_NONE;
1173         }
1174
1175         ret = func_output->output_get_dpms(private_output->output_backend, dpms_value);
1176
1177         _pthread_mutex_unlock(&private_display->lock);
1178
1179         return ret;
1180 }
1181
1182 EXTERN tdm_capture *
1183 tdm_output_create_capture(tdm_output *output, tdm_error *error)
1184 {
1185         tdm_capture *capture = NULL;
1186
1187         OUTPUT_FUNC_ENTRY_ERROR();
1188
1189         _pthread_mutex_lock(&private_display->lock);
1190
1191         capture = (tdm_capture *)tdm_capture_create_output_internal(private_output, error);
1192
1193         _pthread_mutex_unlock(&private_display->lock);
1194
1195         return capture;
1196 }
1197
1198 INTERN void
1199 tdm_output_call_change_handler_internal(tdm_private_output *private_output,
1200                                                                                 struct list_head *change_handler_list,
1201                                                                                 tdm_output_change_type type,
1202                                                                                 tdm_value value,
1203                                                                                 int no_check_thread_id)
1204 {
1205         tdm_private_display *private_display;
1206         tdm_private_change_handler *change_handler = NULL;
1207
1208         TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED());
1209         TDM_RETURN_IF_FAIL(private_output);
1210
1211         private_display = private_output->private_display;
1212         if (!tdm_thread_in_display_thread(syscall(SYS_gettid))) {
1213                 if (type & TDM_OUTPUT_CHANGE_CONNECTION)
1214                         TDM_INFO("output(%d) changed: %s (%d)",
1215                                          private_output->pipe, tdm_status_str(value.u32), value.u32);
1216                 if (type & TDM_OUTPUT_CHANGE_DPMS)
1217                         TDM_INFO("output(%d) changed: dpms %s (%d)",
1218                                          private_output->pipe, tdm_dpms_str(value.u32), value.u32);
1219         }
1220
1221         if (LIST_IS_EMPTY(change_handler_list))
1222                 return;
1223
1224         LIST_FOR_EACH_ENTRY(change_handler, change_handler_list, link) {
1225                 if (!no_check_thread_id && change_handler->owner_tid != syscall(SYS_gettid))
1226                         TDM_NEVER_GET_HERE();
1227
1228                 _pthread_mutex_unlock(&private_display->lock);
1229                 change_handler->func(private_output, type,
1230                                                          value, change_handler->user_data);
1231                 _pthread_mutex_lock(&private_display->lock);
1232         }
1233 }
1234
1235 EXTERN tdm_error
1236 tdm_layer_get_capabilities(tdm_layer *layer, tdm_layer_capability *capabilities)
1237 {
1238         LAYER_FUNC_ENTRY();
1239
1240         TDM_RETURN_VAL_IF_FAIL(capabilities != NULL, TDM_ERROR_INVALID_PARAMETER);
1241
1242         _pthread_mutex_lock(&private_display->lock);
1243
1244         *capabilities = private_layer->caps.capabilities;
1245
1246         _pthread_mutex_unlock(&private_display->lock);
1247
1248         return ret;
1249 }
1250
1251 EXTERN tdm_error
1252 tdm_layer_get_available_formats(tdm_layer *layer, const tbm_format **formats, int *count)
1253 {
1254         LAYER_FUNC_ENTRY();
1255
1256         TDM_RETURN_VAL_IF_FAIL(formats != NULL, TDM_ERROR_INVALID_PARAMETER);
1257         TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
1258
1259         _pthread_mutex_lock(&private_display->lock);
1260
1261         *formats = (const tbm_format *)private_layer->caps.formats;
1262         *count = private_layer->caps.format_count;
1263
1264         _pthread_mutex_unlock(&private_display->lock);
1265
1266         return ret;
1267 }
1268
1269 EXTERN tdm_error
1270 tdm_layer_get_available_properties(tdm_layer *layer, const tdm_prop **props, int *count)
1271 {
1272         LAYER_FUNC_ENTRY();
1273
1274         TDM_RETURN_VAL_IF_FAIL(props != NULL, TDM_ERROR_INVALID_PARAMETER);
1275         TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
1276
1277         _pthread_mutex_lock(&private_display->lock);
1278
1279         *props = (const tdm_prop *)private_layer->caps.props;
1280         *count = private_layer->caps.prop_count;
1281
1282         _pthread_mutex_unlock(&private_display->lock);
1283
1284         return ret;
1285 }
1286
1287 EXTERN tdm_error
1288 tdm_layer_get_zpos(tdm_layer *layer, int *zpos)
1289 {
1290         LAYER_FUNC_ENTRY();
1291
1292         TDM_RETURN_VAL_IF_FAIL(zpos != NULL, TDM_ERROR_INVALID_PARAMETER);
1293
1294         _pthread_mutex_lock(&private_display->lock);
1295
1296         *zpos = private_layer->caps.zpos;
1297
1298         _pthread_mutex_unlock(&private_display->lock);
1299
1300         return ret;
1301 }
1302
1303 EXTERN tdm_error
1304 tdm_layer_set_property(tdm_layer *layer, unsigned int id, tdm_value value)
1305 {
1306         tdm_func_layer *func_layer;
1307         LAYER_FUNC_ENTRY();
1308
1309         _pthread_mutex_lock(&private_display->lock);
1310
1311         func_layer = &private_display->func_layer;
1312
1313         if (!func_layer->layer_set_property) {
1314                 _pthread_mutex_unlock(&private_display->lock);
1315                 TDM_ERR("not implemented!!");
1316                 return TDM_ERROR_NOT_IMPLEMENTED;
1317         }
1318
1319         ret = func_layer->layer_set_property(private_layer->layer_backend, id, value);
1320
1321         _pthread_mutex_unlock(&private_display->lock);
1322
1323         return ret;
1324 }
1325
1326 EXTERN tdm_error
1327 tdm_layer_get_property(tdm_layer *layer, unsigned int id, tdm_value *value)
1328 {
1329         tdm_func_layer *func_layer;
1330         LAYER_FUNC_ENTRY();
1331
1332         TDM_RETURN_VAL_IF_FAIL(value != NULL, TDM_ERROR_INVALID_PARAMETER);
1333
1334         _pthread_mutex_lock(&private_display->lock);
1335
1336         func_layer = &private_display->func_layer;
1337
1338         if (!func_layer->layer_get_property) {
1339                 _pthread_mutex_unlock(&private_display->lock);
1340                 TDM_ERR("not implemented!!");
1341                 return TDM_ERROR_NOT_IMPLEMENTED;
1342         }
1343
1344         ret = func_layer->layer_get_property(private_layer->layer_backend, id, value);
1345
1346         _pthread_mutex_unlock(&private_display->lock);
1347
1348         return ret;
1349 }
1350
1351 EXTERN tdm_error
1352 tdm_layer_set_info(tdm_layer *layer, tdm_info_layer *info)
1353 {
1354         tdm_func_layer *func_layer;
1355         char fmtstr[128];
1356
1357         LAYER_FUNC_ENTRY();
1358
1359         TDM_RETURN_VAL_IF_FAIL(info != NULL, TDM_ERROR_INVALID_PARAMETER);
1360
1361         _pthread_mutex_lock(&private_display->lock);
1362
1363         func_layer = &private_display->func_layer;
1364
1365         if (private_layer->usable)
1366                 TDM_INFO("layer(%p) not usable", private_layer);
1367
1368         private_layer->usable = 0;
1369
1370         if (!func_layer->layer_set_info) {
1371                 _pthread_mutex_unlock(&private_display->lock);
1372                 TDM_ERR("not implemented!!");
1373                 return TDM_ERROR_NOT_IMPLEMENTED;
1374         }
1375
1376         if (info->src_config.format)
1377                 snprintf(fmtstr, 128, "%c%c%c%c", FOURCC_STR(info->src_config.format));
1378         else
1379                 snprintf(fmtstr, 128, "NONE");
1380
1381         TDM_INFO("layer(%p) info: src(%dx%d %d,%d %dx%d %s) dst(%d,%d %dx%d) trans(%d)",
1382                          private_layer, info->src_config.size.h, info->src_config.size.v,
1383                          info->src_config.pos.x, info->src_config.pos.y,
1384                          info->src_config.pos.w, info->src_config.pos.h,
1385                          fmtstr,
1386                          info->dst_pos.x, info->dst_pos.y,
1387                          info->dst_pos.w, info->dst_pos.h,
1388                          info->transform);
1389
1390         ret = func_layer->layer_set_info(private_layer->layer_backend, info);
1391         TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
1392
1393         _pthread_mutex_unlock(&private_display->lock);
1394
1395         return ret;
1396 }
1397
1398 EXTERN tdm_error
1399 tdm_layer_get_info(tdm_layer *layer, tdm_info_layer *info)
1400 {
1401         tdm_func_layer *func_layer;
1402         LAYER_FUNC_ENTRY();
1403
1404         TDM_RETURN_VAL_IF_FAIL(info != NULL, TDM_ERROR_INVALID_PARAMETER);
1405
1406         _pthread_mutex_lock(&private_display->lock);
1407
1408         func_layer = &private_display->func_layer;
1409
1410         if (!func_layer->layer_get_info) {
1411                 _pthread_mutex_unlock(&private_display->lock);
1412                 TDM_ERR("not implemented!!");
1413                 return TDM_ERROR_NOT_IMPLEMENTED;
1414         }
1415
1416         ret = func_layer->layer_get_info(private_layer->layer_backend, info);
1417
1418         _pthread_mutex_unlock(&private_display->lock);
1419
1420         return ret;
1421 }
1422
1423 static void
1424 _tdm_layer_dump_buffer(tdm_layer *layer, tbm_surface_h buffer)
1425 {
1426         tdm_private_layer *private_layer = (tdm_private_layer*)layer;
1427         tdm_private_output *private_output = private_layer->private_output;
1428         unsigned int pipe;
1429         int zpos;
1430         char fname[PATH_MAX];
1431
1432         pipe = private_output->pipe;
1433         zpos = private_layer->caps.zpos;
1434
1435         snprintf(fname, sizeof(fname), "tdm_%d_lyr_%d", pipe, zpos);
1436
1437         tbm_surface_internal_dump_buffer(buffer, fname);
1438         TDM_DBG("%s dump excute", fname);
1439
1440         return;
1441 }
1442
1443 EXTERN tdm_error
1444 tdm_layer_set_buffer(tdm_layer *layer, tbm_surface_h buffer)
1445 {
1446         tdm_func_layer *func_layer;
1447
1448         LAYER_FUNC_ENTRY();
1449
1450         TDM_RETURN_VAL_IF_FAIL(buffer != NULL, TDM_ERROR_INVALID_PARAMETER);
1451
1452         _pthread_mutex_lock(&private_display->lock);
1453
1454         if (tdm_debug_dump & TDM_DUMP_FLAG_LAYER &&
1455                 !(private_layer->caps.capabilities & TDM_LAYER_CAPABILITY_VIDEO)) {
1456                 char str[TDM_PATH_LEN];
1457                 static int i;
1458                 snprintf(str, TDM_PATH_LEN, "layer_%d_%d_%03d",
1459                                  private_output->pipe, private_layer->caps.zpos, i++);
1460                 tdm_helper_dump_buffer_str(buffer, str);
1461         }
1462
1463         func_layer = &private_display->func_layer;
1464
1465         if (private_layer->usable)
1466                 TDM_INFO("layer(%p) not usable", private_layer);
1467
1468         private_layer->usable = 0;
1469
1470         if (!func_layer->layer_set_buffer) {
1471                 _pthread_mutex_unlock(&private_display->lock);
1472                 TDM_ERR("not implemented!!");
1473                 return TDM_ERROR_NOT_IMPLEMENTED;
1474         }
1475
1476         ret = func_layer->layer_set_buffer(private_layer->layer_backend, buffer);
1477         TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
1478
1479         /* dump buffer */
1480         if (tdm_dump_enable && !(private_layer->caps.capabilities & TDM_LAYER_CAPABILITY_VIDEO))
1481                 _tdm_layer_dump_buffer(layer, buffer);
1482
1483         if (ret == TDM_ERROR_NONE) {
1484                 /* FIXME: should save to pending_buffer first. And after committing
1485                  * successfully, need to move to waiting_buffer.
1486                  */
1487                 if (private_layer->waiting_buffer) {
1488                         _pthread_mutex_unlock(&private_display->lock);
1489                         tdm_buffer_unref_backend(private_layer->waiting_buffer);
1490                         _pthread_mutex_lock(&private_display->lock);
1491                 }
1492
1493                 private_layer->waiting_buffer = tdm_buffer_ref_backend(buffer);
1494                 if (tdm_debug_module & TDM_DEBUG_BUFFER)
1495                         TDM_INFO("layer(%p) waiting_buffer(%p)",
1496                                          private_layer, private_layer->waiting_buffer);
1497         }
1498
1499         _pthread_mutex_unlock(&private_display->lock);
1500
1501         return ret;
1502 }
1503
1504 EXTERN tdm_error
1505 tdm_layer_unset_buffer(tdm_layer *layer)
1506 {
1507         tdm_func_layer *func_layer;
1508         LAYER_FUNC_ENTRY();
1509
1510         _pthread_mutex_lock(&private_display->lock);
1511
1512         func_layer = &private_display->func_layer;
1513
1514         if (private_layer->waiting_buffer) {
1515                 _pthread_mutex_unlock(&private_display->lock);
1516                 tdm_buffer_unref_backend(private_layer->waiting_buffer);
1517                 _pthread_mutex_lock(&private_display->lock);
1518                 private_layer->waiting_buffer = NULL;
1519
1520                 if (tdm_debug_module & TDM_DEBUG_BUFFER)
1521                         TDM_INFO("layer(%p) waiting_buffer(%p)",
1522                                          private_layer, private_layer->waiting_buffer);
1523         }
1524
1525         if (private_layer->showing_buffer) {
1526                 _pthread_mutex_unlock(&private_display->lock);
1527                 tdm_buffer_unref_backend(private_layer->showing_buffer);
1528                 _pthread_mutex_lock(&private_display->lock);
1529                 private_layer->showing_buffer = NULL;
1530
1531                 if (tdm_debug_module & TDM_DEBUG_BUFFER)
1532                         TDM_INFO("layer(%p) showing_buffer(%p)",
1533                                          private_layer, private_layer->showing_buffer);
1534         }
1535
1536         private_layer->usable = 1;
1537
1538         if (private_layer->usable)
1539                 TDM_INFO("layer(%p) now usable", private_layer);
1540
1541         if (!func_layer->layer_unset_buffer) {
1542                 _pthread_mutex_unlock(&private_display->lock);
1543                 TDM_ERR("not implemented!!");
1544                 return TDM_ERROR_NOT_IMPLEMENTED;
1545         }
1546
1547         ret = func_layer->layer_unset_buffer(private_layer->layer_backend);
1548         TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
1549
1550         _pthread_mutex_unlock(&private_display->lock);
1551
1552         return ret;
1553 }
1554
1555 EXTERN tbm_surface_h
1556 tdm_layer_get_displaying_buffer(tdm_layer *layer, tdm_error *error)
1557 {
1558         tbm_surface_h buffer;
1559         LAYER_FUNC_ENTRY_ERROR();
1560
1561         _pthread_mutex_lock(&private_display->lock);
1562
1563         if (error)
1564                 *error = TDM_ERROR_NONE;
1565
1566         if (private_layer->showing_buffer) {
1567                 buffer = private_layer->showing_buffer;
1568         } else {
1569                 if (error)
1570                         *error = TDM_ERROR_OPERATION_FAILED;
1571                 _pthread_mutex_unlock(&private_display->lock);
1572                 TDM_DBG("layer(%p) showing_buffer is null", private_layer);
1573                 return NULL;
1574         }
1575         _pthread_mutex_unlock(&private_display->lock);
1576
1577         return buffer;
1578 }
1579
1580 static void
1581 _tbm_layer_queue_acquirable_cb(tbm_surface_queue_h surface_queue, void *data)
1582 {
1583         TDM_RETURN_IF_FAIL(data != NULL);
1584         tdm_layer *layer = data;
1585         tdm_func_layer *func_layer;
1586         tbm_surface_h surface = NULL;
1587         LAYER_FUNC_ENTRY_VOID_RETURN();
1588
1589         _pthread_mutex_lock(&private_display->lock);
1590
1591         func_layer = &private_display->func_layer;
1592         if (!func_layer->layer_set_buffer) {
1593                 _pthread_mutex_unlock(&private_display->lock);
1594                 return;
1595         }
1596
1597         if (TBM_SURFACE_QUEUE_ERROR_NONE != tbm_surface_queue_acquire(private_layer->buffer_queue, &surface) ||
1598                 surface == NULL) {
1599                 TDM_ERR("layer(%p) tbm_surface_queue_acquire() failed surface:%p",
1600                                 private_layer, surface);
1601                 _pthread_mutex_unlock(&private_display->lock);
1602                 return;
1603         }
1604
1605         ret = func_layer->layer_set_buffer(private_layer->layer_backend, surface);
1606         TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
1607
1608         if (ret == TDM_ERROR_NONE) {
1609                 if (private_layer->waiting_buffer) {
1610                         TDM_DBG("layer(%p) drop waiting_buffer(%p)", private_layer, private_layer->waiting_buffer);
1611                         _pthread_mutex_unlock(&private_display->lock);
1612                         tdm_buffer_unref_backend(private_layer->waiting_buffer);
1613                         tbm_surface_queue_release(private_layer->buffer_queue,
1614                                                                           private_layer->waiting_buffer);
1615                         _pthread_mutex_lock(&private_display->lock);
1616                 }
1617
1618                 private_layer->waiting_buffer = tdm_buffer_ref_backend(surface);
1619
1620                 if (tdm_debug_module & TDM_DEBUG_BUFFER)
1621                         TDM_INFO("layer(%p) waiting_buffer(%p)",
1622                                          private_layer, private_layer->waiting_buffer);
1623
1624                 ret = _tdm_output_commit(private_layer->private_output, 0, NULL, NULL);
1625                 if (ret != TDM_ERROR_NONE)
1626                         TDM_ERR("layer(%p) _tdm_output_commit() is fail", private_layer);
1627         }
1628
1629         _pthread_mutex_unlock(&private_display->lock);
1630 }
1631
1632 static void
1633 _tbm_layer_queue_destroy_cb(tbm_surface_queue_h surface_queue, void *data)
1634 {
1635         TDM_RETURN_IF_FAIL(data != NULL);
1636         tdm_layer *layer = data;
1637         LAYER_FUNC_ENTRY_VOID_RETURN();
1638         TDM_RETURN_IF_FAIL(ret == TDM_ERROR_NONE);
1639
1640         _pthread_mutex_lock(&private_display->lock);
1641
1642         if (private_layer->waiting_buffer) {
1643                 _pthread_mutex_unlock(&private_display->lock);
1644                 tdm_buffer_unref_backend(private_layer->waiting_buffer);
1645                 tbm_surface_queue_release(private_layer->buffer_queue,
1646                                                                   private_layer->waiting_buffer);
1647                 _pthread_mutex_lock(&private_display->lock);
1648         }
1649
1650         private_layer->buffer_queue = NULL;
1651
1652         _pthread_mutex_unlock(&private_display->lock);
1653 }
1654
1655 EXTERN tdm_error
1656 tdm_layer_set_buffer_queue(tdm_layer *layer, tbm_surface_queue_h buffer_queue)
1657 {
1658         tdm_func_layer *func_layer;
1659         LAYER_FUNC_ENTRY();
1660
1661         TDM_RETURN_VAL_IF_FAIL(buffer_queue != NULL, TDM_ERROR_INVALID_PARAMETER);
1662
1663         _pthread_mutex_lock(&private_display->lock);
1664
1665         func_layer = &private_display->func_layer;
1666
1667         if (private_layer->usable)
1668                 TDM_INFO("layer(%p) not usable", private_layer);
1669
1670         private_layer->usable = 0;
1671
1672         if (!func_layer->layer_set_buffer) {
1673                 _pthread_mutex_unlock(&private_display->lock);
1674                 TDM_ERR("not implemented!!");
1675                 return TDM_ERROR_NOT_IMPLEMENTED;
1676         }
1677
1678         if (buffer_queue == private_layer->buffer_queue) {
1679                 _pthread_mutex_unlock(&private_display->lock);
1680                 return TDM_ERROR_NONE;
1681         }
1682
1683         if (private_layer->waiting_buffer) {
1684                 _pthread_mutex_unlock(&private_display->lock);
1685                 tdm_buffer_unref_backend(private_layer->waiting_buffer);
1686                 tbm_surface_queue_release(private_layer->buffer_queue,
1687                                                                   private_layer->waiting_buffer);
1688                 private_layer->waiting_buffer = NULL;
1689                 _pthread_mutex_lock(&private_display->lock);
1690
1691                 if (tdm_debug_module & TDM_DEBUG_BUFFER)
1692                         TDM_INFO("layer(%p) waiting_buffer(%p)",
1693                                          private_layer, private_layer->waiting_buffer);
1694         }
1695
1696         private_layer->buffer_queue = buffer_queue;
1697         tbm_surface_queue_add_acquirable_cb(private_layer->buffer_queue,
1698                                                                                 _tbm_layer_queue_acquirable_cb,
1699                                                                                 layer);
1700         tbm_surface_queue_add_destroy_cb(private_layer->buffer_queue,
1701                                                                          _tbm_layer_queue_destroy_cb,
1702                                                                          layer);
1703         _pthread_mutex_unlock(&private_display->lock);
1704
1705         return ret;
1706 }
1707
1708 EXTERN tdm_error
1709 tdm_layer_unset_buffer_queue(tdm_layer *layer)
1710 {
1711         tdm_func_layer *func_layer;
1712         LAYER_FUNC_ENTRY();
1713
1714         _pthread_mutex_lock(&private_display->lock);
1715
1716         func_layer = &private_display->func_layer;
1717
1718         if (private_layer->waiting_buffer) {
1719                 _pthread_mutex_unlock(&private_display->lock);
1720                 tdm_buffer_unref_backend(private_layer->waiting_buffer);
1721                 tbm_surface_queue_release(private_layer->buffer_queue,
1722                                                                   private_layer->waiting_buffer);
1723                 private_layer->waiting_buffer = NULL;
1724                 _pthread_mutex_lock(&private_display->lock);
1725
1726                 if (tdm_debug_module & TDM_DEBUG_BUFFER)
1727                         TDM_INFO("layer(%p) waiting_buffer(%p)",
1728                                          private_layer, private_layer->waiting_buffer);
1729         }
1730
1731         if (private_layer->showing_buffer) {
1732                 _pthread_mutex_unlock(&private_display->lock);
1733                 tdm_buffer_unref_backend(private_layer->showing_buffer);
1734                 tbm_surface_queue_release(private_layer->buffer_queue,
1735                                                                   private_layer->showing_buffer);
1736                 _pthread_mutex_lock(&private_display->lock);
1737                 private_layer->showing_buffer = NULL;
1738
1739                 if (tdm_debug_module & TDM_DEBUG_BUFFER)
1740                         TDM_INFO("layer(%p) showing_buffer(%p)",
1741                                          private_layer, private_layer->showing_buffer);
1742         }
1743
1744         tbm_surface_queue_remove_acquirable_cb(private_layer->buffer_queue, _tbm_layer_queue_acquirable_cb, layer);
1745         tbm_surface_queue_remove_destroy_cb(private_layer->buffer_queue, _tbm_layer_queue_destroy_cb, layer);
1746         private_layer->buffer_queue = NULL;
1747         private_layer->usable = 1;
1748
1749         if (private_layer->usable)
1750                 TDM_INFO("layer(%p) now usable", private_layer);
1751
1752         if (!func_layer->layer_unset_buffer) {
1753                 _pthread_mutex_unlock(&private_display->lock);
1754                 TDM_ERR("not implemented!!");
1755                 return TDM_ERROR_NOT_IMPLEMENTED;
1756         }
1757
1758         ret = func_layer->layer_unset_buffer(private_layer->layer_backend);
1759
1760         _pthread_mutex_unlock(&private_display->lock);
1761
1762         return ret;
1763 }
1764
1765 EXTERN tdm_error
1766 tdm_layer_is_usable(tdm_layer *layer, unsigned int *usable)
1767 {
1768         LAYER_FUNC_ENTRY();
1769
1770         TDM_RETURN_VAL_IF_FAIL(usable != NULL, TDM_ERROR_INVALID_PARAMETER);
1771
1772         _pthread_mutex_lock(&private_display->lock);
1773
1774         *usable = private_layer->usable;
1775
1776         _pthread_mutex_unlock(&private_display->lock);
1777
1778         return ret;
1779 }
1780
1781 EXTERN tdm_error
1782 tdm_layer_set_video_pos(tdm_layer *layer, int zpos)
1783 {
1784         tdm_func_layer *func_layer;
1785         LAYER_FUNC_ENTRY();
1786
1787         _pthread_mutex_lock(&private_display->lock);
1788
1789         func_layer = &private_display->func_layer;
1790
1791         if (!(private_layer->caps.capabilities & TDM_LAYER_CAPABILITY_VIDEO)) {
1792                 TDM_ERR("layer(%p) is not video layer", private_layer);
1793                 _pthread_mutex_unlock(&private_display->lock);
1794                 return TDM_ERROR_INVALID_PARAMETER;
1795         }
1796
1797         if (!func_layer->layer_set_video_pos) {
1798                 _pthread_mutex_unlock(&private_display->lock);
1799                 TDM_ERR("not implemented!!");
1800                 return TDM_ERROR_NOT_IMPLEMENTED;
1801         }
1802
1803         ret = func_layer->layer_set_video_pos(private_layer->layer_backend, zpos);
1804
1805         _pthread_mutex_unlock(&private_display->lock);
1806
1807         return ret;
1808 }
1809
1810 EXTERN tdm_capture *
1811 tdm_layer_create_capture(tdm_layer *layer, tdm_error *error)
1812 {
1813         tdm_capture *capture = NULL;
1814
1815         LAYER_FUNC_ENTRY_ERROR();
1816
1817         _pthread_mutex_lock(&private_display->lock);
1818
1819         capture = (tdm_capture *)tdm_capture_create_layer_internal(private_layer, error);
1820
1821         _pthread_mutex_unlock(&private_display->lock);
1822
1823         return capture;
1824 }
1825
1826 EXTERN tdm_error
1827 tdm_layer_get_buffer_flags(tdm_layer *layer, unsigned int *flags)
1828 {
1829         tdm_func_layer *func_layer;
1830         LAYER_FUNC_ENTRY();
1831
1832         _pthread_mutex_lock(&private_display->lock);
1833
1834         func_layer = &private_display->func_layer;
1835
1836         if (!func_layer->layer_get_buffer_flags) {
1837                 _pthread_mutex_unlock(&private_display->lock);
1838                 TDM_ERR("not implemented!!");
1839                 return TDM_ERROR_NOT_IMPLEMENTED;
1840         }
1841
1842         ret = func_layer->layer_get_buffer_flags(private_layer->layer_backend, flags);
1843
1844         _pthread_mutex_unlock(&private_display->lock);
1845
1846         return ret;
1847 }