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