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