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