fix deadlock and enhance lock/unlock to protect the backend module's data
[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         tbm_surface_info_s info;
1390         tbm_surface_error_e err;
1391
1392         path = tdm_helper_get_dump_path();
1393         TDM_RETURN_IF_FAIL(path != NULL);
1394
1395         count = tdm_helper_get_dump_count();
1396         TDM_RETURN_IF_FAIL(count != 0);
1397
1398         err = tbm_surface_map(buffer, TBM_SURF_OPTION_READ, &info);
1399         TDM_RETURN_IF_FAIL(err == TBM_SURFACE_ERROR_NONE);
1400
1401         char fullpath[PATH_MAX] = {0, };
1402
1403         pipe = private_output->pipe;
1404         zpos = private_layer->caps.zpos;
1405
1406         if (info.format == TBM_FORMAT_ARGB8888 || info.format == TBM_FORMAT_XRGB8888)
1407                 snprintf(fullpath, sizeof(fullpath), "%s/%03d_out_%d_lyr_%d.png",
1408                         path, count, pipe, zpos);
1409         else
1410                 snprintf(fullpath, sizeof(fullpath), "%s/%03d_out_%d_lyr_%d_%dx%d_%c%c%c%c.yuv",
1411                         path, count, pipe, zpos, info.planes[0].stride, info.height, FOURCC_STR(info.format));
1412
1413         tbm_surface_unmap(buffer);
1414
1415         tdm_helper_dump_buffer(buffer, fullpath);
1416         TDM_DBG("%d, %s dump excute", count, fullpath);
1417
1418         return;
1419 }
1420
1421 EXTERN tdm_error
1422 tdm_layer_set_buffer(tdm_layer *layer, tbm_surface_h buffer)
1423 {
1424         tdm_func_layer *func_layer;
1425
1426         LAYER_FUNC_ENTRY();
1427
1428         TDM_RETURN_VAL_IF_FAIL(buffer != NULL, TDM_ERROR_INVALID_PARAMETER);
1429
1430         _pthread_mutex_lock(&private_display->lock);
1431
1432         func_layer = &private_display->func_layer;
1433
1434         private_layer->usable = 0;
1435
1436         if (!func_layer->layer_set_buffer) {
1437                 _pthread_mutex_unlock(&private_display->lock);
1438                 TDM_DBG("failed: not implemented!!");
1439                 return TDM_ERROR_NOT_IMPLEMENTED;
1440         }
1441
1442         ret = func_layer->layer_set_buffer(private_layer->layer_backend, buffer);
1443         TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
1444
1445         /* dump buffer */
1446         _tdm_layer_dump_buffer(layer, buffer);
1447
1448         if (ret == TDM_ERROR_NONE) {
1449                 /* FIXME: should save to pending_buffer first. And after committing
1450                  * successfully, need to move to waiting_buffer.
1451                  */
1452                 if (private_layer->waiting_buffer) {
1453                         _pthread_mutex_unlock(&private_display->lock);
1454                         tdm_buffer_unref_backend(private_layer->waiting_buffer);
1455                         _pthread_mutex_lock(&private_display->lock);
1456                 }
1457
1458                 private_layer->waiting_buffer = tdm_buffer_ref_backend(buffer);
1459                 if (tdm_debug_buffer)
1460                         TDM_INFO("layer(%p) waiting_buffer(%p)",
1461                                  private_layer, private_layer->waiting_buffer);
1462         }
1463
1464         _pthread_mutex_unlock(&private_display->lock);
1465
1466         return ret;
1467 }
1468
1469 EXTERN tdm_error
1470 tdm_layer_unset_buffer(tdm_layer *layer)
1471 {
1472         tdm_func_layer *func_layer;
1473         LAYER_FUNC_ENTRY();
1474
1475         _pthread_mutex_lock(&private_display->lock);
1476
1477         func_layer = &private_display->func_layer;
1478
1479         if (private_layer->waiting_buffer) {
1480                 _pthread_mutex_unlock(&private_display->lock);
1481                 tdm_buffer_unref_backend(private_layer->waiting_buffer);
1482                 _pthread_mutex_lock(&private_display->lock);
1483                 private_layer->waiting_buffer = NULL;
1484
1485                 if (tdm_debug_buffer)
1486                         TDM_INFO("layer(%p) waiting_buffer(%p)",
1487                                  private_layer, private_layer->waiting_buffer);
1488         }
1489
1490         if (private_layer->showing_buffer) {
1491                 _pthread_mutex_unlock(&private_display->lock);
1492                 tdm_buffer_unref_backend(private_layer->showing_buffer);
1493                 _pthread_mutex_lock(&private_display->lock);
1494                 private_layer->showing_buffer = NULL;
1495
1496                 if (tdm_debug_buffer)
1497                         TDM_INFO("layer(%p) showing_buffer(%p)",
1498                                  private_layer, private_layer->showing_buffer);
1499         }
1500
1501         private_layer->usable = 1;
1502
1503         if (!func_layer->layer_unset_buffer) {
1504                 _pthread_mutex_unlock(&private_display->lock);
1505                 TDM_DBG("failed: not implemented!!");
1506                 return TDM_ERROR_NOT_IMPLEMENTED;
1507         }
1508
1509         ret = func_layer->layer_unset_buffer(private_layer->layer_backend);
1510         TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
1511
1512         _pthread_mutex_unlock(&private_display->lock);
1513
1514         return ret;
1515 }
1516
1517 static void
1518 _tbm_layer_queue_acquirable_cb(tbm_surface_queue_h surface_queue, void *data)
1519 {
1520         TDM_RETURN_IF_FAIL(data != NULL);
1521         tdm_layer *layer = data;
1522         tdm_func_layer *func_layer;
1523         tbm_surface_h surface = NULL;
1524         LAYER_FUNC_ENTRY_VOID_RETURN();
1525
1526         _pthread_mutex_lock(&private_display->lock);
1527
1528         func_layer = &private_display->func_layer;
1529         if (!func_layer->layer_set_buffer) {
1530                 _pthread_mutex_unlock(&private_display->lock);
1531                 return;
1532         }
1533
1534         if (TBM_SURFACE_QUEUE_ERROR_NONE != tbm_surface_queue_acquire(
1535                     private_layer->buffer_queue, &surface) ||
1536             surface == NULL) {
1537                 TDM_ERR("layer(%p) tbm_surface_queue_acquire() failed surface:%p",
1538                         private_layer, surface);
1539                 _pthread_mutex_unlock(&private_display->lock);
1540                 return;
1541         }
1542
1543         ret = func_layer->layer_set_buffer(private_layer->layer_backend, surface);
1544         TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
1545
1546         if (ret == TDM_ERROR_NONE) {
1547                 if (private_layer->waiting_buffer) {
1548                         _pthread_mutex_unlock(&private_display->lock);
1549                         tdm_buffer_unref_backend(private_layer->waiting_buffer);
1550                         tbm_surface_queue_release(private_layer->buffer_queue,
1551                                                   private_layer->waiting_buffer);
1552                         _pthread_mutex_lock(&private_display->lock);
1553                 }
1554
1555                 private_layer->waiting_buffer = tdm_buffer_ref_backend(surface);
1556
1557                 if (tdm_debug_buffer)
1558                         TDM_INFO("layer(%p) waiting_buffer(%p)",
1559                                  private_layer, private_layer->waiting_buffer);
1560
1561                 ret = _tdm_output_commit(private_layer->private_output, 0, NULL, NULL);
1562                 if (ret != TDM_ERROR_NONE)
1563                         TDM_ERR("layer(%p) _tdm_output_commit() is fail", private_layer);
1564         }
1565
1566         _pthread_mutex_unlock(&private_display->lock);
1567 }
1568
1569 static void
1570 _tbm_layer_queue_destroy_cb(tbm_surface_queue_h surface_queue, void *data)
1571 {
1572         TDM_RETURN_IF_FAIL(data != NULL);
1573         tdm_layer *layer = data;
1574         LAYER_FUNC_ENTRY_VOID_RETURN();
1575         TDM_RETURN_IF_FAIL(ret == TDM_ERROR_NONE);
1576
1577         _pthread_mutex_lock(&private_display->lock);
1578
1579         if (private_layer->waiting_buffer) {
1580                 _pthread_mutex_unlock(&private_display->lock);
1581                 tdm_buffer_unref_backend(private_layer->waiting_buffer);
1582                 tbm_surface_queue_release(private_layer->buffer_queue,
1583                                           private_layer->waiting_buffer);
1584                 _pthread_mutex_lock(&private_display->lock);
1585         }
1586
1587         private_layer->buffer_queue = NULL;
1588
1589         _pthread_mutex_unlock(&private_display->lock);
1590 }
1591
1592 EXTERN tdm_error
1593 tdm_layer_set_buffer_queue(tdm_layer *layer, tbm_surface_queue_h buffer_queue)
1594 {
1595         tdm_func_layer *func_layer;
1596         LAYER_FUNC_ENTRY();
1597
1598         TDM_RETURN_VAL_IF_FAIL(buffer_queue != NULL, TDM_ERROR_INVALID_PARAMETER);
1599
1600         _pthread_mutex_lock(&private_display->lock);
1601
1602         func_layer = &private_display->func_layer;
1603
1604         private_layer->usable = 0;
1605
1606         if (!func_layer->layer_set_buffer) {
1607                 _pthread_mutex_unlock(&private_display->lock);
1608                 TDM_DBG("failed: not implemented!!");
1609                 return TDM_ERROR_NOT_IMPLEMENTED;
1610         }
1611
1612         if (buffer_queue == private_layer->buffer_queue) {
1613                 _pthread_mutex_unlock(&private_display->lock);
1614                 return TDM_ERROR_NONE;
1615         }
1616
1617         if (private_layer->waiting_buffer) {
1618                 _pthread_mutex_unlock(&private_display->lock);
1619                 tdm_buffer_unref_backend(private_layer->waiting_buffer);
1620                 tbm_surface_queue_release(private_layer->buffer_queue,
1621                                           private_layer->waiting_buffer);
1622                 private_layer->waiting_buffer = NULL;
1623                 _pthread_mutex_lock(&private_display->lock);
1624
1625                 if (tdm_debug_buffer)
1626                         TDM_INFO("layer(%p) waiting_buffer(%p)",
1627                                  private_layer, private_layer->waiting_buffer);
1628         }
1629
1630         private_layer->buffer_queue = buffer_queue;
1631         tbm_surface_queue_add_acquirable_cb(private_layer->buffer_queue,
1632                                             _tbm_layer_queue_acquirable_cb,
1633                                             layer);
1634         tbm_surface_queue_add_destroy_cb(private_layer->buffer_queue,
1635                                          _tbm_layer_queue_destroy_cb,
1636                                          layer);
1637         _pthread_mutex_unlock(&private_display->lock);
1638
1639         return ret;
1640 }
1641
1642 EXTERN tdm_error
1643 tdm_layer_unset_buffer_queue(tdm_layer *layer)
1644 {
1645         tdm_func_layer *func_layer;
1646         LAYER_FUNC_ENTRY();
1647
1648         _pthread_mutex_lock(&private_display->lock);
1649
1650         func_layer = &private_display->func_layer;
1651
1652         if (private_layer->waiting_buffer) {
1653                 _pthread_mutex_unlock(&private_display->lock);
1654                 tdm_buffer_unref_backend(private_layer->waiting_buffer);
1655                 tbm_surface_queue_release(private_layer->buffer_queue,
1656                                           private_layer->waiting_buffer);
1657                 private_layer->waiting_buffer = NULL;
1658                 _pthread_mutex_lock(&private_display->lock);
1659
1660                 if (tdm_debug_buffer)
1661                         TDM_INFO("layer(%p) waiting_buffer(%p)",
1662                                  private_layer, private_layer->waiting_buffer);
1663         }
1664
1665         if (private_layer->showing_buffer) {
1666                 _pthread_mutex_unlock(&private_display->lock);
1667                 tdm_buffer_unref_backend(private_layer->showing_buffer);
1668                 tbm_surface_queue_release(private_layer->buffer_queue,
1669                                           private_layer->showing_buffer);
1670                 _pthread_mutex_lock(&private_display->lock);
1671                 private_layer->showing_buffer = NULL;
1672
1673                 if (tdm_debug_buffer)
1674                         TDM_INFO("layer(%p) showing_buffer(%p)",
1675                                  private_layer, private_layer->showing_buffer);
1676         }
1677
1678         tbm_surface_queue_remove_acquirable_cb(private_layer->buffer_queue, _tbm_layer_queue_acquirable_cb, layer);
1679         tbm_surface_queue_remove_destroy_cb(private_layer->buffer_queue, _tbm_layer_queue_destroy_cb, layer);
1680         private_layer->buffer_queue = NULL;
1681         private_layer->usable = 1;
1682
1683         if (!func_layer->layer_unset_buffer) {
1684                 _pthread_mutex_unlock(&private_display->lock);
1685                 TDM_DBG("failed: not implemented!!");
1686                 return TDM_ERROR_NOT_IMPLEMENTED;
1687         }
1688
1689         ret = func_layer->layer_unset_buffer(private_layer->layer_backend);
1690
1691         _pthread_mutex_unlock(&private_display->lock);
1692
1693         return ret;
1694 }
1695
1696 EXTERN tdm_error
1697 tdm_layer_is_usable(tdm_layer *layer, unsigned int *usable)
1698 {
1699         LAYER_FUNC_ENTRY();
1700
1701         TDM_RETURN_VAL_IF_FAIL(usable != NULL, TDM_ERROR_INVALID_PARAMETER);
1702
1703         _pthread_mutex_lock(&private_display->lock);
1704
1705         *usable = private_layer->usable;
1706
1707         _pthread_mutex_unlock(&private_display->lock);
1708
1709         return ret;
1710 }
1711
1712 EXTERN tdm_error
1713 tdm_layer_set_video_pos(tdm_layer *layer, int zpos)
1714 {
1715         tdm_func_layer *func_layer;
1716         LAYER_FUNC_ENTRY();
1717
1718         _pthread_mutex_lock(&private_display->lock);
1719
1720         func_layer = &private_display->func_layer;
1721
1722         if (!(private_layer->caps.capabilities & TDM_LAYER_CAPABILITY_VIDEO)) {
1723                 TDM_ERR("layer(%p) is not video layer", private_layer);
1724                 _pthread_mutex_unlock(&private_display->lock);
1725                 return TDM_ERROR_INVALID_PARAMETER;
1726         }
1727
1728         if (!func_layer->layer_set_video_pos) {
1729                 _pthread_mutex_unlock(&private_display->lock);
1730                 TDM_DBG("failed: not implemented!!");
1731                 return TDM_ERROR_NOT_IMPLEMENTED;
1732         }
1733
1734         ret = func_layer->layer_set_video_pos(private_layer->layer_backend, zpos);
1735
1736         _pthread_mutex_unlock(&private_display->lock);
1737
1738         return ret;
1739 }
1740
1741 EXTERN tdm_capture *
1742 tdm_layer_create_capture(tdm_layer *layer, tdm_error *error)
1743 {
1744         tdm_capture *capture = NULL;
1745
1746         LAYER_FUNC_ENTRY_ERROR();
1747
1748         _pthread_mutex_lock(&private_display->lock);
1749
1750         capture = (tdm_capture *)tdm_capture_create_layer_internal(private_layer,
1751                         error);
1752
1753         _pthread_mutex_unlock(&private_display->lock);
1754
1755         return capture;
1756 }