0d6e2749fed66fc7ffc799c425eb7f0f14cea4b4
[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_ERR("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_ERR("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_ERR("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_ERR("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_ERR("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_ERR("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_ERR("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_ERR("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_ERR("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                 private_output->current_dpms_value = dpms_value;
1101                 TDM_WRN("not implemented!!");
1102                 return TDM_ERROR_NONE;
1103         }
1104
1105         ret = func_output->output_set_dpms(private_output->output_backend, dpms_value);
1106         if (ret == TDM_ERROR_NONE) {
1107                 tdm_value value;
1108
1109                 private_output->current_dpms_value = dpms_value;
1110
1111                 value.u32 = dpms_value;
1112                 tdm_output_call_change_handler_internal(private_output,
1113                                                         &private_output->change_handler_list_main,
1114                                                         TDM_OUTPUT_CHANGE_DPMS,
1115                                                         value);
1116         }
1117
1118         _pthread_mutex_unlock(&private_display->lock);
1119
1120         return ret;
1121 }
1122
1123 EXTERN tdm_error
1124 tdm_output_get_dpms(tdm_output *output, tdm_output_dpms *dpms_value)
1125 {
1126         tdm_func_output *func_output;
1127         OUTPUT_FUNC_ENTRY();
1128
1129         TDM_RETURN_VAL_IF_FAIL(dpms_value != NULL, TDM_ERROR_INVALID_PARAMETER);
1130
1131         _pthread_mutex_lock(&private_display->lock);
1132
1133         func_output = &private_display->func_output;
1134
1135         if (!func_output->output_get_dpms) {
1136                 *dpms_value = private_output->current_dpms_value;
1137                 _pthread_mutex_unlock(&private_display->lock);
1138                 TDM_WRN("not implemented!!");
1139                 return TDM_ERROR_NONE;
1140         }
1141
1142         ret = func_output->output_get_dpms(private_output->output_backend, dpms_value);
1143
1144         _pthread_mutex_unlock(&private_display->lock);
1145
1146         return ret;
1147 }
1148
1149 EXTERN tdm_capture *
1150 tdm_output_create_capture(tdm_output *output, tdm_error *error)
1151 {
1152         tdm_capture *capture = NULL;
1153
1154         OUTPUT_FUNC_ENTRY_ERROR();
1155
1156         _pthread_mutex_lock(&private_display->lock);
1157
1158         capture = (tdm_capture *)tdm_capture_create_output_internal(private_output,
1159                         error);
1160
1161         _pthread_mutex_unlock(&private_display->lock);
1162
1163         return capture;
1164 }
1165
1166 INTERN void
1167 tdm_output_call_change_handler_internal(tdm_private_output *private_output,
1168                                         struct list_head *change_handler_list,
1169                                         tdm_output_change_type type,
1170                                         tdm_value value)
1171 {
1172         tdm_private_display *private_display;
1173         tdm_private_change_handler *change_handler;
1174
1175         TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED());
1176         TDM_RETURN_IF_FAIL(private_output);
1177
1178         private_display = private_output->private_display;
1179         if (!tdm_thread_in_display_thread(syscall(SYS_gettid))) {
1180                 if (type & TDM_OUTPUT_CHANGE_CONNECTION)
1181                         TDM_INFO("output(%d) changed: %s (%d)",
1182                                  private_output->pipe, status_str(value.u32), value.u32);
1183                 if (type & TDM_OUTPUT_CHANGE_DPMS)
1184                         TDM_INFO("output(%d) changed: dpms %s (%d)",
1185                                  private_output->pipe, dpms_str(value.u32), value.u32);
1186         }
1187
1188         if (LIST_IS_EMPTY(change_handler_list))
1189                 return;
1190
1191         LIST_FOR_EACH_ENTRY(change_handler, change_handler_list, link) {
1192                 if (change_handler->owner_tid != syscall(SYS_gettid))
1193                         TDM_NEVER_GET_HERE();
1194
1195                 _pthread_mutex_unlock(&private_display->lock);
1196                 change_handler->func(private_output, type,
1197                                      value, change_handler->user_data);
1198                 _pthread_mutex_lock(&private_display->lock);
1199         }
1200 }
1201
1202 EXTERN tdm_error
1203 tdm_layer_get_capabilities(tdm_layer *layer, tdm_layer_capability *capabilities)
1204 {
1205         LAYER_FUNC_ENTRY();
1206
1207         TDM_RETURN_VAL_IF_FAIL(capabilities != NULL, TDM_ERROR_INVALID_PARAMETER);
1208
1209         _pthread_mutex_lock(&private_display->lock);
1210
1211         *capabilities = private_layer->caps.capabilities;
1212
1213         _pthread_mutex_unlock(&private_display->lock);
1214
1215         return ret;
1216 }
1217
1218 EXTERN tdm_error
1219 tdm_layer_get_available_formats(tdm_layer *layer, const tbm_format **formats,
1220                                 int *count)
1221 {
1222         LAYER_FUNC_ENTRY();
1223
1224         TDM_RETURN_VAL_IF_FAIL(formats != NULL, TDM_ERROR_INVALID_PARAMETER);
1225         TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
1226
1227         _pthread_mutex_lock(&private_display->lock);
1228
1229         *formats = (const tbm_format *)private_layer->caps.formats;
1230         *count = private_layer->caps.format_count;
1231
1232         _pthread_mutex_unlock(&private_display->lock);
1233
1234         return ret;
1235 }
1236
1237 EXTERN tdm_error
1238 tdm_layer_get_available_properties(tdm_layer *layer, const tdm_prop **props,
1239                                    int *count)
1240 {
1241         LAYER_FUNC_ENTRY();
1242
1243         TDM_RETURN_VAL_IF_FAIL(props != NULL, TDM_ERROR_INVALID_PARAMETER);
1244         TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
1245
1246         _pthread_mutex_lock(&private_display->lock);
1247
1248         *props = (const tdm_prop *)private_layer->caps.props;
1249         *count = private_layer->caps.prop_count;
1250
1251         _pthread_mutex_unlock(&private_display->lock);
1252
1253         return ret;
1254 }
1255
1256 EXTERN tdm_error
1257 tdm_layer_get_zpos(tdm_layer *layer, unsigned int *zpos)
1258 {
1259         LAYER_FUNC_ENTRY();
1260
1261         TDM_RETURN_VAL_IF_FAIL(zpos != NULL, TDM_ERROR_INVALID_PARAMETER);
1262
1263         _pthread_mutex_lock(&private_display->lock);
1264
1265         *zpos = private_layer->caps.zpos;
1266
1267         _pthread_mutex_unlock(&private_display->lock);
1268
1269         return ret;
1270 }
1271
1272 EXTERN tdm_error
1273 tdm_layer_set_property(tdm_layer *layer, unsigned int id, tdm_value value)
1274 {
1275         tdm_func_layer *func_layer;
1276         LAYER_FUNC_ENTRY();
1277
1278         _pthread_mutex_lock(&private_display->lock);
1279
1280         func_layer = &private_display->func_layer;
1281
1282         if (!func_layer->layer_set_property) {
1283                 _pthread_mutex_unlock(&private_display->lock);
1284                 TDM_ERR("not implemented!!");
1285                 return TDM_ERROR_NOT_IMPLEMENTED;
1286         }
1287
1288         ret = func_layer->layer_set_property(private_layer->layer_backend, id, value);
1289
1290         _pthread_mutex_unlock(&private_display->lock);
1291
1292         return ret;
1293 }
1294
1295 EXTERN tdm_error
1296 tdm_layer_get_property(tdm_layer *layer, unsigned int id, tdm_value *value)
1297 {
1298         tdm_func_layer *func_layer;
1299         LAYER_FUNC_ENTRY();
1300
1301         TDM_RETURN_VAL_IF_FAIL(value != NULL, TDM_ERROR_INVALID_PARAMETER);
1302
1303         _pthread_mutex_lock(&private_display->lock);
1304
1305         func_layer = &private_display->func_layer;
1306
1307         if (!func_layer->layer_get_property) {
1308                 _pthread_mutex_unlock(&private_display->lock);
1309                 TDM_ERR("not implemented!!");
1310                 return TDM_ERROR_NOT_IMPLEMENTED;
1311         }
1312
1313         ret = func_layer->layer_get_property(private_layer->layer_backend, id, value);
1314
1315         _pthread_mutex_unlock(&private_display->lock);
1316
1317         return ret;
1318 }
1319
1320 EXTERN tdm_error
1321 tdm_layer_set_info(tdm_layer *layer, tdm_info_layer *info)
1322 {
1323         tdm_func_layer *func_layer;
1324         LAYER_FUNC_ENTRY();
1325
1326         TDM_RETURN_VAL_IF_FAIL(info != NULL, TDM_ERROR_INVALID_PARAMETER);
1327
1328         _pthread_mutex_lock(&private_display->lock);
1329
1330         func_layer = &private_display->func_layer;
1331
1332         private_layer->usable = 0;
1333
1334         if (!func_layer->layer_set_info) {
1335                 _pthread_mutex_unlock(&private_display->lock);
1336                 TDM_ERR("not implemented!!");
1337                 return TDM_ERROR_NOT_IMPLEMENTED;
1338         }
1339
1340         TDM_INFO("layer(%p) info: src(%dx%d %d,%d %dx%d %c%c%c%c) dst(%d,%d %dx%d) trans(%d)",
1341                  private_layer, info->src_config.size.h, info->src_config.size.v,
1342                  info->src_config.pos.x, info->src_config.pos.y,
1343                  info->src_config.pos.w, info->src_config.pos.h,
1344                  FOURCC_STR(info->src_config.format),
1345                  info->dst_pos.x, info->dst_pos.y,
1346                  info->dst_pos.w, info->dst_pos.h,
1347                  info->transform);
1348
1349         ret = func_layer->layer_set_info(private_layer->layer_backend, info);
1350         TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
1351
1352         _pthread_mutex_unlock(&private_display->lock);
1353
1354         return ret;
1355 }
1356
1357 EXTERN tdm_error
1358 tdm_layer_get_info(tdm_layer *layer, tdm_info_layer *info)
1359 {
1360         tdm_func_layer *func_layer;
1361         LAYER_FUNC_ENTRY();
1362
1363         TDM_RETURN_VAL_IF_FAIL(info != NULL, TDM_ERROR_INVALID_PARAMETER);
1364
1365         _pthread_mutex_lock(&private_display->lock);
1366
1367         func_layer = &private_display->func_layer;
1368
1369         if (!func_layer->layer_get_info) {
1370                 _pthread_mutex_unlock(&private_display->lock);
1371                 TDM_ERR("not implemented!!");
1372                 return TDM_ERROR_NOT_IMPLEMENTED;
1373         }
1374
1375         ret = func_layer->layer_get_info(private_layer->layer_backend, info);
1376
1377         _pthread_mutex_unlock(&private_display->lock);
1378
1379         return ret;
1380 }
1381
1382 static void
1383 _tdm_layer_dump_buffer(tdm_layer *layer, tbm_surface_h buffer)
1384 {
1385         tdm_private_layer *private_layer = (tdm_private_layer*)layer;
1386         tdm_private_output *private_output = private_layer->private_output;
1387         char *path = NULL;
1388         int count;
1389         unsigned int pipe;
1390         int zpos;
1391         char fullpath[PATH_MAX];
1392         tbm_surface_info_s info;
1393         tbm_surface_error_e err;
1394
1395         path = tdm_helper_get_dump_path();
1396         if (!path)
1397                 return;
1398
1399         count = tdm_helper_get_dump_count();
1400         if (count <= 0)
1401                 return;
1402
1403         err = tbm_surface_map(buffer, TBM_SURF_OPTION_READ, &info);
1404         TDM_RETURN_IF_FAIL(err == TBM_SURFACE_ERROR_NONE);
1405
1406         pipe = private_output->pipe;
1407         zpos = private_layer->caps.zpos;
1408
1409         if (info.format == TBM_FORMAT_ARGB8888 || info.format == TBM_FORMAT_XRGB8888)
1410                 snprintf(fullpath, sizeof(fullpath), "%s/%03d_out_%d_lyr_%d.png",
1411                         path, count, pipe, zpos);
1412         else
1413                 snprintf(fullpath, sizeof(fullpath), "%s/%03d_out_%d_lyr_%d_%dx%d_%c%c%c%c.yuv",
1414                         path, count, pipe, zpos, info.planes[0].stride, info.height, FOURCC_STR(info.format));
1415
1416         tbm_surface_unmap(buffer);
1417
1418         tdm_helper_dump_buffer(buffer, fullpath);
1419         TDM_DBG("%d, %s dump excute", count, fullpath);
1420
1421         return;
1422 }
1423
1424 EXTERN tdm_error
1425 tdm_layer_set_buffer(tdm_layer *layer, tbm_surface_h buffer)
1426 {
1427         tdm_func_layer *func_layer;
1428
1429         LAYER_FUNC_ENTRY();
1430
1431         TDM_RETURN_VAL_IF_FAIL(buffer != NULL, TDM_ERROR_INVALID_PARAMETER);
1432
1433         _pthread_mutex_lock(&private_display->lock);
1434
1435         func_layer = &private_display->func_layer;
1436
1437         private_layer->usable = 0;
1438
1439         if (!func_layer->layer_set_buffer) {
1440                 _pthread_mutex_unlock(&private_display->lock);
1441                 TDM_ERR("not implemented!!");
1442                 return TDM_ERROR_NOT_IMPLEMENTED;
1443         }
1444
1445         ret = func_layer->layer_set_buffer(private_layer->layer_backend, buffer);
1446         TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
1447
1448         /* dump buffer */
1449         if (tdm_dump_enable)
1450                 _tdm_layer_dump_buffer(layer, buffer);
1451
1452         if (ret == TDM_ERROR_NONE) {
1453                 /* FIXME: should save to pending_buffer first. And after committing
1454                  * successfully, need to move to waiting_buffer.
1455                  */
1456                 if (private_layer->waiting_buffer) {
1457                         _pthread_mutex_unlock(&private_display->lock);
1458                         tdm_buffer_unref_backend(private_layer->waiting_buffer);
1459                         _pthread_mutex_lock(&private_display->lock);
1460                 }
1461
1462                 private_layer->waiting_buffer = tdm_buffer_ref_backend(buffer);
1463                 if (tdm_debug_buffer)
1464                         TDM_INFO("layer(%p) waiting_buffer(%p)",
1465                                  private_layer, private_layer->waiting_buffer);
1466         }
1467
1468         _pthread_mutex_unlock(&private_display->lock);
1469
1470         return ret;
1471 }
1472
1473 EXTERN tdm_error
1474 tdm_layer_unset_buffer(tdm_layer *layer)
1475 {
1476         tdm_func_layer *func_layer;
1477         LAYER_FUNC_ENTRY();
1478
1479         _pthread_mutex_lock(&private_display->lock);
1480
1481         func_layer = &private_display->func_layer;
1482
1483         if (private_layer->waiting_buffer) {
1484                 _pthread_mutex_unlock(&private_display->lock);
1485                 tdm_buffer_unref_backend(private_layer->waiting_buffer);
1486                 _pthread_mutex_lock(&private_display->lock);
1487                 private_layer->waiting_buffer = NULL;
1488
1489                 if (tdm_debug_buffer)
1490                         TDM_INFO("layer(%p) waiting_buffer(%p)",
1491                                  private_layer, private_layer->waiting_buffer);
1492         }
1493
1494         if (private_layer->showing_buffer) {
1495                 _pthread_mutex_unlock(&private_display->lock);
1496                 tdm_buffer_unref_backend(private_layer->showing_buffer);
1497                 _pthread_mutex_lock(&private_display->lock);
1498                 private_layer->showing_buffer = NULL;
1499
1500                 if (tdm_debug_buffer)
1501                         TDM_INFO("layer(%p) showing_buffer(%p)",
1502                                  private_layer, private_layer->showing_buffer);
1503         }
1504
1505         private_layer->usable = 1;
1506
1507         if (!func_layer->layer_unset_buffer) {
1508                 _pthread_mutex_unlock(&private_display->lock);
1509                 TDM_ERR("not implemented!!");
1510                 return TDM_ERROR_NOT_IMPLEMENTED;
1511         }
1512
1513         ret = func_layer->layer_unset_buffer(private_layer->layer_backend);
1514         TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
1515
1516         _pthread_mutex_unlock(&private_display->lock);
1517
1518         return ret;
1519 }
1520
1521 static void
1522 _tbm_layer_queue_acquirable_cb(tbm_surface_queue_h surface_queue, void *data)
1523 {
1524         TDM_RETURN_IF_FAIL(data != NULL);
1525         tdm_layer *layer = data;
1526         tdm_func_layer *func_layer;
1527         tbm_surface_h surface = NULL;
1528         LAYER_FUNC_ENTRY_VOID_RETURN();
1529
1530         _pthread_mutex_lock(&private_display->lock);
1531
1532         func_layer = &private_display->func_layer;
1533         if (!func_layer->layer_set_buffer) {
1534                 _pthread_mutex_unlock(&private_display->lock);
1535                 return;
1536         }
1537
1538         if (TBM_SURFACE_QUEUE_ERROR_NONE != tbm_surface_queue_acquire(
1539                     private_layer->buffer_queue, &surface) ||
1540             surface == NULL) {
1541                 TDM_ERR("layer(%p) tbm_surface_queue_acquire() failed surface:%p",
1542                         private_layer, surface);
1543                 _pthread_mutex_unlock(&private_display->lock);
1544                 return;
1545         }
1546
1547         ret = func_layer->layer_set_buffer(private_layer->layer_backend, surface);
1548         TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
1549
1550         if (ret == TDM_ERROR_NONE) {
1551                 if (private_layer->waiting_buffer) {
1552                         _pthread_mutex_unlock(&private_display->lock);
1553                         tdm_buffer_unref_backend(private_layer->waiting_buffer);
1554                         tbm_surface_queue_release(private_layer->buffer_queue,
1555                                                   private_layer->waiting_buffer);
1556                         _pthread_mutex_lock(&private_display->lock);
1557                 }
1558
1559                 private_layer->waiting_buffer = tdm_buffer_ref_backend(surface);
1560
1561                 if (tdm_debug_buffer)
1562                         TDM_INFO("layer(%p) waiting_buffer(%p)",
1563                                  private_layer, private_layer->waiting_buffer);
1564
1565                 ret = _tdm_output_commit(private_layer->private_output, 0, NULL, NULL);
1566                 if (ret != TDM_ERROR_NONE)
1567                         TDM_ERR("layer(%p) _tdm_output_commit() is fail", private_layer);
1568         }
1569
1570         _pthread_mutex_unlock(&private_display->lock);
1571 }
1572
1573 static void
1574 _tbm_layer_queue_destroy_cb(tbm_surface_queue_h surface_queue, void *data)
1575 {
1576         TDM_RETURN_IF_FAIL(data != NULL);
1577         tdm_layer *layer = data;
1578         LAYER_FUNC_ENTRY_VOID_RETURN();
1579         TDM_RETURN_IF_FAIL(ret == TDM_ERROR_NONE);
1580
1581         _pthread_mutex_lock(&private_display->lock);
1582
1583         if (private_layer->waiting_buffer) {
1584                 _pthread_mutex_unlock(&private_display->lock);
1585                 tdm_buffer_unref_backend(private_layer->waiting_buffer);
1586                 tbm_surface_queue_release(private_layer->buffer_queue,
1587                                           private_layer->waiting_buffer);
1588                 _pthread_mutex_lock(&private_display->lock);
1589         }
1590
1591         private_layer->buffer_queue = NULL;
1592
1593         _pthread_mutex_unlock(&private_display->lock);
1594 }
1595
1596 EXTERN tdm_error
1597 tdm_layer_set_buffer_queue(tdm_layer *layer, tbm_surface_queue_h buffer_queue)
1598 {
1599         tdm_func_layer *func_layer;
1600         LAYER_FUNC_ENTRY();
1601
1602         TDM_RETURN_VAL_IF_FAIL(buffer_queue != NULL, TDM_ERROR_INVALID_PARAMETER);
1603
1604         _pthread_mutex_lock(&private_display->lock);
1605
1606         func_layer = &private_display->func_layer;
1607
1608         private_layer->usable = 0;
1609
1610         if (!func_layer->layer_set_buffer) {
1611                 _pthread_mutex_unlock(&private_display->lock);
1612                 TDM_ERR("not implemented!!");
1613                 return TDM_ERROR_NOT_IMPLEMENTED;
1614         }
1615
1616         if (buffer_queue == private_layer->buffer_queue) {
1617                 _pthread_mutex_unlock(&private_display->lock);
1618                 return TDM_ERROR_NONE;
1619         }
1620
1621         if (private_layer->waiting_buffer) {
1622                 _pthread_mutex_unlock(&private_display->lock);
1623                 tdm_buffer_unref_backend(private_layer->waiting_buffer);
1624                 tbm_surface_queue_release(private_layer->buffer_queue,
1625                                           private_layer->waiting_buffer);
1626                 private_layer->waiting_buffer = NULL;
1627                 _pthread_mutex_lock(&private_display->lock);
1628
1629                 if (tdm_debug_buffer)
1630                         TDM_INFO("layer(%p) waiting_buffer(%p)",
1631                                  private_layer, private_layer->waiting_buffer);
1632         }
1633
1634         private_layer->buffer_queue = buffer_queue;
1635         tbm_surface_queue_add_acquirable_cb(private_layer->buffer_queue,
1636                                             _tbm_layer_queue_acquirable_cb,
1637                                             layer);
1638         tbm_surface_queue_add_destroy_cb(private_layer->buffer_queue,
1639                                          _tbm_layer_queue_destroy_cb,
1640                                          layer);
1641         _pthread_mutex_unlock(&private_display->lock);
1642
1643         return ret;
1644 }
1645
1646 EXTERN tdm_error
1647 tdm_layer_unset_buffer_queue(tdm_layer *layer)
1648 {
1649         tdm_func_layer *func_layer;
1650         LAYER_FUNC_ENTRY();
1651
1652         _pthread_mutex_lock(&private_display->lock);
1653
1654         func_layer = &private_display->func_layer;
1655
1656         if (private_layer->waiting_buffer) {
1657                 _pthread_mutex_unlock(&private_display->lock);
1658                 tdm_buffer_unref_backend(private_layer->waiting_buffer);
1659                 tbm_surface_queue_release(private_layer->buffer_queue,
1660                                           private_layer->waiting_buffer);
1661                 private_layer->waiting_buffer = NULL;
1662                 _pthread_mutex_lock(&private_display->lock);
1663
1664                 if (tdm_debug_buffer)
1665                         TDM_INFO("layer(%p) waiting_buffer(%p)",
1666                                  private_layer, private_layer->waiting_buffer);
1667         }
1668
1669         if (private_layer->showing_buffer) {
1670                 _pthread_mutex_unlock(&private_display->lock);
1671                 tdm_buffer_unref_backend(private_layer->showing_buffer);
1672                 tbm_surface_queue_release(private_layer->buffer_queue,
1673                                           private_layer->showing_buffer);
1674                 _pthread_mutex_lock(&private_display->lock);
1675                 private_layer->showing_buffer = NULL;
1676
1677                 if (tdm_debug_buffer)
1678                         TDM_INFO("layer(%p) showing_buffer(%p)",
1679                                  private_layer, private_layer->showing_buffer);
1680         }
1681
1682         tbm_surface_queue_remove_acquirable_cb(private_layer->buffer_queue, _tbm_layer_queue_acquirable_cb, layer);
1683         tbm_surface_queue_remove_destroy_cb(private_layer->buffer_queue, _tbm_layer_queue_destroy_cb, layer);
1684         private_layer->buffer_queue = NULL;
1685         private_layer->usable = 1;
1686
1687         if (!func_layer->layer_unset_buffer) {
1688                 _pthread_mutex_unlock(&private_display->lock);
1689                 TDM_ERR("not implemented!!");
1690                 return TDM_ERROR_NOT_IMPLEMENTED;
1691         }
1692
1693         ret = func_layer->layer_unset_buffer(private_layer->layer_backend);
1694
1695         _pthread_mutex_unlock(&private_display->lock);
1696
1697         return ret;
1698 }
1699
1700 EXTERN tdm_error
1701 tdm_layer_is_usable(tdm_layer *layer, unsigned int *usable)
1702 {
1703         LAYER_FUNC_ENTRY();
1704
1705         TDM_RETURN_VAL_IF_FAIL(usable != NULL, TDM_ERROR_INVALID_PARAMETER);
1706
1707         _pthread_mutex_lock(&private_display->lock);
1708
1709         *usable = private_layer->usable;
1710
1711         _pthread_mutex_unlock(&private_display->lock);
1712
1713         return ret;
1714 }
1715
1716 EXTERN tdm_error
1717 tdm_layer_set_video_pos(tdm_layer *layer, int zpos)
1718 {
1719         tdm_func_layer *func_layer;
1720         LAYER_FUNC_ENTRY();
1721
1722         _pthread_mutex_lock(&private_display->lock);
1723
1724         func_layer = &private_display->func_layer;
1725
1726         if (!(private_layer->caps.capabilities & TDM_LAYER_CAPABILITY_VIDEO)) {
1727                 TDM_ERR("layer(%p) is not video layer", private_layer);
1728                 _pthread_mutex_unlock(&private_display->lock);
1729                 return TDM_ERROR_INVALID_PARAMETER;
1730         }
1731
1732         if (!func_layer->layer_set_video_pos) {
1733                 _pthread_mutex_unlock(&private_display->lock);
1734                 TDM_ERR("not implemented!!");
1735                 return TDM_ERROR_NOT_IMPLEMENTED;
1736         }
1737
1738         ret = func_layer->layer_set_video_pos(private_layer->layer_backend, zpos);
1739
1740         _pthread_mutex_unlock(&private_display->lock);
1741
1742         return ret;
1743 }
1744
1745 EXTERN tdm_capture *
1746 tdm_layer_create_capture(tdm_layer *layer, tdm_error *error)
1747 {
1748         tdm_capture *capture = NULL;
1749
1750         LAYER_FUNC_ENTRY_ERROR();
1751
1752         _pthread_mutex_lock(&private_display->lock);
1753
1754         capture = (tdm_capture *)tdm_capture_create_layer_internal(private_layer,
1755                         error);
1756
1757         _pthread_mutex_unlock(&private_display->lock);
1758
1759         return capture;
1760 }