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