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