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