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