update output when udev event occured
[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         unsigned int i;                                 \
115         for (i = 0; i < ARRAY_SIZE(res##_names); i++) { \
116                 if (res##_names[i].type == type)        \
117                         return res##_names[i].name;     \
118         }                                               \
119         return "(invalid)";                             \
120 }
121
122 struct type_name dpms_names[] = {
123         { TDM_OUTPUT_DPMS_ON, "on" },
124         { TDM_OUTPUT_DPMS_STANDBY, "standby" },
125         { TDM_OUTPUT_DPMS_SUSPEND, "suspend" },
126         { TDM_OUTPUT_DPMS_OFF, "off" },
127 };
128
129 INTERN type_name_fn(dpms)
130
131 struct type_name status_names[] = {
132         { TDM_OUTPUT_CONN_STATUS_DISCONNECTED, "disconnected" },
133         { TDM_OUTPUT_CONN_STATUS_CONNECTED, "connected" },
134         { TDM_OUTPUT_CONN_STATUS_MODE_SETTED, "mode_setted" },
135 };
136
137 INTERN type_name_fn(status)
138
139 INTERN const char*
140 tdm_get_dpms_str(tdm_output_dpms dpms_value)
141 {
142         return dpms_str(dpms_value);
143 }
144
145 INTERN tdm_error
146 _tdm_display_lock(tdm_display *dpy, const char *func)
147 {
148         tdm_private_display *private_display = (tdm_private_display*)dpy;
149         int ret;
150
151         if (tdm_debug_mutex)
152                 TDM_INFO("mutex lock: %s", func);
153
154         ret = pthread_mutex_trylock(&private_display->lock);
155         if (ret < 0) {
156                 if (ret == EBUSY) {
157                         TDM_ERR("mutex lock busy: %s", func);
158                 } else {
159                         TDM_ERR("mutex lock failed: %s(%m)", func);
160                 }
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                                 tbm_surface_queue_release(private_layer->buffer_queue,
953                                                           private_layer->showing_buffer);
954                         }
955                 }
956
957                 private_layer->showing_buffer = private_layer->waiting_buffer;
958                 private_layer->waiting_buffer = NULL;
959
960                 if (tdm_debug_buffer)
961                         TDM_INFO("layer(%p) waiting_buffer(%p) showing_buffer(%p)",
962                                  private_layer, private_layer->waiting_buffer,
963                                  private_layer->showing_buffer);
964         }
965
966         if (commit_handler->func) {
967                 _pthread_mutex_unlock(&private_display->lock);
968                 commit_handler->func(private_output, sequence,
969                                      tv_sec, tv_usec, commit_handler->user_data);
970                 _pthread_mutex_lock(&private_display->lock);
971         }
972
973         LIST_DEL(&commit_handler->link);
974         free(commit_handler);
975 }
976
977 EXTERN tdm_error
978 tdm_output_wait_vblank(tdm_output *output, int interval, int sync,
979                        tdm_output_vblank_handler func, void *user_data)
980 {
981         tdm_func_output *func_output;
982         tdm_private_vblank_handler *vblank_handler;
983         OUTPUT_FUNC_ENTRY();
984
985         _pthread_mutex_lock(&private_display->lock);
986
987         if (private_output->current_dpms_value > TDM_OUTPUT_DPMS_ON) {
988                 TDM_ERR("output(%d) dpms: %s", private_output->pipe,
989                         dpms_str(private_output->current_dpms_value));
990                 _pthread_mutex_unlock(&private_display->lock);
991                 return TDM_ERROR_BAD_REQUEST;
992         }
993
994         func_output = &private_display->func_output;
995
996         if (!func_output->output_wait_vblank) {
997                 _pthread_mutex_unlock(&private_display->lock);
998                 TDM_ERR("not implemented!!");
999                 return TDM_ERROR_NOT_IMPLEMENTED;
1000         }
1001
1002         vblank_handler = calloc(1, sizeof(tdm_private_vblank_handler));
1003         if (!vblank_handler) {
1004                 TDM_ERR("failed: alloc memory");
1005                 _pthread_mutex_unlock(&private_display->lock);
1006                 return TDM_ERROR_OUT_OF_MEMORY;
1007         }
1008
1009         LIST_ADD(&vblank_handler->link, &private_output->vblank_handler_list);
1010         vblank_handler->private_output = private_output;
1011         vblank_handler->func = func;
1012         vblank_handler->user_data = user_data;
1013         vblank_handler->owner_tid = syscall(SYS_gettid);
1014
1015         ret = func_output->output_wait_vblank(private_output->output_backend, interval,
1016                                               sync, vblank_handler);
1017         if (ret != TDM_ERROR_NONE) {
1018                 _pthread_mutex_unlock(&private_display->lock);
1019                 return ret;
1020         }
1021
1022         if (!private_output->regist_vblank_cb) {
1023                 private_output->regist_vblank_cb = 1;
1024                 ret = func_output->output_set_vblank_handler(private_output->output_backend,
1025                                 tdm_output_cb_vblank);
1026         }
1027
1028         _pthread_mutex_unlock(&private_display->lock);
1029
1030         return ret;
1031 }
1032
1033 static tdm_error
1034 _tdm_output_commit(tdm_output *output, int sync, tdm_output_commit_handler func,
1035                    void *user_data)
1036 {
1037         tdm_func_output *func_output;
1038         tdm_private_commit_handler *commit_handler;
1039         OUTPUT_FUNC_ENTRY();
1040
1041         func_output = &private_display->func_output;
1042
1043         if (!func_output->output_commit) {
1044                 TDM_ERR("not implemented!!");
1045                 return TDM_ERROR_NOT_IMPLEMENTED;
1046         }
1047
1048         commit_handler = calloc(1, sizeof(tdm_private_commit_handler));
1049         if (!commit_handler) {
1050                 TDM_ERR("failed: alloc memory");
1051                 return TDM_ERROR_OUT_OF_MEMORY;
1052         }
1053
1054         LIST_ADD(&commit_handler->link, &private_output->commit_handler_list);
1055         commit_handler->private_output = private_output;
1056         commit_handler->func = func;
1057         commit_handler->user_data = user_data;
1058         commit_handler->owner_tid = syscall(SYS_gettid);
1059
1060         ret = func_output->output_commit(private_output->output_backend, sync,
1061                                          commit_handler);
1062         TDM_RETURN_VAL_IF_FAIL(ret == TDM_ERROR_NONE, ret);
1063
1064         if (!private_output->regist_commit_cb) {
1065                 private_output->regist_commit_cb = 1;
1066                 ret = func_output->output_set_commit_handler(private_output->output_backend,
1067                                 tdm_output_cb_commit);
1068         }
1069
1070         return ret;
1071 }
1072
1073 EXTERN tdm_error
1074 tdm_output_commit(tdm_output *output, int sync, tdm_output_commit_handler func,
1075                   void *user_data)
1076 {
1077         OUTPUT_FUNC_ENTRY();
1078
1079         _pthread_mutex_lock(&private_display->lock);
1080
1081         if (private_output->current_dpms_value > TDM_OUTPUT_DPMS_ON) {
1082                 TDM_ERR("output(%d) dpms: %s", private_output->pipe,
1083                         dpms_str(private_output->current_dpms_value));
1084                 _pthread_mutex_unlock(&private_display->lock);
1085                 return TDM_ERROR_BAD_REQUEST;
1086         }
1087
1088         ret = _tdm_output_commit(output, sync, func, user_data);
1089
1090         _pthread_mutex_unlock(&private_display->lock);
1091
1092         return ret;
1093 }
1094
1095 EXTERN tdm_error
1096 tdm_output_set_mode(tdm_output *output, const tdm_output_mode *mode)
1097 {
1098         tdm_func_output *func_output;
1099         OUTPUT_FUNC_ENTRY();
1100
1101         TDM_RETURN_VAL_IF_FAIL(mode != NULL, TDM_ERROR_INVALID_PARAMETER);
1102
1103         _pthread_mutex_lock(&private_display->lock);
1104
1105         func_output = &private_display->func_output;
1106
1107         if (!func_output->output_set_mode) {
1108                 _pthread_mutex_unlock(&private_display->lock);
1109                 TDM_ERR("not implemented!!");
1110                 return TDM_ERROR_NOT_IMPLEMENTED;
1111         }
1112
1113         ret = func_output->output_set_mode(private_output->output_backend, mode);
1114
1115         _pthread_mutex_unlock(&private_display->lock);
1116
1117         return ret;
1118 }
1119
1120 EXTERN tdm_error
1121 tdm_output_get_mode(tdm_output *output, const tdm_output_mode **mode)
1122 {
1123         tdm_func_output *func_output;
1124         OUTPUT_FUNC_ENTRY();
1125
1126         TDM_RETURN_VAL_IF_FAIL(mode != NULL, TDM_ERROR_INVALID_PARAMETER);
1127
1128         _pthread_mutex_lock(&private_display->lock);
1129
1130         func_output = &private_display->func_output;
1131
1132         if (!func_output->output_get_mode) {
1133                 _pthread_mutex_unlock(&private_display->lock);
1134                 TDM_ERR("not implemented!!");
1135                 return TDM_ERROR_NOT_IMPLEMENTED;
1136         }
1137
1138         ret = func_output->output_get_mode(private_output->output_backend, mode);
1139
1140         _pthread_mutex_unlock(&private_display->lock);
1141
1142         return ret;
1143 }
1144
1145 EXTERN tdm_error
1146 tdm_output_set_dpms(tdm_output *output, tdm_output_dpms dpms_value)
1147 {
1148         tdm_func_output *func_output;
1149         OUTPUT_FUNC_ENTRY();
1150
1151         if (dpms_value < TDM_OUTPUT_DPMS_ON)
1152                 dpms_value = TDM_OUTPUT_DPMS_ON;
1153         else if (dpms_value > TDM_OUTPUT_DPMS_OFF)
1154                 dpms_value = TDM_OUTPUT_DPMS_OFF;
1155
1156         _pthread_mutex_lock(&private_display->lock);
1157
1158         if (private_output->current_dpms_value == dpms_value) {
1159                 _pthread_mutex_unlock(&private_display->lock);
1160                 return TDM_ERROR_NONE;
1161         }
1162
1163         func_output = &private_display->func_output;
1164
1165         if (!func_output->output_set_dpms) {
1166                 _pthread_mutex_unlock(&private_display->lock);
1167                 private_output->current_dpms_value = dpms_value;
1168                 TDM_WRN("not implemented!!");
1169                 return TDM_ERROR_NONE;
1170         }
1171
1172         ret = func_output->output_set_dpms(private_output->output_backend, dpms_value);
1173         if (ret == TDM_ERROR_NONE) {
1174                 tdm_value value;
1175
1176                 private_output->current_dpms_value = dpms_value;
1177
1178                 value.u32 = dpms_value;
1179                 tdm_output_call_change_handler_internal(private_output,
1180                                                         &private_output->change_handler_list_main,
1181                                                         TDM_OUTPUT_CHANGE_DPMS,
1182                                                         value);
1183         }
1184
1185         _pthread_mutex_unlock(&private_display->lock);
1186
1187         return ret;
1188 }
1189
1190 EXTERN tdm_error
1191 tdm_output_get_dpms(tdm_output *output, tdm_output_dpms *dpms_value)
1192 {
1193         tdm_func_output *func_output;
1194         OUTPUT_FUNC_ENTRY();
1195
1196         TDM_RETURN_VAL_IF_FAIL(dpms_value != NULL, TDM_ERROR_INVALID_PARAMETER);
1197
1198         _pthread_mutex_lock(&private_display->lock);
1199
1200         func_output = &private_display->func_output;
1201
1202         if (!func_output->output_get_dpms) {
1203                 *dpms_value = private_output->current_dpms_value;
1204                 _pthread_mutex_unlock(&private_display->lock);
1205                 TDM_WRN("not implemented!!");
1206                 return TDM_ERROR_NONE;
1207         }
1208
1209         ret = func_output->output_get_dpms(private_output->output_backend, dpms_value);
1210
1211         _pthread_mutex_unlock(&private_display->lock);
1212
1213         return ret;
1214 }
1215
1216 EXTERN tdm_capture *
1217 tdm_output_create_capture(tdm_output *output, tdm_error *error)
1218 {
1219         tdm_capture *capture = NULL;
1220
1221         OUTPUT_FUNC_ENTRY_ERROR();
1222
1223         _pthread_mutex_lock(&private_display->lock);
1224
1225         capture = (tdm_capture *)tdm_capture_create_output_internal(private_output,
1226                         error);
1227
1228         _pthread_mutex_unlock(&private_display->lock);
1229
1230         return capture;
1231 }
1232
1233 INTERN void
1234 tdm_output_call_change_handler_internal(tdm_private_output *private_output,
1235                                         struct list_head *change_handler_list,
1236                                         tdm_output_change_type type,
1237                                         tdm_value value)
1238 {
1239         tdm_private_display *private_display;
1240         tdm_private_change_handler *change_handler;
1241
1242         TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED());
1243         TDM_RETURN_IF_FAIL(private_output);
1244
1245         private_display = private_output->private_display;
1246         if (!tdm_thread_in_display_thread(syscall(SYS_gettid))) {
1247                 if (type & TDM_OUTPUT_CHANGE_CONNECTION)
1248                         TDM_INFO("output(%d) changed: %s (%d)",
1249                                  private_output->pipe, status_str(value.u32), value.u32);
1250                 if (type & TDM_OUTPUT_CHANGE_DPMS)
1251                         TDM_INFO("output(%d) changed: dpms %s (%d)",
1252                                  private_output->pipe, dpms_str(value.u32), value.u32);
1253         }
1254
1255         if (LIST_IS_EMPTY(change_handler_list))
1256                 return;
1257
1258         LIST_FOR_EACH_ENTRY(change_handler, change_handler_list, link) {
1259                 if (change_handler->owner_tid != syscall(SYS_gettid))
1260                         TDM_NEVER_GET_HERE();
1261
1262                 _pthread_mutex_unlock(&private_display->lock);
1263                 change_handler->func(private_output, type,
1264                                      value, change_handler->user_data);
1265                 _pthread_mutex_lock(&private_display->lock);
1266         }
1267 }
1268
1269 EXTERN tdm_error
1270 tdm_layer_get_capabilities(tdm_layer *layer, tdm_layer_capability *capabilities)
1271 {
1272         LAYER_FUNC_ENTRY();
1273
1274         TDM_RETURN_VAL_IF_FAIL(capabilities != NULL, TDM_ERROR_INVALID_PARAMETER);
1275
1276         _pthread_mutex_lock(&private_display->lock);
1277
1278         *capabilities = private_layer->caps.capabilities;
1279
1280         _pthread_mutex_unlock(&private_display->lock);
1281
1282         return ret;
1283 }
1284
1285 EXTERN tdm_error
1286 tdm_layer_get_available_formats(tdm_layer *layer, const tbm_format **formats,
1287                                 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,
1306                                    int *count)
1307 {
1308         LAYER_FUNC_ENTRY();
1309
1310         TDM_RETURN_VAL_IF_FAIL(props != NULL, TDM_ERROR_INVALID_PARAMETER);
1311         TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
1312
1313         _pthread_mutex_lock(&private_display->lock);
1314
1315         *props = (const tdm_prop *)private_layer->caps.props;
1316         *count = private_layer->caps.prop_count;
1317
1318         _pthread_mutex_unlock(&private_display->lock);
1319
1320         return ret;
1321 }
1322
1323 EXTERN tdm_error
1324 tdm_layer_get_zpos(tdm_layer *layer, unsigned int *zpos)
1325 {
1326         LAYER_FUNC_ENTRY();
1327
1328         TDM_RETURN_VAL_IF_FAIL(zpos != NULL, TDM_ERROR_INVALID_PARAMETER);
1329
1330         _pthread_mutex_lock(&private_display->lock);
1331
1332         *zpos = private_layer->caps.zpos;
1333
1334         _pthread_mutex_unlock(&private_display->lock);
1335
1336         return ret;
1337 }
1338
1339 EXTERN tdm_error
1340 tdm_layer_set_property(tdm_layer *layer, unsigned int id, tdm_value value)
1341 {
1342         tdm_func_layer *func_layer;
1343         LAYER_FUNC_ENTRY();
1344
1345         _pthread_mutex_lock(&private_display->lock);
1346
1347         func_layer = &private_display->func_layer;
1348
1349         if (!func_layer->layer_set_property) {
1350                 _pthread_mutex_unlock(&private_display->lock);
1351                 TDM_ERR("not implemented!!");
1352                 return TDM_ERROR_NOT_IMPLEMENTED;
1353         }
1354
1355         ret = func_layer->layer_set_property(private_layer->layer_backend, id, value);
1356
1357         _pthread_mutex_unlock(&private_display->lock);
1358
1359         return ret;
1360 }
1361
1362 EXTERN tdm_error
1363 tdm_layer_get_property(tdm_layer *layer, unsigned int id, tdm_value *value)
1364 {
1365         tdm_func_layer *func_layer;
1366         LAYER_FUNC_ENTRY();
1367
1368         TDM_RETURN_VAL_IF_FAIL(value != NULL, TDM_ERROR_INVALID_PARAMETER);
1369
1370         _pthread_mutex_lock(&private_display->lock);
1371
1372         func_layer = &private_display->func_layer;
1373
1374         if (!func_layer->layer_get_property) {
1375                 _pthread_mutex_unlock(&private_display->lock);
1376                 TDM_ERR("not implemented!!");
1377                 return TDM_ERROR_NOT_IMPLEMENTED;
1378         }
1379
1380         ret = func_layer->layer_get_property(private_layer->layer_backend, id, value);
1381
1382         _pthread_mutex_unlock(&private_display->lock);
1383
1384         return ret;
1385 }
1386
1387 EXTERN tdm_error
1388 tdm_layer_set_info(tdm_layer *layer, tdm_info_layer *info)
1389 {
1390         tdm_func_layer *func_layer;
1391         LAYER_FUNC_ENTRY();
1392
1393         TDM_RETURN_VAL_IF_FAIL(info != NULL, TDM_ERROR_INVALID_PARAMETER);
1394
1395         _pthread_mutex_lock(&private_display->lock);
1396
1397         func_layer = &private_display->func_layer;
1398
1399         private_layer->usable = 0;
1400
1401         if (!func_layer->layer_set_info) {
1402                 _pthread_mutex_unlock(&private_display->lock);
1403                 TDM_ERR("not implemented!!");
1404                 return TDM_ERROR_NOT_IMPLEMENTED;
1405         }
1406
1407         TDM_INFO("layer(%p) info: src(%dx%d %d,%d %dx%d %c%c%c%c) dst(%d,%d %dx%d) trans(%d)",
1408                  private_layer, info->src_config.size.h, info->src_config.size.v,
1409                  info->src_config.pos.x, info->src_config.pos.y,
1410                  info->src_config.pos.w, info->src_config.pos.h,
1411                  FOURCC_STR(info->src_config.format),
1412                  info->dst_pos.x, info->dst_pos.y,
1413                  info->dst_pos.w, info->dst_pos.h,
1414                  info->transform);
1415
1416         ret = func_layer->layer_set_info(private_layer->layer_backend, info);
1417         TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
1418
1419         _pthread_mutex_unlock(&private_display->lock);
1420
1421         return ret;
1422 }
1423
1424 EXTERN tdm_error
1425 tdm_layer_get_info(tdm_layer *layer, tdm_info_layer *info)
1426 {
1427         tdm_func_layer *func_layer;
1428         LAYER_FUNC_ENTRY();
1429
1430         TDM_RETURN_VAL_IF_FAIL(info != NULL, TDM_ERROR_INVALID_PARAMETER);
1431
1432         _pthread_mutex_lock(&private_display->lock);
1433
1434         func_layer = &private_display->func_layer;
1435
1436         if (!func_layer->layer_get_info) {
1437                 _pthread_mutex_unlock(&private_display->lock);
1438                 TDM_ERR("not implemented!!");
1439                 return TDM_ERROR_NOT_IMPLEMENTED;
1440         }
1441
1442         ret = func_layer->layer_get_info(private_layer->layer_backend, info);
1443
1444         _pthread_mutex_unlock(&private_display->lock);
1445
1446         return ret;
1447 }
1448
1449 static void
1450 _tdm_layer_dump_buffer(tdm_layer *layer, tbm_surface_h buffer)
1451 {
1452         tdm_private_layer *private_layer = (tdm_private_layer*)layer;
1453         tdm_private_output *private_output = private_layer->private_output;
1454         unsigned int pipe;
1455         int zpos;
1456         char fname[PATH_MAX];
1457
1458         pipe = private_output->pipe;
1459         zpos = private_layer->caps.zpos;
1460
1461         snprintf(fname, sizeof(fname), "tdm_%d_lyr_%d", pipe, zpos);
1462
1463         tbm_surface_internal_dump_buffer(buffer, fname);
1464         TDM_DBG("%s dump excute", fname);
1465
1466         return;
1467 }
1468
1469 EXTERN tdm_error
1470 tdm_layer_set_buffer(tdm_layer *layer, tbm_surface_h buffer)
1471 {
1472         tdm_func_layer *func_layer;
1473
1474         LAYER_FUNC_ENTRY();
1475
1476         TDM_RETURN_VAL_IF_FAIL(buffer != NULL, TDM_ERROR_INVALID_PARAMETER);
1477
1478         _pthread_mutex_lock(&private_display->lock);
1479
1480         func_layer = &private_display->func_layer;
1481
1482         private_layer->usable = 0;
1483
1484         if (!func_layer->layer_set_buffer) {
1485                 _pthread_mutex_unlock(&private_display->lock);
1486                 TDM_ERR("not implemented!!");
1487                 return TDM_ERROR_NOT_IMPLEMENTED;
1488         }
1489
1490         ret = func_layer->layer_set_buffer(private_layer->layer_backend, buffer);
1491         TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
1492
1493         /* dump buffer */
1494         if (tdm_dump_enable)
1495                 _tdm_layer_dump_buffer(layer, buffer);
1496
1497         if (ret == TDM_ERROR_NONE) {
1498                 /* FIXME: should save to pending_buffer first. And after committing
1499                  * successfully, need to move to waiting_buffer.
1500                  */
1501                 if (private_layer->waiting_buffer) {
1502                         _pthread_mutex_unlock(&private_display->lock);
1503                         tdm_buffer_unref_backend(private_layer->waiting_buffer);
1504                         _pthread_mutex_lock(&private_display->lock);
1505                 }
1506
1507                 private_layer->waiting_buffer = tdm_buffer_ref_backend(buffer);
1508                 if (tdm_debug_buffer)
1509                         TDM_INFO("layer(%p) waiting_buffer(%p)",
1510                                  private_layer, private_layer->waiting_buffer);
1511         }
1512
1513         _pthread_mutex_unlock(&private_display->lock);
1514
1515         return ret;
1516 }
1517
1518 EXTERN tdm_error
1519 tdm_layer_unset_buffer(tdm_layer *layer)
1520 {
1521         tdm_func_layer *func_layer;
1522         LAYER_FUNC_ENTRY();
1523
1524         _pthread_mutex_lock(&private_display->lock);
1525
1526         func_layer = &private_display->func_layer;
1527
1528         if (private_layer->waiting_buffer) {
1529                 _pthread_mutex_unlock(&private_display->lock);
1530                 tdm_buffer_unref_backend(private_layer->waiting_buffer);
1531                 _pthread_mutex_lock(&private_display->lock);
1532                 private_layer->waiting_buffer = NULL;
1533
1534                 if (tdm_debug_buffer)
1535                         TDM_INFO("layer(%p) waiting_buffer(%p)",
1536                                  private_layer, private_layer->waiting_buffer);
1537         }
1538
1539         if (private_layer->showing_buffer) {
1540                 _pthread_mutex_unlock(&private_display->lock);
1541                 tdm_buffer_unref_backend(private_layer->showing_buffer);
1542                 _pthread_mutex_lock(&private_display->lock);
1543                 private_layer->showing_buffer = NULL;
1544
1545                 if (tdm_debug_buffer)
1546                         TDM_INFO("layer(%p) showing_buffer(%p)",
1547                                  private_layer, private_layer->showing_buffer);
1548         }
1549
1550         private_layer->usable = 1;
1551
1552         if (!func_layer->layer_unset_buffer) {
1553                 _pthread_mutex_unlock(&private_display->lock);
1554                 TDM_ERR("not implemented!!");
1555                 return TDM_ERROR_NOT_IMPLEMENTED;
1556         }
1557
1558         ret = func_layer->layer_unset_buffer(private_layer->layer_backend);
1559         TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
1560
1561         _pthread_mutex_unlock(&private_display->lock);
1562
1563         return ret;
1564 }
1565
1566 EXTERN tbm_surface_h
1567 tdm_layer_get_displaying_buffer(tdm_layer *layer, tdm_error *error)
1568 {
1569         tbm_surface_h buffer;
1570         LAYER_FUNC_ENTRY_ERROR();
1571
1572         _pthread_mutex_lock(&private_display->lock);
1573
1574         if (error)
1575                 *error = TDM_ERROR_NONE;
1576
1577         if (private_layer->showing_buffer) {
1578                 buffer = private_layer->showing_buffer;
1579         } else {
1580                 if (error)
1581                         *error = TDM_ERROR_OPERATION_FAILED;
1582                 _pthread_mutex_unlock(&private_display->lock);
1583                 TDM_ERR("layer(%p) showing_buffer is null",
1584                         private_layer);
1585                 return NULL;
1586         }
1587         _pthread_mutex_unlock(&private_display->lock);
1588
1589         return buffer;
1590 }
1591
1592 static void
1593 _tbm_layer_queue_acquirable_cb(tbm_surface_queue_h surface_queue, void *data)
1594 {
1595         TDM_RETURN_IF_FAIL(data != NULL);
1596         tdm_layer *layer = data;
1597         tdm_func_layer *func_layer;
1598         tbm_surface_h surface = NULL;
1599         LAYER_FUNC_ENTRY_VOID_RETURN();
1600
1601         _pthread_mutex_lock(&private_display->lock);
1602
1603         func_layer = &private_display->func_layer;
1604         if (!func_layer->layer_set_buffer) {
1605                 _pthread_mutex_unlock(&private_display->lock);
1606                 return;
1607         }
1608
1609         if (TBM_SURFACE_QUEUE_ERROR_NONE != tbm_surface_queue_acquire(
1610                     private_layer->buffer_queue, &surface) ||
1611             surface == NULL) {
1612                 TDM_ERR("layer(%p) tbm_surface_queue_acquire() failed surface:%p",
1613                         private_layer, surface);
1614                 _pthread_mutex_unlock(&private_display->lock);
1615                 return;
1616         }
1617
1618         ret = func_layer->layer_set_buffer(private_layer->layer_backend, surface);
1619         TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
1620
1621         if (ret == TDM_ERROR_NONE) {
1622                 if (private_layer->waiting_buffer) {
1623                         _pthread_mutex_unlock(&private_display->lock);
1624                         tdm_buffer_unref_backend(private_layer->waiting_buffer);
1625                         tbm_surface_queue_release(private_layer->buffer_queue,
1626                                                   private_layer->waiting_buffer);
1627                         _pthread_mutex_lock(&private_display->lock);
1628                 }
1629
1630                 private_layer->waiting_buffer = tdm_buffer_ref_backend(surface);
1631
1632                 if (tdm_debug_buffer)
1633                         TDM_INFO("layer(%p) waiting_buffer(%p)",
1634                                  private_layer, private_layer->waiting_buffer);
1635
1636                 ret = _tdm_output_commit(private_layer->private_output, 0, NULL, NULL);
1637                 if (ret != TDM_ERROR_NONE)
1638                         TDM_ERR("layer(%p) _tdm_output_commit() is fail", private_layer);
1639         }
1640
1641         _pthread_mutex_unlock(&private_display->lock);
1642 }
1643
1644 static void
1645 _tbm_layer_queue_destroy_cb(tbm_surface_queue_h surface_queue, void *data)
1646 {
1647         TDM_RETURN_IF_FAIL(data != NULL);
1648         tdm_layer *layer = data;
1649         LAYER_FUNC_ENTRY_VOID_RETURN();
1650         TDM_RETURN_IF_FAIL(ret == TDM_ERROR_NONE);
1651
1652         _pthread_mutex_lock(&private_display->lock);
1653
1654         if (private_layer->waiting_buffer) {
1655                 _pthread_mutex_unlock(&private_display->lock);
1656                 tdm_buffer_unref_backend(private_layer->waiting_buffer);
1657                 tbm_surface_queue_release(private_layer->buffer_queue,
1658                                           private_layer->waiting_buffer);
1659                 _pthread_mutex_lock(&private_display->lock);
1660         }
1661
1662         private_layer->buffer_queue = NULL;
1663
1664         _pthread_mutex_unlock(&private_display->lock);
1665 }
1666
1667 EXTERN tdm_error
1668 tdm_layer_set_buffer_queue(tdm_layer *layer, tbm_surface_queue_h buffer_queue)
1669 {
1670         tdm_func_layer *func_layer;
1671         LAYER_FUNC_ENTRY();
1672
1673         TDM_RETURN_VAL_IF_FAIL(buffer_queue != NULL, TDM_ERROR_INVALID_PARAMETER);
1674
1675         _pthread_mutex_lock(&private_display->lock);
1676
1677         func_layer = &private_display->func_layer;
1678
1679         private_layer->usable = 0;
1680
1681         if (!func_layer->layer_set_buffer) {
1682                 _pthread_mutex_unlock(&private_display->lock);
1683                 TDM_ERR("not implemented!!");
1684                 return TDM_ERROR_NOT_IMPLEMENTED;
1685         }
1686
1687         if (buffer_queue == private_layer->buffer_queue) {
1688                 _pthread_mutex_unlock(&private_display->lock);
1689                 return TDM_ERROR_NONE;
1690         }
1691
1692         if (private_layer->waiting_buffer) {
1693                 _pthread_mutex_unlock(&private_display->lock);
1694                 tdm_buffer_unref_backend(private_layer->waiting_buffer);
1695                 tbm_surface_queue_release(private_layer->buffer_queue,
1696                                           private_layer->waiting_buffer);
1697                 private_layer->waiting_buffer = NULL;
1698                 _pthread_mutex_lock(&private_display->lock);
1699
1700                 if (tdm_debug_buffer)
1701                         TDM_INFO("layer(%p) waiting_buffer(%p)",
1702                                  private_layer, private_layer->waiting_buffer);
1703         }
1704
1705         private_layer->buffer_queue = buffer_queue;
1706         tbm_surface_queue_add_acquirable_cb(private_layer->buffer_queue,
1707                                             _tbm_layer_queue_acquirable_cb,
1708                                             layer);
1709         tbm_surface_queue_add_destroy_cb(private_layer->buffer_queue,
1710                                          _tbm_layer_queue_destroy_cb,
1711                                          layer);
1712         _pthread_mutex_unlock(&private_display->lock);
1713
1714         return ret;
1715 }
1716
1717 EXTERN tdm_error
1718 tdm_layer_unset_buffer_queue(tdm_layer *layer)
1719 {
1720         tdm_func_layer *func_layer;
1721         LAYER_FUNC_ENTRY();
1722
1723         _pthread_mutex_lock(&private_display->lock);
1724
1725         func_layer = &private_display->func_layer;
1726
1727         if (private_layer->waiting_buffer) {
1728                 _pthread_mutex_unlock(&private_display->lock);
1729                 tdm_buffer_unref_backend(private_layer->waiting_buffer);
1730                 tbm_surface_queue_release(private_layer->buffer_queue,
1731                                           private_layer->waiting_buffer);
1732                 private_layer->waiting_buffer = NULL;
1733                 _pthread_mutex_lock(&private_display->lock);
1734
1735                 if (tdm_debug_buffer)
1736                         TDM_INFO("layer(%p) waiting_buffer(%p)",
1737                                  private_layer, private_layer->waiting_buffer);
1738         }
1739
1740         if (private_layer->showing_buffer) {
1741                 _pthread_mutex_unlock(&private_display->lock);
1742                 tdm_buffer_unref_backend(private_layer->showing_buffer);
1743                 tbm_surface_queue_release(private_layer->buffer_queue,
1744                                           private_layer->showing_buffer);
1745                 _pthread_mutex_lock(&private_display->lock);
1746                 private_layer->showing_buffer = NULL;
1747
1748                 if (tdm_debug_buffer)
1749                         TDM_INFO("layer(%p) showing_buffer(%p)",
1750                                  private_layer, private_layer->showing_buffer);
1751         }
1752
1753         tbm_surface_queue_remove_acquirable_cb(private_layer->buffer_queue, _tbm_layer_queue_acquirable_cb, layer);
1754         tbm_surface_queue_remove_destroy_cb(private_layer->buffer_queue, _tbm_layer_queue_destroy_cb, layer);
1755         private_layer->buffer_queue = NULL;
1756         private_layer->usable = 1;
1757
1758         if (!func_layer->layer_unset_buffer) {
1759                 _pthread_mutex_unlock(&private_display->lock);
1760                 TDM_ERR("not implemented!!");
1761                 return TDM_ERROR_NOT_IMPLEMENTED;
1762         }
1763
1764         ret = func_layer->layer_unset_buffer(private_layer->layer_backend);
1765
1766         _pthread_mutex_unlock(&private_display->lock);
1767
1768         return ret;
1769 }
1770
1771 EXTERN tdm_error
1772 tdm_layer_is_usable(tdm_layer *layer, unsigned int *usable)
1773 {
1774         LAYER_FUNC_ENTRY();
1775
1776         TDM_RETURN_VAL_IF_FAIL(usable != NULL, TDM_ERROR_INVALID_PARAMETER);
1777
1778         _pthread_mutex_lock(&private_display->lock);
1779
1780         *usable = private_layer->usable;
1781
1782         _pthread_mutex_unlock(&private_display->lock);
1783
1784         return ret;
1785 }
1786
1787 EXTERN tdm_error
1788 tdm_layer_set_video_pos(tdm_layer *layer, int zpos)
1789 {
1790         tdm_func_layer *func_layer;
1791         LAYER_FUNC_ENTRY();
1792
1793         _pthread_mutex_lock(&private_display->lock);
1794
1795         func_layer = &private_display->func_layer;
1796
1797         if (!(private_layer->caps.capabilities & TDM_LAYER_CAPABILITY_VIDEO)) {
1798                 TDM_ERR("layer(%p) is not video layer", private_layer);
1799                 _pthread_mutex_unlock(&private_display->lock);
1800                 return TDM_ERROR_INVALID_PARAMETER;
1801         }
1802
1803         if (!func_layer->layer_set_video_pos) {
1804                 _pthread_mutex_unlock(&private_display->lock);
1805                 TDM_ERR("not implemented!!");
1806                 return TDM_ERROR_NOT_IMPLEMENTED;
1807         }
1808
1809         ret = func_layer->layer_set_video_pos(private_layer->layer_backend, zpos);
1810
1811         _pthread_mutex_unlock(&private_display->lock);
1812
1813         return ret;
1814 }
1815
1816 EXTERN tdm_capture *
1817 tdm_layer_create_capture(tdm_layer *layer, tdm_error *error)
1818 {
1819         tdm_capture *capture = NULL;
1820
1821         LAYER_FUNC_ENTRY_ERROR();
1822
1823         _pthread_mutex_lock(&private_display->lock);
1824
1825         capture = (tdm_capture *)tdm_capture_create_layer_internal(private_layer,
1826                         error);
1827
1828         _pthread_mutex_unlock(&private_display->lock);
1829
1830         return capture;
1831 }