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