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