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);
1160 TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, commit_failed);
1163 output_commit_handler = calloc(1, sizeof(tdm_private_output_commit_handler));
1164 if (!output_commit_handler) {
1165 TDM_ERR("failed: alloc memory");
1166 return TDM_ERROR_OUT_OF_MEMORY;
1169 LIST_ADD(&output_commit_handler->link, &private_output->output_commit_handler_list);
1170 output_commit_handler->private_output = private_output;
1171 output_commit_handler->func = func;
1172 output_commit_handler->user_data = user_data;
1173 output_commit_handler->owner_tid = syscall(SYS_gettid);
1175 ret = func_output->output_commit(private_output->output_backend, sync,
1176 output_commit_handler);
1177 TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, commit_failed);
1179 if (tdm_debug_module & TDM_DEBUG_COMMIT)
1180 TDM_INFO("output(%d) backend commit", private_output->pipe);
1185 if (output_commit_handler) {
1186 LIST_DEL(&output_commit_handler->link);
1187 free(output_commit_handler);
1193 tdm_output_commit(tdm_output *output, int sync, tdm_output_commit_handler func,
1196 OUTPUT_FUNC_ENTRY();
1198 _pthread_mutex_lock(&private_display->lock);
1200 if (private_display->commit_type == TDM_COMMIT_TYPE_NONE)
1201 private_display->commit_type = TDM_COMMIT_TYPE_OUTPUT;
1202 else if (private_display->commit_type == TDM_COMMIT_TYPE_LAYER) {
1203 TDM_ERR("Can't supported. Use tdm_layer_commit");
1204 _pthread_mutex_unlock(&private_display->lock);
1205 return TDM_ERROR_BAD_REQUEST;
1208 if (private_display->commit_per_vblank) {
1209 TDM_ERR("Use tdm_layer_commit");
1210 _pthread_mutex_unlock(&private_display->lock);
1211 return TDM_ERROR_BAD_REQUEST;
1214 if (private_output->current_dpms_value > TDM_OUTPUT_DPMS_ON) {
1215 TDM_ERR("output(%d) dpms: %s", private_output->pipe,
1216 tdm_dpms_str(private_output->current_dpms_value));
1217 _pthread_mutex_unlock(&private_display->lock);
1218 return TDM_ERROR_DPMS_OFF;
1221 if (tdm_debug_module & TDM_DEBUG_COMMIT)
1222 TDM_INFO("output(%d) commit", private_output->pipe);
1224 ret = _tdm_output_commit(output, sync, func, user_data);
1226 _pthread_mutex_unlock(&private_display->lock);
1232 tdm_output_set_mode(tdm_output *output, const tdm_output_mode *mode)
1234 tdm_func_output *func_output;
1235 OUTPUT_FUNC_ENTRY();
1237 TDM_RETURN_VAL_IF_FAIL(mode != NULL, TDM_ERROR_INVALID_PARAMETER);
1239 _pthread_mutex_lock(&private_display->lock);
1241 func_output = &private_display->func_output;
1243 if (!func_output->output_set_mode) {
1244 _pthread_mutex_unlock(&private_display->lock);
1245 TDM_ERR("not implemented!!");
1246 return TDM_ERROR_NOT_IMPLEMENTED;
1249 ret = func_output->output_set_mode(private_output->output_backend, mode);
1250 if (ret == TDM_ERROR_NONE)
1251 private_output->current_mode = mode;
1252 _pthread_mutex_unlock(&private_display->lock);
1258 tdm_output_get_mode(tdm_output *output, const tdm_output_mode **mode)
1260 OUTPUT_FUNC_ENTRY();
1262 TDM_RETURN_VAL_IF_FAIL(mode != NULL, TDM_ERROR_INVALID_PARAMETER);
1264 _pthread_mutex_lock(&private_display->lock);
1266 *mode = private_output->current_mode;
1268 _pthread_mutex_unlock(&private_display->lock);
1274 _tdm_output_dpms_changed_timeout(void *user_data)
1276 tdm_private_output *private_output = user_data;
1279 value.u32 = private_output->current_dpms_value;
1280 tdm_output_call_change_handler_internal(private_output,
1281 &private_output->change_handler_list_sub,
1282 TDM_OUTPUT_CHANGE_DPMS,
1285 return TDM_ERROR_NONE;
1289 tdm_output_cb_dpms(tdm_output *output_backend, tdm_output_dpms dpms, void *user_data)
1291 tdm_private_display *private_display;
1292 tdm_private_output *private_output = user_data;
1295 TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED());
1296 TDM_RETURN_IF_FAIL(private_output);
1298 private_display = private_output->private_display;
1300 if (!tdm_thread_in_display_thread(syscall(SYS_gettid))) {
1301 tdm_thread_cb_output_dpms output_dpms;
1304 _tdm_output_update(output_backend, user_data);
1306 output_dpms.base.type = TDM_THREAD_CB_OUTPUT_DPMS;
1307 output_dpms.base.length = sizeof output_dpms;
1308 output_dpms.output_stamp = private_output->stamp;
1309 output_dpms.dpms = dpms;
1310 output_dpms.user_data = user_data;
1313 tdm_output_call_change_handler_internal(private_output,
1314 &private_output->change_handler_list_sub,
1315 TDM_OUTPUT_CHANGE_DPMS,
1318 ret = tdm_thread_send_cb(private_display->private_loop, &output_dpms.base);
1319 TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
1324 private_output->current_dpms_value = dpms;
1327 tdm_output_call_change_handler_internal(private_output,
1328 &private_output->change_handler_list_main,
1329 TDM_OUTPUT_CHANGE_DPMS,
1334 tdm_output_set_dpms(tdm_output *output, tdm_output_dpms dpms_value)
1336 tdm_func_output *func_output;
1337 OUTPUT_FUNC_ENTRY();
1339 if (dpms_value > TDM_OUTPUT_DPMS_OFF)
1340 dpms_value = TDM_OUTPUT_DPMS_OFF;
1342 _pthread_mutex_lock(&private_display->lock);
1344 if (private_output->current_dpms_value == dpms_value) {
1345 _pthread_mutex_unlock(&private_display->lock);
1346 return TDM_ERROR_NONE;
1349 /** Use timer to call the output change callback of the sub-thread.
1350 * The output change callback of tdm_server and tdm_vblank was called
1351 * in the main thread. And it made the multi thread issue. If we use
1352 * the timer, we can call the sub-thread's output change callback in
1355 if (!private_output->dpms_changed_timer) {
1356 private_output->dpms_changed_timer =
1357 tdm_event_loop_add_timer_handler(private_output->private_display,
1358 _tdm_output_dpms_changed_timeout, private_output, NULL);
1359 if (!private_output->dpms_changed_timer) {
1360 TDM_ERR("can't create dpms timer!!");
1361 _pthread_mutex_unlock(&private_display->lock);
1362 return TDM_ERROR_OUT_OF_MEMORY;
1366 func_output = &private_display->func_output;
1368 if (!func_output->output_set_dpms) {
1369 _pthread_mutex_unlock(&private_display->lock);
1370 private_output->current_dpms_value = dpms_value;
1371 TDM_WRN("not implemented!!");
1372 return TDM_ERROR_NONE;
1375 if (func_output->output_set_dpms_handler) {
1376 if (!private_output->regist_dpms_cb) {
1377 private_output->regist_dpms_cb = 1;
1378 ret = func_output->output_set_dpms_handler(private_output->output_backend,
1379 tdm_output_cb_dpms, private_output);
1380 if (ret != TDM_ERROR_NONE) {
1381 _pthread_mutex_unlock(&private_display->lock);
1382 TDM_ERR("Can't set the dpms handler!!");
1388 ret = func_output->output_set_dpms(private_output->output_backend, dpms_value);
1390 if (ret == TDM_ERROR_NONE && !func_output->output_set_dpms_handler) {
1393 private_output->current_dpms_value = dpms_value;
1395 value.u32 = dpms_value;
1396 tdm_output_call_change_handler_internal(private_output,
1397 &private_output->change_handler_list_main,
1398 TDM_OUTPUT_CHANGE_DPMS,
1401 if (!LIST_IS_EMPTY(&private_output->change_handler_list_sub)) {
1402 ret = tdm_event_loop_source_timer_update(private_output->dpms_changed_timer, 1);
1403 if (ret != TDM_ERROR_NONE)
1404 TDM_NEVER_GET_HERE();
1408 _pthread_mutex_unlock(&private_display->lock);
1414 tdm_output_get_dpms(tdm_output *output, tdm_output_dpms *dpms_value)
1416 tdm_func_output *func_output;
1417 OUTPUT_FUNC_ENTRY();
1419 TDM_RETURN_VAL_IF_FAIL(dpms_value != NULL, TDM_ERROR_INVALID_PARAMETER);
1421 _pthread_mutex_lock(&private_display->lock);
1423 func_output = &private_display->func_output;
1425 if (!func_output->output_get_dpms) {
1426 *dpms_value = private_output->current_dpms_value;
1427 _pthread_mutex_unlock(&private_display->lock);
1428 TDM_WRN("not implemented!!");
1429 return TDM_ERROR_NONE;
1432 ret = func_output->output_get_dpms(private_output->output_backend, dpms_value);
1434 _pthread_mutex_unlock(&private_display->lock);
1439 EXTERN tdm_capture *
1440 tdm_output_create_capture(tdm_output *output, tdm_error *error)
1442 tdm_capture *capture = NULL;
1444 OUTPUT_FUNC_ENTRY_ERROR();
1446 _pthread_mutex_lock(&private_display->lock);
1448 capture = (tdm_capture *)tdm_capture_create_output_internal(private_output, error);
1450 _pthread_mutex_unlock(&private_display->lock);
1456 tdm_output_call_change_handler_internal(tdm_private_output *private_output,
1457 struct list_head *change_handler_list,
1458 tdm_output_change_type type,
1460 int no_check_thread_id)
1462 tdm_private_display *private_display;
1463 tdm_private_change_handler *change_handler = NULL;
1465 TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED());
1466 TDM_RETURN_IF_FAIL(private_output);
1468 private_display = private_output->private_display;
1469 if (!tdm_thread_in_display_thread(syscall(SYS_gettid))) {
1470 if (type & TDM_OUTPUT_CHANGE_CONNECTION)
1471 TDM_INFO("output(%d) changed: %s (%d)",
1472 private_output->pipe, tdm_status_str(value.u32), value.u32);
1473 if (type & TDM_OUTPUT_CHANGE_DPMS)
1474 TDM_INFO("output(%d) changed: dpms %s (%d)",
1475 private_output->pipe, tdm_dpms_str(value.u32), value.u32);
1478 if (LIST_IS_EMPTY(change_handler_list))
1481 LIST_FOR_EACH_ENTRY(change_handler, change_handler_list, link) {
1482 if (!no_check_thread_id && change_handler->owner_tid != syscall(SYS_gettid))
1483 TDM_NEVER_GET_HERE();
1485 _pthread_mutex_unlock(&private_display->lock);
1486 change_handler->func(private_output, type,
1487 value, change_handler->user_data);
1488 _pthread_mutex_lock(&private_display->lock);
1493 tdm_layer_get_capabilities(tdm_layer *layer, tdm_layer_capability *capabilities)
1497 TDM_RETURN_VAL_IF_FAIL(capabilities != NULL, TDM_ERROR_INVALID_PARAMETER);
1499 _pthread_mutex_lock(&private_display->lock);
1501 *capabilities = private_layer->caps.capabilities;
1503 _pthread_mutex_unlock(&private_display->lock);
1509 tdm_layer_get_available_formats(tdm_layer *layer, const tbm_format **formats, int *count)
1513 TDM_RETURN_VAL_IF_FAIL(formats != NULL, TDM_ERROR_INVALID_PARAMETER);
1514 TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
1516 _pthread_mutex_lock(&private_display->lock);
1518 *formats = (const tbm_format *)private_layer->caps.formats;
1519 *count = private_layer->caps.format_count;
1521 _pthread_mutex_unlock(&private_display->lock);
1527 tdm_layer_get_available_properties(tdm_layer *layer, const tdm_prop **props, int *count)
1531 TDM_RETURN_VAL_IF_FAIL(props != NULL, TDM_ERROR_INVALID_PARAMETER);
1532 TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
1534 _pthread_mutex_lock(&private_display->lock);
1536 *props = (const tdm_prop *)private_layer->caps.props;
1537 *count = private_layer->caps.prop_count;
1539 _pthread_mutex_unlock(&private_display->lock);
1545 tdm_layer_get_zpos(tdm_layer *layer, int *zpos)
1549 TDM_RETURN_VAL_IF_FAIL(zpos != NULL, TDM_ERROR_INVALID_PARAMETER);
1551 _pthread_mutex_lock(&private_display->lock);
1553 *zpos = private_layer->caps.zpos;
1555 _pthread_mutex_unlock(&private_display->lock);
1561 tdm_layer_set_property(tdm_layer *layer, unsigned int id, tdm_value value)
1563 tdm_func_layer *func_layer;
1566 _pthread_mutex_lock(&private_display->lock);
1568 func_layer = &private_display->func_layer;
1570 if (private_layer->usable)
1571 TDM_INFO("layer(%d) not usable", private_layer->index);
1573 private_layer->usable = 0;
1575 if (!func_layer->layer_set_property) {
1576 _pthread_mutex_unlock(&private_display->lock);
1577 TDM_ERR("not implemented!!");
1578 return TDM_ERROR_NOT_IMPLEMENTED;
1581 ret = func_layer->layer_set_property(private_layer->layer_backend, id, value);
1583 _pthread_mutex_unlock(&private_display->lock);
1589 tdm_layer_get_property(tdm_layer *layer, unsigned int id, tdm_value *value)
1591 tdm_func_layer *func_layer;
1594 TDM_RETURN_VAL_IF_FAIL(value != NULL, TDM_ERROR_INVALID_PARAMETER);
1596 _pthread_mutex_lock(&private_display->lock);
1598 func_layer = &private_display->func_layer;
1600 if (!func_layer->layer_get_property) {
1601 _pthread_mutex_unlock(&private_display->lock);
1602 TDM_ERR("not implemented!!");
1603 return TDM_ERROR_NOT_IMPLEMENTED;
1606 ret = func_layer->layer_get_property(private_layer->layer_backend, id, value);
1608 _pthread_mutex_unlock(&private_display->lock);
1614 tdm_layer_set_info(tdm_layer *layer, tdm_info_layer *info)
1616 tdm_func_layer *func_layer;
1621 TDM_RETURN_VAL_IF_FAIL(info != NULL, TDM_ERROR_INVALID_PARAMETER);
1623 _pthread_mutex_lock(&private_display->lock);
1625 func_layer = &private_display->func_layer;
1627 if (private_layer->usable)
1628 TDM_INFO("layer(%p) not usable", private_layer);
1630 private_layer->usable = 0;
1632 if (!func_layer->layer_set_info) {
1633 _pthread_mutex_unlock(&private_display->lock);
1634 TDM_ERR("not implemented!!");
1635 return TDM_ERROR_NOT_IMPLEMENTED;
1638 if (info->src_config.format)
1639 snprintf(fmtstr, 128, "%c%c%c%c", FOURCC_STR(info->src_config.format));
1641 snprintf(fmtstr, 128, "NONE");
1643 TDM_INFO("layer(%p) info: src(%dx%d %d,%d %dx%d %s) dst(%d,%d %dx%d) trans(%d)",
1644 private_layer, info->src_config.size.h, info->src_config.size.v,
1645 info->src_config.pos.x, info->src_config.pos.y,
1646 info->src_config.pos.w, info->src_config.pos.h,
1648 info->dst_pos.x, info->dst_pos.y,
1649 info->dst_pos.w, info->dst_pos.h,
1652 ret = func_layer->layer_set_info(private_layer->layer_backend, info);
1653 TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
1655 _pthread_mutex_unlock(&private_display->lock);
1661 tdm_layer_get_info(tdm_layer *layer, tdm_info_layer *info)
1663 tdm_func_layer *func_layer;
1666 TDM_RETURN_VAL_IF_FAIL(info != NULL, TDM_ERROR_INVALID_PARAMETER);
1668 _pthread_mutex_lock(&private_display->lock);
1670 func_layer = &private_display->func_layer;
1672 if (!func_layer->layer_get_info) {
1673 _pthread_mutex_unlock(&private_display->lock);
1674 TDM_ERR("not implemented!!");
1675 return TDM_ERROR_NOT_IMPLEMENTED;
1678 ret = func_layer->layer_get_info(private_layer->layer_backend, info);
1680 _pthread_mutex_unlock(&private_display->lock);
1686 _tdm_layer_dump_buffer(tdm_layer *layer, tbm_surface_h buffer)
1688 tdm_private_layer *private_layer = (tdm_private_layer*)layer;
1689 tdm_private_output *private_output = private_layer->private_output;
1692 char fname[PATH_MAX];
1694 pipe = private_output->pipe;
1695 zpos = private_layer->caps.zpos;
1697 snprintf(fname, sizeof(fname), "tdm_%d_lyr_%d", pipe, zpos);
1699 tbm_surface_internal_dump_buffer(buffer, fname);
1700 TDM_DBG("%s dump excute", fname);
1706 tdm_layer_set_buffer(tdm_layer *layer, tbm_surface_h buffer)
1708 tdm_func_layer *func_layer;
1712 TDM_RETURN_VAL_IF_FAIL(buffer != NULL, TDM_ERROR_INVALID_PARAMETER);
1714 _pthread_mutex_lock(&private_display->lock);
1716 if (tdm_debug_dump & TDM_DUMP_FLAG_LAYER &&
1717 !(private_layer->caps.capabilities & TDM_LAYER_CAPABILITY_VIDEO)) {
1718 char str[TDM_PATH_LEN];
1720 snprintf(str, TDM_PATH_LEN, "layer_%d_%d_%03d",
1721 private_output->index, private_layer->index, i++);
1722 tdm_helper_dump_buffer_str(buffer, tdm_debug_dump_dir, str);
1725 func_layer = &private_display->func_layer;
1727 if (private_layer->usable)
1728 TDM_INFO("layer(%p) not usable", private_layer);
1730 private_layer->usable = 0;
1732 if (!func_layer->layer_set_buffer) {
1733 _pthread_mutex_unlock(&private_display->lock);
1734 TDM_ERR("not implemented!!");
1735 return TDM_ERROR_NOT_IMPLEMENTED;
1738 ret = func_layer->layer_set_buffer(private_layer->layer_backend, buffer);
1739 TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
1742 if (tdm_dump_enable && !(private_layer->caps.capabilities & TDM_LAYER_CAPABILITY_VIDEO))
1743 _tdm_layer_dump_buffer(layer, buffer);
1745 if (ret == TDM_ERROR_NONE) {
1746 /* FIXME: should save to pending_buffer first. And after committing
1747 * successfully, need to move to waiting_buffer.
1749 if (private_layer->waiting_buffer) {
1750 _pthread_mutex_unlock(&private_display->lock);
1751 tdm_buffer_unref_backend(private_layer->waiting_buffer);
1752 _pthread_mutex_lock(&private_display->lock);
1755 private_layer->waiting_buffer = tdm_buffer_ref_backend(buffer);
1756 if (tdm_debug_module & TDM_DEBUG_BUFFER)
1757 TDM_INFO("layer(%p) waiting_buffer(%p)",
1758 private_layer, private_layer->waiting_buffer);
1761 _pthread_mutex_unlock(&private_display->lock);
1767 tdm_layer_unset_buffer(tdm_layer *layer)
1769 tdm_private_layer_commit_handler *lm = NULL, *lmm = NULL;
1770 tdm_func_layer *func_layer;
1773 _pthread_mutex_lock(&private_display->lock);
1775 func_layer = &private_display->func_layer;
1777 if (private_layer->waiting_buffer) {
1778 _pthread_mutex_unlock(&private_display->lock);
1779 tdm_buffer_unref_backend(private_layer->waiting_buffer);
1780 _pthread_mutex_lock(&private_display->lock);
1781 private_layer->waiting_buffer = NULL;
1783 if (tdm_debug_module & TDM_DEBUG_BUFFER)
1784 TDM_INFO("layer(%p) waiting_buffer(%p)",
1785 private_layer, private_layer->waiting_buffer);
1788 if (private_layer->showing_buffer) {
1789 _pthread_mutex_unlock(&private_display->lock);
1790 tdm_buffer_unref_backend(private_layer->showing_buffer);
1791 _pthread_mutex_lock(&private_display->lock);
1792 private_layer->showing_buffer = NULL;
1794 if (tdm_debug_module & TDM_DEBUG_BUFFER)
1795 TDM_INFO("layer(%p) showing_buffer(%p)",
1796 private_layer, private_layer->showing_buffer);
1799 LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &private_output->layer_commit_handler_list, link) {
1800 if (lm->private_layer != private_layer)
1802 LIST_DEL(&lm->link);
1806 LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &private_output->pending_commit_handler_list, link) {
1807 if (lm->private_layer != private_layer)
1809 LIST_DEL(&lm->link);
1813 private_layer->usable = 1;
1815 if (private_layer->usable)
1816 TDM_INFO("layer(%p) now usable", private_layer);
1818 if (!func_layer->layer_unset_buffer) {
1819 _pthread_mutex_unlock(&private_display->lock);
1820 TDM_ERR("not implemented!!");
1821 return TDM_ERROR_NOT_IMPLEMENTED;
1824 ret = func_layer->layer_unset_buffer(private_layer->layer_backend);
1825 TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
1827 _pthread_mutex_unlock(&private_display->lock);
1833 _tdm_layer_committed(tdm_private_layer *private_layer)
1835 tdm_private_output *private_output = private_layer->private_output;
1836 tdm_private_display *private_display = private_output->private_display;
1838 private_layer->committing = 0;
1840 if (private_display->print_fps) {
1841 double curr = tdm_helper_get_time();
1842 private_layer->fps_count++;
1843 if (private_layer->fps_stamp == 0) {
1844 private_layer->fps_stamp = curr;
1845 } else if ((curr - private_layer->fps_stamp) > 1.0) {
1846 TDM_INFO("output(%d) layer(%d) fps: %d", private_output->index, private_layer->index, private_layer->fps_count - 1);
1847 private_layer->fps_count = 1;
1848 private_layer->fps_stamp = curr;
1850 } else if (private_layer->fps_stamp != 0) {
1851 private_layer->fps_stamp = 0;
1852 private_layer->fps_count = 0;
1855 if (!private_layer->waiting_buffer)
1858 if (private_layer->showing_buffer) {
1859 _pthread_mutex_unlock(&private_display->lock);
1860 tdm_buffer_unref_backend(private_layer->showing_buffer);
1861 _pthread_mutex_lock(&private_display->lock);
1863 if (private_layer->buffer_queue) {
1864 _pthread_mutex_unlock(&private_display->lock);
1865 tbm_surface_queue_release(private_layer->buffer_queue,
1866 private_layer->showing_buffer);
1867 _pthread_mutex_lock(&private_display->lock);
1871 private_layer->showing_buffer = private_layer->waiting_buffer;
1872 private_layer->waiting_buffer = NULL;
1874 if (tdm_debug_module & TDM_DEBUG_BUFFER)
1875 TDM_INFO("layer(%p) waiting_buffer(%p) showing_buffer(%p)",
1876 private_layer, private_layer->waiting_buffer,
1877 private_layer->showing_buffer);
1881 _tdm_layer_got_output_vblank(tdm_private_output *private_output, unsigned int sequence,
1882 unsigned int tv_sec, unsigned int tv_usec)
1884 tdm_private_layer_commit_handler *lm = NULL, *lmm = NULL;
1885 tdm_private_display *private_display;
1888 private_display = private_output->private_display;
1890 private_output->waiting_vblank = 0;
1892 LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &private_output->layer_commit_handler_list, link) {
1893 _tdm_layer_committed(lm->private_layer);
1896 _pthread_mutex_unlock(&private_display->lock);
1897 lm->func(lm->private_layer, sequence, tv_sec, tv_usec, lm->user_data);
1898 _pthread_mutex_lock(&private_display->lock);
1901 LIST_DEL(&lm->link);
1905 if (LIST_IS_EMPTY(&private_output->pending_commit_handler_list))
1909 ret = _tdm_output_commit(private_output, 0, _tdm_layer_cb_output_commit, NULL);
1910 TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, wait_failed);
1912 if (tdm_debug_module & TDM_DEBUG_COMMIT)
1913 TDM_INFO("layer commit: output(%d) commit", private_output->pipe);
1915 private_output->waiting_vblank = 1;
1917 ret = _tdm_output_commit(private_output, 0, NULL, NULL);
1918 TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, wait_failed);
1920 if (tdm_debug_module & TDM_DEBUG_COMMIT)
1921 TDM_INFO("layer commit: output(%d) commit", private_output->pipe);
1923 TDM_RETURN_IF_FAIL(private_output->vblank != NULL);
1925 /* tdm_vblank APIs is for server. it should be called in unlock status*/
1926 _pthread_mutex_unlock(&private_display->lock);
1927 ret = tdm_vblank_wait(private_output->vblank, 0, 0, 1, _tdm_layer_cb_wait_vblank, private_output);
1928 _pthread_mutex_lock(&private_display->lock);
1929 TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, wait_failed);
1930 private_output->waiting_vblank = 1;
1932 if (tdm_debug_module & TDM_DEBUG_COMMIT)
1933 TDM_INFO("layer commit: output(%d) wait vblank", private_output->pipe);
1936 LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &private_output->pending_commit_handler_list, link) {
1937 LIST_DEL(&lm->link);
1938 LIST_ADD(&lm->link, &private_output->layer_commit_handler_list);
1943 LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &private_output->pending_commit_handler_list, link) {
1944 LIST_DEL(&lm->link);
1951 _tdm_layer_cb_output_commit(tdm_output *output, unsigned int sequence,
1952 unsigned int tv_sec, unsigned int tv_usec, void *user_data)
1954 tdm_private_layer_commit_handler *layer_commit_handler = user_data;
1955 tdm_private_display *private_display;
1956 tdm_private_output *private_output = output;
1957 tdm_private_layer *private_layer;
1959 private_display = private_output->private_display;
1961 _pthread_mutex_lock(&private_display->lock);
1963 if (layer_commit_handler) {
1964 tdm_private_layer_commit_handler *lm = NULL;
1967 LIST_FOR_EACH_ENTRY(lm, &private_output->layer_commit_handler_list, link) {
1968 if (layer_commit_handler == lm) {
1975 private_layer = layer_commit_handler->private_layer;
1977 if (tdm_debug_module & TDM_DEBUG_COMMIT)
1978 TDM_INFO("layer(%p) commit: output(%d) committed", private_layer, private_output->pipe);
1980 _tdm_layer_committed(private_layer);
1982 if (layer_commit_handler->func) {
1983 _pthread_mutex_unlock(&private_display->lock);
1984 layer_commit_handler->func(private_output, sequence,
1985 tv_sec, tv_usec, layer_commit_handler->user_data);
1986 _pthread_mutex_lock(&private_display->lock);
1989 LIST_DEL(&layer_commit_handler->link);
1990 free(layer_commit_handler);
1993 if (tdm_debug_module & TDM_DEBUG_COMMIT)
1994 TDM_INFO("layer commit: output(%d) committed", private_output->pipe);
1996 _tdm_layer_got_output_vblank(private_output, sequence, tv_sec, tv_usec);
1999 _pthread_mutex_unlock(&private_display->lock);
2003 _tdm_layer_cb_wait_vblank(tdm_vblank *vblank, tdm_error error, unsigned int sequence,
2004 unsigned int tv_sec, unsigned int tv_usec, void *user_data)
2006 tdm_private_output *private_output = user_data;
2007 tdm_private_display *private_display;
2009 TDM_RETURN_IF_FAIL(private_output != NULL);
2011 private_display = private_output->private_display;
2013 _pthread_mutex_lock(&private_display->lock);
2015 if (tdm_debug_module & TDM_DEBUG_COMMIT)
2016 TDM_INFO("layer commit: output(%d) got vblank", private_output->pipe);
2018 _tdm_layer_got_output_vblank(private_output, sequence, tv_sec, tv_usec);
2020 _pthread_mutex_unlock(&private_display->lock);
2024 _tdm_layer_commit_possible(tdm_private_layer *private_layer)
2026 tdm_private_output *private_output = private_layer->private_output;
2027 tdm_private_display *private_display = private_output->private_display;
2029 if (!private_display->commit_per_vblank) {
2030 if (tdm_debug_module & TDM_DEBUG_COMMIT)
2031 TDM_INFO("layer(%p) commit: commit_per_vblank false", private_layer);
2035 if (private_display->commit_per_vblank == 1 && _tdm_output_used_layer_count(private_output) == 1) {
2036 if (tdm_debug_module & TDM_DEBUG_COMMIT)
2037 TDM_INFO("layer(%p) commit: 1 layer", private_layer);
2041 if (private_display->commit_per_vblank == 2 && LIST_IS_EMPTY(&private_output->layer_commit_handler_list)) {
2042 if (tdm_debug_module & TDM_DEBUG_COMMIT)
2043 TDM_INFO("layer(%p) commit: non previous commit", private_layer);
2051 _tdm_layer_commit(tdm_layer *layer, tdm_layer_commit_handler func, void *user_data)
2053 tdm_private_layer_commit_handler *layer_commit_handler;
2056 layer_commit_handler = calloc(1, sizeof(tdm_private_layer_commit_handler));
2057 if (!layer_commit_handler) {
2058 TDM_ERR("failed: alloc memory");
2059 return TDM_ERROR_OUT_OF_MEMORY;
2062 LIST_INITHEAD(&layer_commit_handler->link);
2063 layer_commit_handler->private_layer = private_layer;
2064 layer_commit_handler->func = func;
2065 layer_commit_handler->user_data = user_data;
2067 if (_tdm_layer_commit_possible(private_layer)) {
2068 if (private_layer->committing)
2069 TDM_WRN("layer(%d) too many commit", private_layer->index);
2071 private_layer->committing = 1;
2073 LIST_ADD(&layer_commit_handler->link, &private_output->layer_commit_handler_list);
2074 ret = _tdm_output_commit(private_layer->private_output, 0, _tdm_layer_cb_output_commit, layer_commit_handler);
2075 TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, commit_failed);
2077 if (tdm_debug_module & TDM_DEBUG_COMMIT)
2078 TDM_INFO("layer(%p) commit: output", private_layer);
2080 if (private_layer->committing)
2081 TDM_WRN("layer(%d) too many commit", private_layer->index);
2083 private_layer->committing = 1;
2085 LIST_ADD(&layer_commit_handler->link, &private_output->pending_commit_handler_list);
2087 if (tdm_debug_module & TDM_DEBUG_COMMIT)
2088 TDM_INFO("layer(%p) commit: pending", private_layer);
2090 if (!private_output->vblank) {
2091 /* tdm_vblank APIs is for server. it should be called in unlock status*/
2092 _pthread_mutex_unlock(&private_display->lock);
2093 private_output->vblank = tdm_vblank_create(private_display, private_output, NULL);
2094 _pthread_mutex_lock(&private_display->lock);
2095 TDM_GOTO_IF_FAIL(private_output->vblank != NULL, commit_failed);
2098 if (!private_output->waiting_vblank) {
2099 /* tdm_vblank APIs is for server. it should be called in unlock status*/
2100 _pthread_mutex_unlock(&private_display->lock);
2101 ret = tdm_vblank_wait(private_output->vblank, 0, 0, 1, _tdm_layer_cb_wait_vblank, private_output);
2102 _pthread_mutex_lock(&private_display->lock);
2103 TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, commit_failed);
2104 private_output->waiting_vblank = 1;
2106 if (tdm_debug_module & TDM_DEBUG_COMMIT)
2107 TDM_INFO("layer(%p) commit: wait vblank", private_layer);
2114 if (layer_commit_handler) {
2115 LIST_DEL(&layer_commit_handler->link);
2116 free(layer_commit_handler);
2122 tdm_layer_commit(tdm_layer *layer, tdm_layer_commit_handler func, void *user_data)
2126 _pthread_mutex_lock(&private_display->lock);
2128 if (private_display->commit_type == TDM_COMMIT_TYPE_NONE)
2129 private_display->commit_type = TDM_COMMIT_TYPE_LAYER;
2130 else if (private_display->commit_type == TDM_COMMIT_TYPE_OUTPUT) {
2131 TDM_ERR("Can't supported. Use tdm_output_commit");
2132 _pthread_mutex_unlock(&private_display->lock);
2133 return TDM_ERROR_BAD_REQUEST;
2136 if (private_output->current_dpms_value > TDM_OUTPUT_DPMS_ON) {
2137 TDM_ERR("layer(%p)'s output(%d) dpms: %s", layer, private_output->pipe,
2138 tdm_dpms_str(private_output->current_dpms_value));
2139 _pthread_mutex_unlock(&private_display->lock);
2140 return TDM_ERROR_DPMS_OFF;
2143 if (tdm_debug_module & TDM_DEBUG_COMMIT)
2144 TDM_INFO("layer(%p) commit", private_layer);
2146 ret = _tdm_layer_commit(private_layer, func, user_data);
2148 _pthread_mutex_unlock(&private_display->lock);
2154 tdm_layer_is_committing(tdm_layer *layer, unsigned int *committing)
2158 TDM_RETURN_VAL_IF_FAIL(committing != NULL, TDM_ERROR_INVALID_PARAMETER);
2160 _pthread_mutex_lock(&private_display->lock);
2162 *committing = private_layer->committing;
2164 _pthread_mutex_unlock(&private_display->lock);
2169 EXTERN tbm_surface_h
2170 tdm_layer_get_displaying_buffer(tdm_layer *layer, tdm_error *error)
2172 tbm_surface_h buffer;
2173 LAYER_FUNC_ENTRY_ERROR();
2175 _pthread_mutex_lock(&private_display->lock);
2178 *error = TDM_ERROR_NONE;
2180 if (private_layer->showing_buffer) {
2181 buffer = private_layer->showing_buffer;
2184 *error = TDM_ERROR_OPERATION_FAILED;
2185 _pthread_mutex_unlock(&private_display->lock);
2186 TDM_DBG("layer(%p) showing_buffer is null", private_layer);
2189 _pthread_mutex_unlock(&private_display->lock);
2195 _tbm_layer_queue_acquirable_cb(tbm_surface_queue_h surface_queue, void *data)
2197 TDM_RETURN_IF_FAIL(data != NULL);
2198 tdm_layer *layer = data;
2199 tdm_func_layer *func_layer;
2200 tbm_surface_h surface = NULL;
2201 LAYER_FUNC_ENTRY_VOID_RETURN();
2203 _pthread_mutex_lock(&private_display->lock);
2205 func_layer = &private_display->func_layer;
2206 if (!func_layer->layer_set_buffer) {
2207 _pthread_mutex_unlock(&private_display->lock);
2211 if (TBM_SURFACE_QUEUE_ERROR_NONE != tbm_surface_queue_acquire(private_layer->buffer_queue, &surface) ||
2213 TDM_ERR("layer(%p) tbm_surface_queue_acquire() failed surface:%p",
2214 private_layer, surface);
2215 _pthread_mutex_unlock(&private_display->lock);
2219 ret = func_layer->layer_set_buffer(private_layer->layer_backend, surface);
2220 TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
2222 if (ret == TDM_ERROR_NONE) {
2223 if (private_layer->waiting_buffer) {
2224 TDM_DBG("layer(%p) drop waiting_buffer(%p)", private_layer, private_layer->waiting_buffer);
2225 _pthread_mutex_unlock(&private_display->lock);
2226 tdm_buffer_unref_backend(private_layer->waiting_buffer);
2227 tbm_surface_queue_release(private_layer->buffer_queue,
2228 private_layer->waiting_buffer);
2229 _pthread_mutex_lock(&private_display->lock);
2232 private_layer->waiting_buffer = tdm_buffer_ref_backend(surface);
2234 if (tdm_debug_module & TDM_DEBUG_BUFFER)
2235 TDM_INFO("layer(%p) waiting_buffer(%p)",
2236 private_layer, private_layer->waiting_buffer);
2238 if (private_display->commit_type == TDM_COMMIT_TYPE_OUTPUT) {
2239 ret = _tdm_output_commit(private_layer->private_output, 0, NULL, NULL);
2240 if (ret != TDM_ERROR_NONE)
2241 TDM_ERR("_tdm_output_commit() is fail");
2242 } else if (private_display->commit_type == TDM_COMMIT_TYPE_LAYER) {
2243 ret = _tdm_layer_commit(private_layer, NULL, NULL);
2244 if (ret != TDM_ERROR_NONE)
2245 TDM_ERR("layer(%p) _tdm_layer_commit() is fail", private_layer);
2247 TDM_NEVER_GET_HERE();
2251 _pthread_mutex_unlock(&private_display->lock);
2255 _tbm_layer_queue_destroy_cb(tbm_surface_queue_h surface_queue, void *data)
2257 TDM_RETURN_IF_FAIL(data != NULL);
2258 tdm_layer *layer = data;
2259 LAYER_FUNC_ENTRY_VOID_RETURN();
2260 TDM_RETURN_IF_FAIL(ret == TDM_ERROR_NONE);
2262 _pthread_mutex_lock(&private_display->lock);
2264 if (private_layer->waiting_buffer) {
2265 _pthread_mutex_unlock(&private_display->lock);
2266 tdm_buffer_unref_backend(private_layer->waiting_buffer);
2267 tbm_surface_queue_release(private_layer->buffer_queue,
2268 private_layer->waiting_buffer);
2269 _pthread_mutex_lock(&private_display->lock);
2272 private_layer->buffer_queue = NULL;
2274 _pthread_mutex_unlock(&private_display->lock);
2278 tdm_layer_set_buffer_queue(tdm_layer *layer, tbm_surface_queue_h buffer_queue)
2280 tdm_func_layer *func_layer;
2283 TDM_RETURN_VAL_IF_FAIL(buffer_queue != NULL, TDM_ERROR_INVALID_PARAMETER);
2285 _pthread_mutex_lock(&private_display->lock);
2287 func_layer = &private_display->func_layer;
2289 if (private_layer->usable)
2290 TDM_INFO("layer(%p) not usable", private_layer);
2292 private_layer->usable = 0;
2294 if (!func_layer->layer_set_buffer) {
2295 _pthread_mutex_unlock(&private_display->lock);
2296 TDM_ERR("not implemented!!");
2297 return TDM_ERROR_NOT_IMPLEMENTED;
2300 if (buffer_queue == private_layer->buffer_queue) {
2301 _pthread_mutex_unlock(&private_display->lock);
2302 return TDM_ERROR_NONE;
2305 if (private_layer->waiting_buffer) {
2306 _pthread_mutex_unlock(&private_display->lock);
2307 tdm_buffer_unref_backend(private_layer->waiting_buffer);
2308 tbm_surface_queue_release(private_layer->buffer_queue,
2309 private_layer->waiting_buffer);
2310 private_layer->waiting_buffer = NULL;
2311 _pthread_mutex_lock(&private_display->lock);
2313 if (tdm_debug_module & TDM_DEBUG_BUFFER)
2314 TDM_INFO("layer(%p) waiting_buffer(%p)",
2315 private_layer, private_layer->waiting_buffer);
2318 private_layer->buffer_queue = buffer_queue;
2319 tbm_surface_queue_add_acquirable_cb(private_layer->buffer_queue,
2320 _tbm_layer_queue_acquirable_cb,
2322 tbm_surface_queue_add_destroy_cb(private_layer->buffer_queue,
2323 _tbm_layer_queue_destroy_cb,
2325 _pthread_mutex_unlock(&private_display->lock);
2331 tdm_layer_unset_buffer_queue(tdm_layer *layer)
2333 tdm_func_layer *func_layer;
2336 _pthread_mutex_lock(&private_display->lock);
2338 func_layer = &private_display->func_layer;
2340 if (private_layer->waiting_buffer) {
2341 _pthread_mutex_unlock(&private_display->lock);
2342 tdm_buffer_unref_backend(private_layer->waiting_buffer);
2343 tbm_surface_queue_release(private_layer->buffer_queue,
2344 private_layer->waiting_buffer);
2345 private_layer->waiting_buffer = NULL;
2346 _pthread_mutex_lock(&private_display->lock);
2348 if (tdm_debug_module & TDM_DEBUG_BUFFER)
2349 TDM_INFO("layer(%p) waiting_buffer(%p)",
2350 private_layer, private_layer->waiting_buffer);
2353 if (private_layer->showing_buffer) {
2354 _pthread_mutex_unlock(&private_display->lock);
2355 tdm_buffer_unref_backend(private_layer->showing_buffer);
2356 tbm_surface_queue_release(private_layer->buffer_queue,
2357 private_layer->showing_buffer);
2358 _pthread_mutex_lock(&private_display->lock);
2359 private_layer->showing_buffer = NULL;
2361 if (tdm_debug_module & TDM_DEBUG_BUFFER)
2362 TDM_INFO("layer(%p) showing_buffer(%p)",
2363 private_layer, private_layer->showing_buffer);
2366 tbm_surface_queue_remove_acquirable_cb(private_layer->buffer_queue, _tbm_layer_queue_acquirable_cb, layer);
2367 tbm_surface_queue_remove_destroy_cb(private_layer->buffer_queue, _tbm_layer_queue_destroy_cb, layer);
2368 private_layer->buffer_queue = NULL;
2369 private_layer->usable = 1;
2371 if (private_layer->usable)
2372 TDM_INFO("layer(%p) now usable", private_layer);
2374 if (!func_layer->layer_unset_buffer) {
2375 _pthread_mutex_unlock(&private_display->lock);
2376 TDM_ERR("not implemented!!");
2377 return TDM_ERROR_NOT_IMPLEMENTED;
2380 ret = func_layer->layer_unset_buffer(private_layer->layer_backend);
2382 _pthread_mutex_unlock(&private_display->lock);
2388 tdm_layer_is_usable(tdm_layer *layer, unsigned int *usable)
2392 TDM_RETURN_VAL_IF_FAIL(usable != NULL, TDM_ERROR_INVALID_PARAMETER);
2394 _pthread_mutex_lock(&private_display->lock);
2396 *usable = private_layer->usable;
2398 _pthread_mutex_unlock(&private_display->lock);
2404 tdm_layer_set_video_pos(tdm_layer *layer, int zpos)
2406 tdm_func_layer *func_layer;
2409 _pthread_mutex_lock(&private_display->lock);
2411 func_layer = &private_display->func_layer;
2413 if (!(private_layer->caps.capabilities & TDM_LAYER_CAPABILITY_VIDEO)) {
2414 TDM_ERR("layer(%p) is not video layer", private_layer);
2415 _pthread_mutex_unlock(&private_display->lock);
2416 return TDM_ERROR_INVALID_PARAMETER;
2419 if (!func_layer->layer_set_video_pos) {
2420 _pthread_mutex_unlock(&private_display->lock);
2421 TDM_ERR("not implemented!!");
2422 return TDM_ERROR_NOT_IMPLEMENTED;
2425 ret = func_layer->layer_set_video_pos(private_layer->layer_backend, zpos);
2427 _pthread_mutex_unlock(&private_display->lock);
2432 EXTERN tdm_capture *
2433 tdm_layer_create_capture(tdm_layer *layer, tdm_error *error)
2435 tdm_capture *capture = NULL;
2437 LAYER_FUNC_ENTRY_ERROR();
2439 _pthread_mutex_lock(&private_display->lock);
2441 capture = (tdm_capture *)tdm_capture_create_layer_internal(private_layer, error);
2443 _pthread_mutex_unlock(&private_display->lock);
2449 tdm_layer_get_buffer_flags(tdm_layer *layer, unsigned int *flags)
2451 tdm_func_layer *func_layer;
2454 _pthread_mutex_lock(&private_display->lock);
2456 func_layer = &private_display->func_layer;
2458 if (!func_layer->layer_get_buffer_flags) {
2459 _pthread_mutex_unlock(&private_display->lock);
2460 TDM_ERR("not implemented!!");
2461 return TDM_ERROR_NOT_IMPLEMENTED;
2464 ret = func_layer->layer_get_buffer_flags(private_layer->layer_backend, flags);
2466 _pthread_mutex_unlock(&private_display->lock);