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