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