1 /**************************************************************************
5 * Copyright 2015 Samsung Electronics co., Ltd. All Rights Reserved.
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>
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:
22 * The above copyright notice and this permission notice (including the
23 * next paragraph) shall be included in all copies or substantial portions
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.
34 **************************************************************************/
41 #include "tdm_backend.h"
42 #include "tdm_private.h"
43 #include "tdm_helper.h"
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;
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;
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
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
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
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
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
105 static void _tdm_layer_committed(tdm_private_layer *private_layer);
106 static void _tdm_layer_cb_output_commit(tdm_output *output, unsigned int sequence,
107 unsigned int tv_sec, unsigned int tv_usec, void *user_data);
108 static void _tdm_layer_cb_wait_vblank(tdm_vblank *vblank, tdm_error error, unsigned int sequence,
109 unsigned int tv_sec, unsigned int tv_usec, void *user_data);
112 tdm_display_get_capabilities(tdm_display *dpy,
113 tdm_display_capability *capabilities)
115 DISPLAY_FUNC_ENTRY();
117 TDM_RETURN_VAL_IF_FAIL(capabilities != NULL, TDM_ERROR_INVALID_PARAMETER);
119 _pthread_mutex_lock(&private_display->lock);
121 *capabilities = private_display->capabilities;
123 _pthread_mutex_unlock(&private_display->lock);
129 tdm_display_get_pp_capabilities(tdm_display *dpy,
130 tdm_pp_capability *capabilities)
132 DISPLAY_FUNC_ENTRY();
134 TDM_RETURN_VAL_IF_FAIL(capabilities != NULL, TDM_ERROR_INVALID_PARAMETER);
136 _pthread_mutex_lock(&private_display->lock);
138 if (!(private_display->capabilities & TDM_DISPLAY_CAPABILITY_PP)) {
139 TDM_ERR("no pp capability");
140 _pthread_mutex_unlock(&private_display->lock);
141 return TDM_ERROR_NO_CAPABILITY;
144 *capabilities = private_display->caps_pp.capabilities;
146 _pthread_mutex_unlock(&private_display->lock);
152 tdm_display_get_pp_available_formats(tdm_display *dpy,
153 const tbm_format **formats, int *count)
155 DISPLAY_FUNC_ENTRY();
157 TDM_RETURN_VAL_IF_FAIL(formats != NULL, TDM_ERROR_INVALID_PARAMETER);
158 TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
160 _pthread_mutex_lock(&private_display->lock);
162 if (!(private_display->capabilities & TDM_DISPLAY_CAPABILITY_PP)) {
163 TDM_ERR("no pp capability");
164 _pthread_mutex_unlock(&private_display->lock);
165 return TDM_ERROR_NO_CAPABILITY;
168 *formats = (const tbm_format *)private_display->caps_pp.formats;
169 *count = private_display->caps_pp.format_count;
171 _pthread_mutex_unlock(&private_display->lock);
177 tdm_display_get_pp_available_size(tdm_display *dpy, int *min_w, int *min_h,
178 int *max_w, int *max_h, int *preferred_align)
180 DISPLAY_FUNC_ENTRY();
182 _pthread_mutex_lock(&private_display->lock);
184 if (!(private_display->capabilities & TDM_DISPLAY_CAPABILITY_PP)) {
185 TDM_ERR("no pp capability");
186 _pthread_mutex_unlock(&private_display->lock);
187 return TDM_ERROR_NO_CAPABILITY;
191 *min_w = TDM_FRONT_VALUE(private_display->caps_pp.min_w);
193 *min_h = TDM_FRONT_VALUE(private_display->caps_pp.min_h);
195 *max_w = TDM_FRONT_VALUE(private_display->caps_pp.max_w);
197 *max_h = TDM_FRONT_VALUE(private_display->caps_pp.max_h);
199 *preferred_align = TDM_FRONT_VALUE(private_display->caps_pp.preferred_align);
201 _pthread_mutex_unlock(&private_display->lock);
207 tdm_display_get_capture_capabilities(tdm_display *dpy,
208 tdm_capture_capability *capabilities)
210 DISPLAY_FUNC_ENTRY();
212 TDM_RETURN_VAL_IF_FAIL(capabilities != NULL, TDM_ERROR_INVALID_PARAMETER);
214 _pthread_mutex_lock(&private_display->lock);
216 if (!(private_display->capabilities & TDM_DISPLAY_CAPABILITY_CAPTURE)) {
217 TDM_ERR("no capture capability");
218 _pthread_mutex_unlock(&private_display->lock);
219 return TDM_ERROR_NO_CAPABILITY;
222 *capabilities = private_display->caps_capture.capabilities;
224 _pthread_mutex_unlock(&private_display->lock);
230 tdm_display_get_catpure_available_formats(tdm_display *dpy,
231 const tbm_format **formats, int *count)
233 DISPLAY_FUNC_ENTRY();
235 TDM_RETURN_VAL_IF_FAIL(formats != NULL, TDM_ERROR_INVALID_PARAMETER);
236 TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
238 _pthread_mutex_lock(&private_display->lock);
240 if (!(private_display->capabilities & TDM_DISPLAY_CAPABILITY_CAPTURE)) {
241 TDM_ERR("no capture capability");
242 _pthread_mutex_unlock(&private_display->lock);
243 return TDM_ERROR_NO_CAPABILITY;
246 *formats = (const tbm_format *)private_display->caps_capture.formats;
247 *count = private_display->caps_capture.format_count;
249 _pthread_mutex_unlock(&private_display->lock);
255 tdm_display_get_capture_available_size(tdm_display *dpy, int *min_w, int *min_h,
256 int *max_w, int *max_h, int *preferred_align)
258 DISPLAY_FUNC_ENTRY();
260 _pthread_mutex_lock(&private_display->lock);
262 if (!(private_display->capabilities & TDM_DISPLAY_CAPABILITY_CAPTURE)) {
263 TDM_ERR("no capture capability");
264 _pthread_mutex_unlock(&private_display->lock);
265 return TDM_ERROR_NO_CAPABILITY;
269 *min_w = TDM_FRONT_VALUE(private_display->caps_capture.min_w);
271 *min_h = TDM_FRONT_VALUE(private_display->caps_capture.min_h);
273 *max_w = TDM_FRONT_VALUE(private_display->caps_capture.max_w);
275 *max_h = TDM_FRONT_VALUE(private_display->caps_capture.max_h);
277 *preferred_align = TDM_FRONT_VALUE(private_display->caps_capture.preferred_align);
279 _pthread_mutex_unlock(&private_display->lock);
285 tdm_display_get_max_layer_count(tdm_display *dpy, int *max_count)
287 DISPLAY_FUNC_ENTRY();
289 TDM_RETURN_VAL_IF_FAIL(max_count != NULL, TDM_ERROR_INVALID_PARAMETER);
291 _pthread_mutex_lock(&private_display->lock);
293 *max_count = TDM_FRONT_VALUE(private_display->caps_display.max_layer_count);
295 _pthread_mutex_unlock(&private_display->lock);
301 tdm_display_get_output_count(tdm_display *dpy, int *count)
303 tdm_private_output *private_output = NULL;
305 DISPLAY_FUNC_ENTRY();
307 TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
309 _pthread_mutex_lock(&private_display->lock);
312 LIST_FOR_EACH_ENTRY(private_output, &private_display->output_list, link)
316 _pthread_mutex_unlock(&private_display->lock);
317 return TDM_ERROR_NONE;
320 _pthread_mutex_unlock(&private_display->lock);
327 tdm_display_get_output(tdm_display *dpy, int index, tdm_error *error)
329 tdm_private_output *private_output = NULL;
331 DISPLAY_FUNC_ENTRY_ERROR();
333 _pthread_mutex_lock(&private_display->lock);
336 *error = TDM_ERROR_NONE;
338 LIST_FOR_EACH_ENTRY(private_output, &private_display->output_list, link) {
339 if (private_output->index == index) {
340 _pthread_mutex_unlock(&private_display->lock);
341 return private_output;
345 _pthread_mutex_unlock(&private_display->lock);
351 tdm_display_get_fd(tdm_display *dpy, int *fd)
353 DISPLAY_FUNC_ENTRY();
355 TDM_RETURN_VAL_IF_FAIL(fd != NULL, TDM_ERROR_INVALID_PARAMETER);
357 _pthread_mutex_lock(&private_display->lock);
359 if (tdm_thread_is_running())
360 *fd = tdm_thread_get_fd(private_display->private_loop);
362 *fd = tdm_event_loop_get_fd(private_display);
364 _pthread_mutex_unlock(&private_display->lock);
370 tdm_display_handle_events(tdm_display *dpy)
375 DISPLAY_FUNC_ENTRY();
377 ret = tdm_display_get_fd(dpy, &fd);
378 TDM_RETURN_VAL_IF_FAIL(fd >= 0, ret);
384 if (tdm_debug_module & TDM_DEBUG_THREAD)
385 TDM_INFO("fd(%d) polling in", fd);
387 while (poll(&fds, 1, -1) < 0) {
388 if (errno == EINTR || errno == EAGAIN) /* normal case */
391 TDM_ERR("poll failed: %m");
392 return TDM_ERROR_OPERATION_FAILED;
396 if (tdm_debug_module & TDM_DEBUG_THREAD)
397 TDM_INFO("fd(%d) polling out", fd);
399 if (tdm_thread_is_running())
400 ret = tdm_thread_handle_cb(private_display->private_loop);
402 ret = tdm_event_loop_dispatch(private_display);
408 tdm_display_get_backend_info(tdm_display *dpy, const char **name,
409 const char **vendor, int *major, int *minor)
411 tdm_backend_module *module_data;
413 DISPLAY_FUNC_ENTRY();
415 _pthread_mutex_lock(&private_display->lock);
417 module_data = private_display->module_data;
420 *name = module_data->name;
422 *vendor = module_data->vendor;
424 *major = TDM_BACKEND_GET_ABI_MAJOR(module_data->abi_version);
426 *minor = TDM_BACKEND_GET_ABI_MINOR(module_data->abi_version);
428 _pthread_mutex_unlock(&private_display->lock);
434 tdm_display_create_pp(tdm_display *dpy, tdm_error *error)
438 DISPLAY_FUNC_ENTRY_ERROR();
440 _pthread_mutex_lock(&private_display->lock);
442 pp = (tdm_pp *)tdm_pp_create_internal(private_display, error);
444 _pthread_mutex_unlock(&private_display->lock);
450 tdm_output_get_model_info(tdm_output *output, const char **maker,
451 const char **model, const char **name)
455 _pthread_mutex_lock(&private_display->lock);
458 *maker = private_output->caps.maker;
460 *model = private_output->caps.model;
462 *name = private_output->caps.name;
464 _pthread_mutex_unlock(&private_display->lock);
470 tdm_output_get_capabilities(tdm_output *output, tdm_output_capability *capabilities)
474 TDM_RETURN_VAL_IF_FAIL(capabilities != NULL, TDM_ERROR_INVALID_PARAMETER);
476 _pthread_mutex_lock(&private_display->lock);
478 *capabilities = private_output->caps.capabilities;
480 _pthread_mutex_unlock(&private_display->lock);
486 tdm_output_get_conn_status(tdm_output *output, tdm_output_conn_status *status)
490 TDM_RETURN_VAL_IF_FAIL(status != NULL, TDM_ERROR_INVALID_PARAMETER);
492 _pthread_mutex_lock(&private_display->lock);
494 *status = private_output->caps.status;
496 _pthread_mutex_unlock(&private_display->lock);
502 _tdm_output_used_layer_count(tdm_private_output *private_output)
504 tdm_private_layer *private_layer = NULL;
505 unsigned int count = 0;
507 LIST_FOR_EACH_ENTRY(private_layer, &private_output->layer_list, link) {
508 if (!private_layer->usable)
516 _tdm_output_update(tdm_output *output_backend, void *user_data)
518 tdm_private_display *private_display;
519 tdm_private_output *private_output = user_data;
522 TDM_RETURN_IF_FAIL(private_output);
524 private_display = private_output->private_display;
526 ret = tdm_display_update_output(private_display, output_backend, private_output->pipe);
527 TDM_RETURN_IF_FAIL(ret == TDM_ERROR_NONE);
531 tdm_output_cb_status(tdm_output *output_backend, tdm_output_conn_status status,
534 tdm_private_display *private_display;
535 tdm_private_output *private_output = user_data;
538 TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED());
539 TDM_RETURN_IF_FAIL(private_output);
541 private_display = private_output->private_display;
543 if (!tdm_thread_in_display_thread(syscall(SYS_gettid))) {
544 tdm_thread_cb_output_status output_status;
547 _tdm_output_update(output_backend, user_data);
549 output_status.base.type = TDM_THREAD_CB_OUTPUT_STATUS;
550 output_status.base.length = sizeof output_status;
551 output_status.output_stamp = private_output->stamp;
552 output_status.status = status;
553 output_status.user_data = user_data;
556 tdm_output_call_change_handler_internal(private_output,
557 &private_output->change_handler_list_sub,
558 TDM_OUTPUT_CHANGE_CONNECTION,
561 ret = tdm_thread_send_cb(private_display->private_loop, &output_status.base);
562 TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
567 if (!tdm_thread_is_running())
568 _tdm_output_update(output_backend, user_data);
571 tdm_output_call_change_handler_internal(private_output,
572 &private_output->change_handler_list_main,
573 TDM_OUTPUT_CHANGE_CONNECTION,
578 tdm_output_add_change_handler(tdm_output *output,
579 tdm_output_change_handler func,
582 tdm_private_change_handler *change_handler;
585 TDM_RETURN_VAL_IF_FAIL(func != NULL, TDM_ERROR_INVALID_PARAMETER);
587 pthread_mutex_lock(&private_display->lock);
589 change_handler = calloc(1, sizeof(tdm_private_change_handler));
590 if (!change_handler) {
591 TDM_ERR("failed: alloc memory");
592 _pthread_mutex_unlock(&private_display->lock);
593 return TDM_ERROR_OUT_OF_MEMORY;
596 change_handler->private_output = private_output;
597 change_handler->func = func;
598 change_handler->user_data = user_data;
599 change_handler->owner_tid = syscall(SYS_gettid);
601 if (!tdm_thread_in_display_thread(change_handler->owner_tid))
602 LIST_ADD(&change_handler->link, &private_output->change_handler_list_sub);
604 LIST_ADD(&change_handler->link, &private_output->change_handler_list_main);
606 _pthread_mutex_unlock(&private_display->lock);
612 tdm_output_remove_change_handler(tdm_output *output,
613 tdm_output_change_handler func,
616 tdm_private_display *private_display;
617 tdm_private_output *private_output;
618 tdm_private_change_handler *h = NULL, *hh = NULL;
620 TDM_RETURN_IF_FAIL(output != NULL);
621 TDM_RETURN_IF_FAIL(func != NULL);
623 private_output = (tdm_private_output*)output;
624 private_display = private_output->private_display;
626 _pthread_mutex_lock(&private_display->lock);
628 LIST_FOR_EACH_ENTRY_SAFE(h, hh, &private_output->change_handler_list_main, link) {
629 if (h->func != func || h->user_data != user_data)
635 _pthread_mutex_unlock(&private_display->lock);
640 LIST_FOR_EACH_ENTRY_SAFE(h, hh, &private_output->change_handler_list_sub, link) {
641 if (h->func != func || h->user_data != user_data)
647 _pthread_mutex_unlock(&private_display->lock);
652 _pthread_mutex_unlock(&private_display->lock);
656 tdm_output_get_output_type(tdm_output *output, tdm_output_type *type)
660 TDM_RETURN_VAL_IF_FAIL(type != NULL, TDM_ERROR_INVALID_PARAMETER);
662 _pthread_mutex_lock(&private_display->lock);
664 *type = private_output->caps.type;
666 _pthread_mutex_unlock(&private_display->lock);
672 tdm_output_get_layer_count(tdm_output *output, int *count)
674 tdm_private_layer *private_layer = NULL;
678 TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
680 _pthread_mutex_lock(&private_display->lock);
683 LIST_FOR_EACH_ENTRY(private_layer, &private_output->layer_list, link)
686 _pthread_mutex_unlock(&private_display->lock);
687 return TDM_ERROR_NONE;
690 _pthread_mutex_unlock(&private_display->lock);
697 tdm_output_get_layer(tdm_output *output, int index, tdm_error *error)
699 tdm_private_layer *private_layer = NULL;
701 OUTPUT_FUNC_ENTRY_ERROR();
703 _pthread_mutex_lock(&private_display->lock);
706 *error = TDM_ERROR_NONE;
708 LIST_FOR_EACH_ENTRY(private_layer, &private_output->layer_list, link) {
709 if (private_layer->index == index) {
710 _pthread_mutex_unlock(&private_display->lock);
711 return private_layer;
715 _pthread_mutex_unlock(&private_display->lock);
721 tdm_output_get_available_properties(tdm_output *output, const tdm_prop **props,
726 TDM_RETURN_VAL_IF_FAIL(props != NULL, TDM_ERROR_INVALID_PARAMETER);
727 TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
729 _pthread_mutex_lock(&private_display->lock);
731 *props = (const tdm_prop *)private_output->caps.props;
732 *count = private_output->caps.prop_count;
734 _pthread_mutex_unlock(&private_display->lock);
740 tdm_output_get_available_modes(tdm_output *output,
741 const tdm_output_mode **modes, int *count)
745 TDM_RETURN_VAL_IF_FAIL(modes != NULL, TDM_ERROR_INVALID_PARAMETER);
746 TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
748 _pthread_mutex_lock(&private_display->lock);
750 *modes = (const tdm_output_mode *)private_output->caps.modes;
751 *count = private_output->caps.mode_count;
753 _pthread_mutex_unlock(&private_display->lock);
759 tdm_output_get_available_size(tdm_output *output, int *min_w, int *min_h,
760 int *max_w, int *max_h, int *preferred_align)
764 _pthread_mutex_lock(&private_display->lock);
767 *min_w = TDM_FRONT_VALUE(private_output->caps.min_w);
769 *min_h = TDM_FRONT_VALUE(private_output->caps.min_h);
771 *max_w = TDM_FRONT_VALUE(private_output->caps.max_w);
773 *max_h = TDM_FRONT_VALUE(private_output->caps.max_h);
775 *preferred_align = TDM_FRONT_VALUE(private_output->caps.preferred_align);
777 _pthread_mutex_unlock(&private_display->lock);
783 tdm_output_get_cursor_available_size(tdm_output *output, int *min_w, int *min_h,
784 int *max_w, int *max_h, int *preferred_align)
788 _pthread_mutex_lock(&private_display->lock);
790 if (!tdm_display_check_module_abi(private_display, 1, 5)) {
801 *preferred_align = -1;
803 _pthread_mutex_unlock(&private_display->lock);
805 return TDM_ERROR_BAD_MODULE;
809 *min_w = TDM_FRONT_VALUE(private_output->caps.cursor_min_w);
811 *min_h = TDM_FRONT_VALUE(private_output->caps.cursor_min_h);
813 *max_w = TDM_FRONT_VALUE(private_output->caps.cursor_max_w);
815 *max_h = TDM_FRONT_VALUE(private_output->caps.cursor_max_h);
817 *preferred_align = TDM_FRONT_VALUE(private_output->caps.cursor_preferred_align);
819 _pthread_mutex_unlock(&private_display->lock);
825 tdm_output_get_physical_size(tdm_output *output, unsigned int *mmWidth,
826 unsigned int *mmHeight)
830 _pthread_mutex_lock(&private_display->lock);
833 *mmWidth = private_output->caps.mmWidth;
835 *mmHeight = private_output->caps.mmHeight;
837 _pthread_mutex_unlock(&private_display->lock);
843 tdm_output_get_subpixel(tdm_output *output, unsigned int *subpixel)
846 TDM_RETURN_VAL_IF_FAIL(subpixel != NULL, TDM_ERROR_INVALID_PARAMETER);
848 _pthread_mutex_lock(&private_display->lock);
850 *subpixel = private_output->caps.subpixel;
852 _pthread_mutex_unlock(&private_display->lock);
858 tdm_output_get_pipe(tdm_output *output, unsigned int *pipe)
861 TDM_RETURN_VAL_IF_FAIL(pipe != NULL, TDM_ERROR_INVALID_PARAMETER);
863 _pthread_mutex_lock(&private_display->lock);
865 *pipe = private_output->pipe;
867 _pthread_mutex_unlock(&private_display->lock);
873 tdm_output_get_primary_index(tdm_output *output, int *index)
875 tdm_private_layer *private_layer = NULL;
878 TDM_RETURN_VAL_IF_FAIL(index != NULL, TDM_ERROR_INVALID_PARAMETER);
880 _pthread_mutex_lock(&private_display->lock);
882 LIST_FOR_EACH_ENTRY(private_layer, &private_output->layer_list, link) {
883 if (private_layer->caps.capabilities & TDM_LAYER_CAPABILITY_PRIMARY) {
884 *index = private_layer->index;
889 _pthread_mutex_unlock(&private_display->lock);
895 tdm_output_set_property(tdm_output *output, unsigned int id, tdm_value value)
897 tdm_func_output *func_output;
900 _pthread_mutex_lock(&private_display->lock);
902 func_output = &private_display->func_output;
904 if (!func_output->output_set_property) {
905 _pthread_mutex_unlock(&private_display->lock);
906 TDM_ERR("not implemented!!");
907 return TDM_ERROR_NOT_IMPLEMENTED;
910 ret = func_output->output_set_property(private_output->output_backend, id,
913 _pthread_mutex_unlock(&private_display->lock);
919 tdm_output_get_property(tdm_output *output, unsigned int id, tdm_value *value)
921 tdm_func_output *func_output;
924 TDM_RETURN_VAL_IF_FAIL(value != NULL, TDM_ERROR_INVALID_PARAMETER);
926 _pthread_mutex_lock(&private_display->lock);
928 func_output = &private_display->func_output;
930 if (!func_output->output_get_property) {
931 _pthread_mutex_unlock(&private_display->lock);
932 TDM_ERR("not implemented!!");
933 return TDM_ERROR_NOT_IMPLEMENTED;
936 ret = func_output->output_get_property(private_output->output_backend, id,
939 _pthread_mutex_unlock(&private_display->lock);
945 tdm_output_cb_vblank(tdm_output *output_backend, unsigned int sequence,
946 unsigned int tv_sec, unsigned int tv_usec, void *user_data)
948 tdm_private_vblank_handler *vblank_handler = user_data;
949 tdm_private_vblank_handler *v = NULL, *vv = NULL;
950 tdm_private_output *private_output;
951 tdm_private_display *private_display;
952 struct list_head clone_list;
954 pid_t tid = syscall(SYS_gettid);
956 TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED());
957 TDM_RETURN_IF_FAIL(vblank_handler);
959 private_output = vblank_handler->private_output;
960 private_display = private_output->private_display;
962 if (vblank_handler->owner_tid != tid) {
963 tdm_thread_cb_output_vblank output_vblank;
966 output_vblank.base.type = TDM_THREAD_CB_OUTPUT_VBLANK;
967 output_vblank.base.length = sizeof output_vblank;
968 output_vblank.output_stamp = vblank_handler->private_output->stamp;
969 output_vblank.sequence = sequence;
970 output_vblank.tv_sec = tv_sec;
971 output_vblank.tv_usec = tv_usec;
972 output_vblank.user_data = user_data;
974 ret = tdm_thread_send_cb(private_display->private_loop, &output_vblank.base);
975 TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
980 if (vblank_handler->owner_tid != tid)
981 TDM_NEVER_GET_HERE();
983 interval = vblank_handler->interval;
984 sync = vblank_handler->sync;
986 LIST_INITHEAD(&clone_list);
988 LIST_FOR_EACH_ENTRY_SAFE(v, vv, &private_output->vblank_handler_list, link) {
989 if (v->interval != interval || v->sync != sync || v->owner_tid != tid)
993 LIST_ADD(&v->link, &clone_list);
996 _pthread_mutex_unlock(&private_display->lock);
997 LIST_FOR_EACH_ENTRY_SAFE(v, vv, &clone_list, link) {
999 v->func(v->private_output, sequence, tv_sec, tv_usec, v->user_data);
1003 _pthread_mutex_lock(&private_display->lock);
1007 tdm_output_cb_commit(tdm_output *output_backend, unsigned int sequence,
1008 unsigned int tv_sec, unsigned int tv_usec, void *user_data)
1010 tdm_private_output_commit_handler *output_commit_handler = user_data;
1011 tdm_private_display *private_display;
1012 tdm_private_output *private_output;
1013 tdm_private_layer *private_layer = NULL;
1015 TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED());
1016 TDM_RETURN_IF_FAIL(output_commit_handler);
1018 private_output = output_commit_handler->private_output;
1019 private_display = private_output->private_display;
1021 if (output_commit_handler->owner_tid != syscall(SYS_gettid)) {
1022 tdm_thread_cb_output_commit output_commit;
1025 output_commit.base.type = TDM_THREAD_CB_OUTPUT_COMMIT;
1026 output_commit.base.length = sizeof output_commit;
1027 output_commit.output_stamp = private_output->stamp;
1028 output_commit.sequence = sequence;
1029 output_commit.tv_sec = tv_sec;
1030 output_commit.tv_usec = tv_usec;
1031 output_commit.user_data = user_data;
1033 ret = tdm_thread_send_cb(private_display->private_loop, &output_commit.base);
1034 TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
1039 if (private_display->commit_type == TDM_COMMIT_TYPE_OUTPUT) {
1040 /* In case of layer commit, the below will be handled in the layer commit callback */
1041 LIST_FOR_EACH_ENTRY(private_layer, &private_output->layer_list, link) {
1042 _tdm_layer_committed(private_layer);
1046 if (output_commit_handler->func) {
1047 _pthread_mutex_unlock(&private_display->lock);
1048 output_commit_handler->func(private_output, sequence,
1049 tv_sec, tv_usec, output_commit_handler->user_data);
1050 _pthread_mutex_lock(&private_display->lock);
1053 LIST_DEL(&output_commit_handler->link);
1054 free(output_commit_handler);
1058 _tdm_output_wait_vblank(tdm_output *output, int interval, int sync,
1059 tdm_output_vblank_handler func, void *user_data)
1061 tdm_func_output *func_output;
1062 tdm_private_vblank_handler *vblank_handler = NULL, *v = NULL;
1063 unsigned int skip_request = 0;
1064 pid_t tid = syscall(SYS_gettid);
1066 OUTPUT_FUNC_ENTRY();
1068 func_output = &private_display->func_output;
1070 if (!func_output->output_wait_vblank) {
1071 TDM_ERR("not implemented!!");
1072 return TDM_ERROR_NOT_IMPLEMENTED;
1075 if (!private_output->regist_vblank_cb) {
1076 private_output->regist_vblank_cb = 1;
1077 ret = func_output->output_set_vblank_handler(private_output->output_backend,
1078 tdm_output_cb_vblank);
1081 vblank_handler = calloc(1, sizeof(tdm_private_vblank_handler));
1082 if (!vblank_handler) {
1083 TDM_ERR("failed: alloc memory");
1084 return TDM_ERROR_OUT_OF_MEMORY;
1087 LIST_FOR_EACH_ENTRY(v, &private_output->vblank_handler_list, link) {
1088 if (v->interval == interval && v->sync == sync && v->owner_tid == tid) {
1094 LIST_ADD(&vblank_handler->link, &private_output->vblank_handler_list);
1095 vblank_handler->private_output = private_output;
1096 vblank_handler->interval = interval;
1097 vblank_handler->sync = sync;
1098 vblank_handler->func = func;
1099 vblank_handler->user_data = user_data;
1100 vblank_handler->owner_tid = tid;
1102 /* If there is the previous request, we can skip to call output_wait_vblank() */
1103 if (!skip_request) {
1104 ret = func_output->output_wait_vblank(private_output->output_backend, interval,
1105 sync, vblank_handler);
1106 TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, wait_failed);
1112 if (vblank_handler) {
1113 LIST_DEL(&vblank_handler->link);
1114 free(vblank_handler);
1120 tdm_output_wait_vblank(tdm_output *output, int interval, int sync,
1121 tdm_output_vblank_handler func, void *user_data)
1123 OUTPUT_FUNC_ENTRY();
1125 _pthread_mutex_lock(&private_display->lock);
1127 if (private_output->current_dpms_value > TDM_OUTPUT_DPMS_ON) {
1128 TDM_WRN("output(%d) dpms: %s", private_output->pipe,
1129 tdm_dpms_str(private_output->current_dpms_value));
1130 _pthread_mutex_unlock(&private_display->lock);
1131 return TDM_ERROR_DPMS_OFF;
1134 ret = _tdm_output_wait_vblank(output, interval, sync, func, user_data);
1136 _pthread_mutex_unlock(&private_display->lock);
1142 _tdm_output_commit(tdm_output *output, int sync, tdm_output_commit_handler func,
1145 tdm_func_output *func_output;
1146 tdm_private_output_commit_handler *output_commit_handler = NULL;
1147 OUTPUT_FUNC_ENTRY();
1149 func_output = &private_display->func_output;
1151 if (!func_output->output_commit) {
1152 TDM_ERR("not implemented!!");
1153 return TDM_ERROR_NOT_IMPLEMENTED;
1156 if (!private_output->regist_commit_cb) {
1157 private_output->regist_commit_cb = 1;
1158 ret = func_output->output_set_commit_handler(private_output->output_backend,
1159 tdm_output_cb_commit);
1162 output_commit_handler = calloc(1, sizeof(tdm_private_output_commit_handler));
1163 if (!output_commit_handler) {
1164 TDM_ERR("failed: alloc memory");
1165 return TDM_ERROR_OUT_OF_MEMORY;
1168 LIST_ADD(&output_commit_handler->link, &private_output->output_commit_handler_list);
1169 output_commit_handler->private_output = private_output;
1170 output_commit_handler->func = func;
1171 output_commit_handler->user_data = user_data;
1172 output_commit_handler->owner_tid = syscall(SYS_gettid);
1174 ret = func_output->output_commit(private_output->output_backend, sync,
1175 output_commit_handler);
1176 TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, commit_failed);
1178 if (tdm_debug_module & TDM_DEBUG_COMMIT)
1179 TDM_INFO("output(%d) backend commit", private_output->pipe);
1184 if (output_commit_handler) {
1185 LIST_DEL(&output_commit_handler->link);
1186 free(output_commit_handler);
1192 tdm_output_commit(tdm_output *output, int sync, tdm_output_commit_handler func,
1195 OUTPUT_FUNC_ENTRY();
1197 _pthread_mutex_lock(&private_display->lock);
1199 if (private_display->commit_type == TDM_COMMIT_TYPE_NONE)
1200 private_display->commit_type = TDM_COMMIT_TYPE_OUTPUT;
1201 else if (private_display->commit_type == TDM_COMMIT_TYPE_LAYER) {
1202 TDM_ERR("Can't supported. Use tdm_layer_commit");
1203 _pthread_mutex_unlock(&private_display->lock);
1204 return TDM_ERROR_BAD_REQUEST;
1207 if (private_display->commit_per_vblank) {
1208 TDM_ERR("Use tdm_layer_commit");
1209 _pthread_mutex_unlock(&private_display->lock);
1210 return TDM_ERROR_BAD_REQUEST;
1213 if (private_output->current_dpms_value > TDM_OUTPUT_DPMS_ON) {
1214 TDM_ERR("output(%d) dpms: %s", private_output->pipe,
1215 tdm_dpms_str(private_output->current_dpms_value));
1216 _pthread_mutex_unlock(&private_display->lock);
1217 return TDM_ERROR_DPMS_OFF;
1220 if (tdm_debug_module & TDM_DEBUG_COMMIT)
1221 TDM_INFO("output(%d) commit", private_output->pipe);
1223 ret = _tdm_output_commit(output, sync, func, user_data);
1225 _pthread_mutex_unlock(&private_display->lock);
1231 tdm_output_set_mode(tdm_output *output, const tdm_output_mode *mode)
1233 tdm_func_output *func_output;
1234 OUTPUT_FUNC_ENTRY();
1236 TDM_RETURN_VAL_IF_FAIL(mode != NULL, TDM_ERROR_INVALID_PARAMETER);
1238 _pthread_mutex_lock(&private_display->lock);
1240 func_output = &private_display->func_output;
1242 if (!func_output->output_set_mode) {
1243 _pthread_mutex_unlock(&private_display->lock);
1244 TDM_ERR("not implemented!!");
1245 return TDM_ERROR_NOT_IMPLEMENTED;
1248 ret = func_output->output_set_mode(private_output->output_backend, mode);
1249 if (ret == TDM_ERROR_NONE)
1250 private_output->current_mode = mode;
1251 _pthread_mutex_unlock(&private_display->lock);
1257 tdm_output_get_mode(tdm_output *output, const tdm_output_mode **mode)
1259 OUTPUT_FUNC_ENTRY();
1261 TDM_RETURN_VAL_IF_FAIL(mode != NULL, TDM_ERROR_INVALID_PARAMETER);
1263 _pthread_mutex_lock(&private_display->lock);
1265 *mode = private_output->current_mode;
1267 _pthread_mutex_unlock(&private_display->lock);
1273 _tdm_output_dpms_changed_timeout(void *user_data)
1275 tdm_private_output *private_output = user_data;
1278 value.u32 = private_output->current_dpms_value;
1279 tdm_output_call_change_handler_internal(private_output,
1280 &private_output->change_handler_list_sub,
1281 TDM_OUTPUT_CHANGE_DPMS,
1284 return TDM_ERROR_NONE;
1288 tdm_output_cb_dpms(tdm_output *output_backend, tdm_output_dpms dpms, void *user_data)
1290 tdm_private_display *private_display;
1291 tdm_private_output *private_output = user_data;
1294 TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED());
1295 TDM_RETURN_IF_FAIL(private_output);
1297 private_display = private_output->private_display;
1299 if (!tdm_thread_in_display_thread(syscall(SYS_gettid))) {
1300 tdm_thread_cb_output_dpms output_dpms;
1303 _tdm_output_update(output_backend, user_data);
1305 output_dpms.base.type = TDM_THREAD_CB_OUTPUT_DPMS;
1306 output_dpms.base.length = sizeof output_dpms;
1307 output_dpms.output_stamp = private_output->stamp;
1308 output_dpms.dpms = dpms;
1309 output_dpms.user_data = user_data;
1312 tdm_output_call_change_handler_internal(private_output,
1313 &private_output->change_handler_list_sub,
1314 TDM_OUTPUT_CHANGE_DPMS,
1317 ret = tdm_thread_send_cb(private_display->private_loop, &output_dpms.base);
1318 TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
1323 private_output->current_dpms_value = dpms;
1326 tdm_output_call_change_handler_internal(private_output,
1327 &private_output->change_handler_list_main,
1328 TDM_OUTPUT_CHANGE_DPMS,
1333 tdm_output_set_dpms(tdm_output *output, tdm_output_dpms dpms_value)
1335 tdm_func_output *func_output;
1336 OUTPUT_FUNC_ENTRY();
1338 if (dpms_value > TDM_OUTPUT_DPMS_OFF)
1339 dpms_value = TDM_OUTPUT_DPMS_OFF;
1341 _pthread_mutex_lock(&private_display->lock);
1343 if (private_output->current_dpms_value == dpms_value) {
1344 _pthread_mutex_unlock(&private_display->lock);
1345 return TDM_ERROR_NONE;
1348 /** Use timer to call the output change callback of the sub-thread.
1349 * The output change callback of tdm_server and tdm_vblank was called
1350 * in the main thread. And it made the multi thread issue. If we use
1351 * the timer, we can call the sub-thread's output change callback in
1354 if (!private_output->dpms_changed_timer) {
1355 private_output->dpms_changed_timer =
1356 tdm_event_loop_add_timer_handler(private_output->private_display,
1357 _tdm_output_dpms_changed_timeout, private_output, NULL);
1358 if (!private_output->dpms_changed_timer) {
1359 TDM_ERR("can't create dpms timer!!");
1360 _pthread_mutex_unlock(&private_display->lock);
1361 return TDM_ERROR_OUT_OF_MEMORY;
1365 func_output = &private_display->func_output;
1367 if (!func_output->output_set_dpms) {
1368 _pthread_mutex_unlock(&private_display->lock);
1369 private_output->current_dpms_value = dpms_value;
1370 TDM_WRN("not implemented!!");
1371 return TDM_ERROR_NONE;
1374 if (func_output->output_set_dpms_handler) {
1375 if (!private_output->regist_dpms_cb) {
1376 private_output->regist_dpms_cb = 1;
1377 ret = func_output->output_set_dpms_handler(private_output->output_backend,
1378 tdm_output_cb_dpms, private_output);
1382 ret = func_output->output_set_dpms(private_output->output_backend, dpms_value);
1384 if (ret == TDM_ERROR_NONE && !func_output->output_set_dpms_handler) {
1387 private_output->current_dpms_value = dpms_value;
1389 value.u32 = dpms_value;
1390 tdm_output_call_change_handler_internal(private_output,
1391 &private_output->change_handler_list_main,
1392 TDM_OUTPUT_CHANGE_DPMS,
1395 if (!LIST_IS_EMPTY(&private_output->change_handler_list_sub)) {
1396 ret = tdm_event_loop_source_timer_update(private_output->dpms_changed_timer, 1);
1397 if (ret != TDM_ERROR_NONE)
1398 TDM_NEVER_GET_HERE();
1402 _pthread_mutex_unlock(&private_display->lock);
1408 tdm_output_get_dpms(tdm_output *output, tdm_output_dpms *dpms_value)
1410 tdm_func_output *func_output;
1411 OUTPUT_FUNC_ENTRY();
1413 TDM_RETURN_VAL_IF_FAIL(dpms_value != NULL, TDM_ERROR_INVALID_PARAMETER);
1415 _pthread_mutex_lock(&private_display->lock);
1417 func_output = &private_display->func_output;
1419 if (!func_output->output_get_dpms) {
1420 *dpms_value = private_output->current_dpms_value;
1421 _pthread_mutex_unlock(&private_display->lock);
1422 TDM_WRN("not implemented!!");
1423 return TDM_ERROR_NONE;
1426 ret = func_output->output_get_dpms(private_output->output_backend, dpms_value);
1428 _pthread_mutex_unlock(&private_display->lock);
1433 EXTERN tdm_capture *
1434 tdm_output_create_capture(tdm_output *output, tdm_error *error)
1436 tdm_capture *capture = NULL;
1438 OUTPUT_FUNC_ENTRY_ERROR();
1440 _pthread_mutex_lock(&private_display->lock);
1442 capture = (tdm_capture *)tdm_capture_create_output_internal(private_output, error);
1444 _pthread_mutex_unlock(&private_display->lock);
1450 tdm_output_call_change_handler_internal(tdm_private_output *private_output,
1451 struct list_head *change_handler_list,
1452 tdm_output_change_type type,
1454 int no_check_thread_id)
1456 tdm_private_display *private_display;
1457 tdm_private_change_handler *change_handler = NULL;
1459 TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED());
1460 TDM_RETURN_IF_FAIL(private_output);
1462 private_display = private_output->private_display;
1463 if (!tdm_thread_in_display_thread(syscall(SYS_gettid))) {
1464 if (type & TDM_OUTPUT_CHANGE_CONNECTION)
1465 TDM_INFO("output(%d) changed: %s (%d)",
1466 private_output->pipe, tdm_status_str(value.u32), value.u32);
1467 if (type & TDM_OUTPUT_CHANGE_DPMS)
1468 TDM_INFO("output(%d) changed: dpms %s (%d)",
1469 private_output->pipe, tdm_dpms_str(value.u32), value.u32);
1472 if (LIST_IS_EMPTY(change_handler_list))
1475 LIST_FOR_EACH_ENTRY(change_handler, change_handler_list, link) {
1476 if (!no_check_thread_id && change_handler->owner_tid != syscall(SYS_gettid))
1477 TDM_NEVER_GET_HERE();
1479 _pthread_mutex_unlock(&private_display->lock);
1480 change_handler->func(private_output, type,
1481 value, change_handler->user_data);
1482 _pthread_mutex_lock(&private_display->lock);
1487 tdm_layer_get_capabilities(tdm_layer *layer, tdm_layer_capability *capabilities)
1491 TDM_RETURN_VAL_IF_FAIL(capabilities != NULL, TDM_ERROR_INVALID_PARAMETER);
1493 _pthread_mutex_lock(&private_display->lock);
1495 *capabilities = private_layer->caps.capabilities;
1497 _pthread_mutex_unlock(&private_display->lock);
1503 tdm_layer_get_available_formats(tdm_layer *layer, const tbm_format **formats, int *count)
1507 TDM_RETURN_VAL_IF_FAIL(formats != NULL, TDM_ERROR_INVALID_PARAMETER);
1508 TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
1510 _pthread_mutex_lock(&private_display->lock);
1512 *formats = (const tbm_format *)private_layer->caps.formats;
1513 *count = private_layer->caps.format_count;
1515 _pthread_mutex_unlock(&private_display->lock);
1521 tdm_layer_get_available_properties(tdm_layer *layer, const tdm_prop **props, int *count)
1525 TDM_RETURN_VAL_IF_FAIL(props != NULL, TDM_ERROR_INVALID_PARAMETER);
1526 TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
1528 _pthread_mutex_lock(&private_display->lock);
1530 *props = (const tdm_prop *)private_layer->caps.props;
1531 *count = private_layer->caps.prop_count;
1533 _pthread_mutex_unlock(&private_display->lock);
1539 tdm_layer_get_zpos(tdm_layer *layer, int *zpos)
1543 TDM_RETURN_VAL_IF_FAIL(zpos != NULL, TDM_ERROR_INVALID_PARAMETER);
1545 _pthread_mutex_lock(&private_display->lock);
1547 *zpos = private_layer->caps.zpos;
1549 _pthread_mutex_unlock(&private_display->lock);
1555 tdm_layer_set_property(tdm_layer *layer, unsigned int id, tdm_value value)
1557 tdm_func_layer *func_layer;
1560 _pthread_mutex_lock(&private_display->lock);
1562 func_layer = &private_display->func_layer;
1564 if (private_layer->usable)
1565 TDM_INFO("layer(%d) not usable", private_layer->index);
1567 private_layer->usable = 0;
1569 if (!func_layer->layer_set_property) {
1570 _pthread_mutex_unlock(&private_display->lock);
1571 TDM_ERR("not implemented!!");
1572 return TDM_ERROR_NOT_IMPLEMENTED;
1575 ret = func_layer->layer_set_property(private_layer->layer_backend, id, value);
1577 _pthread_mutex_unlock(&private_display->lock);
1583 tdm_layer_get_property(tdm_layer *layer, unsigned int id, tdm_value *value)
1585 tdm_func_layer *func_layer;
1588 TDM_RETURN_VAL_IF_FAIL(value != NULL, TDM_ERROR_INVALID_PARAMETER);
1590 _pthread_mutex_lock(&private_display->lock);
1592 func_layer = &private_display->func_layer;
1594 if (!func_layer->layer_get_property) {
1595 _pthread_mutex_unlock(&private_display->lock);
1596 TDM_ERR("not implemented!!");
1597 return TDM_ERROR_NOT_IMPLEMENTED;
1600 ret = func_layer->layer_get_property(private_layer->layer_backend, id, value);
1602 _pthread_mutex_unlock(&private_display->lock);
1608 tdm_layer_set_info(tdm_layer *layer, tdm_info_layer *info)
1610 tdm_func_layer *func_layer;
1615 TDM_RETURN_VAL_IF_FAIL(info != NULL, TDM_ERROR_INVALID_PARAMETER);
1617 _pthread_mutex_lock(&private_display->lock);
1619 func_layer = &private_display->func_layer;
1621 if (private_layer->usable)
1622 TDM_INFO("layer(%p) not usable", private_layer);
1624 private_layer->usable = 0;
1626 if (!func_layer->layer_set_info) {
1627 _pthread_mutex_unlock(&private_display->lock);
1628 TDM_ERR("not implemented!!");
1629 return TDM_ERROR_NOT_IMPLEMENTED;
1632 if (info->src_config.format)
1633 snprintf(fmtstr, 128, "%c%c%c%c", FOURCC_STR(info->src_config.format));
1635 snprintf(fmtstr, 128, "NONE");
1637 TDM_INFO("layer(%p) info: src(%dx%d %d,%d %dx%d %s) dst(%d,%d %dx%d) trans(%d)",
1638 private_layer, info->src_config.size.h, info->src_config.size.v,
1639 info->src_config.pos.x, info->src_config.pos.y,
1640 info->src_config.pos.w, info->src_config.pos.h,
1642 info->dst_pos.x, info->dst_pos.y,
1643 info->dst_pos.w, info->dst_pos.h,
1646 ret = func_layer->layer_set_info(private_layer->layer_backend, info);
1647 TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
1649 _pthread_mutex_unlock(&private_display->lock);
1655 tdm_layer_get_info(tdm_layer *layer, tdm_info_layer *info)
1657 tdm_func_layer *func_layer;
1660 TDM_RETURN_VAL_IF_FAIL(info != NULL, TDM_ERROR_INVALID_PARAMETER);
1662 _pthread_mutex_lock(&private_display->lock);
1664 func_layer = &private_display->func_layer;
1666 if (!func_layer->layer_get_info) {
1667 _pthread_mutex_unlock(&private_display->lock);
1668 TDM_ERR("not implemented!!");
1669 return TDM_ERROR_NOT_IMPLEMENTED;
1672 ret = func_layer->layer_get_info(private_layer->layer_backend, info);
1674 _pthread_mutex_unlock(&private_display->lock);
1680 _tdm_layer_dump_buffer(tdm_layer *layer, tbm_surface_h buffer)
1682 tdm_private_layer *private_layer = (tdm_private_layer*)layer;
1683 tdm_private_output *private_output = private_layer->private_output;
1686 char fname[PATH_MAX];
1688 pipe = private_output->pipe;
1689 zpos = private_layer->caps.zpos;
1691 snprintf(fname, sizeof(fname), "tdm_%d_lyr_%d", pipe, zpos);
1693 tbm_surface_internal_dump_buffer(buffer, fname);
1694 TDM_DBG("%s dump excute", fname);
1700 tdm_layer_set_buffer(tdm_layer *layer, tbm_surface_h buffer)
1702 tdm_func_layer *func_layer;
1706 TDM_RETURN_VAL_IF_FAIL(buffer != NULL, TDM_ERROR_INVALID_PARAMETER);
1708 _pthread_mutex_lock(&private_display->lock);
1710 if (tdm_debug_dump & TDM_DUMP_FLAG_LAYER &&
1711 !(private_layer->caps.capabilities & TDM_LAYER_CAPABILITY_VIDEO)) {
1712 char str[TDM_PATH_LEN];
1714 snprintf(str, TDM_PATH_LEN, "layer_%d_%d_%03d",
1715 private_output->index, private_layer->index, i++);
1716 tdm_helper_dump_buffer_str(buffer, tdm_debug_dump_dir, str);
1719 func_layer = &private_display->func_layer;
1721 if (private_layer->usable)
1722 TDM_INFO("layer(%p) not usable", private_layer);
1724 private_layer->usable = 0;
1726 if (!func_layer->layer_set_buffer) {
1727 _pthread_mutex_unlock(&private_display->lock);
1728 TDM_ERR("not implemented!!");
1729 return TDM_ERROR_NOT_IMPLEMENTED;
1732 ret = func_layer->layer_set_buffer(private_layer->layer_backend, buffer);
1733 TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
1736 if (tdm_dump_enable && !(private_layer->caps.capabilities & TDM_LAYER_CAPABILITY_VIDEO))
1737 _tdm_layer_dump_buffer(layer, buffer);
1739 if (ret == TDM_ERROR_NONE) {
1740 /* FIXME: should save to pending_buffer first. And after committing
1741 * successfully, need to move to waiting_buffer.
1743 if (private_layer->waiting_buffer) {
1744 _pthread_mutex_unlock(&private_display->lock);
1745 tdm_buffer_unref_backend(private_layer->waiting_buffer);
1746 _pthread_mutex_lock(&private_display->lock);
1749 private_layer->waiting_buffer = tdm_buffer_ref_backend(buffer);
1750 if (tdm_debug_module & TDM_DEBUG_BUFFER)
1751 TDM_INFO("layer(%p) waiting_buffer(%p)",
1752 private_layer, private_layer->waiting_buffer);
1755 _pthread_mutex_unlock(&private_display->lock);
1761 tdm_layer_unset_buffer(tdm_layer *layer)
1763 tdm_private_layer_commit_handler *lm = NULL, *lmm = NULL;
1764 tdm_func_layer *func_layer;
1767 _pthread_mutex_lock(&private_display->lock);
1769 func_layer = &private_display->func_layer;
1771 if (private_layer->waiting_buffer) {
1772 _pthread_mutex_unlock(&private_display->lock);
1773 tdm_buffer_unref_backend(private_layer->waiting_buffer);
1774 _pthread_mutex_lock(&private_display->lock);
1775 private_layer->waiting_buffer = NULL;
1777 if (tdm_debug_module & TDM_DEBUG_BUFFER)
1778 TDM_INFO("layer(%p) waiting_buffer(%p)",
1779 private_layer, private_layer->waiting_buffer);
1782 if (private_layer->showing_buffer) {
1783 _pthread_mutex_unlock(&private_display->lock);
1784 tdm_buffer_unref_backend(private_layer->showing_buffer);
1785 _pthread_mutex_lock(&private_display->lock);
1786 private_layer->showing_buffer = NULL;
1788 if (tdm_debug_module & TDM_DEBUG_BUFFER)
1789 TDM_INFO("layer(%p) showing_buffer(%p)",
1790 private_layer, private_layer->showing_buffer);
1793 LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &private_output->layer_commit_handler_list, link) {
1794 if (lm->private_layer != private_layer)
1796 LIST_DEL(&lm->link);
1800 LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &private_output->pending_commit_handler_list, link) {
1801 if (lm->private_layer != private_layer)
1803 LIST_DEL(&lm->link);
1807 private_layer->usable = 1;
1809 if (private_layer->usable)
1810 TDM_INFO("layer(%p) now usable", private_layer);
1812 if (!func_layer->layer_unset_buffer) {
1813 _pthread_mutex_unlock(&private_display->lock);
1814 TDM_ERR("not implemented!!");
1815 return TDM_ERROR_NOT_IMPLEMENTED;
1818 ret = func_layer->layer_unset_buffer(private_layer->layer_backend);
1819 TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
1821 _pthread_mutex_unlock(&private_display->lock);
1827 _tdm_layer_committed(tdm_private_layer *private_layer)
1829 tdm_private_output *private_output = private_layer->private_output;
1830 tdm_private_display *private_display = private_output->private_display;
1832 private_layer->committing = 0;
1834 if (private_display->print_fps) {
1835 double curr = tdm_helper_get_time();
1836 private_layer->fps_count++;
1837 if (private_layer->fps_stamp == 0) {
1838 private_layer->fps_stamp = curr;
1839 } else if ((curr - private_layer->fps_stamp) > 1.0) {
1840 TDM_INFO("output(%d) layer(%d) fps: %d", private_output->index, private_layer->index, private_layer->fps_count - 1);
1841 private_layer->fps_count = 1;
1842 private_layer->fps_stamp = curr;
1844 } else if (private_layer->fps_stamp != 0) {
1845 private_layer->fps_stamp = 0;
1846 private_layer->fps_count = 0;
1849 if (!private_layer->waiting_buffer)
1852 if (private_layer->showing_buffer) {
1853 _pthread_mutex_unlock(&private_display->lock);
1854 tdm_buffer_unref_backend(private_layer->showing_buffer);
1855 _pthread_mutex_lock(&private_display->lock);
1857 if (private_layer->buffer_queue) {
1858 _pthread_mutex_unlock(&private_display->lock);
1859 tbm_surface_queue_release(private_layer->buffer_queue,
1860 private_layer->showing_buffer);
1861 _pthread_mutex_lock(&private_display->lock);
1865 private_layer->showing_buffer = private_layer->waiting_buffer;
1866 private_layer->waiting_buffer = NULL;
1868 if (tdm_debug_module & TDM_DEBUG_BUFFER)
1869 TDM_INFO("layer(%p) waiting_buffer(%p) showing_buffer(%p)",
1870 private_layer, private_layer->waiting_buffer,
1871 private_layer->showing_buffer);
1875 _tdm_layer_got_output_vblank(tdm_private_output *private_output, unsigned int sequence,
1876 unsigned int tv_sec, unsigned int tv_usec)
1878 tdm_private_layer_commit_handler *lm = NULL, *lmm = NULL;
1879 tdm_private_display *private_display;
1882 private_display = private_output->private_display;
1884 private_output->waiting_vblank = 0;
1886 LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &private_output->layer_commit_handler_list, link) {
1887 _tdm_layer_committed(lm->private_layer);
1890 _pthread_mutex_unlock(&private_display->lock);
1891 lm->func(lm->private_layer, sequence, tv_sec, tv_usec, lm->user_data);
1892 _pthread_mutex_lock(&private_display->lock);
1895 LIST_DEL(&lm->link);
1899 if (LIST_IS_EMPTY(&private_output->pending_commit_handler_list))
1903 ret = _tdm_output_commit(private_output, 0, _tdm_layer_cb_output_commit, NULL);
1904 TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, wait_failed);
1906 if (tdm_debug_module & TDM_DEBUG_COMMIT)
1907 TDM_INFO("layer commit: output(%d) commit", private_output->pipe);
1909 private_output->waiting_vblank = 1;
1911 ret = _tdm_output_commit(private_output, 0, NULL, NULL);
1912 TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, wait_failed);
1914 if (tdm_debug_module & TDM_DEBUG_COMMIT)
1915 TDM_INFO("layer commit: output(%d) commit", private_output->pipe);
1917 TDM_RETURN_IF_FAIL(private_output->vblank != NULL);
1919 /* tdm_vblank APIs is for server. it should be called in unlock status*/
1920 _pthread_mutex_unlock(&private_display->lock);
1921 ret = tdm_vblank_wait(private_output->vblank, 0, 0, 1, _tdm_layer_cb_wait_vblank, private_output);
1922 _pthread_mutex_lock(&private_display->lock);
1923 TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, wait_failed);
1924 private_output->waiting_vblank = 1;
1926 if (tdm_debug_module & TDM_DEBUG_COMMIT)
1927 TDM_INFO("layer commit: output(%d) wait vblank", private_output->pipe);
1930 LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &private_output->pending_commit_handler_list, link) {
1931 LIST_DEL(&lm->link);
1932 LIST_ADD(&lm->link, &private_output->layer_commit_handler_list);
1937 LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &private_output->pending_commit_handler_list, link) {
1938 LIST_DEL(&lm->link);
1945 _tdm_layer_cb_output_commit(tdm_output *output, unsigned int sequence,
1946 unsigned int tv_sec, unsigned int tv_usec, void *user_data)
1948 tdm_private_layer_commit_handler *layer_commit_handler = user_data;
1949 tdm_private_display *private_display;
1950 tdm_private_output *private_output = output;
1951 tdm_private_layer *private_layer;
1953 private_display = private_output->private_display;
1955 _pthread_mutex_lock(&private_display->lock);
1957 if (layer_commit_handler) {
1958 tdm_private_layer_commit_handler *lm = NULL;
1961 LIST_FOR_EACH_ENTRY(lm, &private_output->layer_commit_handler_list, link) {
1962 if (layer_commit_handler == lm) {
1969 private_layer = layer_commit_handler->private_layer;
1971 if (tdm_debug_module & TDM_DEBUG_COMMIT)
1972 TDM_INFO("layer(%p) commit: output(%d) committed", private_layer, private_output->pipe);
1974 _tdm_layer_committed(private_layer);
1976 if (layer_commit_handler->func) {
1977 _pthread_mutex_unlock(&private_display->lock);
1978 layer_commit_handler->func(private_output, sequence,
1979 tv_sec, tv_usec, layer_commit_handler->user_data);
1980 _pthread_mutex_lock(&private_display->lock);
1983 LIST_DEL(&layer_commit_handler->link);
1984 free(layer_commit_handler);
1987 if (tdm_debug_module & TDM_DEBUG_COMMIT)
1988 TDM_INFO("layer commit: output(%d) committed", private_output->pipe);
1990 _tdm_layer_got_output_vblank(private_output, sequence, tv_sec, tv_usec);
1993 _pthread_mutex_unlock(&private_display->lock);
1997 _tdm_layer_cb_wait_vblank(tdm_vblank *vblank, tdm_error error, unsigned int sequence,
1998 unsigned int tv_sec, unsigned int tv_usec, void *user_data)
2000 tdm_private_output *private_output = user_data;
2001 tdm_private_display *private_display;
2003 TDM_RETURN_IF_FAIL(private_output != NULL);
2005 private_display = private_output->private_display;
2007 _pthread_mutex_lock(&private_display->lock);
2009 if (tdm_debug_module & TDM_DEBUG_COMMIT)
2010 TDM_INFO("layer commit: output(%d) got vblank", private_output->pipe);
2012 _tdm_layer_got_output_vblank(private_output, sequence, tv_sec, tv_usec);
2014 _pthread_mutex_unlock(&private_display->lock);
2018 _tdm_layer_commit_possible(tdm_private_layer *private_layer)
2020 tdm_private_output *private_output = private_layer->private_output;
2021 tdm_private_display *private_display = private_output->private_display;
2023 if (!private_display->commit_per_vblank) {
2024 if (tdm_debug_module & TDM_DEBUG_COMMIT)
2025 TDM_INFO("layer(%p) commit: commit_per_vblank false", private_layer);
2029 if (private_display->commit_per_vblank == 1 && _tdm_output_used_layer_count(private_output) == 1) {
2030 if (tdm_debug_module & TDM_DEBUG_COMMIT)
2031 TDM_INFO("layer(%p) commit: 1 layer", private_layer);
2035 if (private_display->commit_per_vblank == 2 && LIST_IS_EMPTY(&private_output->layer_commit_handler_list)) {
2036 if (tdm_debug_module & TDM_DEBUG_COMMIT)
2037 TDM_INFO("layer(%p) commit: non previous commit", private_layer);
2045 _tdm_layer_commit(tdm_layer *layer, tdm_layer_commit_handler func, void *user_data)
2047 tdm_private_layer_commit_handler *layer_commit_handler;
2050 layer_commit_handler = calloc(1, sizeof(tdm_private_layer_commit_handler));
2051 if (!layer_commit_handler) {
2052 TDM_ERR("failed: alloc memory");
2053 return TDM_ERROR_OUT_OF_MEMORY;
2056 LIST_INITHEAD(&layer_commit_handler->link);
2057 layer_commit_handler->private_layer = private_layer;
2058 layer_commit_handler->func = func;
2059 layer_commit_handler->user_data = user_data;
2061 if (_tdm_layer_commit_possible(private_layer)) {
2062 if (private_layer->committing)
2063 TDM_WRN("layer(%d) too many commit", private_layer->index);
2065 private_layer->committing = 1;
2067 LIST_ADD(&layer_commit_handler->link, &private_output->layer_commit_handler_list);
2068 ret = _tdm_output_commit(private_layer->private_output, 0, _tdm_layer_cb_output_commit, layer_commit_handler);
2069 TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, commit_failed);
2071 if (tdm_debug_module & TDM_DEBUG_COMMIT)
2072 TDM_INFO("layer(%p) commit: output", private_layer);
2074 if (private_layer->committing)
2075 TDM_WRN("layer(%d) too many commit", private_layer->index);
2077 private_layer->committing = 1;
2079 LIST_ADD(&layer_commit_handler->link, &private_output->pending_commit_handler_list);
2081 if (tdm_debug_module & TDM_DEBUG_COMMIT)
2082 TDM_INFO("layer(%p) commit: pending", private_layer);
2084 if (!private_output->vblank) {
2085 /* tdm_vblank APIs is for server. it should be called in unlock status*/
2086 _pthread_mutex_unlock(&private_display->lock);
2087 private_output->vblank = tdm_vblank_create(private_display, private_output, NULL);
2088 _pthread_mutex_lock(&private_display->lock);
2089 TDM_GOTO_IF_FAIL(private_output->vblank != NULL, commit_failed);
2092 if (!private_output->waiting_vblank) {
2093 /* tdm_vblank APIs is for server. it should be called in unlock status*/
2094 _pthread_mutex_unlock(&private_display->lock);
2095 ret = tdm_vblank_wait(private_output->vblank, 0, 0, 1, _tdm_layer_cb_wait_vblank, private_output);
2096 _pthread_mutex_lock(&private_display->lock);
2097 TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, commit_failed);
2098 private_output->waiting_vblank = 1;
2100 if (tdm_debug_module & TDM_DEBUG_COMMIT)
2101 TDM_INFO("layer(%p) commit: wait vblank", private_layer);
2108 if (layer_commit_handler) {
2109 LIST_DEL(&layer_commit_handler->link);
2110 free(layer_commit_handler);
2116 tdm_layer_commit(tdm_layer *layer, tdm_layer_commit_handler func, void *user_data)
2120 _pthread_mutex_lock(&private_display->lock);
2122 if (private_display->commit_type == TDM_COMMIT_TYPE_NONE)
2123 private_display->commit_type = TDM_COMMIT_TYPE_LAYER;
2124 else if (private_display->commit_type == TDM_COMMIT_TYPE_OUTPUT) {
2125 TDM_ERR("Can't supported. Use tdm_output_commit");
2126 _pthread_mutex_unlock(&private_display->lock);
2127 return TDM_ERROR_BAD_REQUEST;
2130 if (private_output->current_dpms_value > TDM_OUTPUT_DPMS_ON) {
2131 TDM_ERR("layer(%p)'s output(%d) dpms: %s", layer, private_output->pipe,
2132 tdm_dpms_str(private_output->current_dpms_value));
2133 _pthread_mutex_unlock(&private_display->lock);
2134 return TDM_ERROR_DPMS_OFF;
2137 if (tdm_debug_module & TDM_DEBUG_COMMIT)
2138 TDM_INFO("layer(%p) commit", private_layer);
2140 ret = _tdm_layer_commit(private_layer, func, user_data);
2142 _pthread_mutex_unlock(&private_display->lock);
2148 tdm_layer_is_committing(tdm_layer *layer, unsigned int *committing)
2152 TDM_RETURN_VAL_IF_FAIL(committing != NULL, TDM_ERROR_INVALID_PARAMETER);
2154 _pthread_mutex_lock(&private_display->lock);
2156 *committing = private_layer->committing;
2158 _pthread_mutex_unlock(&private_display->lock);
2163 EXTERN tbm_surface_h
2164 tdm_layer_get_displaying_buffer(tdm_layer *layer, tdm_error *error)
2166 tbm_surface_h buffer;
2167 LAYER_FUNC_ENTRY_ERROR();
2169 _pthread_mutex_lock(&private_display->lock);
2172 *error = TDM_ERROR_NONE;
2174 if (private_layer->showing_buffer) {
2175 buffer = private_layer->showing_buffer;
2178 *error = TDM_ERROR_OPERATION_FAILED;
2179 _pthread_mutex_unlock(&private_display->lock);
2180 TDM_DBG("layer(%p) showing_buffer is null", private_layer);
2183 _pthread_mutex_unlock(&private_display->lock);
2189 _tbm_layer_queue_acquirable_cb(tbm_surface_queue_h surface_queue, void *data)
2191 TDM_RETURN_IF_FAIL(data != NULL);
2192 tdm_layer *layer = data;
2193 tdm_func_layer *func_layer;
2194 tbm_surface_h surface = NULL;
2195 LAYER_FUNC_ENTRY_VOID_RETURN();
2197 _pthread_mutex_lock(&private_display->lock);
2199 func_layer = &private_display->func_layer;
2200 if (!func_layer->layer_set_buffer) {
2201 _pthread_mutex_unlock(&private_display->lock);
2205 if (TBM_SURFACE_QUEUE_ERROR_NONE != tbm_surface_queue_acquire(private_layer->buffer_queue, &surface) ||
2207 TDM_ERR("layer(%p) tbm_surface_queue_acquire() failed surface:%p",
2208 private_layer, surface);
2209 _pthread_mutex_unlock(&private_display->lock);
2213 ret = func_layer->layer_set_buffer(private_layer->layer_backend, surface);
2214 TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
2216 if (ret == TDM_ERROR_NONE) {
2217 if (private_layer->waiting_buffer) {
2218 TDM_DBG("layer(%p) drop waiting_buffer(%p)", private_layer, private_layer->waiting_buffer);
2219 _pthread_mutex_unlock(&private_display->lock);
2220 tdm_buffer_unref_backend(private_layer->waiting_buffer);
2221 tbm_surface_queue_release(private_layer->buffer_queue,
2222 private_layer->waiting_buffer);
2223 _pthread_mutex_lock(&private_display->lock);
2226 private_layer->waiting_buffer = tdm_buffer_ref_backend(surface);
2228 if (tdm_debug_module & TDM_DEBUG_BUFFER)
2229 TDM_INFO("layer(%p) waiting_buffer(%p)",
2230 private_layer, private_layer->waiting_buffer);
2232 if (private_display->commit_type == TDM_COMMIT_TYPE_OUTPUT) {
2233 ret = _tdm_output_commit(private_layer->private_output, 0, NULL, NULL);
2234 if (ret != TDM_ERROR_NONE)
2235 TDM_ERR("_tdm_output_commit() is fail");
2236 } else if (private_display->commit_type == TDM_COMMIT_TYPE_LAYER) {
2237 ret = _tdm_layer_commit(private_layer, NULL, NULL);
2238 if (ret != TDM_ERROR_NONE)
2239 TDM_ERR("layer(%p) _tdm_layer_commit() is fail", private_layer);
2241 TDM_NEVER_GET_HERE();
2245 _pthread_mutex_unlock(&private_display->lock);
2249 _tbm_layer_queue_destroy_cb(tbm_surface_queue_h surface_queue, void *data)
2251 TDM_RETURN_IF_FAIL(data != NULL);
2252 tdm_layer *layer = data;
2253 LAYER_FUNC_ENTRY_VOID_RETURN();
2254 TDM_RETURN_IF_FAIL(ret == TDM_ERROR_NONE);
2256 _pthread_mutex_lock(&private_display->lock);
2258 if (private_layer->waiting_buffer) {
2259 _pthread_mutex_unlock(&private_display->lock);
2260 tdm_buffer_unref_backend(private_layer->waiting_buffer);
2261 tbm_surface_queue_release(private_layer->buffer_queue,
2262 private_layer->waiting_buffer);
2263 _pthread_mutex_lock(&private_display->lock);
2266 private_layer->buffer_queue = NULL;
2268 _pthread_mutex_unlock(&private_display->lock);
2272 tdm_layer_set_buffer_queue(tdm_layer *layer, tbm_surface_queue_h buffer_queue)
2274 tdm_func_layer *func_layer;
2277 TDM_RETURN_VAL_IF_FAIL(buffer_queue != NULL, TDM_ERROR_INVALID_PARAMETER);
2279 _pthread_mutex_lock(&private_display->lock);
2281 func_layer = &private_display->func_layer;
2283 if (private_layer->usable)
2284 TDM_INFO("layer(%p) not usable", private_layer);
2286 private_layer->usable = 0;
2288 if (!func_layer->layer_set_buffer) {
2289 _pthread_mutex_unlock(&private_display->lock);
2290 TDM_ERR("not implemented!!");
2291 return TDM_ERROR_NOT_IMPLEMENTED;
2294 if (buffer_queue == private_layer->buffer_queue) {
2295 _pthread_mutex_unlock(&private_display->lock);
2296 return TDM_ERROR_NONE;
2299 if (private_layer->waiting_buffer) {
2300 _pthread_mutex_unlock(&private_display->lock);
2301 tdm_buffer_unref_backend(private_layer->waiting_buffer);
2302 tbm_surface_queue_release(private_layer->buffer_queue,
2303 private_layer->waiting_buffer);
2304 private_layer->waiting_buffer = NULL;
2305 _pthread_mutex_lock(&private_display->lock);
2307 if (tdm_debug_module & TDM_DEBUG_BUFFER)
2308 TDM_INFO("layer(%p) waiting_buffer(%p)",
2309 private_layer, private_layer->waiting_buffer);
2312 private_layer->buffer_queue = buffer_queue;
2313 tbm_surface_queue_add_acquirable_cb(private_layer->buffer_queue,
2314 _tbm_layer_queue_acquirable_cb,
2316 tbm_surface_queue_add_destroy_cb(private_layer->buffer_queue,
2317 _tbm_layer_queue_destroy_cb,
2319 _pthread_mutex_unlock(&private_display->lock);
2325 tdm_layer_unset_buffer_queue(tdm_layer *layer)
2327 tdm_func_layer *func_layer;
2330 _pthread_mutex_lock(&private_display->lock);
2332 func_layer = &private_display->func_layer;
2334 if (private_layer->waiting_buffer) {
2335 _pthread_mutex_unlock(&private_display->lock);
2336 tdm_buffer_unref_backend(private_layer->waiting_buffer);
2337 tbm_surface_queue_release(private_layer->buffer_queue,
2338 private_layer->waiting_buffer);
2339 private_layer->waiting_buffer = NULL;
2340 _pthread_mutex_lock(&private_display->lock);
2342 if (tdm_debug_module & TDM_DEBUG_BUFFER)
2343 TDM_INFO("layer(%p) waiting_buffer(%p)",
2344 private_layer, private_layer->waiting_buffer);
2347 if (private_layer->showing_buffer) {
2348 _pthread_mutex_unlock(&private_display->lock);
2349 tdm_buffer_unref_backend(private_layer->showing_buffer);
2350 tbm_surface_queue_release(private_layer->buffer_queue,
2351 private_layer->showing_buffer);
2352 _pthread_mutex_lock(&private_display->lock);
2353 private_layer->showing_buffer = NULL;
2355 if (tdm_debug_module & TDM_DEBUG_BUFFER)
2356 TDM_INFO("layer(%p) showing_buffer(%p)",
2357 private_layer, private_layer->showing_buffer);
2360 tbm_surface_queue_remove_acquirable_cb(private_layer->buffer_queue, _tbm_layer_queue_acquirable_cb, layer);
2361 tbm_surface_queue_remove_destroy_cb(private_layer->buffer_queue, _tbm_layer_queue_destroy_cb, layer);
2362 private_layer->buffer_queue = NULL;
2363 private_layer->usable = 1;
2365 if (private_layer->usable)
2366 TDM_INFO("layer(%p) now usable", private_layer);
2368 if (!func_layer->layer_unset_buffer) {
2369 _pthread_mutex_unlock(&private_display->lock);
2370 TDM_ERR("not implemented!!");
2371 return TDM_ERROR_NOT_IMPLEMENTED;
2374 ret = func_layer->layer_unset_buffer(private_layer->layer_backend);
2376 _pthread_mutex_unlock(&private_display->lock);
2382 tdm_layer_is_usable(tdm_layer *layer, unsigned int *usable)
2386 TDM_RETURN_VAL_IF_FAIL(usable != NULL, TDM_ERROR_INVALID_PARAMETER);
2388 _pthread_mutex_lock(&private_display->lock);
2390 *usable = private_layer->usable;
2392 _pthread_mutex_unlock(&private_display->lock);
2398 tdm_layer_set_video_pos(tdm_layer *layer, int zpos)
2400 tdm_func_layer *func_layer;
2403 _pthread_mutex_lock(&private_display->lock);
2405 func_layer = &private_display->func_layer;
2407 if (!(private_layer->caps.capabilities & TDM_LAYER_CAPABILITY_VIDEO)) {
2408 TDM_ERR("layer(%p) is not video layer", private_layer);
2409 _pthread_mutex_unlock(&private_display->lock);
2410 return TDM_ERROR_INVALID_PARAMETER;
2413 if (!func_layer->layer_set_video_pos) {
2414 _pthread_mutex_unlock(&private_display->lock);
2415 TDM_ERR("not implemented!!");
2416 return TDM_ERROR_NOT_IMPLEMENTED;
2419 ret = func_layer->layer_set_video_pos(private_layer->layer_backend, zpos);
2421 _pthread_mutex_unlock(&private_display->lock);
2426 EXTERN tdm_capture *
2427 tdm_layer_create_capture(tdm_layer *layer, tdm_error *error)
2429 tdm_capture *capture = NULL;
2431 LAYER_FUNC_ENTRY_ERROR();
2433 _pthread_mutex_lock(&private_display->lock);
2435 capture = (tdm_capture *)tdm_capture_create_layer_internal(private_layer, error);
2437 _pthread_mutex_unlock(&private_display->lock);
2443 tdm_layer_get_buffer_flags(tdm_layer *layer, unsigned int *flags)
2445 tdm_func_layer *func_layer;
2448 _pthread_mutex_lock(&private_display->lock);
2450 func_layer = &private_display->func_layer;
2452 if (!func_layer->layer_get_buffer_flags) {
2453 _pthread_mutex_unlock(&private_display->lock);
2454 TDM_ERR("not implemented!!");
2455 return TDM_ERROR_NOT_IMPLEMENTED;
2458 ret = func_layer->layer_get_buffer_flags(private_layer->layer_backend, flags);
2460 _pthread_mutex_unlock(&private_display->lock);