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