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