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_free_buffer(tdm_private_layer *private_layer, tdm_private_layer_buffer *layer_buffer);
106 static void _tdm_layer_committed(tdm_private_layer *private_layer, tdm_private_layer_buffer **committed_buffer);
107 static void _tdm_layer_cb_wait_vblank(tdm_vblank *vblank, tdm_error error, unsigned int sequence,
108 unsigned int tv_sec, unsigned int tv_usec, void *user_data);
109 static void _tbm_layer_queue_acquirable_cb(tbm_surface_queue_h surface_queue, void *data);
110 static void _tbm_layer_queue_destroy_cb(tbm_surface_queue_h surface_queue, void *data);
113 tdm_display_get_capabilities(tdm_display *dpy,
114 tdm_display_capability *capabilities)
116 DISPLAY_FUNC_ENTRY();
118 TDM_RETURN_VAL_IF_FAIL(capabilities != NULL, TDM_ERROR_INVALID_PARAMETER);
120 _pthread_mutex_lock(&private_display->lock);
122 *capabilities = private_display->capabilities;
124 _pthread_mutex_unlock(&private_display->lock);
130 tdm_display_get_pp_capabilities(tdm_display *dpy,
131 tdm_pp_capability *capabilities)
133 DISPLAY_FUNC_ENTRY();
135 TDM_RETURN_VAL_IF_FAIL(capabilities != NULL, TDM_ERROR_INVALID_PARAMETER);
137 _pthread_mutex_lock(&private_display->lock);
139 if (!(private_display->capabilities & TDM_DISPLAY_CAPABILITY_PP)) {
140 TDM_ERR("no pp capability");
141 _pthread_mutex_unlock(&private_display->lock);
142 return TDM_ERROR_NO_CAPABILITY;
145 *capabilities = private_display->caps_pp.capabilities;
147 _pthread_mutex_unlock(&private_display->lock);
153 tdm_display_get_pp_available_formats(tdm_display *dpy,
154 const tbm_format **formats, int *count)
156 DISPLAY_FUNC_ENTRY();
158 TDM_RETURN_VAL_IF_FAIL(formats != NULL, TDM_ERROR_INVALID_PARAMETER);
159 TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
161 _pthread_mutex_lock(&private_display->lock);
163 if (!(private_display->capabilities & TDM_DISPLAY_CAPABILITY_PP)) {
164 TDM_ERR("no pp capability");
165 _pthread_mutex_unlock(&private_display->lock);
166 return TDM_ERROR_NO_CAPABILITY;
169 *formats = (const tbm_format *)private_display->caps_pp.formats;
170 *count = private_display->caps_pp.format_count;
172 _pthread_mutex_unlock(&private_display->lock);
178 tdm_display_get_pp_available_size(tdm_display *dpy, int *min_w, int *min_h,
179 int *max_w, int *max_h, int *preferred_align)
181 DISPLAY_FUNC_ENTRY();
183 _pthread_mutex_lock(&private_display->lock);
185 if (!(private_display->capabilities & TDM_DISPLAY_CAPABILITY_PP)) {
186 TDM_ERR("no pp capability");
187 _pthread_mutex_unlock(&private_display->lock);
188 return TDM_ERROR_NO_CAPABILITY;
192 *min_w = TDM_FRONT_VALUE(private_display->caps_pp.min_w);
194 *min_h = TDM_FRONT_VALUE(private_display->caps_pp.min_h);
196 *max_w = TDM_FRONT_VALUE(private_display->caps_pp.max_w);
198 *max_h = TDM_FRONT_VALUE(private_display->caps_pp.max_h);
200 *preferred_align = TDM_FRONT_VALUE(private_display->caps_pp.preferred_align);
202 _pthread_mutex_unlock(&private_display->lock);
208 tdm_display_get_capture_capabilities(tdm_display *dpy,
209 tdm_capture_capability *capabilities)
211 DISPLAY_FUNC_ENTRY();
213 TDM_RETURN_VAL_IF_FAIL(capabilities != NULL, TDM_ERROR_INVALID_PARAMETER);
215 _pthread_mutex_lock(&private_display->lock);
217 if (!(private_display->capabilities & TDM_DISPLAY_CAPABILITY_CAPTURE)) {
218 TDM_ERR("no capture capability");
219 _pthread_mutex_unlock(&private_display->lock);
220 return TDM_ERROR_NO_CAPABILITY;
223 *capabilities = private_display->caps_capture.capabilities;
225 _pthread_mutex_unlock(&private_display->lock);
231 tdm_display_get_catpure_available_formats(tdm_display *dpy,
232 const tbm_format **formats, int *count)
234 DISPLAY_FUNC_ENTRY();
236 TDM_RETURN_VAL_IF_FAIL(formats != NULL, TDM_ERROR_INVALID_PARAMETER);
237 TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
239 _pthread_mutex_lock(&private_display->lock);
241 if (!(private_display->capabilities & TDM_DISPLAY_CAPABILITY_CAPTURE)) {
242 TDM_ERR("no capture capability");
243 _pthread_mutex_unlock(&private_display->lock);
244 return TDM_ERROR_NO_CAPABILITY;
247 *formats = (const tbm_format *)private_display->caps_capture.formats;
248 *count = private_display->caps_capture.format_count;
250 _pthread_mutex_unlock(&private_display->lock);
256 tdm_display_get_capture_available_size(tdm_display *dpy, int *min_w, int *min_h,
257 int *max_w, int *max_h, int *preferred_align)
259 DISPLAY_FUNC_ENTRY();
261 _pthread_mutex_lock(&private_display->lock);
263 if (!(private_display->capabilities & TDM_DISPLAY_CAPABILITY_CAPTURE)) {
264 TDM_ERR("no capture capability");
265 _pthread_mutex_unlock(&private_display->lock);
266 return TDM_ERROR_NO_CAPABILITY;
270 *min_w = TDM_FRONT_VALUE(private_display->caps_capture.min_w);
272 *min_h = TDM_FRONT_VALUE(private_display->caps_capture.min_h);
274 *max_w = TDM_FRONT_VALUE(private_display->caps_capture.max_w);
276 *max_h = TDM_FRONT_VALUE(private_display->caps_capture.max_h);
278 *preferred_align = TDM_FRONT_VALUE(private_display->caps_capture.preferred_align);
280 _pthread_mutex_unlock(&private_display->lock);
286 tdm_display_get_max_layer_count(tdm_display *dpy, int *max_count)
288 DISPLAY_FUNC_ENTRY();
290 TDM_RETURN_VAL_IF_FAIL(max_count != NULL, TDM_ERROR_INVALID_PARAMETER);
292 _pthread_mutex_lock(&private_display->lock);
294 *max_count = TDM_FRONT_VALUE(private_display->caps_display.max_layer_count);
296 _pthread_mutex_unlock(&private_display->lock);
302 tdm_display_get_output_count(tdm_display *dpy, int *count)
304 tdm_private_output *private_output = NULL;
306 DISPLAY_FUNC_ENTRY();
308 TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
310 _pthread_mutex_lock(&private_display->lock);
313 LIST_FOR_EACH_ENTRY(private_output, &private_display->output_list, link)
317 _pthread_mutex_unlock(&private_display->lock);
318 return TDM_ERROR_NONE;
321 _pthread_mutex_unlock(&private_display->lock);
328 tdm_display_get_output(tdm_display *dpy, int index, tdm_error *error)
330 tdm_private_output *private_output = NULL;
332 DISPLAY_FUNC_ENTRY_ERROR();
334 _pthread_mutex_lock(&private_display->lock);
337 *error = TDM_ERROR_NONE;
339 LIST_FOR_EACH_ENTRY(private_output, &private_display->output_list, link) {
340 if (private_output->index == index) {
341 _pthread_mutex_unlock(&private_display->lock);
342 return private_output;
346 _pthread_mutex_unlock(&private_display->lock);
352 tdm_display_get_fd(tdm_display *dpy, int *fd)
354 DISPLAY_FUNC_ENTRY();
356 TDM_RETURN_VAL_IF_FAIL(fd != NULL, TDM_ERROR_INVALID_PARAMETER);
358 _pthread_mutex_lock(&private_display->lock);
360 if (tdm_thread_is_running())
361 *fd = tdm_thread_get_fd(private_display->private_loop);
363 *fd = tdm_event_loop_get_fd(private_display);
365 _pthread_mutex_unlock(&private_display->lock);
371 tdm_display_handle_events(tdm_display *dpy)
376 DISPLAY_FUNC_ENTRY();
378 ret = tdm_display_get_fd(dpy, &fd);
379 TDM_RETURN_VAL_IF_FAIL(fd >= 0, ret);
385 if (tdm_debug_module & TDM_DEBUG_THREAD)
386 TDM_INFO("fd(%d) polling in", fd);
388 while (poll(&fds, 1, -1) < 0) {
389 if (errno == EINTR || errno == EAGAIN) /* normal case */
392 TDM_ERR("poll failed: %m");
393 return TDM_ERROR_OPERATION_FAILED;
397 if (tdm_debug_module & TDM_DEBUG_THREAD)
398 TDM_INFO("fd(%d) polling out", fd);
400 if (tdm_thread_is_running())
401 ret = tdm_thread_handle_cb(private_display->private_loop);
403 ret = tdm_event_loop_dispatch(private_display);
409 tdm_display_get_backend_info(tdm_display *dpy, const char **name,
410 const char **vendor, int *major, int *minor)
412 tdm_backend_module *module_data;
414 DISPLAY_FUNC_ENTRY();
416 _pthread_mutex_lock(&private_display->lock);
418 module_data = private_display->module_data;
421 *name = module_data->name;
423 *vendor = module_data->vendor;
425 *major = TDM_BACKEND_GET_ABI_MAJOR(module_data->abi_version);
427 *minor = TDM_BACKEND_GET_ABI_MINOR(module_data->abi_version);
429 _pthread_mutex_unlock(&private_display->lock);
435 tdm_display_create_pp(tdm_display *dpy, tdm_error *error)
439 DISPLAY_FUNC_ENTRY_ERROR();
441 _pthread_mutex_lock(&private_display->lock);
443 pp = (tdm_pp *)tdm_pp_create_internal(private_display, error);
445 _pthread_mutex_unlock(&private_display->lock);
451 tdm_output_get_model_info(tdm_output *output, const char **maker,
452 const char **model, const char **name)
456 _pthread_mutex_lock(&private_display->lock);
459 *maker = private_output->caps.maker;
461 *model = private_output->caps.model;
463 *name = private_output->caps.name;
465 _pthread_mutex_unlock(&private_display->lock);
471 tdm_output_get_capabilities(tdm_output *output, tdm_output_capability *capabilities)
475 TDM_RETURN_VAL_IF_FAIL(capabilities != NULL, TDM_ERROR_INVALID_PARAMETER);
477 _pthread_mutex_lock(&private_display->lock);
479 *capabilities = private_output->caps.capabilities;
481 _pthread_mutex_unlock(&private_display->lock);
487 tdm_output_get_conn_status(tdm_output *output, tdm_output_conn_status *status)
491 TDM_RETURN_VAL_IF_FAIL(status != NULL, TDM_ERROR_INVALID_PARAMETER);
493 _pthread_mutex_lock(&private_display->lock);
495 *status = private_output->caps.status;
497 _pthread_mutex_unlock(&private_display->lock);
503 _tdm_output_used_layer_count(tdm_private_output *private_output)
505 tdm_private_layer *private_layer = NULL;
506 unsigned int count = 0;
508 LIST_FOR_EACH_ENTRY(private_layer, &private_output->layer_list, link) {
509 if (!private_layer->usable)
517 _tdm_output_update(tdm_output *output_backend, void *user_data)
519 tdm_private_display *private_display;
520 tdm_private_output *private_output = user_data;
523 TDM_RETURN_IF_FAIL(private_output);
525 private_display = private_output->private_display;
527 ret = tdm_display_update_output(private_display, output_backend, private_output->pipe);
528 TDM_RETURN_IF_FAIL(ret == TDM_ERROR_NONE);
532 tdm_output_cb_status(tdm_output *output_backend, tdm_output_conn_status status,
535 tdm_private_display *private_display;
536 tdm_private_output *private_output = user_data;
539 TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED());
540 TDM_RETURN_IF_FAIL(private_output);
542 private_display = private_output->private_display;
544 if (!tdm_thread_in_display_thread(syscall(SYS_gettid))) {
545 tdm_thread_cb_output_status output_status;
548 _tdm_output_update(output_backend, user_data);
550 output_status.base.type = TDM_THREAD_CB_OUTPUT_STATUS;
551 output_status.base.length = sizeof output_status;
552 output_status.output_stamp = private_output->stamp;
553 output_status.status = status;
554 output_status.user_data = user_data;
557 tdm_output_call_change_handler_internal(private_output,
558 &private_output->change_handler_list_sub,
559 TDM_OUTPUT_CHANGE_CONNECTION,
562 ret = tdm_thread_send_cb(private_display->private_loop, &output_status.base);
563 TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
568 if (!tdm_thread_is_running())
569 _tdm_output_update(output_backend, user_data);
572 tdm_output_call_change_handler_internal(private_output,
573 &private_output->change_handler_list_main,
574 TDM_OUTPUT_CHANGE_CONNECTION,
579 tdm_output_add_change_handler(tdm_output *output,
580 tdm_output_change_handler func,
583 tdm_private_change_handler *change_handler;
586 TDM_RETURN_VAL_IF_FAIL(func != NULL, TDM_ERROR_INVALID_PARAMETER);
588 pthread_mutex_lock(&private_display->lock);
590 change_handler = calloc(1, sizeof(tdm_private_change_handler));
591 if (!change_handler) {
592 TDM_ERR("failed: alloc memory");
593 _pthread_mutex_unlock(&private_display->lock);
594 return TDM_ERROR_OUT_OF_MEMORY;
597 change_handler->private_output = private_output;
598 change_handler->func = func;
599 change_handler->user_data = user_data;
600 change_handler->owner_tid = syscall(SYS_gettid);
602 if (!tdm_thread_in_display_thread(change_handler->owner_tid))
603 LIST_ADDTAIL(&change_handler->link, &private_output->change_handler_list_sub);
605 LIST_ADDTAIL(&change_handler->link, &private_output->change_handler_list_main);
607 _pthread_mutex_unlock(&private_display->lock);
613 tdm_output_remove_change_handler(tdm_output *output,
614 tdm_output_change_handler func,
617 tdm_private_display *private_display;
618 tdm_private_output *private_output;
619 tdm_private_change_handler *h = NULL, *hh = NULL;
621 TDM_RETURN_IF_FAIL(output != NULL);
622 TDM_RETURN_IF_FAIL(func != NULL);
624 private_output = (tdm_private_output*)output;
625 private_display = private_output->private_display;
627 _pthread_mutex_lock(&private_display->lock);
629 LIST_FOR_EACH_ENTRY_SAFE(h, hh, &private_output->change_handler_list_main, link) {
630 if (h->func != func || h->user_data != user_data)
636 _pthread_mutex_unlock(&private_display->lock);
641 LIST_FOR_EACH_ENTRY_SAFE(h, hh, &private_output->change_handler_list_sub, link) {
642 if (h->func != func || h->user_data != user_data)
648 _pthread_mutex_unlock(&private_display->lock);
653 _pthread_mutex_unlock(&private_display->lock);
657 tdm_output_get_output_type(tdm_output *output, tdm_output_type *type)
661 TDM_RETURN_VAL_IF_FAIL(type != NULL, TDM_ERROR_INVALID_PARAMETER);
663 _pthread_mutex_lock(&private_display->lock);
665 *type = private_output->caps.type;
667 _pthread_mutex_unlock(&private_display->lock);
673 tdm_output_get_layer_count(tdm_output *output, int *count)
675 tdm_private_layer *private_layer = NULL;
679 TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
681 _pthread_mutex_lock(&private_display->lock);
684 LIST_FOR_EACH_ENTRY(private_layer, &private_output->layer_list, link)
687 _pthread_mutex_unlock(&private_display->lock);
688 return TDM_ERROR_NONE;
691 _pthread_mutex_unlock(&private_display->lock);
698 tdm_output_get_layer(tdm_output *output, int index, tdm_error *error)
700 tdm_private_layer *private_layer = NULL;
702 OUTPUT_FUNC_ENTRY_ERROR();
704 _pthread_mutex_lock(&private_display->lock);
707 *error = TDM_ERROR_NONE;
709 LIST_FOR_EACH_ENTRY(private_layer, &private_output->layer_list, link) {
710 if (private_layer->index == index) {
711 _pthread_mutex_unlock(&private_display->lock);
712 return private_layer;
716 _pthread_mutex_unlock(&private_display->lock);
722 tdm_output_get_available_properties(tdm_output *output, const tdm_prop **props,
727 TDM_RETURN_VAL_IF_FAIL(props != NULL, TDM_ERROR_INVALID_PARAMETER);
728 TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
730 _pthread_mutex_lock(&private_display->lock);
732 *props = (const tdm_prop *)private_output->caps.props;
733 *count = private_output->caps.prop_count;
735 _pthread_mutex_unlock(&private_display->lock);
741 tdm_output_get_available_modes(tdm_output *output,
742 const tdm_output_mode **modes, int *count)
746 TDM_RETURN_VAL_IF_FAIL(modes != NULL, TDM_ERROR_INVALID_PARAMETER);
747 TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
749 _pthread_mutex_lock(&private_display->lock);
751 *modes = (const tdm_output_mode *)private_output->caps.modes;
752 *count = private_output->caps.mode_count;
754 _pthread_mutex_unlock(&private_display->lock);
760 tdm_output_get_available_size(tdm_output *output, int *min_w, int *min_h,
761 int *max_w, int *max_h, int *preferred_align)
765 _pthread_mutex_lock(&private_display->lock);
768 *min_w = TDM_FRONT_VALUE(private_output->caps.min_w);
770 *min_h = TDM_FRONT_VALUE(private_output->caps.min_h);
772 *max_w = TDM_FRONT_VALUE(private_output->caps.max_w);
774 *max_h = TDM_FRONT_VALUE(private_output->caps.max_h);
776 *preferred_align = TDM_FRONT_VALUE(private_output->caps.preferred_align);
778 _pthread_mutex_unlock(&private_display->lock);
784 tdm_output_get_cursor_available_size(tdm_output *output, int *min_w, int *min_h,
785 int *max_w, int *max_h, int *preferred_align)
789 _pthread_mutex_lock(&private_display->lock);
791 if (!tdm_display_check_module_abi(private_display, 1, 5)) {
802 *preferred_align = -1;
804 _pthread_mutex_unlock(&private_display->lock);
806 return TDM_ERROR_BAD_MODULE;
810 *min_w = TDM_FRONT_VALUE(private_output->caps.cursor_min_w);
812 *min_h = TDM_FRONT_VALUE(private_output->caps.cursor_min_h);
814 *max_w = TDM_FRONT_VALUE(private_output->caps.cursor_max_w);
816 *max_h = TDM_FRONT_VALUE(private_output->caps.cursor_max_h);
818 *preferred_align = TDM_FRONT_VALUE(private_output->caps.cursor_preferred_align);
820 _pthread_mutex_unlock(&private_display->lock);
826 tdm_output_get_physical_size(tdm_output *output, unsigned int *mmWidth,
827 unsigned int *mmHeight)
831 _pthread_mutex_lock(&private_display->lock);
834 *mmWidth = private_output->caps.mmWidth;
836 *mmHeight = private_output->caps.mmHeight;
838 _pthread_mutex_unlock(&private_display->lock);
844 tdm_output_get_subpixel(tdm_output *output, unsigned int *subpixel)
847 TDM_RETURN_VAL_IF_FAIL(subpixel != NULL, TDM_ERROR_INVALID_PARAMETER);
849 _pthread_mutex_lock(&private_display->lock);
851 *subpixel = private_output->caps.subpixel;
853 _pthread_mutex_unlock(&private_display->lock);
859 tdm_output_get_pipe(tdm_output *output, unsigned int *pipe)
862 TDM_RETURN_VAL_IF_FAIL(pipe != NULL, TDM_ERROR_INVALID_PARAMETER);
864 _pthread_mutex_lock(&private_display->lock);
866 *pipe = private_output->pipe;
868 _pthread_mutex_unlock(&private_display->lock);
874 tdm_output_get_primary_index(tdm_output *output, int *index)
876 tdm_private_layer *private_layer = NULL;
879 TDM_RETURN_VAL_IF_FAIL(index != NULL, TDM_ERROR_INVALID_PARAMETER);
881 _pthread_mutex_lock(&private_display->lock);
883 LIST_FOR_EACH_ENTRY(private_layer, &private_output->layer_list, link) {
884 if (private_layer->caps.capabilities & TDM_LAYER_CAPABILITY_PRIMARY) {
885 *index = private_layer->index;
890 _pthread_mutex_unlock(&private_display->lock);
896 tdm_output_set_property(tdm_output *output, unsigned int id, tdm_value value)
898 tdm_func_output *func_output;
901 _pthread_mutex_lock(&private_display->lock);
903 func_output = &private_display->func_output;
905 if (!func_output->output_set_property) {
906 _pthread_mutex_unlock(&private_display->lock);
907 TDM_ERR("not implemented!!");
908 return TDM_ERROR_NOT_IMPLEMENTED;
911 ret = func_output->output_set_property(private_output->output_backend, id,
914 _pthread_mutex_unlock(&private_display->lock);
920 tdm_output_get_property(tdm_output *output, unsigned int id, tdm_value *value)
922 tdm_func_output *func_output;
925 TDM_RETURN_VAL_IF_FAIL(value != NULL, TDM_ERROR_INVALID_PARAMETER);
927 _pthread_mutex_lock(&private_display->lock);
929 func_output = &private_display->func_output;
931 if (!func_output->output_get_property) {
932 _pthread_mutex_unlock(&private_display->lock);
933 TDM_ERR("not implemented!!");
934 return TDM_ERROR_NOT_IMPLEMENTED;
937 ret = func_output->output_get_property(private_output->output_backend, id,
940 _pthread_mutex_unlock(&private_display->lock);
946 tdm_output_cb_vblank(tdm_output *output_backend, unsigned int sequence,
947 unsigned int tv_sec, unsigned int tv_usec, void *user_data)
949 tdm_private_vblank_handler *vblank_handler = user_data;
950 tdm_private_vblank_handler *v = NULL, *vv = NULL;
951 tdm_private_output *private_output;
952 tdm_private_display *private_display;
953 struct list_head clone_list;
955 pid_t tid = syscall(SYS_gettid);
957 TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED());
958 TDM_RETURN_IF_FAIL(vblank_handler);
960 private_output = vblank_handler->private_output;
961 private_display = private_output->private_display;
963 if (vblank_handler->owner_tid != tid) {
964 tdm_thread_cb_output_vblank output_vblank;
967 output_vblank.base.type = TDM_THREAD_CB_OUTPUT_VBLANK;
968 output_vblank.base.length = sizeof output_vblank;
969 output_vblank.output_stamp = vblank_handler->private_output->stamp;
970 output_vblank.sequence = sequence;
971 output_vblank.tv_sec = tv_sec;
972 output_vblank.tv_usec = tv_usec;
973 output_vblank.user_data = user_data;
975 ret = tdm_thread_send_cb(private_display->private_loop, &output_vblank.base);
976 TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
981 if (vblank_handler->owner_tid != tid)
982 TDM_NEVER_GET_HERE();
984 interval = vblank_handler->interval;
985 sync = vblank_handler->sync;
987 LIST_INITHEAD(&clone_list);
989 LIST_FOR_EACH_ENTRY_SAFE(v, vv, &private_output->vblank_handler_list, link) {
990 if (v->interval != interval || v->sync != sync || v->owner_tid != tid)
994 LIST_ADDTAIL(&v->link, &clone_list);
997 if (tdm_debug_module & TDM_DEBUG_COMMIT)
998 TDM_INFO("----------------------------------------- output(%d) got vblank", private_output->pipe);
1000 _pthread_mutex_unlock(&private_display->lock);
1001 LIST_FOR_EACH_ENTRY_SAFE(v, vv, &clone_list, link) {
1002 if (tdm_debug_module & TDM_DEBUG_COMMIT)
1003 TDM_INFO("handler(%p)", v);
1006 v->func(v->private_output, sequence, tv_sec, tv_usec, v->user_data);
1010 _pthread_mutex_lock(&private_display->lock);
1012 if (tdm_debug_module & TDM_DEBUG_COMMIT)
1013 TDM_INFO("-----------------------------------------...");
1017 tdm_output_cb_commit(tdm_output *output_backend, unsigned int sequence,
1018 unsigned int tv_sec, unsigned int tv_usec, void *user_data)
1020 tdm_private_output_commit_handler *output_commit_handler = user_data;
1021 tdm_private_display *private_display;
1022 tdm_private_output *private_output;
1023 tdm_private_layer *private_layer = NULL;
1025 TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED());
1027 if (!output_commit_handler)
1030 private_output = output_commit_handler->private_output;
1031 private_display = private_output->private_display;
1033 if (output_commit_handler->owner_tid != syscall(SYS_gettid)) {
1034 tdm_thread_cb_output_commit output_commit;
1037 output_commit.base.type = TDM_THREAD_CB_OUTPUT_COMMIT;
1038 output_commit.base.length = sizeof output_commit;
1039 output_commit.output_stamp = private_output->stamp;
1040 output_commit.sequence = sequence;
1041 output_commit.tv_sec = tv_sec;
1042 output_commit.tv_usec = tv_usec;
1043 output_commit.user_data = user_data;
1045 ret = tdm_thread_send_cb(private_display->private_loop, &output_commit.base);
1046 TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
1051 if (tdm_debug_module & TDM_DEBUG_COMMIT) {
1052 TDM_INFO("----------------------------------------- output(%d) committed", private_output->pipe);
1053 TDM_INFO("handler(%p)", output_commit_handler);
1056 if (private_display->commit_type == TDM_COMMIT_TYPE_OUTPUT) {
1057 /* In case of layer commit, the below will be handled in the layer commit callback */
1058 LIST_FOR_EACH_ENTRY(private_layer, &private_output->layer_list, link) {
1059 if (private_layer->committed_buffer)
1060 _tdm_layer_committed(private_layer, &private_layer->committed_buffer);
1064 if (output_commit_handler->func) {
1065 _pthread_mutex_unlock(&private_display->lock);
1066 output_commit_handler->func(private_output, sequence,
1067 tv_sec, tv_usec, output_commit_handler->user_data);
1068 _pthread_mutex_lock(&private_display->lock);
1071 LIST_DEL(&output_commit_handler->link);
1072 free(output_commit_handler);
1074 if (tdm_debug_module & TDM_DEBUG_COMMIT)
1075 TDM_INFO("-----------------------------------------...");
1078 /* add_front: To distinguish between the user vblank handlers and the layer
1079 * commit vblank handlers. The layer commit handlers will be called
1080 * before calling the user vblank handlers.
1083 _tdm_output_wait_vblank(tdm_output *output, int interval, int sync,
1084 tdm_output_vblank_handler func, void *user_data,
1085 unsigned int add_front)
1087 tdm_func_output *func_output;
1088 tdm_private_vblank_handler *vblank_handler = NULL, *v = NULL;
1089 unsigned int skip_request = 0;
1090 pid_t tid = syscall(SYS_gettid);
1092 OUTPUT_FUNC_ENTRY();
1094 func_output = &private_display->func_output;
1096 /* interval SHOULD be at least 1 */
1100 if (!func_output->output_wait_vblank) {
1101 TDM_ERR("not implemented!!");
1102 return TDM_ERROR_NOT_IMPLEMENTED;
1105 if (!private_output->regist_vblank_cb) {
1106 private_output->regist_vblank_cb = 1;
1107 ret = func_output->output_set_vblank_handler(private_output->output_backend,
1108 tdm_output_cb_vblank);
1111 vblank_handler = calloc(1, sizeof(tdm_private_vblank_handler));
1112 if (!vblank_handler) {
1113 TDM_ERR("failed: alloc memory");
1114 return TDM_ERROR_OUT_OF_MEMORY;
1117 if (tdm_debug_module & TDM_DEBUG_COMMIT)
1118 TDM_INFO("output(%d) wait_vblank: handler(%p)", private_output->pipe, vblank_handler);
1120 LIST_FOR_EACH_ENTRY(v, &private_output->vblank_handler_list, link) {
1121 if (v->interval == interval && v->sync == sync && v->owner_tid == tid) {
1128 LIST_ADD(&vblank_handler->link, &private_output->vblank_handler_list);
1130 LIST_ADDTAIL(&vblank_handler->link, &private_output->vblank_handler_list);
1132 vblank_handler->private_output = private_output;
1133 vblank_handler->interval = interval;
1134 vblank_handler->sync = sync;
1135 vblank_handler->func = func;
1136 vblank_handler->user_data = user_data;
1137 vblank_handler->owner_tid = tid;
1139 /* If there is the previous request, we can skip to call output_wait_vblank() */
1140 if (!skip_request) {
1141 ret = func_output->output_wait_vblank(private_output->output_backend, interval,
1142 sync, vblank_handler);
1143 TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, wait_failed);
1145 if (tdm_debug_module & TDM_DEBUG_COMMIT)
1146 TDM_INFO("output(%d) backend wait_vblank", private_output->pipe);
1152 if (vblank_handler) {
1153 LIST_DEL(&vblank_handler->link);
1154 free(vblank_handler);
1160 tdm_output_wait_vblank(tdm_output *output, int interval, int sync,
1161 tdm_output_vblank_handler func, void *user_data)
1163 OUTPUT_FUNC_ENTRY();
1165 _pthread_mutex_lock(&private_display->lock);
1167 if (private_output->current_dpms_value > TDM_OUTPUT_DPMS_ON) {
1168 TDM_WRN("output(%d) dpms: %s", private_output->pipe,
1169 tdm_dpms_str(private_output->current_dpms_value));
1170 _pthread_mutex_unlock(&private_display->lock);
1171 return TDM_ERROR_DPMS_OFF;
1174 ret = _tdm_output_wait_vblank(output, interval, sync, func, user_data, 0);
1176 _pthread_mutex_unlock(&private_display->lock);
1182 tdm_output_wait_vblank_add_front(tdm_output *output, int interval, int sync,
1183 tdm_output_vblank_handler func, void *user_data)
1185 OUTPUT_FUNC_ENTRY();
1187 _pthread_mutex_lock(&private_display->lock);
1189 if (private_output->current_dpms_value > TDM_OUTPUT_DPMS_ON) {
1190 TDM_WRN("output(%d) dpms: %s", private_output->pipe,
1191 tdm_dpms_str(private_output->current_dpms_value));
1192 _pthread_mutex_unlock(&private_display->lock);
1193 return TDM_ERROR_DPMS_OFF;
1196 ret = _tdm_output_wait_vblank(output, interval, sync, func, user_data, 1);
1198 _pthread_mutex_unlock(&private_display->lock);
1204 _tdm_output_commit(tdm_output *output, int sync, tdm_output_commit_handler func,
1207 tdm_func_output *func_output;
1208 tdm_private_output_commit_handler *output_commit_handler = NULL;
1209 tdm_private_layer *private_layer = NULL;
1211 OUTPUT_FUNC_ENTRY();
1213 func_output = &private_display->func_output;
1215 if (!func_output->output_commit) {
1216 TDM_ERR("not implemented!!");
1217 return TDM_ERROR_NOT_IMPLEMENTED;
1221 if (!private_output->regist_commit_cb) {
1222 private_output->regist_commit_cb = 1;
1223 ret = func_output->output_set_commit_handler(private_output->output_backend,
1224 tdm_output_cb_commit);
1225 TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, commit_failed);
1228 output_commit_handler = calloc(1, sizeof(tdm_private_output_commit_handler));
1229 if (!output_commit_handler) {
1230 TDM_ERR("failed: alloc memory");
1231 return TDM_ERROR_OUT_OF_MEMORY;
1234 LIST_ADDTAIL(&output_commit_handler->link, &private_output->output_commit_handler_list);
1235 output_commit_handler->private_output = private_output;
1236 output_commit_handler->func = func;
1237 output_commit_handler->user_data = user_data;
1238 output_commit_handler->owner_tid = syscall(SYS_gettid);
1241 ret = func_output->output_commit(private_output->output_backend, sync,
1242 output_commit_handler);
1243 TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, commit_failed);
1245 if (tdm_debug_module & TDM_DEBUG_COMMIT)
1246 TDM_INFO("output(%d) backend commit: handle(%p)", private_output->pipe, output_commit_handler);
1248 LIST_FOR_EACH_ENTRY(private_layer, &private_output->layer_list, link) {
1249 if (!private_layer->waiting_buffer)
1252 private_layer->committed_buffer = private_layer->waiting_buffer;
1253 private_layer->waiting_buffer = NULL;
1254 if (tdm_debug_module & TDM_DEBUG_BUFFER)
1255 TDM_INFO("layer(%p) waiting_buffer(%p) committed_buffer(%p)",
1256 private_layer, private_layer->waiting_buffer,
1257 private_layer->committed_buffer->buffer);
1263 if (output_commit_handler) {
1264 LIST_DEL(&output_commit_handler->link);
1265 free(output_commit_handler);
1271 tdm_output_commit(tdm_output *output, int sync, tdm_output_commit_handler func,
1274 OUTPUT_FUNC_ENTRY();
1276 _pthread_mutex_lock(&private_display->lock);
1278 if (private_display->commit_type == TDM_COMMIT_TYPE_NONE)
1279 private_display->commit_type = TDM_COMMIT_TYPE_OUTPUT;
1280 else if (private_display->commit_type == TDM_COMMIT_TYPE_LAYER) {
1281 TDM_ERR("Can't supported. Use tdm_layer_commit");
1282 _pthread_mutex_unlock(&private_display->lock);
1283 return TDM_ERROR_BAD_REQUEST;
1286 if (private_display->commit_per_vblank) {
1287 TDM_ERR("Use tdm_layer_commit");
1288 _pthread_mutex_unlock(&private_display->lock);
1289 return TDM_ERROR_BAD_REQUEST;
1292 if (private_output->current_dpms_value > TDM_OUTPUT_DPMS_ON) {
1293 TDM_ERR("output(%d) dpms: %s", private_output->pipe,
1294 tdm_dpms_str(private_output->current_dpms_value));
1295 _pthread_mutex_unlock(&private_display->lock);
1296 return TDM_ERROR_DPMS_OFF;
1299 if (tdm_debug_module & TDM_DEBUG_COMMIT)
1300 TDM_INFO("output(%d) commit", private_output->pipe);
1302 ret = _tdm_output_commit(output, sync, func, user_data);
1304 _pthread_mutex_unlock(&private_display->lock);
1310 tdm_output_set_mode(tdm_output *output, const tdm_output_mode *mode)
1312 tdm_func_output *func_output;
1313 OUTPUT_FUNC_ENTRY();
1315 TDM_RETURN_VAL_IF_FAIL(mode != NULL, TDM_ERROR_INVALID_PARAMETER);
1317 _pthread_mutex_lock(&private_display->lock);
1319 func_output = &private_display->func_output;
1321 if (!func_output->output_set_mode) {
1322 _pthread_mutex_unlock(&private_display->lock);
1323 TDM_ERR("not implemented!!");
1324 return TDM_ERROR_NOT_IMPLEMENTED;
1327 ret = func_output->output_set_mode(private_output->output_backend, mode);
1328 if (ret == TDM_ERROR_NONE)
1329 private_output->current_mode = mode;
1330 _pthread_mutex_unlock(&private_display->lock);
1336 tdm_output_get_mode(tdm_output *output, const tdm_output_mode **mode)
1338 OUTPUT_FUNC_ENTRY();
1340 TDM_RETURN_VAL_IF_FAIL(mode != NULL, TDM_ERROR_INVALID_PARAMETER);
1342 _pthread_mutex_lock(&private_display->lock);
1344 *mode = private_output->current_mode;
1346 _pthread_mutex_unlock(&private_display->lock);
1352 _tdm_output_dpms_changed_timeout(void *user_data)
1354 tdm_private_output *private_output = user_data;
1357 value.u32 = private_output->current_dpms_value;
1358 tdm_output_call_change_handler_internal(private_output,
1359 &private_output->change_handler_list_sub,
1360 TDM_OUTPUT_CHANGE_DPMS,
1363 return TDM_ERROR_NONE;
1367 tdm_output_cb_dpms(tdm_output *output_backend, tdm_output_dpms dpms, void *user_data)
1369 tdm_private_display *private_display;
1370 tdm_private_output *private_output = user_data;
1373 TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED());
1374 TDM_RETURN_IF_FAIL(private_output);
1376 private_display = private_output->private_display;
1378 if (!tdm_thread_in_display_thread(syscall(SYS_gettid))) {
1379 tdm_thread_cb_output_dpms output_dpms;
1382 _tdm_output_update(output_backend, user_data);
1384 output_dpms.base.type = TDM_THREAD_CB_OUTPUT_DPMS;
1385 output_dpms.base.length = sizeof output_dpms;
1386 output_dpms.output_stamp = private_output->stamp;
1387 output_dpms.dpms = dpms;
1388 output_dpms.user_data = user_data;
1391 tdm_output_call_change_handler_internal(private_output,
1392 &private_output->change_handler_list_sub,
1393 TDM_OUTPUT_CHANGE_DPMS,
1396 ret = tdm_thread_send_cb(private_display->private_loop, &output_dpms.base);
1397 TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
1402 private_output->current_dpms_value = dpms;
1405 tdm_output_call_change_handler_internal(private_output,
1406 &private_output->change_handler_list_main,
1407 TDM_OUTPUT_CHANGE_DPMS,
1412 tdm_output_set_dpms(tdm_output *output, tdm_output_dpms dpms_value)
1414 tdm_func_output *func_output;
1415 OUTPUT_FUNC_ENTRY();
1417 if (dpms_value > TDM_OUTPUT_DPMS_OFF)
1418 dpms_value = TDM_OUTPUT_DPMS_OFF;
1420 _pthread_mutex_lock(&private_display->lock);
1422 if (private_output->current_dpms_value == dpms_value) {
1423 _pthread_mutex_unlock(&private_display->lock);
1424 return TDM_ERROR_NONE;
1427 /** Use timer to call the output change callback of the sub-thread.
1428 * The output change callback of tdm_server and tdm_vblank was called
1429 * in the main thread. And it made the multi thread issue. If we use
1430 * the timer, we can call the sub-thread's output change callback in
1433 if (!private_output->dpms_changed_timer) {
1434 private_output->dpms_changed_timer =
1435 tdm_event_loop_add_timer_handler(private_output->private_display,
1436 _tdm_output_dpms_changed_timeout, private_output, NULL);
1437 if (!private_output->dpms_changed_timer) {
1438 TDM_ERR("can't create dpms timer!!");
1439 _pthread_mutex_unlock(&private_display->lock);
1440 return TDM_ERROR_OUT_OF_MEMORY;
1444 func_output = &private_display->func_output;
1446 if (!func_output->output_set_dpms) {
1447 _pthread_mutex_unlock(&private_display->lock);
1448 private_output->current_dpms_value = dpms_value;
1449 TDM_WRN("not implemented!!");
1450 return TDM_ERROR_NONE;
1453 if (func_output->output_set_dpms_handler) {
1454 if (!private_output->regist_dpms_cb) {
1455 private_output->regist_dpms_cb = 1;
1456 ret = func_output->output_set_dpms_handler(private_output->output_backend,
1457 tdm_output_cb_dpms, private_output);
1458 if (ret != TDM_ERROR_NONE) {
1459 _pthread_mutex_unlock(&private_display->lock);
1460 TDM_ERR("Can't set the dpms handler!!");
1466 ret = func_output->output_set_dpms(private_output->output_backend, dpms_value);
1468 if (ret == TDM_ERROR_NONE && !func_output->output_set_dpms_handler) {
1471 private_output->current_dpms_value = dpms_value;
1473 value.u32 = dpms_value;
1474 tdm_output_call_change_handler_internal(private_output,
1475 &private_output->change_handler_list_main,
1476 TDM_OUTPUT_CHANGE_DPMS,
1479 if (!LIST_IS_EMPTY(&private_output->change_handler_list_sub)) {
1480 ret = tdm_event_loop_source_timer_update(private_output->dpms_changed_timer, 1);
1481 if (ret != TDM_ERROR_NONE)
1482 TDM_NEVER_GET_HERE();
1486 _pthread_mutex_unlock(&private_display->lock);
1492 tdm_output_get_dpms(tdm_output *output, tdm_output_dpms *dpms_value)
1494 tdm_func_output *func_output;
1495 OUTPUT_FUNC_ENTRY();
1497 TDM_RETURN_VAL_IF_FAIL(dpms_value != NULL, TDM_ERROR_INVALID_PARAMETER);
1499 _pthread_mutex_lock(&private_display->lock);
1501 func_output = &private_display->func_output;
1503 if (!func_output->output_get_dpms) {
1504 *dpms_value = private_output->current_dpms_value;
1505 _pthread_mutex_unlock(&private_display->lock);
1506 TDM_WRN("not implemented!!");
1507 return TDM_ERROR_NONE;
1510 ret = func_output->output_get_dpms(private_output->output_backend, dpms_value);
1512 _pthread_mutex_unlock(&private_display->lock);
1517 EXTERN tdm_capture *
1518 tdm_output_create_capture(tdm_output *output, tdm_error *error)
1520 tdm_capture *capture = NULL;
1522 OUTPUT_FUNC_ENTRY_ERROR();
1524 _pthread_mutex_lock(&private_display->lock);
1526 capture = (tdm_capture *)tdm_capture_create_output_internal(private_output, error);
1528 _pthread_mutex_unlock(&private_display->lock);
1534 tdm_output_call_change_handler_internal(tdm_private_output *private_output,
1535 struct list_head *change_handler_list,
1536 tdm_output_change_type type,
1538 int no_check_thread_id)
1540 tdm_private_display *private_display;
1541 tdm_private_change_handler *change_handler = NULL;
1543 TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED());
1544 TDM_RETURN_IF_FAIL(private_output);
1546 private_display = private_output->private_display;
1547 if (!tdm_thread_in_display_thread(syscall(SYS_gettid))) {
1548 if (type & TDM_OUTPUT_CHANGE_CONNECTION)
1549 TDM_INFO("output(%d) changed: %s (%d)",
1550 private_output->pipe, tdm_status_str(value.u32), value.u32);
1551 if (type & TDM_OUTPUT_CHANGE_DPMS)
1552 TDM_INFO("output(%d) changed: dpms %s (%d)",
1553 private_output->pipe, tdm_dpms_str(value.u32), value.u32);
1556 if (LIST_IS_EMPTY(change_handler_list))
1559 LIST_FOR_EACH_ENTRY(change_handler, change_handler_list, link) {
1560 if (!no_check_thread_id && change_handler->owner_tid != syscall(SYS_gettid))
1561 TDM_NEVER_GET_HERE();
1563 _pthread_mutex_unlock(&private_display->lock);
1564 change_handler->func(private_output, type,
1565 value, change_handler->user_data);
1566 _pthread_mutex_lock(&private_display->lock);
1571 tdm_layer_get_capabilities(tdm_layer *layer, tdm_layer_capability *capabilities)
1575 TDM_RETURN_VAL_IF_FAIL(capabilities != NULL, TDM_ERROR_INVALID_PARAMETER);
1577 _pthread_mutex_lock(&private_display->lock);
1579 *capabilities = private_layer->caps.capabilities;
1581 _pthread_mutex_unlock(&private_display->lock);
1587 tdm_layer_get_available_formats(tdm_layer *layer, const tbm_format **formats, int *count)
1591 TDM_RETURN_VAL_IF_FAIL(formats != NULL, TDM_ERROR_INVALID_PARAMETER);
1592 TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
1594 _pthread_mutex_lock(&private_display->lock);
1596 *formats = (const tbm_format *)private_layer->caps.formats;
1597 *count = private_layer->caps.format_count;
1599 _pthread_mutex_unlock(&private_display->lock);
1605 tdm_layer_get_available_properties(tdm_layer *layer, const tdm_prop **props, int *count)
1609 TDM_RETURN_VAL_IF_FAIL(props != NULL, TDM_ERROR_INVALID_PARAMETER);
1610 TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
1612 _pthread_mutex_lock(&private_display->lock);
1614 *props = (const tdm_prop *)private_layer->caps.props;
1615 *count = private_layer->caps.prop_count;
1617 _pthread_mutex_unlock(&private_display->lock);
1623 tdm_layer_get_zpos(tdm_layer *layer, int *zpos)
1627 TDM_RETURN_VAL_IF_FAIL(zpos != NULL, TDM_ERROR_INVALID_PARAMETER);
1629 _pthread_mutex_lock(&private_display->lock);
1631 *zpos = private_layer->caps.zpos;
1633 _pthread_mutex_unlock(&private_display->lock);
1639 tdm_layer_set_property(tdm_layer *layer, unsigned int id, tdm_value value)
1641 tdm_func_layer *func_layer;
1644 _pthread_mutex_lock(&private_display->lock);
1646 func_layer = &private_display->func_layer;
1648 if (private_layer->usable)
1649 TDM_INFO("layer(%d) not usable", private_layer->index);
1651 private_layer->usable = 0;
1653 if (!func_layer->layer_set_property) {
1654 _pthread_mutex_unlock(&private_display->lock);
1655 TDM_ERR("not implemented!!");
1656 return TDM_ERROR_NOT_IMPLEMENTED;
1659 ret = func_layer->layer_set_property(private_layer->layer_backend, id, value);
1661 _pthread_mutex_unlock(&private_display->lock);
1667 tdm_layer_get_property(tdm_layer *layer, unsigned int id, tdm_value *value)
1669 tdm_func_layer *func_layer;
1672 TDM_RETURN_VAL_IF_FAIL(value != NULL, TDM_ERROR_INVALID_PARAMETER);
1674 _pthread_mutex_lock(&private_display->lock);
1676 func_layer = &private_display->func_layer;
1678 if (!func_layer->layer_get_property) {
1679 _pthread_mutex_unlock(&private_display->lock);
1680 TDM_ERR("not implemented!!");
1681 return TDM_ERROR_NOT_IMPLEMENTED;
1684 ret = func_layer->layer_get_property(private_layer->layer_backend, id, value);
1686 _pthread_mutex_unlock(&private_display->lock);
1692 tdm_layer_set_info(tdm_layer *layer, tdm_info_layer *info)
1694 tdm_func_layer *func_layer;
1699 TDM_RETURN_VAL_IF_FAIL(info != NULL, TDM_ERROR_INVALID_PARAMETER);
1701 _pthread_mutex_lock(&private_display->lock);
1703 func_layer = &private_display->func_layer;
1705 if (private_layer->usable)
1706 TDM_INFO("layer(%p) not usable", private_layer);
1708 private_layer->usable = 0;
1710 if (!func_layer->layer_set_info) {
1711 _pthread_mutex_unlock(&private_display->lock);
1712 TDM_ERR("not implemented!!");
1713 return TDM_ERROR_NOT_IMPLEMENTED;
1716 if (info->src_config.format)
1717 snprintf(fmtstr, 128, "%c%c%c%c", FOURCC_STR(info->src_config.format));
1719 snprintf(fmtstr, 128, "NONE");
1721 TDM_INFO("layer(%p) info: src(%dx%d %d,%d %dx%d %s) dst(%d,%d %dx%d) trans(%d)",
1722 private_layer, info->src_config.size.h, info->src_config.size.v,
1723 info->src_config.pos.x, info->src_config.pos.y,
1724 info->src_config.pos.w, info->src_config.pos.h,
1726 info->dst_pos.x, info->dst_pos.y,
1727 info->dst_pos.w, info->dst_pos.h,
1730 ret = func_layer->layer_set_info(private_layer->layer_backend, info);
1731 TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
1733 _pthread_mutex_unlock(&private_display->lock);
1739 tdm_layer_get_info(tdm_layer *layer, tdm_info_layer *info)
1741 tdm_func_layer *func_layer;
1744 TDM_RETURN_VAL_IF_FAIL(info != NULL, TDM_ERROR_INVALID_PARAMETER);
1746 _pthread_mutex_lock(&private_display->lock);
1748 func_layer = &private_display->func_layer;
1750 if (!func_layer->layer_get_info) {
1751 _pthread_mutex_unlock(&private_display->lock);
1752 TDM_ERR("not implemented!!");
1753 return TDM_ERROR_NOT_IMPLEMENTED;
1756 ret = func_layer->layer_get_info(private_layer->layer_backend, info);
1758 _pthread_mutex_unlock(&private_display->lock);
1764 _tdm_layer_dump_buffer(tdm_layer *layer, tbm_surface_h buffer)
1766 tdm_private_layer *private_layer = (tdm_private_layer*)layer;
1767 tdm_private_output *private_output = private_layer->private_output;
1770 char fname[PATH_MAX];
1772 pipe = private_output->pipe;
1773 zpos = private_layer->caps.zpos;
1775 snprintf(fname, sizeof(fname), "tdm_%d_lyr_%d", pipe, zpos);
1777 tbm_surface_internal_dump_buffer(buffer, fname);
1778 TDM_DBG("%s dump excute", fname);
1784 _tdm_layer_free_buffer(tdm_private_layer *private_layer, tdm_private_layer_buffer *layer_buffer)
1786 tdm_private_display *private_display;
1791 private_display = private_layer->private_output->private_display;
1793 LIST_DEL(&layer_buffer->link);
1794 if (layer_buffer->buffer) {
1795 _pthread_mutex_unlock(&private_display->lock);
1796 tdm_buffer_unref_backend(layer_buffer->buffer);
1797 if (private_layer->buffer_queue)
1798 tbm_surface_queue_release(private_layer->buffer_queue, layer_buffer->buffer);
1799 _pthread_mutex_lock(&private_display->lock);
1805 _tdm_layer_free_all_buffers(tdm_private_layer *private_layer)
1807 tdm_private_output *private_output = private_layer->private_output;
1808 tdm_private_layer_commit_handler *lm = NULL, *lmm = NULL;
1809 struct list_head clone_list;
1811 LIST_INITHEAD(&clone_list);
1813 if (private_layer->waiting_buffer) {
1814 _tdm_layer_free_buffer(private_layer, private_layer->waiting_buffer);
1815 private_layer->waiting_buffer = NULL;
1817 if (tdm_debug_module & TDM_DEBUG_BUFFER)
1818 TDM_INFO("layer(%p) waiting_buffer(%p)",
1819 private_layer, private_layer->waiting_buffer);
1822 if (private_layer->committed_buffer) {
1823 _tdm_layer_free_buffer(private_layer, private_layer->committed_buffer);
1824 private_layer->committed_buffer = NULL;
1826 if (tdm_debug_module & TDM_DEBUG_BUFFER)
1827 TDM_INFO("layer(%p) committed_buffer(%p)",
1828 private_layer, private_layer->committed_buffer);
1831 if (private_layer->showing_buffer) {
1832 _tdm_layer_free_buffer(private_layer, private_layer->showing_buffer);
1833 private_layer->showing_buffer = NULL;
1835 if (tdm_debug_module & TDM_DEBUG_BUFFER)
1836 TDM_INFO("layer(%p) showing_buffer(%p)",
1837 private_layer, private_layer->showing_buffer);
1840 LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &private_output->layer_commit_handler_list, link) {
1841 if (lm->private_layer != private_layer)
1843 LIST_DEL(&lm->link);
1844 LIST_ADDTAIL(&lm->link, &clone_list);
1847 LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &clone_list, link) {
1848 LIST_DEL(&lm->link);
1849 _tdm_layer_free_buffer(private_layer, lm->committed_buffer);
1853 LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &private_output->pending_commit_handler_list, link) {
1854 if (lm->private_layer != private_layer)
1856 LIST_DEL(&lm->link);
1857 LIST_ADDTAIL(&lm->link, &clone_list);
1860 LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &clone_list, link) {
1861 LIST_DEL(&lm->link);
1862 _tdm_layer_free_buffer(private_layer, lm->committed_buffer);
1866 if (private_layer->buffer_queue) {
1867 tbm_surface_queue_remove_acquirable_cb(private_layer->buffer_queue, _tbm_layer_queue_acquirable_cb, private_layer);
1868 tbm_surface_queue_remove_destroy_cb(private_layer->buffer_queue, _tbm_layer_queue_destroy_cb, private_layer);
1869 private_layer->buffer_queue = NULL;
1874 tdm_layer_set_buffer(tdm_layer *layer, tbm_surface_h buffer)
1876 tdm_func_layer *func_layer;
1877 tdm_private_layer_buffer *layer_buffer;
1881 TDM_RETURN_VAL_IF_FAIL(buffer != NULL, TDM_ERROR_INVALID_PARAMETER);
1883 _pthread_mutex_lock(&private_display->lock);
1885 if (tdm_debug_dump & TDM_DUMP_FLAG_LAYER &&
1886 !(private_layer->caps.capabilities & TDM_LAYER_CAPABILITY_VIDEO)) {
1887 char str[TDM_PATH_LEN];
1889 snprintf(str, TDM_PATH_LEN, "layer_%d_%d_%03d",
1890 private_output->index, private_layer->index, i++);
1891 tdm_helper_dump_buffer_str(buffer, tdm_debug_dump_dir, str);
1894 func_layer = &private_display->func_layer;
1896 if (private_layer->usable)
1897 TDM_INFO("layer(%p) not usable", private_layer);
1899 private_layer->usable = 0;
1901 if (!func_layer->layer_set_buffer) {
1902 _pthread_mutex_unlock(&private_display->lock);
1903 TDM_ERR("not implemented!!");
1904 return TDM_ERROR_NOT_IMPLEMENTED;
1907 layer_buffer = calloc(1, sizeof(tdm_private_layer_buffer));
1908 if (!layer_buffer) {
1909 _pthread_mutex_unlock(&private_display->lock);
1910 TDM_ERR("alloc failed");
1911 return TDM_ERROR_OUT_OF_MEMORY;
1913 LIST_INITHEAD(&layer_buffer->link);
1915 ret = func_layer->layer_set_buffer(private_layer->layer_backend, buffer);
1916 TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
1919 if (tdm_dump_enable && !(private_layer->caps.capabilities & TDM_LAYER_CAPABILITY_VIDEO))
1920 _tdm_layer_dump_buffer(layer, buffer);
1922 if (ret == TDM_ERROR_NONE) {
1923 if (private_layer->waiting_buffer)
1924 _tdm_layer_free_buffer(private_layer, private_layer->waiting_buffer);
1926 private_layer->waiting_buffer = layer_buffer;
1927 private_layer->waiting_buffer->buffer = tdm_buffer_ref_backend(buffer);
1928 if (tdm_debug_module & TDM_DEBUG_BUFFER)
1929 TDM_INFO("layer(%p) waiting_buffer(%p)",
1930 private_layer, private_layer->waiting_buffer->buffer);
1932 _tdm_layer_free_buffer(private_layer, layer_buffer);
1934 _pthread_mutex_unlock(&private_display->lock);
1940 tdm_layer_unset_buffer(tdm_layer *layer)
1942 tdm_func_layer *func_layer;
1945 _pthread_mutex_lock(&private_display->lock);
1947 func_layer = &private_display->func_layer;
1949 _tdm_layer_free_all_buffers(private_layer);
1951 private_layer->usable = 1;
1953 if (private_layer->usable)
1954 TDM_INFO("layer(%p) now usable", private_layer);
1956 if (!func_layer->layer_unset_buffer) {
1957 _pthread_mutex_unlock(&private_display->lock);
1958 TDM_ERR("not implemented!!");
1959 return TDM_ERROR_NOT_IMPLEMENTED;
1962 ret = func_layer->layer_unset_buffer(private_layer->layer_backend);
1963 TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
1965 _pthread_mutex_unlock(&private_display->lock);
1971 _tdm_layer_committed(tdm_private_layer *private_layer, tdm_private_layer_buffer **committed_buffer)
1973 tdm_private_output *private_output = private_layer->private_output;
1974 tdm_private_display *private_display = private_output->private_display;
1976 if (private_display->print_fps) {
1977 double curr = tdm_helper_get_time();
1978 if (private_layer->fps_stamp == 0) {
1979 private_layer->fps_stamp = curr;
1980 } else if ((curr - private_layer->fps_stamp) > 1.0) {
1981 TDM_INFO("output(%d) layer(%d) fps: %d", private_output->index, private_layer->index, private_layer->fps_count);
1982 private_layer->fps_count = 0;
1983 private_layer->fps_stamp = curr;
1985 private_layer->fps_count++;
1986 } else if (private_layer->fps_stamp != 0) {
1987 private_layer->fps_stamp = 0;
1988 private_layer->fps_count = 0;
1991 if (private_layer->showing_buffer)
1992 _tdm_layer_free_buffer(private_layer, private_layer->showing_buffer);
1994 private_layer->showing_buffer = *committed_buffer;
1995 *committed_buffer = NULL;
1997 if (tdm_debug_module & TDM_DEBUG_BUFFER)
1998 TDM_INFO("layer(%p) committed_buffer(%p) showing_buffer(%p)",
1999 private_layer, *committed_buffer,
2000 (private_layer->showing_buffer) ? private_layer->showing_buffer->buffer : NULL);
2004 _tdm_layer_got_output_vblank(tdm_private_output *private_output, unsigned int sequence,
2005 unsigned int tv_sec, unsigned int tv_usec)
2007 tdm_private_layer_commit_handler *lm = NULL, *lmm = NULL;
2008 tdm_private_display *private_display;
2009 struct list_head clone_list, pending_clone_list;
2012 private_display = private_output->private_display;
2014 private_output->layer_waiting_vblank = 0;
2016 LIST_INITHEAD(&clone_list);
2017 LIST_INITHEAD(&pending_clone_list);
2019 LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &private_output->layer_commit_handler_list, link) {
2020 LIST_DEL(&lm->link);
2021 lm->private_layer->committing = 0;
2022 LIST_ADDTAIL(&lm->link, &clone_list);
2025 LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &private_output->pending_commit_handler_list, link) {
2026 LIST_DEL(&lm->link);
2027 lm->private_layer->committing = 0;
2028 LIST_ADDTAIL(&lm->link, &pending_clone_list);
2031 LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &clone_list, link) {
2032 if (tdm_debug_module & TDM_DEBUG_COMMIT)
2033 TDM_INFO("layer(%p) committed. handle(%p) commited_buffer(%p)",
2034 lm->private_layer, lm, (lm->committed_buffer) ? lm->committed_buffer->buffer : NULL);
2036 LIST_DEL(&lm->link);
2037 _tdm_layer_committed(lm->private_layer, &lm->committed_buffer);
2038 _pthread_mutex_unlock(&private_display->lock);
2040 lm->func(lm->private_layer, sequence, tv_sec, tv_usec, lm->user_data);
2041 _pthread_mutex_lock(&private_display->lock);
2042 if (lm->committed_buffer)
2043 _tdm_layer_free_buffer(lm->private_layer, lm->committed_buffer);
2047 if (LIST_IS_EMPTY(&pending_clone_list))
2050 TDM_GOTO_IF_FAIL(private_output->vblank != NULL, wait_failed);
2052 ret = _tdm_output_commit(private_output, 0, NULL, NULL);
2053 TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, wait_failed);
2055 if (tdm_debug_module & TDM_DEBUG_COMMIT)
2056 TDM_INFO("layer commit: output(%d) commit", private_output->pipe);
2058 /* tdm_vblank APIs is for server. it should be called in unlock status*/
2059 if (!private_output->layer_waiting_vblank) {
2060 _pthread_mutex_unlock(&private_display->lock);
2061 ret = tdm_vblank_wait(private_output->vblank, 0, 0, 1, _tdm_layer_cb_wait_vblank, private_output);
2062 _pthread_mutex_lock(&private_display->lock);
2063 TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, wait_failed);
2064 private_output->layer_waiting_vblank = 1;
2067 if (tdm_debug_module & TDM_DEBUG_COMMIT)
2068 TDM_INFO("layer commit: output(%d) wait vblank", private_output->pipe);
2070 LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &pending_clone_list, link) {
2071 LIST_DEL(&lm->link);
2072 LIST_ADDTAIL(&lm->link, &private_output->layer_commit_handler_list);
2077 LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &pending_clone_list, link) {
2078 LIST_DEL(&lm->link);
2079 _tdm_layer_free_buffer(lm->private_layer, lm->committed_buffer);
2086 _tdm_layer_cb_output_commit(tdm_output *output, unsigned int sequence,
2087 unsigned int tv_sec, unsigned int tv_usec, void *user_data)
2089 tdm_private_layer_commit_handler *layer_commit_handler = user_data;
2090 tdm_private_layer_commit_handler *lm = NULL;
2091 tdm_private_display *private_display;
2092 tdm_private_output *private_output = output;
2093 tdm_private_layer *private_layer;
2096 TDM_RETURN_IF_FAIL(layer_commit_handler != NULL);
2098 private_display = private_output->private_display;
2100 LIST_FOR_EACH_ENTRY(lm, &private_output->layer_commit_handler_list, link) {
2101 if (layer_commit_handler == lm) {
2110 private_layer = layer_commit_handler->private_layer;
2112 if (tdm_debug_module & TDM_DEBUG_COMMIT)
2113 TDM_INFO("layer(%p) commit: output(%d) committed. handle(%p)",
2114 private_layer, private_output->pipe, layer_commit_handler);
2116 _pthread_mutex_lock(&private_display->lock);
2118 _tdm_layer_committed(private_layer, &layer_commit_handler->committed_buffer);
2120 if (layer_commit_handler->func) {
2121 _pthread_mutex_unlock(&private_display->lock);
2122 layer_commit_handler->func(private_output, sequence,
2123 tv_sec, tv_usec, layer_commit_handler->user_data);
2124 _pthread_mutex_lock(&private_display->lock);
2127 LIST_DEL(&layer_commit_handler->link);
2128 free(layer_commit_handler);
2130 _pthread_mutex_unlock(&private_display->lock);
2134 _tdm_layer_cb_wait_vblank(tdm_vblank *vblank, tdm_error error, unsigned int sequence,
2135 unsigned int tv_sec, unsigned int tv_usec, void *user_data)
2137 tdm_private_output *private_output = user_data;
2138 tdm_private_display *private_display;
2140 TDM_RETURN_IF_FAIL(private_output != NULL);
2142 private_display = private_output->private_display;
2144 _pthread_mutex_lock(&private_display->lock);
2146 if (tdm_debug_module & TDM_DEBUG_COMMIT)
2147 TDM_INFO("layer commit: output(%d) got vblank", private_output->pipe);
2149 _tdm_layer_got_output_vblank(private_output, sequence, tv_sec, tv_usec);
2151 _pthread_mutex_unlock(&private_display->lock);
2155 _tdm_layer_commit_possible(tdm_private_layer *private_layer)
2157 tdm_private_output *private_output = private_layer->private_output;
2158 tdm_private_display *private_display = private_output->private_display;
2160 if (private_display->commit_per_vblank == 1 && _tdm_output_used_layer_count(private_output) == 1) {
2161 if (tdm_debug_module & TDM_DEBUG_COMMIT)
2162 TDM_INFO("layer(%p) commit: 1 layer", private_layer);
2166 if (private_display->commit_per_vblank == 2 && LIST_IS_EMPTY(&private_output->layer_commit_handler_list)) {
2167 if (tdm_debug_module & TDM_DEBUG_COMMIT)
2168 TDM_INFO("layer(%p) commit: non previous commit", private_layer);
2176 _tdm_layer_commit(tdm_layer *layer, tdm_layer_commit_handler func, void *user_data)
2178 tdm_private_layer_commit_handler *layer_commit_handler;
2181 layer_commit_handler = calloc(1, sizeof(tdm_private_layer_commit_handler));
2182 if (!layer_commit_handler) {
2183 TDM_ERR("failed: alloc memory");
2184 return TDM_ERROR_OUT_OF_MEMORY;
2187 if (tdm_debug_module & TDM_DEBUG_COMMIT)
2188 TDM_INFO("layer(%p) commit: handle(%p)", private_layer, layer_commit_handler);
2190 LIST_INITHEAD(&layer_commit_handler->link);
2191 layer_commit_handler->private_layer = private_layer;
2192 layer_commit_handler->func = func;
2193 layer_commit_handler->user_data = user_data;
2195 layer_commit_handler->committed_buffer = private_layer->waiting_buffer;
2196 private_layer->waiting_buffer = NULL;
2198 if (tdm_debug_module & TDM_DEBUG_BUFFER)
2199 TDM_INFO("layer(%p) waiting_buffer(%p) committed_buffer(%p)",
2200 private_layer, private_layer->waiting_buffer,
2201 (layer_commit_handler->committed_buffer) ? layer_commit_handler->committed_buffer->buffer : NULL);
2203 if (!private_display->commit_per_vblank) {
2204 TDM_GOTO_IF_FAIL(private_display->commit_type == TDM_COMMIT_TYPE_OUTPUT, commit_failed);
2206 LIST_ADDTAIL(&layer_commit_handler->link, &private_output->layer_commit_handler_list);
2207 ret = _tdm_output_commit(private_layer->private_output, 0, _tdm_layer_cb_output_commit, layer_commit_handler);
2208 TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, commit_failed);
2210 if (tdm_debug_module & TDM_DEBUG_COMMIT)
2211 TDM_INFO("layer(%p) commit: no commit-per-vblank", private_layer);
2213 TDM_GOTO_IF_FAIL(private_display->commit_type == TDM_COMMIT_TYPE_LAYER, commit_failed);
2215 if (private_layer->committing)
2216 TDM_WRN("layer(%d) too many commit", private_layer->index);
2218 private_layer->committing = 1;
2220 if (_tdm_layer_commit_possible(private_layer)) {
2221 /* add to layer_commit_handler_list */
2222 LIST_ADDTAIL(&layer_commit_handler->link, &private_output->layer_commit_handler_list);
2223 ret = _tdm_output_commit(private_layer->private_output, 0, NULL, NULL);
2224 TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, commit_failed);
2226 if (tdm_debug_module & TDM_DEBUG_COMMIT)
2227 TDM_INFO("layer(%p) commit: output", private_layer);
2229 /* add to pending_commit_handler_list. It will be commited when a vblank occurs */
2230 LIST_ADDTAIL(&layer_commit_handler->link, &private_output->pending_commit_handler_list);
2232 if (tdm_debug_module & TDM_DEBUG_COMMIT)
2233 TDM_INFO("layer(%p) commit: pending", private_layer);
2236 if (!private_output->vblank) {
2237 /* tdm_vblank APIs is for server. it should be called in unlock status*/
2238 _pthread_mutex_unlock(&private_display->lock);
2239 private_output->vblank = tdm_vblank_create(private_display, private_output, NULL);
2240 _pthread_mutex_lock(&private_display->lock);
2241 TDM_GOTO_IF_FAIL(private_output->vblank != NULL, commit_failed);
2244 if (!private_output->layer_waiting_vblank) {
2245 /* tdm_vblank APIs is for server. it should be called in unlock status*/
2246 _pthread_mutex_unlock(&private_display->lock);
2247 ret = tdm_vblank_wait(private_output->vblank, 0, 0, 1, _tdm_layer_cb_wait_vblank, private_output);
2248 _pthread_mutex_lock(&private_display->lock);
2249 TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, commit_failed);
2250 private_output->layer_waiting_vblank = 1;
2252 if (tdm_debug_module & TDM_DEBUG_COMMIT)
2253 TDM_INFO("layer(%p) commit: wait vblank", private_layer);
2260 if (layer_commit_handler) {
2261 private_layer->waiting_buffer = layer_commit_handler->committed_buffer;
2262 LIST_DEL(&layer_commit_handler->link);
2263 free(layer_commit_handler);
2269 tdm_layer_commit(tdm_layer *layer, tdm_layer_commit_handler func, void *user_data)
2273 _pthread_mutex_lock(&private_display->lock);
2275 if (private_display->commit_type == TDM_COMMIT_TYPE_NONE) {
2276 if (!private_display->commit_per_vblank)
2277 private_display->commit_type = TDM_COMMIT_TYPE_OUTPUT;
2279 private_display->commit_type = TDM_COMMIT_TYPE_LAYER;
2282 if (private_output->current_dpms_value > TDM_OUTPUT_DPMS_ON) {
2283 TDM_ERR("layer(%p)'s output(%d) dpms: %s", layer, private_output->pipe,
2284 tdm_dpms_str(private_output->current_dpms_value));
2285 _pthread_mutex_unlock(&private_display->lock);
2286 return TDM_ERROR_DPMS_OFF;
2289 ret = _tdm_layer_commit(private_layer, func, user_data);
2291 _pthread_mutex_unlock(&private_display->lock);
2297 tdm_layer_is_committing(tdm_layer *layer, unsigned int *committing)
2301 TDM_RETURN_VAL_IF_FAIL(committing != NULL, TDM_ERROR_INVALID_PARAMETER);
2303 _pthread_mutex_lock(&private_display->lock);
2305 *committing = private_layer->committing;
2307 _pthread_mutex_unlock(&private_display->lock);
2312 EXTERN tbm_surface_h
2313 tdm_layer_get_displaying_buffer(tdm_layer *layer, tdm_error *error)
2315 tbm_surface_h buffer;
2316 LAYER_FUNC_ENTRY_ERROR();
2318 _pthread_mutex_lock(&private_display->lock);
2321 *error = TDM_ERROR_NONE;
2323 if (private_layer->showing_buffer) {
2324 buffer = private_layer->showing_buffer->buffer;
2327 *error = TDM_ERROR_OPERATION_FAILED;
2328 _pthread_mutex_unlock(&private_display->lock);
2329 TDM_DBG("layer(%p) showing_buffer is null", private_layer);
2332 _pthread_mutex_unlock(&private_display->lock);
2338 _tbm_layer_queue_acquirable_cb(tbm_surface_queue_h surface_queue, void *data)
2340 TDM_RETURN_IF_FAIL(data != NULL);
2341 tdm_layer *layer = data;
2342 tdm_func_layer *func_layer;
2343 tbm_surface_h surface = NULL;
2344 tdm_private_layer_buffer *layer_buffer;
2345 LAYER_FUNC_ENTRY_VOID_RETURN();
2347 _pthread_mutex_lock(&private_display->lock);
2349 func_layer = &private_display->func_layer;
2350 if (!func_layer->layer_set_buffer) {
2351 _pthread_mutex_unlock(&private_display->lock);
2355 layer_buffer = calloc(1, sizeof(tdm_private_layer_buffer));
2356 if (!layer_buffer) {
2357 _pthread_mutex_unlock(&private_display->lock);
2358 TDM_ERR("alloc failed");
2361 LIST_INITHEAD(&layer_buffer->link);
2363 if (TBM_SURFACE_QUEUE_ERROR_NONE != tbm_surface_queue_acquire(private_layer->buffer_queue, &surface) ||
2365 TDM_ERR("layer(%p) tbm_surface_queue_acquire() failed surface:%p",
2366 private_layer, surface);
2367 _pthread_mutex_unlock(&private_display->lock);
2372 ret = func_layer->layer_set_buffer(private_layer->layer_backend, surface);
2373 TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
2375 if (ret == TDM_ERROR_NONE) {
2376 if (private_layer->waiting_buffer) {
2377 TDM_DBG("layer(%p) drop waiting_buffer(%p)", private_layer, private_layer->waiting_buffer->buffer);
2378 _tdm_layer_free_buffer(private_layer, private_layer->waiting_buffer);
2381 private_layer->waiting_buffer = layer_buffer;
2382 private_layer->waiting_buffer->buffer = tdm_buffer_ref_backend(surface);
2384 if (tdm_debug_module & TDM_DEBUG_BUFFER)
2385 TDM_INFO("layer(%p) waiting_buffer(%p)",
2386 private_layer, private_layer->waiting_buffer->buffer);
2388 if (private_display->commit_type == TDM_COMMIT_TYPE_OUTPUT) {
2389 ret = _tdm_output_commit(private_layer->private_output, 0, NULL, NULL);
2390 if (ret != TDM_ERROR_NONE)
2391 TDM_ERR("_tdm_output_commit() is fail");
2392 } else if (private_display->commit_type == TDM_COMMIT_TYPE_LAYER) {
2393 ret = _tdm_layer_commit(private_layer, NULL, NULL);
2394 if (ret != TDM_ERROR_NONE)
2395 TDM_ERR("layer(%p) _tdm_layer_commit() is fail", private_layer);
2397 TDM_NEVER_GET_HERE();
2400 _tdm_layer_free_buffer(private_layer, layer_buffer);
2402 _pthread_mutex_unlock(&private_display->lock);
2406 _tbm_layer_queue_destroy_cb(tbm_surface_queue_h surface_queue, void *data)
2408 TDM_RETURN_IF_FAIL(data != NULL);
2409 tdm_layer *layer = data;
2410 LAYER_FUNC_ENTRY_VOID_RETURN();
2411 TDM_RETURN_IF_FAIL(ret == TDM_ERROR_NONE);
2413 _pthread_mutex_lock(&private_display->lock);
2415 private_layer->buffer_queue = NULL;
2417 _tdm_layer_free_all_buffers(private_layer);
2419 _pthread_mutex_unlock(&private_display->lock);
2423 tdm_layer_set_buffer_queue(tdm_layer *layer, tbm_surface_queue_h buffer_queue)
2425 tdm_func_layer *func_layer;
2428 TDM_RETURN_VAL_IF_FAIL(buffer_queue != NULL, TDM_ERROR_INVALID_PARAMETER);
2430 _pthread_mutex_lock(&private_display->lock);
2432 func_layer = &private_display->func_layer;
2434 if (private_layer->usable)
2435 TDM_INFO("layer(%p) not usable", private_layer);
2437 private_layer->usable = 0;
2439 if (!func_layer->layer_set_buffer) {
2440 _pthread_mutex_unlock(&private_display->lock);
2441 TDM_ERR("not implemented!!");
2442 return TDM_ERROR_NOT_IMPLEMENTED;
2445 if (buffer_queue == private_layer->buffer_queue) {
2446 _pthread_mutex_unlock(&private_display->lock);
2447 return TDM_ERROR_NONE;
2450 if (private_layer->waiting_buffer) {
2451 _tdm_layer_free_buffer(private_layer, private_layer->waiting_buffer);
2452 private_layer->waiting_buffer = NULL;
2454 if (tdm_debug_module & TDM_DEBUG_BUFFER)
2455 TDM_INFO("layer(%p) waiting_buffer(%p)",
2456 private_layer, private_layer->waiting_buffer);
2459 private_layer->buffer_queue = buffer_queue;
2460 tbm_surface_queue_add_acquirable_cb(private_layer->buffer_queue,
2461 _tbm_layer_queue_acquirable_cb,
2463 tbm_surface_queue_add_destroy_cb(private_layer->buffer_queue,
2464 _tbm_layer_queue_destroy_cb,
2466 _pthread_mutex_unlock(&private_display->lock);
2472 tdm_layer_unset_buffer_queue(tdm_layer *layer)
2474 return tdm_layer_unset_buffer(layer);
2478 tdm_layer_is_usable(tdm_layer *layer, unsigned int *usable)
2482 TDM_RETURN_VAL_IF_FAIL(usable != NULL, TDM_ERROR_INVALID_PARAMETER);
2484 _pthread_mutex_lock(&private_display->lock);
2486 *usable = private_layer->usable;
2488 _pthread_mutex_unlock(&private_display->lock);
2494 tdm_layer_set_video_pos(tdm_layer *layer, int zpos)
2496 tdm_func_layer *func_layer;
2499 _pthread_mutex_lock(&private_display->lock);
2501 func_layer = &private_display->func_layer;
2503 if (!(private_layer->caps.capabilities & TDM_LAYER_CAPABILITY_VIDEO)) {
2504 TDM_ERR("layer(%p) is not video layer", private_layer);
2505 _pthread_mutex_unlock(&private_display->lock);
2506 return TDM_ERROR_INVALID_PARAMETER;
2509 if (!func_layer->layer_set_video_pos) {
2510 _pthread_mutex_unlock(&private_display->lock);
2511 TDM_ERR("not implemented!!");
2512 return TDM_ERROR_NOT_IMPLEMENTED;
2515 ret = func_layer->layer_set_video_pos(private_layer->layer_backend, zpos);
2517 _pthread_mutex_unlock(&private_display->lock);
2522 EXTERN tdm_capture *
2523 tdm_layer_create_capture(tdm_layer *layer, tdm_error *error)
2525 tdm_capture *capture = NULL;
2527 LAYER_FUNC_ENTRY_ERROR();
2529 _pthread_mutex_lock(&private_display->lock);
2531 capture = (tdm_capture *)tdm_capture_create_layer_internal(private_layer, error);
2533 _pthread_mutex_unlock(&private_display->lock);
2539 tdm_layer_get_buffer_flags(tdm_layer *layer, unsigned int *flags)
2541 tdm_func_layer *func_layer;
2544 _pthread_mutex_lock(&private_display->lock);
2546 func_layer = &private_display->func_layer;
2548 if (!func_layer->layer_get_buffer_flags) {
2549 _pthread_mutex_unlock(&private_display->lock);
2550 TDM_ERR("not implemented!!");
2551 return TDM_ERROR_NOT_IMPLEMENTED;
2554 ret = func_layer->layer_get_buffer_flags(private_layer->layer_backend, flags);
2556 _pthread_mutex_unlock(&private_display->lock);