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