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 <boram1288.park@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 **************************************************************************/
40 #include "tdm_private.h"
44 #define OUTPUT_FUNC_ENTRY() \
45 tdm_private_display *private_display; \
46 tdm_private_output *private_output; \
47 tdm_error ret = TDM_ERROR_NONE; /* default TDM_ERROR_NONE */\
48 TDM_RETURN_VAL_IF_FAIL(output != NULL, TDM_ERROR_INVALID_PARAMETER); \
49 private_output = (tdm_private_output*)output; \
50 private_display = private_output->private_display
52 #define OUTPUT_FUNC_ENTRY_ERROR() \
53 tdm_private_display *private_display; \
54 tdm_private_output *private_output; \
55 tdm_error ret = TDM_ERROR_NONE; /* default TDM_ERROR_NONE */\
56 TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(output != NULL, TDM_ERROR_INVALID_PARAMETER, NULL); \
57 private_output = (tdm_private_output*)output; \
58 private_display = private_output->private_display
61 _tdm_output_vblank_timeout_update(tdm_private_output *private_output, int ms_delay);
64 _tdm_output_vblank_timeout_cb(void *user_data)
66 tdm_private_output *private_output = user_data;
67 tdm_private_output_vblank_handler *v = NULL;
69 TDM_RETURN_VAL_IF_FAIL(private_output != NULL, TDM_ERROR_OPERATION_FAILED);
71 private_output->vblank_timeout_timer_expired++;
73 TDM_ERR("TDM output(%d) vblank TIMEOUT!! (%d time%s)",
75 private_output->vblank_timeout_timer_expired,
76 (private_output->vblank_timeout_timer_expired > 1) ? "s" : "");
78 LIST_FOR_EACH_ENTRY(v, &private_output->vblank_handler_list, link) {
79 TDM_ERR("vblank_handler(%p) interval(%d) sync(%d) sent_to_frontend(%u) owner_tid(%d)",
80 v, v->interval, v->sync, v->sent_to_frontend, v->owner_tid);
83 return TDM_ERROR_NONE;
87 tdm_output_vblank_print_wait_information(tdm_private_output *private_output, void *user_data)
89 tdm_private_output_vblank_handler *v = NULL;
91 TDM_RETURN_IF_FAIL(private_output != NULL);
92 TDM_RETURN_IF_FAIL(user_data != NULL);
94 TDM_ERR("TDM output(%d) vblank user_data(%p) info!!", private_output->pipe, user_data);
96 LIST_FOR_EACH_ENTRY(v, &private_output->vblank_handler_list, link) {
97 if (v->user_data != user_data)
99 TDM_ERR("vblank_handler(%p) interval(%d) sync(%d) sent_to_frontend(%u) owner_tid(%d)",
100 v, v->interval, v->sync, v->sent_to_frontend, v->owner_tid);
105 _tdm_output_vblank_timeout_update(tdm_private_output *private_output, int ms_delay)
109 if (!private_output->vblank_timeout_timer) {
110 private_output->vblank_timeout_timer =
111 tdm_event_loop_add_timer_handler(private_output->private_display,
112 _tdm_output_vblank_timeout_cb,
115 if (!private_output->vblank_timeout_timer) {
116 TDM_ERR("output(%d) couldn't add timer", private_output->pipe);
119 TDM_INFO("output(%d) create vblank timeout timer", private_output->pipe);
120 private_output->vblank_timeout_timer_expired = 0;
123 ret = tdm_event_loop_source_timer_update(private_output->vblank_timeout_timer, ms_delay);
124 if (ret != TDM_ERROR_NONE) {
125 TDM_ERR("output(%d) couldn't update timer", private_output->pipe);
131 tdm_output_init(tdm_private_display *private_display)
133 tdm_thread_cb_set_find_func(TDM_THREAD_CB_OUTPUT_DESTROY, tdm_display_find_output_stamp);
134 tdm_thread_cb_set_find_func(TDM_THREAD_CB_OUTPUT_COMMIT, tdm_display_find_output_stamp);
135 tdm_thread_cb_set_find_func(TDM_THREAD_CB_OUTPUT_VBLANK, tdm_display_find_output_stamp);
136 tdm_thread_cb_set_find_func(TDM_THREAD_CB_OUTPUT_STATUS, tdm_display_find_output_stamp);
137 tdm_thread_cb_set_find_func(TDM_THREAD_CB_OUTPUT_DPMS, tdm_display_find_output_stamp);
138 tdm_thread_cb_set_find_func(TDM_THREAD_CB_VOUTPUT_COMMIT, tdm_display_find_private_voutput);
140 return TDM_ERROR_NONE;
144 tdm_output_call_thread_cb_destroy(tdm_private_output *private_output)
146 tdm_thread_cb_output_destroy output_destroy;
149 memset(&output_destroy, 0, sizeof output_destroy);
150 output_destroy.base.type = TDM_THREAD_CB_OUTPUT_DESTROY;
151 output_destroy.base.length = sizeof output_destroy;
152 output_destroy.base.object_stamp = private_output->stamp;
153 output_destroy.base.data = NULL;
154 output_destroy.base.sync = 1;
156 ret = tdm_thread_cb_call(private_output, &output_destroy.base, 1);
157 TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
159 return TDM_ERROR_NONE;
162 /* LCOV_EXCL_START */
164 tdm_output_thread_cb_destroy(tdm_private_display *private_display, void *object, tdm_thread_cb_base *cb_base, void *user_data)
166 tdm_private_output *private_output = object;
167 tdm_private_output_destroy_handler *destroy_handler = user_data;
169 TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED());
171 assert(destroy_handler->owner_tid == syscall(SYS_gettid));
173 _pthread_mutex_unlock(&private_display->lock);
174 destroy_handler->func(private_output, destroy_handler->user_data);
175 _pthread_mutex_lock(&private_display->lock);
179 tdm_output_add_destroy_handler(tdm_output *output,
180 tdm_output_destroy_handler func,
183 tdm_private_output_destroy_handler *destroy_handler = NULL;
186 TDM_RETURN_VAL_IF_FAIL(func != NULL, TDM_ERROR_INVALID_PARAMETER);
188 _pthread_mutex_lock(&private_display->lock);
190 LIST_FOR_EACH_ENTRY(destroy_handler, &private_output->destroy_handler_list, link) {
191 if (destroy_handler->func == func && destroy_handler->user_data == user_data) {
192 TDM_ERR("can't add twice");
193 _pthread_mutex_unlock(&private_display->lock);
194 return TDM_ERROR_BAD_REQUEST;
198 destroy_handler = calloc(1, sizeof(tdm_private_output_destroy_handler));
199 if (!destroy_handler) {
200 TDM_ERR("failed: alloc memory");
201 _pthread_mutex_unlock(&private_display->lock);
202 return TDM_ERROR_OUT_OF_MEMORY;
205 ret = tdm_thread_cb_add(private_output, TDM_THREAD_CB_OUTPUT_DESTROY, NULL, tdm_output_thread_cb_destroy, destroy_handler);
206 if (ret != TDM_ERROR_NONE) {
207 TDM_ERR("tdm_thread_cb_add failed");
208 free(destroy_handler);
209 _pthread_mutex_unlock(&private_display->lock);
210 return TDM_ERROR_OPERATION_FAILED;
213 destroy_handler->private_output = private_output;
214 destroy_handler->func = func;
215 destroy_handler->user_data = user_data;
216 destroy_handler->owner_tid = syscall(SYS_gettid);
218 LIST_ADDTAIL(&destroy_handler->link, &private_output->destroy_handler_list);
220 _pthread_mutex_unlock(&private_display->lock);
226 tdm_output_remove_destroy_handler(tdm_output *output,
227 tdm_output_destroy_handler func,
230 tdm_private_display *private_display;
231 tdm_private_output *private_output;
232 tdm_private_output_destroy_handler *destroy_handler = NULL, *hh = NULL;
234 TDM_RETURN_IF_FAIL(output != NULL);
235 TDM_RETURN_IF_FAIL(func != NULL);
237 private_output = (tdm_private_output*)output;
238 private_display = private_output->private_display;
240 _pthread_mutex_lock(&private_display->lock);
242 LIST_FOR_EACH_ENTRY_SAFE(destroy_handler, hh, &private_output->destroy_handler_list, link) {
243 if (destroy_handler->func != func || destroy_handler->user_data != user_data)
246 tdm_thread_cb_remove(private_output, TDM_THREAD_CB_OUTPUT_DESTROY, NULL, tdm_output_thread_cb_destroy, destroy_handler);
248 LIST_DEL(&destroy_handler->link);
249 free(destroy_handler);
251 _pthread_mutex_unlock(&private_display->lock);
256 _pthread_mutex_unlock(&private_display->lock);
261 tdm_output_get_backend_module(tdm_output *output, tdm_error *error)
263 tdm_private_module *private_module;
265 OUTPUT_FUNC_ENTRY_ERROR();
267 _pthread_mutex_lock(&private_display->lock);
269 private_module = private_output->private_module;
272 *error = TDM_ERROR_NONE;
274 _pthread_mutex_unlock(&private_display->lock);
276 return private_module;
280 tdm_output_get_model_info(tdm_output *output, const char **maker,
281 const char **model, const char **name)
285 _pthread_mutex_lock(&private_display->lock);
288 *maker = private_output->caps.maker;
290 *model = private_output->caps.model;
292 *name = private_output->caps.name;
294 _pthread_mutex_unlock(&private_display->lock);
300 tdm_output_get_capabilities(tdm_output *output, tdm_output_capability *capabilities)
304 TDM_RETURN_VAL_IF_FAIL(capabilities != NULL, TDM_ERROR_INVALID_PARAMETER);
306 _pthread_mutex_lock(&private_display->lock);
308 *capabilities = private_output->caps.capabilities;
310 _pthread_mutex_unlock(&private_display->lock);
316 tdm_output_get_conn_status(tdm_output *output, tdm_output_conn_status *status)
320 TDM_RETURN_VAL_IF_FAIL(status != NULL, TDM_ERROR_INVALID_PARAMETER);
322 _pthread_mutex_lock(&private_display->lock);
324 *status = private_output->caps.status;
326 _pthread_mutex_unlock(&private_display->lock);
332 tdm_output_thread_cb_change(tdm_private_display *private_display, void *object, tdm_thread_cb_base *cb_base, void *user_data)
334 tdm_private_output *private_output = object;
335 tdm_private_output_change_handler *change_handler = user_data;
336 tdm_output_change_type type = TDM_OUTPUT_CHANGE_CONNECTION;
337 tdm_value value = {.u32 = 0 };
339 TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED());
341 assert(change_handler->owner_tid == syscall(SYS_gettid));
343 if (cb_base->type == TDM_THREAD_CB_OUTPUT_STATUS) {
344 tdm_thread_cb_output_status *output_status = (tdm_thread_cb_output_status *)cb_base;
345 type = TDM_OUTPUT_CHANGE_CONNECTION;
346 value.u32 = output_status->status;
347 } else if (cb_base->type == TDM_THREAD_CB_OUTPUT_DPMS) {
348 tdm_thread_cb_output_dpms *output_dpms = (tdm_thread_cb_output_dpms *)cb_base;
349 type = TDM_OUTPUT_CHANGE_DPMS;
350 value.u32 = output_dpms->dpms;
352 TDM_NEVER_GET_HERE();
356 _pthread_mutex_unlock(&private_display->lock);
357 change_handler->func(private_output, type, value, change_handler->user_data);
358 _pthread_mutex_lock(&private_display->lock);
363 _tdm_output_call_thread_cb_status(tdm_private_output *private_output, tdm_output_conn_status status)
365 tdm_thread_cb_output_status output_status;
366 pid_t caller_tid = syscall(SYS_gettid);
369 memset(&output_status, 0, sizeof output_status);
370 output_status.base.type = TDM_THREAD_CB_OUTPUT_STATUS;
371 output_status.base.length = sizeof output_status;
372 output_status.base.object_stamp = private_output->stamp;
373 output_status.base.data = NULL;
374 if (tdm_thread_in_display_thread(caller_tid))
375 output_status.base.sync = 0;
377 output_status.base.sync = 1;
378 output_status.status = status;
380 ret = tdm_thread_cb_call(private_output, &output_status.base, 1);
381 TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
383 return TDM_ERROR_NONE;
387 _tdm_output_call_thread_cb_dpms(tdm_private_output *private_output, tdm_output_dpms dpms)
389 tdm_thread_cb_output_dpms output_dpms;
392 memset(&output_dpms, 0, sizeof output_dpms);
393 output_dpms.base.type = TDM_THREAD_CB_OUTPUT_DPMS;
394 output_dpms.base.length = sizeof output_dpms;
395 output_dpms.base.object_stamp = private_output->stamp;
396 output_dpms.base.data = NULL;
397 output_dpms.base.sync = 0;
398 output_dpms.dpms = dpms;
400 ret = tdm_thread_cb_call(private_output, &output_dpms.base, 1);
401 TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
403 return TDM_ERROR_NONE;
406 /* LCOV_EXCL_START */
408 tdm_output_cb_status(tdm_output *output_backend, tdm_output_conn_status status, void *user_data)
410 tdm_private_output *private_output = user_data;
413 TDM_RETURN_IF_FAIL(private_output);
415 TDM_INFO("output(%d) %s", private_output->pipe, tdm_status_str(status));
417 if ((private_output->caps.status == TDM_OUTPUT_CONN_STATUS_DISCONNECTED && status != TDM_OUTPUT_CONN_STATUS_DISCONNECTED) ||
418 (private_output->caps.status != TDM_OUTPUT_CONN_STATUS_DISCONNECTED && status == TDM_OUTPUT_CONN_STATUS_DISCONNECTED)) {
419 ret = tdm_display_update_output(private_output->private_module, output_backend);
420 TDM_RETURN_IF_FAIL(ret == TDM_ERROR_NONE);
422 private_output->caps.status = status;
425 ret = _tdm_output_call_thread_cb_status(private_output, status);
426 TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
430 tdm_output_cb_dpms(tdm_output *output_backend, tdm_output_dpms dpms, void *user_data)
432 tdm_private_output *private_output = user_data;
435 TDM_INFO("output(%d) %s", private_output->pipe, tdm_dpms_str(dpms));
437 private_output->current_dpms_value = dpms;
438 private_output->waiting_dpms_change = 0;
439 TDM_INFO("output(%d) DPMS async '%s' done", private_output->pipe, tdm_dpms_str(dpms));
441 ret = _tdm_output_call_thread_cb_dpms(private_output, dpms);
442 TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
446 tdm_output_cb_status_hal_tdm(hal_tdm_output *output_backend, hal_tdm_output_conn_status status, void *user_data)
448 tdm_private_output *private_output = user_data;
451 TDM_RETURN_IF_FAIL(private_output);
453 TDM_INFO("output(%d) %s", private_output->pipe, tdm_status_str((tdm_output_conn_status)status));
455 if ((private_output->caps.status == TDM_OUTPUT_CONN_STATUS_DISCONNECTED && status != HAL_TDM_OUTPUT_CONN_STATUS_DISCONNECTED) ||
456 (private_output->caps.status != TDM_OUTPUT_CONN_STATUS_DISCONNECTED && status == HAL_TDM_OUTPUT_CONN_STATUS_DISCONNECTED)) {
457 ret = tdm_display_update_output(private_output->private_module, output_backend);
458 TDM_RETURN_IF_FAIL(ret == TDM_ERROR_NONE);
460 private_output->caps.status = (tdm_output_conn_status)status;
463 ret = _tdm_output_call_thread_cb_status(private_output, (tdm_output_conn_status)status);
464 TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
468 tdm_output_cb_dpms_hal_tdm(hal_tdm_output *output_backend, hal_tdm_output_dpms dpms, void *user_data)
470 tdm_private_output *private_output = user_data;
473 TDM_INFO("output(%d) %s", private_output->pipe, tdm_dpms_str((tdm_output_dpms)dpms));
475 private_output->current_dpms_value = (tdm_output_dpms)dpms;
476 private_output->waiting_dpms_change = 0;
477 TDM_INFO("output(%d) DPMS async '%s' done", private_output->pipe, tdm_dpms_str((tdm_output_dpms)dpms));
479 ret = _tdm_output_call_thread_cb_dpms(private_output, (tdm_output_dpms)dpms);
480 TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
485 tdm_output_add_change_handler(tdm_output *output,
486 tdm_output_change_handler func,
489 tdm_private_output_change_handler *change_handler = NULL;
492 TDM_RETURN_VAL_IF_FAIL(func != NULL, TDM_ERROR_INVALID_PARAMETER);
494 _pthread_mutex_lock(&private_display->lock);
496 LIST_FOR_EACH_ENTRY(change_handler, &private_output->change_handler_list, link) {
497 if (change_handler->func == func && change_handler->user_data == user_data) {
498 TDM_ERR("can't add twice");
499 _pthread_mutex_unlock(&private_display->lock);
500 return TDM_ERROR_BAD_REQUEST;
504 change_handler = calloc(1, sizeof(tdm_private_output_change_handler));
505 if (!change_handler) {
506 /* LCOV_EXCL_START */
507 TDM_ERR("failed: alloc memory");
508 _pthread_mutex_unlock(&private_display->lock);
509 return TDM_ERROR_OUT_OF_MEMORY;
513 ret = tdm_thread_cb_add(private_output, TDM_THREAD_CB_OUTPUT_DPMS, NULL, tdm_output_thread_cb_change, change_handler);
514 if (ret != TDM_ERROR_NONE) {
515 /* LCOV_EXCL_START */
516 TDM_ERR("tdm_thread_cb_add failed");
517 free(change_handler);
518 _pthread_mutex_unlock(&private_display->lock);
519 return TDM_ERROR_OPERATION_FAILED;
523 ret = tdm_thread_cb_add(private_output, TDM_THREAD_CB_OUTPUT_STATUS, NULL, tdm_output_thread_cb_change, change_handler);
524 if (ret != TDM_ERROR_NONE) {
525 /* LCOV_EXCL_START */
526 TDM_ERR("tdm_thread_cb_add failed");
527 tdm_thread_cb_remove(private_output, TDM_THREAD_CB_OUTPUT_DPMS, NULL, tdm_output_thread_cb_change, change_handler);
528 free(change_handler);
529 _pthread_mutex_unlock(&private_display->lock);
530 return TDM_ERROR_OPERATION_FAILED;
534 change_handler->private_output = private_output;
535 change_handler->func = func;
536 change_handler->user_data = user_data;
537 change_handler->owner_tid = syscall(SYS_gettid);
539 LIST_ADDTAIL(&change_handler->link, &private_output->change_handler_list);
541 _pthread_mutex_unlock(&private_display->lock);
546 /* LCOV_EXCL_START */
548 tdm_output_add_mode_change_request_handler(tdm_output *output,
549 tdm_output_mode_change_request_handler func,
552 tdm_private_display *private_display;
553 tdm_private_output *private_output;
554 tdm_private_output_mode_change_handler *mode_change_handler = NULL;
556 TDM_RETURN_VAL_IF_FAIL(output != NULL, TDM_ERROR_INVALID_PARAMETER);
557 TDM_RETURN_VAL_IF_FAIL(func != NULL, TDM_ERROR_INVALID_PARAMETER);
559 private_output = (tdm_private_output*)output;
560 private_display = private_output->private_display;
562 _pthread_mutex_lock(&private_display->lock);
564 LIST_FOR_EACH_ENTRY(mode_change_handler, &private_output->mode_change_request_handler_list, link) {
565 if (mode_change_handler->func == func && mode_change_handler->user_data == user_data) {
566 TDM_ERR("can't add twice");
567 _pthread_mutex_unlock(&private_display->lock);
568 return TDM_ERROR_BAD_REQUEST;
572 mode_change_handler = calloc(1, sizeof(tdm_private_output_mode_change_handler));
573 if (!mode_change_handler) {
574 /* LCOV_EXCL_START */
575 TDM_ERR("failed: alloc memory");
576 _pthread_mutex_unlock(&private_display->lock);
577 return TDM_ERROR_OUT_OF_MEMORY;
581 mode_change_handler->private_output = private_output;
582 mode_change_handler->func = func;
583 mode_change_handler->user_data = user_data;
585 LIST_ADDTAIL(&mode_change_handler->link, &private_output->mode_change_request_handler_list);
587 _pthread_mutex_unlock(&private_display->lock);
589 return TDM_ERROR_NONE;
593 tdm_output_remove_mode_change_request_handler(tdm_output *output,
594 tdm_output_mode_change_request_handler func,
597 tdm_private_display *private_display;
598 tdm_private_output *private_output;
599 tdm_private_output_mode_change_handler *mode_change_handler = NULL, *hh = NULL;
601 TDM_RETURN_VAL_IF_FAIL(output != NULL, TDM_ERROR_INVALID_PARAMETER);
602 TDM_RETURN_VAL_IF_FAIL(func != NULL, TDM_ERROR_INVALID_PARAMETER);
604 private_output = (tdm_private_output*)output;
605 private_display = private_output->private_display;
607 _pthread_mutex_lock(&private_display->lock);
609 LIST_FOR_EACH_ENTRY_SAFE(mode_change_handler, hh, &private_output->mode_change_request_handler_list, link) {
610 if (mode_change_handler->func != func || mode_change_handler->user_data != user_data)
613 LIST_DEL(&mode_change_handler->link);
614 free(mode_change_handler);
616 _pthread_mutex_unlock(&private_display->lock);
618 return TDM_ERROR_NONE;
621 _pthread_mutex_unlock(&private_display->lock);
623 return TDM_ERROR_INVALID_PARAMETER;
628 tdm_output_remove_change_handler(tdm_output *output,
629 tdm_output_change_handler func,
632 tdm_private_display *private_display;
633 tdm_private_output *private_output;
634 tdm_private_output_change_handler *change_handler = NULL, *hh = NULL;
636 TDM_RETURN_IF_FAIL(output != NULL);
637 TDM_RETURN_IF_FAIL(func != NULL);
639 private_output = (tdm_private_output*)output;
640 private_display = private_output->private_display;
642 _pthread_mutex_lock(&private_display->lock);
644 LIST_FOR_EACH_ENTRY_SAFE(change_handler, hh, &private_output->change_handler_list, link) {
645 if (change_handler->func != func || change_handler->user_data != user_data)
648 tdm_thread_cb_remove(private_output, TDM_THREAD_CB_OUTPUT_DPMS, NULL, tdm_output_thread_cb_change, change_handler);
649 tdm_thread_cb_remove(private_output, TDM_THREAD_CB_OUTPUT_STATUS, NULL, tdm_output_thread_cb_change, change_handler);
651 LIST_DEL(&change_handler->link);
652 free(change_handler);
654 _pthread_mutex_unlock(&private_display->lock);
659 _pthread_mutex_unlock(&private_display->lock);
663 tdm_output_get_output_type(tdm_output *output, tdm_output_type *type)
667 TDM_RETURN_VAL_IF_FAIL(type != NULL, TDM_ERROR_INVALID_PARAMETER);
669 _pthread_mutex_lock(&private_display->lock);
671 *type = private_output->caps.type;
673 _pthread_mutex_unlock(&private_display->lock);
679 tdm_output_get_layer_count(tdm_output *output, int *count)
681 tdm_private_layer *private_layer = NULL;
685 TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
687 _pthread_mutex_lock(&private_display->lock);
689 if (private_output->caps.capabilities & TDM_OUTPUT_CAPABILITY_HWC) {
690 TDM_ERR("output(%p) support HWC. Use HWC functions", private_output);
692 _pthread_mutex_unlock(&private_display->lock);
693 return TDM_ERROR_BAD_REQUEST;
697 LIST_FOR_EACH_ENTRY(private_layer, &private_output->layer_list, link)
700 _pthread_mutex_unlock(&private_display->lock);
701 return TDM_ERROR_NONE;
704 _pthread_mutex_unlock(&private_display->lock);
711 tdm_output_get_layer(tdm_output *output, int index, tdm_error *error)
713 tdm_private_layer *private_layer = NULL;
715 OUTPUT_FUNC_ENTRY_ERROR();
717 _pthread_mutex_lock(&private_display->lock);
720 *error = TDM_ERROR_NONE;
722 if (private_output->caps.capabilities & TDM_OUTPUT_CAPABILITY_HWC) {
723 _pthread_mutex_unlock(&private_display->lock);
724 TDM_ERR("output(%p) support HWC. Use HWC functions", private_output);
726 *error = TDM_ERROR_BAD_REQUEST;
730 LIST_FOR_EACH_ENTRY(private_layer, &private_output->layer_list, link) {
731 if (private_layer->index == index) {
732 _pthread_mutex_unlock(&private_display->lock);
733 return private_layer;
737 _pthread_mutex_unlock(&private_display->lock);
743 tdm_output_get_available_properties(tdm_output *output, const tdm_prop **props,
748 TDM_RETURN_VAL_IF_FAIL(props != NULL, TDM_ERROR_INVALID_PARAMETER);
749 TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
751 _pthread_mutex_lock(&private_display->lock);
753 *props = (const tdm_prop *)private_output->caps.props;
754 *count = private_output->caps.prop_count;
756 _pthread_mutex_unlock(&private_display->lock);
762 tdm_output_get_available_modes(tdm_output *output,
763 const tdm_output_mode **modes, int *count)
767 TDM_RETURN_VAL_IF_FAIL(modes != NULL, TDM_ERROR_INVALID_PARAMETER);
768 TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
770 _pthread_mutex_lock(&private_display->lock);
772 *modes = (const tdm_output_mode *)private_output->caps.modes;
773 *count = private_output->caps.mode_count;
775 _pthread_mutex_unlock(&private_display->lock);
781 tdm_output_get_available_size(tdm_output *output, int *min_w, int *min_h,
782 int *max_w, int *max_h, int *preferred_align)
786 _pthread_mutex_lock(&private_display->lock);
789 *min_w = TDM_FRONT_VALUE(private_output->caps.min_w);
791 *min_h = TDM_FRONT_VALUE(private_output->caps.min_h);
793 *max_w = TDM_FRONT_VALUE(private_output->caps.max_w);
795 *max_h = TDM_FRONT_VALUE(private_output->caps.max_h);
797 *preferred_align = TDM_FRONT_VALUE(private_output->caps.preferred_align);
799 _pthread_mutex_unlock(&private_display->lock);
805 tdm_output_get_cursor_available_size(tdm_output *output, int *min_w, int *min_h,
806 int *max_w, int *max_h, int *preferred_align)
810 _pthread_mutex_lock(&private_display->lock);
812 if (!tdm_module_check_abi(private_output->private_module, 1, 5)) {
813 _pthread_mutex_unlock(&private_display->lock);
814 return TDM_ERROR_BAD_REQUEST;
818 *min_w = TDM_FRONT_VALUE(private_output->caps.cursor_min_w);
820 *min_h = TDM_FRONT_VALUE(private_output->caps.cursor_min_h);
822 *max_w = TDM_FRONT_VALUE(private_output->caps.cursor_max_w);
824 *max_h = TDM_FRONT_VALUE(private_output->caps.cursor_max_h);
826 *preferred_align = TDM_FRONT_VALUE(private_output->caps.cursor_preferred_align);
828 _pthread_mutex_unlock(&private_display->lock);
834 tdm_output_get_physical_size(tdm_output *output, unsigned int *mmWidth,
835 unsigned int *mmHeight)
839 _pthread_mutex_lock(&private_display->lock);
842 *mmWidth = private_output->caps.mmWidth;
844 *mmHeight = private_output->caps.mmHeight;
846 _pthread_mutex_unlock(&private_display->lock);
852 tdm_output_get_subpixel(tdm_output *output, unsigned int *subpixel)
855 TDM_RETURN_VAL_IF_FAIL(subpixel != NULL, TDM_ERROR_INVALID_PARAMETER);
857 _pthread_mutex_lock(&private_display->lock);
859 *subpixel = private_output->caps.subpixel;
861 _pthread_mutex_unlock(&private_display->lock);
867 tdm_output_get_pipe(tdm_output *output, unsigned int *pipe)
870 TDM_RETURN_VAL_IF_FAIL(pipe != NULL, TDM_ERROR_INVALID_PARAMETER);
872 _pthread_mutex_lock(&private_display->lock);
874 *pipe = private_output->pipe;
876 _pthread_mutex_unlock(&private_display->lock);
882 tdm_output_get_primary_index(tdm_output *output, int *index)
884 tdm_private_layer *private_layer = NULL;
887 TDM_RETURN_VAL_IF_FAIL(index != NULL, TDM_ERROR_INVALID_PARAMETER);
889 _pthread_mutex_lock(&private_display->lock);
891 LIST_FOR_EACH_ENTRY(private_layer, &private_output->layer_list, link) {
892 if (private_layer->caps.capabilities & TDM_LAYER_CAPABILITY_PRIMARY) {
893 *index = private_layer->index;
898 _pthread_mutex_unlock(&private_display->lock);
904 tdm_output_set_property(tdm_output *output, unsigned int id, tdm_value value)
906 tdm_private_module *private_module;
907 tdm_func_output *func_output;
910 _pthread_mutex_lock(&private_display->lock);
912 private_module = private_output->private_module;
914 if (private_module->use_hal_tdm) {
915 hal_tdm_value hvalue;
916 memcpy(&hvalue.ptr, &value.ptr, sizeof(hal_tdm_value));
917 ret = (tdm_error)hal_tdm_output_set_property(private_output->output_backend, id, hvalue);
919 func_output = &private_module->func_output;
921 if (!func_output->output_set_property) {
922 /* LCOV_EXCL_START */
923 _pthread_mutex_unlock(&private_display->lock);
924 TDM_WRN("not implemented!!");
925 return TDM_ERROR_NOT_IMPLEMENTED;
929 ret = func_output->output_set_property(private_output->output_backend, id, value);
932 _pthread_mutex_unlock(&private_display->lock);
938 tdm_output_get_property(tdm_output *output, unsigned int id, tdm_value *value)
940 tdm_private_module *private_module;
941 tdm_func_output *func_output;
944 TDM_RETURN_VAL_IF_FAIL(value != NULL, TDM_ERROR_INVALID_PARAMETER);
946 _pthread_mutex_lock(&private_display->lock);
948 private_module = private_output->private_module;
950 if (private_module->use_hal_tdm) {
951 hal_tdm_value hvalue;
952 ret = (tdm_error)hal_tdm_output_get_property(private_output->output_backend, id, &hvalue);
953 memcpy(value->ptr, &hvalue.ptr, sizeof(tdm_value));
955 func_output = &private_module->func_output;
957 if (!func_output->output_get_property) {
958 /* LCOV_EXCL_START */
959 _pthread_mutex_unlock(&private_display->lock);
960 TDM_WRN("not implemented!!");
961 return TDM_ERROR_NOT_IMPLEMENTED;
965 ret = func_output->output_get_property(private_output->output_backend, id, value);
967 _pthread_mutex_unlock(&private_display->lock);
973 _tdm_output_thread_cb_vblank(tdm_private_display *private_display, void *object, tdm_thread_cb_base *cb_base, void *user_data)
975 tdm_thread_cb_output_vblank *output_vblank = (tdm_thread_cb_output_vblank *)cb_base;
976 tdm_private_output_vblank_handler *vblank_handler = output_vblank->base.data;
977 tdm_private_output_vblank_handler *v = NULL, *vv = NULL;
978 tdm_private_output *private_output = object;
979 struct list_head clone_list;
981 pid_t tid = syscall(SYS_gettid);
983 TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED());
985 assert(vblank_handler->owner_tid == tid);
987 vblank_handler->sent_to_frontend = 0;
989 _tdm_output_vblank_timeout_update(private_output, 0);
991 tdm_thread_cb_remove(private_output, TDM_THREAD_CB_OUTPUT_VBLANK, vblank_handler, _tdm_output_thread_cb_vblank, NULL);
993 interval = vblank_handler->interval;
994 sync = vblank_handler->sync;
996 LIST_INITHEAD(&clone_list);
998 LIST_FOR_EACH_ENTRY_SAFE(v, vv, &private_output->vblank_handler_list, link) {
999 if (v->interval != interval || v->sync != sync || v->owner_tid != tid)
1003 LIST_ADDTAIL(&v->link, &clone_list);
1006 if (tdm_debug_module & TDM_DEBUG_COMMIT)
1007 TDM_INFO("----------------------------------------- output(%d) got vblank", private_output->pipe);
1009 _pthread_mutex_unlock(&private_display->lock);
1010 LIST_FOR_EACH_ENTRY_SAFE(v, vv, &clone_list, link) {
1011 if (tdm_debug_module & TDM_DEBUG_COMMIT)
1012 TDM_INFO("handler(%p)", v);
1017 v->func(v->private_output,
1018 output_vblank->sequence,
1019 output_vblank->tv_sec,
1020 output_vblank->tv_usec,
1025 _pthread_mutex_lock(&private_display->lock);
1027 if (tdm_debug_module & TDM_DEBUG_COMMIT)
1028 TDM_INFO("-----------------------------------------...");
1032 _tdm_output_cb_vblank(tdm_output *output_backend, unsigned int sequence,
1033 unsigned int tv_sec, unsigned int tv_usec, void *user_data)
1035 tdm_private_output_vblank_handler *vblank_handler = user_data;
1036 tdm_thread_cb_output_vblank output_vblank;
1039 memset(&output_vblank, 0, sizeof output_vblank);
1040 output_vblank.base.type = TDM_THREAD_CB_OUTPUT_VBLANK;
1041 output_vblank.base.length = sizeof output_vblank;
1042 output_vblank.base.object_stamp = vblank_handler->private_output->stamp;
1043 output_vblank.base.data = vblank_handler;
1044 output_vblank.base.sync = 0;
1045 output_vblank.sequence = sequence;
1046 output_vblank.tv_sec = tv_sec;
1047 output_vblank.tv_usec = tv_usec;
1049 vblank_handler->sent_to_frontend = 1;
1051 if (tdm_debug_module & TDM_DEBUG_COMMIT)
1052 TDM_INFO("output(%d) wait_vblank: handler(%p)", vblank_handler->private_output->pipe, vblank_handler);
1054 ret = tdm_thread_cb_call(vblank_handler->private_output, &output_vblank.base, 1);
1055 TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
1059 _tdm_output_cb_vblank_hal_tdm(hal_tdm_output *output_backend, unsigned int sequence,
1060 unsigned int tv_sec, unsigned int tv_usec, void *user_data)
1062 tdm_private_output_vblank_handler *vblank_handler = user_data;
1063 tdm_thread_cb_output_vblank output_vblank;
1066 memset(&output_vblank, 0, sizeof output_vblank);
1067 output_vblank.base.type = TDM_THREAD_CB_OUTPUT_VBLANK;
1068 output_vblank.base.length = sizeof output_vblank;
1069 output_vblank.base.object_stamp = vblank_handler->private_output->stamp;
1070 output_vblank.base.data = vblank_handler;
1071 output_vblank.base.sync = 0;
1072 output_vblank.sequence = sequence;
1073 output_vblank.tv_sec = tv_sec;
1074 output_vblank.tv_usec = tv_usec;
1076 vblank_handler->sent_to_frontend = 1;
1078 if (tdm_debug_module & TDM_DEBUG_COMMIT)
1079 TDM_INFO("output(%d) wait_vblank: handler(%p)", vblank_handler->private_output->pipe, vblank_handler);
1081 ret = tdm_thread_cb_call(vblank_handler->private_output, &output_vblank.base, 1);
1082 TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
1085 /* LCOV_EXCL_START */
1087 _tdm_output_thread_cb_commit(tdm_private_display *private_display, void *object, tdm_thread_cb_base *cb_base, void *user_data)
1089 tdm_thread_cb_output_commit *output_commit = (tdm_thread_cb_output_commit *)cb_base;
1090 tdm_private_output_commit_handler *output_commit_handler = output_commit->base.data;
1091 tdm_private_output *private_output = object;
1092 tdm_private_layer *private_layer = NULL;
1094 TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED());
1096 if (!output_commit_handler)
1099 assert(output_commit_handler->owner_tid == syscall(SYS_gettid));
1101 tdm_thread_cb_remove(private_output, TDM_THREAD_CB_OUTPUT_COMMIT, output_commit_handler, _tdm_output_thread_cb_commit, NULL);
1103 LIST_DEL(&output_commit_handler->link);
1105 if (tdm_debug_module & TDM_DEBUG_COMMIT) {
1106 TDM_INFO("----------------------------------------- output(%d) committed", private_output->pipe);
1107 TDM_INFO("handler(%p)", output_commit_handler);
1110 if (private_output->commit_type == TDM_COMMIT_TYPE_OUTPUT) {
1111 /* In case of layer commit, the below will be handled in the layer commit callback */
1112 LIST_FOR_EACH_ENTRY(private_layer, &private_output->layer_list, link) {
1113 if (private_layer->committed_buffer)
1114 tdm_layer_committed(private_layer, &private_layer->committed_buffer);
1118 if (output_commit_handler->func) {
1119 _pthread_mutex_unlock(&private_display->lock);
1120 output_commit_handler->func(private_output,
1121 output_commit->sequence,
1122 output_commit->tv_sec,
1123 output_commit->tv_usec,
1124 output_commit_handler->user_data);
1125 _pthread_mutex_lock(&private_display->lock);
1128 free(output_commit_handler);
1130 if (tdm_debug_module & TDM_DEBUG_COMMIT)
1131 TDM_INFO("-----------------------------------------...");
1135 _tdm_output_cb_commit(tdm_output *output_backend, unsigned int sequence,
1136 unsigned int tv_sec, unsigned int tv_usec, void *user_data)
1138 tdm_private_output_commit_handler *output_commit_handler = user_data;
1139 tdm_private_output *private_output;
1140 tdm_thread_cb_output_commit output_commit;
1143 if (output_commit_handler)
1144 private_output = output_commit_handler->private_output;
1146 private_output = tdm_display_find_private_output(tdm_display_get(), output_backend);
1148 memset(&output_commit, 0, sizeof output_commit);
1149 output_commit.base.type = TDM_THREAD_CB_OUTPUT_COMMIT;
1150 output_commit.base.length = sizeof output_commit;
1151 output_commit.base.object_stamp = private_output->stamp;
1152 output_commit.base.data = output_commit_handler;
1153 output_commit.base.sync = 0;
1154 output_commit.sequence = sequence;
1155 output_commit.tv_sec = tv_sec;
1156 output_commit.tv_usec = tv_usec;
1158 ret = tdm_thread_cb_call(private_output, &output_commit.base, 1);
1159 TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
1163 _tdm_output_cb_commit_hal_tdm(hal_tdm_output *output_backend, unsigned int sequence,
1164 unsigned int tv_sec, unsigned int tv_usec, void *user_data)
1166 tdm_private_output_commit_handler *output_commit_handler = user_data;
1167 tdm_private_output *private_output;
1168 tdm_thread_cb_output_commit output_commit;
1171 if (output_commit_handler)
1172 private_output = output_commit_handler->private_output;
1174 private_output = tdm_display_find_private_output(tdm_display_get(), (tdm_output *)output_backend);
1176 memset(&output_commit, 0, sizeof output_commit);
1177 output_commit.base.type = TDM_THREAD_CB_OUTPUT_COMMIT;
1178 output_commit.base.length = sizeof output_commit;
1179 output_commit.base.object_stamp = private_output->stamp;
1180 output_commit.base.data = output_commit_handler;
1181 output_commit.base.sync = 0;
1182 output_commit.sequence = sequence;
1183 output_commit.tv_sec = tv_sec;
1184 output_commit.tv_usec = tv_usec;
1186 ret = tdm_thread_cb_call(private_output, &output_commit.base, 1);
1187 TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
1189 /* LCOV_EXCL_STOP */
1191 /* LCOV_EXCL_START */
1193 _tdm_voutput_thread_cb_commit(tdm_private_display *private_display, void *object, tdm_thread_cb_base *cb_base, void *user_data)
1195 tdm_thread_cb_voutput_commit *voutput_commit = (tdm_thread_cb_voutput_commit *)cb_base;
1196 tdm_private_voutput_commit_handler *voutput_commit_handler = voutput_commit->base.data;
1197 tdm_private_voutput *private_voutput = object;
1198 tdm_private_output *private_output = NULL;
1200 TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED());
1202 if (!voutput_commit_handler)
1205 assert(voutput_commit_handler->owner_tid == syscall(SYS_gettid));
1207 tdm_thread_cb_remove(private_voutput, TDM_THREAD_CB_VOUTPUT_COMMIT, voutput_commit_handler, _tdm_voutput_thread_cb_commit, NULL);
1209 LIST_DEL(&voutput_commit_handler->link);
1211 private_output = private_voutput->private_output;
1212 if (tdm_debug_module & TDM_DEBUG_COMMIT) {
1213 TDM_INFO("----------------------------------------- voutput(%d) committed", private_output->pipe);
1214 TDM_INFO("handler(%p)", voutput_commit_handler);
1217 if (voutput_commit_handler->func && private_voutput->set_voutput_commit != 0) {
1218 _pthread_mutex_unlock(&private_display->lock);
1219 voutput_commit_handler->func(private_voutput, voutput_commit_handler->user_data);
1220 _pthread_mutex_lock(&private_display->lock);
1223 free(voutput_commit_handler);
1225 if (tdm_debug_module & TDM_DEBUG_COMMIT)
1226 TDM_INFO("-----------------------------------------...");
1230 _tdm_voutput_cb_commit(tdm_voutput *voutput_backend, unsigned int sequence,
1231 unsigned int tv_sec, unsigned int tv_usec, void *user_data)
1233 tdm_private_voutput_commit_handler *voutput_commit_handler = NULL;
1234 tdm_private_module *private_module;
1235 tdm_private_voutput *private_voutput = NULL, *v = NULL;
1236 tdm_private_output *private_output;
1237 tdm_thread_cb_voutput_commit voutput_commit;
1240 private_module = tdm_display_get()->virtual_module;
1242 LIST_FOR_EACH_ENTRY(v, &private_module->voutput_list, link) {
1243 if (v->voutput_backend == voutput_backend) {
1244 private_voutput = v;
1248 if (!private_voutput) {
1249 TDM_ERR("cannot find voutput");
1253 if (LIST_LENGTH(&private_voutput->voutput_commit_handler_list) == 0) return;
1255 voutput_commit_handler = LIST_FIRST_ENTRY(&private_voutput->voutput_commit_handler_list, tdm_private_voutput_commit_handler, link);
1257 private_output = private_voutput->private_output;
1259 memset(&voutput_commit, 0, sizeof voutput_commit);
1260 voutput_commit.base.type = TDM_THREAD_CB_VOUTPUT_COMMIT;
1261 voutput_commit.base.length = sizeof voutput_commit;
1262 voutput_commit.base.object_stamp = private_output->stamp;
1263 voutput_commit.base.data = voutput_commit_handler;
1264 voutput_commit.base.sync = 0;
1265 voutput_commit.sequence = sequence;
1266 voutput_commit.tv_sec = tv_sec;
1267 voutput_commit.tv_usec = tv_usec;
1269 ret = tdm_thread_cb_call(private_voutput, &voutput_commit.base, 1);
1270 TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
1272 /* LCOV_EXCL_STOP */
1274 /* add_front: To distinguish between the user vblank handlers and the layer
1275 * commit vblank handlers. The layer commit handlers will be called
1276 * before calling the user vblank handlers.
1279 _tdm_output_wait_vblank(tdm_private_output *private_output, int interval, int sync,
1280 tdm_output_vblank_handler func, void *user_data,
1281 unsigned int add_front)
1283 tdm_private_module *private_module;
1284 tdm_func_output *func_output;
1285 tdm_private_output_vblank_handler *vblank_handler = NULL, *v = NULL;
1286 unsigned int skip_request = 0;
1287 pid_t tid = syscall(SYS_gettid);
1288 tdm_error ret = TDM_ERROR_NONE;
1290 private_module = private_output->private_module;
1291 func_output = &private_module->func_output;
1293 /* interval SHOULD be at least 1 */
1297 if (private_module->use_hal_tdm) {
1298 if (!private_output->regist_vblank_cb) {
1299 private_output->regist_vblank_cb = 1;
1300 ret = (tdm_error)hal_tdm_output_set_vblank_handler(private_output->output_backend, _tdm_output_cb_vblank_hal_tdm);
1303 if (!func_output->output_wait_vblank) {
1304 /* LCOV_EXCL_START */
1305 TDM_WRN("not implemented!!");
1306 return TDM_ERROR_NOT_IMPLEMENTED;
1307 /* LCOV_EXCL_STOP */
1310 if (!private_output->regist_vblank_cb) {
1311 private_output->regist_vblank_cb = 1;
1312 ret = func_output->output_set_vblank_handler(private_output->output_backend,
1313 _tdm_output_cb_vblank);
1316 vblank_handler = calloc(1, sizeof(tdm_private_output_vblank_handler));
1317 if (!vblank_handler) {
1318 /* LCOV_EXCL_START */
1319 TDM_ERR("failed: alloc memory");
1320 return TDM_ERROR_OUT_OF_MEMORY;
1321 /* LCOV_EXCL_STOP */
1324 if (tdm_debug_module & TDM_DEBUG_COMMIT)
1325 TDM_INFO("output(%d) wait_vblank: handler(%p)", private_output->pipe, vblank_handler);
1327 LIST_FOR_EACH_ENTRY(v, &private_output->vblank_handler_list, link) {
1328 if (v->interval == interval && v->sync == sync && v->owner_tid == tid) {
1335 LIST_ADD(&vblank_handler->link, &private_output->vblank_handler_list);
1337 LIST_ADDTAIL(&vblank_handler->link, &private_output->vblank_handler_list);
1339 vblank_handler->private_output = private_output;
1340 vblank_handler->interval = interval;
1341 vblank_handler->sync = sync;
1342 vblank_handler->func = func;
1343 vblank_handler->user_data = user_data;
1344 vblank_handler->owner_tid = tid;
1346 /* If there is the previous request, we can skip to call output_wait_vblank() */
1347 if (!skip_request) {
1348 ret = tdm_thread_cb_add(private_output, TDM_THREAD_CB_OUTPUT_VBLANK, vblank_handler, _tdm_output_thread_cb_vblank, NULL);
1349 if (ret != TDM_ERROR_NONE) {
1350 TDM_ERR("tdm_thread_cb_add failed");
1353 if (private_module->use_hal_tdm)
1354 ret = (tdm_error)hal_tdm_output_wait_vblank(private_output->output_backend, interval,
1355 sync, vblank_handler);
1357 ret = func_output->output_wait_vblank(private_output->output_backend, interval,
1358 sync, vblank_handler);
1359 TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, wait_failed);
1361 _tdm_output_vblank_timeout_update(private_output, 1000);
1363 if (tdm_debug_module & TDM_DEBUG_COMMIT)
1364 TDM_INFO("output(%d) backend wait_vblank", private_output->pipe);
1370 /* LCOV_EXCL_START */
1371 if (vblank_handler) {
1372 tdm_thread_cb_remove(private_output, TDM_THREAD_CB_OUTPUT_VBLANK, vblank_handler, _tdm_output_thread_cb_vblank, NULL);
1373 LIST_DEL(&vblank_handler->link);
1374 free(vblank_handler);
1377 /* LCOV_EXCL_STOP */
1381 tdm_output_wait_vblank(tdm_output *output, int interval, int sync,
1382 tdm_output_vblank_handler func, void *user_data)
1384 OUTPUT_FUNC_ENTRY();
1385 TDM_RETURN_VAL_IF_FAIL(interval > 0, TDM_ERROR_INVALID_PARAMETER);
1387 _pthread_mutex_lock(&private_display->lock);
1389 if (TDM_OUTPUT_DPMS_VSYNC_IS_OFF(private_output->current_dpms_value)) {
1390 TDM_WRN("output(%d) dpms: %s", private_output->pipe,
1391 tdm_dpms_str(private_output->current_dpms_value));
1392 _pthread_mutex_unlock(&private_display->lock);
1393 return TDM_ERROR_DPMS_OFF;
1396 if (private_output->waiting_dpms_change) {
1397 TDM_WRN("output(%d) dpms is changing: %s", private_output->pipe,
1398 tdm_dpms_str(private_output->current_dpms_value));
1399 _pthread_mutex_unlock(&private_display->lock);
1400 return TDM_ERROR_DPMS_OFF;
1403 ret = _tdm_output_wait_vblank(private_output, interval, sync, func, user_data, 0);
1405 _pthread_mutex_unlock(&private_display->lock);
1410 /* LCOV_EXCL_START */
1412 tdm_output_wait_vblank_add_front(tdm_output *output, int interval, int sync,
1413 tdm_output_vblank_handler func, void *user_data)
1415 OUTPUT_FUNC_ENTRY();
1417 _pthread_mutex_lock(&private_display->lock);
1419 if (TDM_OUTPUT_DPMS_VSYNC_IS_OFF(private_output->current_dpms_value)) {
1420 TDM_WRN("output(%d) dpms: %s", private_output->pipe,
1421 tdm_dpms_str(private_output->current_dpms_value));
1422 _pthread_mutex_unlock(&private_display->lock);
1423 return TDM_ERROR_DPMS_OFF;
1426 if (private_output->waiting_dpms_change) {
1427 TDM_WRN("output(%d) dpms is changing: %s", private_output->pipe,
1428 tdm_dpms_str(private_output->current_dpms_value));
1429 _pthread_mutex_unlock(&private_display->lock);
1430 return TDM_ERROR_DPMS_OFF;
1433 ret = _tdm_output_wait_vblank(private_output, interval, sync, func, user_data, 1);
1435 _pthread_mutex_unlock(&private_display->lock);
1439 /* LCOV_EXCL_STOP */
1442 tdm_output_remove_vblank_handler_internal(tdm_output *output, tdm_output_vblank_handler func, void *user_data)
1444 tdm_private_output *private_output = (tdm_private_output*)output;
1445 tdm_private_output_vblank_handler *v = NULL;
1447 TDM_RETURN_IF_FAIL(private_output != NULL);
1448 TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED());
1450 LIST_FOR_EACH_ENTRY(v, &private_output->vblank_handler_list, link) {
1451 if (v->func == func && v->user_data == user_data) {
1452 /* only set func & user_data to NULL. It will be freed when an event occurs */
1454 v->user_data = NULL;
1460 /* LCOV_EXCL_START */
1462 tdm_output_remove_commit_handler_internal(tdm_output *output, tdm_output_commit_handler func, void *user_data)
1464 tdm_private_output *private_output = (tdm_private_output*)output;
1465 tdm_private_output_commit_handler *c = NULL;
1467 TDM_RETURN_IF_FAIL(private_output != NULL);
1468 TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED());
1470 LIST_FOR_EACH_ENTRY(c, &private_output->output_commit_handler_list, link) {
1471 if (c->func == func && c->user_data == user_data) {
1472 /* only set func & user_data to NULL. It will be freed when an event occurs */
1474 c->user_data = NULL;
1479 /* LCOV_EXCL_STOP */
1482 tdm_output_remove_vblank_handler(tdm_output *output, tdm_output_vblank_handler func, void *user_data)
1484 OUTPUT_FUNC_ENTRY();
1486 _pthread_mutex_lock(&private_display->lock);
1488 tdm_output_remove_vblank_handler_internal(output, func, user_data);
1490 _pthread_mutex_unlock(&private_display->lock);
1495 /* LCOV_EXCL_START */
1497 tdm_output_remove_commit_handler(tdm_output *output, tdm_output_commit_handler func, void *user_data)
1499 OUTPUT_FUNC_ENTRY();
1501 _pthread_mutex_lock(&private_display->lock);
1503 tdm_output_remove_commit_handler_internal(output, func, user_data);
1505 _pthread_mutex_unlock(&private_display->lock);
1509 /* LCOV_EXCL_STOP */
1511 /* LCOV_EXCL_START */
1513 tdm_output_request_mode_set(tdm_output *output, unsigned int index)
1515 tdm_private_output *private_output = (tdm_private_output*)output;
1516 tdm_private_output_mode_change_handler *mode_change_handler = NULL;
1518 TDM_RETURN_IF_FAIL(private_output != NULL);
1520 if (LIST_IS_EMPTY(&private_output->mode_change_request_handler_list))
1523 LIST_FOR_EACH_ENTRY(mode_change_handler, &private_output->mode_change_request_handler_list, link) {
1524 mode_change_handler->func(mode_change_handler->private_output, index, mode_change_handler->user_data);
1529 _voutput_commit_func(tdm_voutput *voutput, tbm_surface_h buffer)
1531 tdm_private_voutput *private_voutput = (tdm_private_voutput *)voutput;
1534 TDM_RETURN_IF_FAIL(voutput != NULL);
1535 TDM_RETURN_IF_FAIL(buffer != NULL);
1537 ret = tdm_voutput_attach_buffer(private_voutput, buffer);
1538 TDM_RETURN_IF_FAIL(ret == TDM_ERROR_NONE);
1539 ret = tdm_voutput_commit_buffer(private_voutput);
1540 TDM_RETURN_IF_FAIL(ret == TDM_ERROR_NONE);
1546 tdm_output_set_voutput_commit(tdm_voutput *voutput)
1548 tdm_private_display *private_display;
1549 tdm_private_output *private_output;
1550 tdm_private_voutput *private_voutput;
1551 tdm_private_voutput_commit_handler *voutput_commit_handler = NULL;
1552 tdm_error ret = TDM_ERROR_NONE;
1554 TDM_RETURN_VAL_IF_FAIL(voutput != NULL, TDM_ERROR_INVALID_PARAMETER);
1556 private_voutput = (tdm_private_voutput *)voutput;
1557 private_display = private_voutput->private_display;
1558 private_output = (tdm_private_output *)private_voutput->private_output;
1560 _pthread_mutex_lock(&private_display->lock);
1562 if (LIST_LENGTH(&private_voutput->voutput_commit_handler_list) != 0) {
1563 _pthread_mutex_unlock(&private_display->lock);
1567 if (!private_voutput->regist_commit_cb) {
1568 private_voutput->regist_commit_cb = 1;
1569 ret = tdm_voutput_set_commit_func(private_voutput, _tdm_voutput_cb_commit);
1570 if (ret != TDM_ERROR_NONE) {
1571 TDM_ERR("failed: tdm_voutput_set_commit_func");
1572 _pthread_mutex_unlock(&private_display->lock);
1577 voutput_commit_handler = calloc(1, sizeof(tdm_private_voutput_commit_handler));
1578 if (!voutput_commit_handler) {
1579 TDM_ERR("failed: alloc memory");
1580 _pthread_mutex_unlock(&private_display->lock);
1581 return TDM_ERROR_OUT_OF_MEMORY;
1584 ret = tdm_thread_cb_add(private_output->private_voutput, TDM_THREAD_CB_VOUTPUT_COMMIT, voutput_commit_handler, _tdm_voutput_thread_cb_commit, NULL);
1585 if (ret != TDM_ERROR_NONE) {
1586 TDM_ERR("tdm_thread_cb_add failed");
1587 free(voutput_commit_handler);
1588 _pthread_mutex_unlock(&private_display->lock);
1592 LIST_ADDTAIL(&voutput_commit_handler->link, &private_voutput->voutput_commit_handler_list);
1593 voutput_commit_handler->private_voutput = private_voutput;
1594 voutput_commit_handler->func = _voutput_commit_func;
1595 voutput_commit_handler->owner_tid = syscall(SYS_gettid);
1597 private_voutput->set_voutput_commit = 1;
1599 _pthread_mutex_unlock(&private_display->lock);
1605 tdm_output_unset_voutput_commit(tdm_voutput *voutput)
1607 tdm_private_display *private_display;
1608 tdm_private_output *private_output;
1609 tdm_private_voutput *private_voutput;
1610 tdm_private_voutput_commit_handler *voutput_commit_handler = NULL;
1611 tdm_error ret = TDM_ERROR_NONE;
1613 TDM_RETURN_VAL_IF_FAIL(voutput != NULL, TDM_ERROR_INVALID_PARAMETER);
1615 private_voutput = (tdm_private_voutput *)voutput;
1616 private_display = private_voutput->private_display;
1617 private_output = (tdm_private_output *)private_voutput->private_output;
1619 _pthread_mutex_lock(&private_display->lock);
1621 private_voutput->set_voutput_commit = 0;
1623 if (private_voutput->regist_commit_cb) {
1624 private_voutput->regist_commit_cb = 0;
1625 ret = tdm_voutput_set_commit_func(private_voutput, NULL);
1626 if (ret != TDM_ERROR_NONE) {
1627 TDM_ERR("failed: tdm_voutput_set_commit_func");
1628 _pthread_mutex_unlock(&private_display->lock);
1633 if (LIST_LENGTH(&private_voutput->voutput_commit_handler_list) == 0) {
1634 _pthread_mutex_unlock(&private_display->lock);
1635 return TDM_ERROR_NONE;
1638 if (LIST_LENGTH(&private_output->output_commit_handler_list) != 0) {
1639 //commiting. don't remove voutput commit thread here
1640 _pthread_mutex_unlock(&private_display->lock);
1641 return TDM_ERROR_NONE;
1644 if (LIST_LENGTH(&private_voutput->voutput_commit_handler_list) != 0) {
1645 voutput_commit_handler = LIST_FIRST_ENTRY(&private_voutput->voutput_commit_handler_list, tdm_private_voutput_commit_handler, link);
1647 _pthread_mutex_unlock(&private_display->lock);
1648 return TDM_ERROR_NONE;
1651 tdm_thread_cb_remove(private_output->private_voutput, TDM_THREAD_CB_VOUTPUT_COMMIT, voutput_commit_handler, _tdm_voutput_thread_cb_commit, NULL);
1653 _pthread_mutex_unlock(&private_display->lock);
1655 return TDM_ERROR_NONE;
1657 /* LCOV_EXCL_STOP */
1659 /* LCOV_EXCL_START */
1661 tdm_output_commit_internal(tdm_output *output, int sync, tdm_output_commit_handler func, void *user_data)
1663 tdm_private_display *private_display;
1664 tdm_private_output *private_output;
1665 tdm_private_voutput *private_voutput;
1666 tdm_private_module *private_module;
1667 tdm_func_output *func_output;
1668 tdm_private_output_commit_handler *output_commit_handler = NULL;
1669 tdm_private_voutput_commit_handler *voutput_commit_handler = NULL;
1670 tdm_private_layer *private_layer = NULL;
1671 tdm_output_dpms dpms_value = TDM_OUTPUT_DPMS_ON;
1672 tdm_error ret = TDM_ERROR_NONE;
1674 TDM_RETURN_VAL_IF_FAIL(output != NULL, TDM_ERROR_INVALID_PARAMETER);
1676 private_output = (tdm_private_output*)output;
1677 private_module = private_output->private_module;
1678 private_display = private_module->private_display;
1679 func_output = &private_module->func_output;
1681 if (!private_module->use_hal_tdm) {
1682 if (!func_output->output_commit) {
1683 TDM_WRN("not implemented!!");
1684 return TDM_ERROR_NOT_IMPLEMENTED;
1688 ret = tdm_output_get_dpms_internal(output, &dpms_value);
1689 TDM_RETURN_VAL_IF_FAIL(ret == TDM_ERROR_NONE, ret);
1691 if (!TDM_OUTPUT_DPMS_VSYNC_IS_OFF(dpms_value)) {
1692 if (!private_output->regist_commit_cb) {
1693 private_output->regist_commit_cb = 1;
1694 if (private_module->use_hal_tdm)
1695 ret = (tdm_error)hal_tdm_output_set_commit_handler(private_output->output_backend, _tdm_output_cb_commit_hal_tdm);
1697 ret = func_output->output_set_commit_handler(private_output->output_backend, _tdm_output_cb_commit);
1698 TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, commit_failed);
1701 output_commit_handler = calloc(1, sizeof(tdm_private_output_commit_handler));
1702 if (!output_commit_handler) {
1703 TDM_ERR("failed: alloc memory");
1704 return TDM_ERROR_OUT_OF_MEMORY;
1707 if (private_module == private_display->virtual_module) {
1708 if (!private_output->private_voutput) {
1709 TDM_ERR("virtual module but don't have voutput");
1710 free(output_commit_handler);
1711 return TDM_ERROR_BAD_MODULE;
1715 ret = tdm_thread_cb_add(private_output, TDM_THREAD_CB_OUTPUT_COMMIT, output_commit_handler, _tdm_output_thread_cb_commit, NULL);
1716 if (ret != TDM_ERROR_NONE) {
1717 TDM_ERR("tdm_thread_cb_add failed");
1718 free(output_commit_handler);
1722 LIST_ADDTAIL(&output_commit_handler->link, &private_output->output_commit_handler_list);
1723 output_commit_handler->private_output = private_output;
1724 output_commit_handler->func = func;
1725 output_commit_handler->user_data = user_data;
1726 output_commit_handler->owner_tid = syscall(SYS_gettid);
1728 if (private_module == private_display->virtual_module) {
1729 private_voutput = private_output->private_voutput;
1731 /* voutput use only 1 layer */
1732 private_layer = LIST_FIRST_ENTRY(&private_output->layer_list, tdm_private_layer, link);
1734 if (LIST_LENGTH(&private_voutput->voutput_commit_handler_list) != 0) {
1735 voutput_commit_handler = LIST_FIRST_ENTRY(&private_voutput->voutput_commit_handler_list, tdm_private_voutput_commit_handler, link);
1736 voutput_commit_handler->user_data = private_layer->commiting_buffer;
1739 if (private_module->use_hal_tdm)
1740 ret = (tdm_error)hal_tdm_output_commit(private_output->output_backend, sync, output_commit_handler);
1742 ret = func_output->output_commit(private_output->output_backend, sync, output_commit_handler);
1743 TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, commit_failed);
1745 if (tdm_debug_module & TDM_DEBUG_COMMIT)
1746 TDM_INFO("output(%d) backend commit: handle(%p) func(%p) user_data(%p)",
1747 private_output->pipe, output_commit_handler, func, user_data);
1750 /* Even if DPMS is off, committed_buffer should be changed because it will be referred
1751 * for tdm_layer_committed() function.
1753 LIST_FOR_EACH_ENTRY(private_layer, &private_output->layer_list, link) {
1754 if (!private_layer->waiting_buffer)
1757 if (private_layer->committed_buffer) {
1758 tdm_layer_free_buffer(private_layer, private_layer->committed_buffer);
1759 private_layer->committed_buffer = NULL;
1760 if (tdm_debug_module & TDM_DEBUG_BUFFER)
1761 TDM_INFO("layer(%p) waiting_buffer(%p) committed_buffer(%p)",
1762 private_layer, private_layer->waiting_buffer->buffer,
1763 private_layer->committed_buffer);
1766 private_layer->committed_buffer = private_layer->waiting_buffer;
1767 private_layer->waiting_buffer = NULL;
1768 private_layer->commiting_buffer = NULL;
1769 if (tdm_debug_module & TDM_DEBUG_BUFFER)
1770 TDM_INFO("layer(%p) waiting_buffer(%p) committed_buffer(%p)",
1771 private_layer, private_layer->waiting_buffer,
1772 private_layer->committed_buffer->buffer);
1775 if (TDM_OUTPUT_DPMS_VSYNC_IS_OFF(dpms_value)) {
1776 TDM_WRN("dpms %s. Directly call commit handler instead of commit.", tdm_dpms_str(dpms_value));
1778 _pthread_mutex_unlock(&private_display->lock);
1779 func(output, 0, 0, 0, user_data);
1780 _pthread_mutex_lock(&private_display->lock);
1787 if (output_commit_handler) {
1788 tdm_thread_cb_remove(private_output, TDM_THREAD_CB_OUTPUT_COMMIT, output_commit_handler, _tdm_output_thread_cb_commit, NULL);
1789 LIST_DEL(&output_commit_handler->link);
1790 free(output_commit_handler);
1797 tdm_output_commit(tdm_output *output, int sync, tdm_output_commit_handler func,
1800 tdm_private_layer *private_layer = NULL;
1802 OUTPUT_FUNC_ENTRY();
1804 _pthread_mutex_lock(&private_display->lock);
1806 if (private_output->commit_type == TDM_COMMIT_TYPE_NONE)
1807 private_output->commit_type = TDM_COMMIT_TYPE_OUTPUT;
1808 else if (private_output->commit_type == TDM_COMMIT_TYPE_LAYER) {
1809 TDM_ERR("Can't supported. Use tdm_layer_commit");
1810 _pthread_mutex_unlock(&private_display->lock);
1811 return TDM_ERROR_BAD_REQUEST;
1814 if (private_output->commit_per_vblank) {
1815 TDM_ERR("Use tdm_layer_commit");
1816 _pthread_mutex_unlock(&private_display->lock);
1817 return TDM_ERROR_BAD_REQUEST;
1820 if (TDM_OUTPUT_DPMS_VSYNC_IS_OFF(private_output->current_dpms_value)) {
1821 TDM_ERR("output(%d) dpms: %s", private_output->pipe,
1822 tdm_dpms_str(private_output->current_dpms_value));
1823 _pthread_mutex_unlock(&private_display->lock);
1824 return TDM_ERROR_DPMS_OFF;
1827 if (tdm_debug_module & TDM_DEBUG_COMMIT)
1828 TDM_INFO("output(%d) commit", private_output->pipe);
1830 /* apply the pending data of all layers */
1831 LIST_FOR_EACH_ENTRY(private_layer, &private_output->layer_list, link) {
1832 tdm_layer_commit_pending_data(private_layer);
1835 ret = tdm_output_commit_internal(output, sync, func, user_data);
1837 _pthread_mutex_unlock(&private_display->lock);
1841 /* LCOV_EXCL_STOP */
1844 tdm_output_set_mode(tdm_output *output, const tdm_output_mode *mode)
1846 tdm_private_module *private_module;
1847 tdm_func_output *func_output;
1848 OUTPUT_FUNC_ENTRY();
1850 TDM_RETURN_VAL_IF_FAIL(mode != NULL, TDM_ERROR_INVALID_PARAMETER);
1852 _pthread_mutex_lock(&private_display->lock);
1854 private_module = private_output->private_module;
1855 func_output = &private_module->func_output;
1857 if (private_module->use_hal_tdm) {
1858 ret = (tdm_error)hal_tdm_output_set_mode(private_output->output_backend, (const hal_tdm_output_mode *)mode);
1860 if (!func_output->output_set_mode) {
1861 /* LCOV_EXCL_START */
1862 _pthread_mutex_unlock(&private_display->lock);
1863 TDM_WRN("not implemented!!");
1864 return TDM_ERROR_NOT_IMPLEMENTED;
1865 /* LCOV_EXCL_STOP */
1868 ret = func_output->output_set_mode(private_output->output_backend, mode);
1870 if (ret == TDM_ERROR_NONE) {
1871 private_output->current_mode = mode;
1872 private_output->need_set_target_info = 1;
1873 TDM_INFO("mode: %dx%d %dhz", mode->hdisplay, mode->vdisplay, mode->vrefresh);
1876 _pthread_mutex_unlock(&private_display->lock);
1882 tdm_output_get_mode(tdm_output *output, const tdm_output_mode **mode)
1884 OUTPUT_FUNC_ENTRY();
1886 TDM_RETURN_VAL_IF_FAIL(mode != NULL, TDM_ERROR_INVALID_PARAMETER);
1888 _pthread_mutex_lock(&private_display->lock);
1890 *mode = private_output->current_mode;
1892 _pthread_mutex_unlock(&private_display->lock);
1898 tdm_output_set_dpms(tdm_output *output, tdm_output_dpms dpms_value)
1900 tdm_private_module *private_module;
1901 tdm_func_output *func_output;
1902 OUTPUT_FUNC_ENTRY();
1904 if (dpms_value > TDM_OUTPUT_DPMS_OFF) {
1905 if (dpms_value & TDM_OUTPUT_DPMS_DEFAULT_MASK) {
1906 TDM_ERR("Don't use the low-4bit for an extended DPMS mode: dpms_value(%x)", dpms_value);
1907 return TDM_ERROR_BAD_REQUEST;
1910 if (!(private_output->caps.capabilities & TDM_OUTPUT_CAPABILITY_EXTENDED_DPMS)) {
1911 TDM_ERR("output(%d) doesn't support the extended DPMS control: '%s'",
1912 private_output->pipe, tdm_dpms_str(dpms_value));
1913 return TDM_ERROR_BAD_REQUEST;
1917 _pthread_mutex_lock(&private_display->lock);
1919 if (private_output->waiting_dpms_change) {
1920 TDM_ERR("DPMS is not changed yet. Can't be changed twice");
1921 _pthread_mutex_unlock(&private_display->lock);
1922 return TDM_ERROR_BAD_REQUEST;
1925 private_module = private_output->private_module;
1926 func_output = &private_module->func_output;
1928 TDM_INFO("output(%d) DPMS '%s'", private_output->pipe, tdm_dpms_str(dpms_value));
1930 if (private_module->use_hal_tdm) {
1931 ret = (tdm_error)hal_tdm_output_set_dpms(private_output->output_backend, (hal_tdm_output_dpms)dpms_value);
1933 if (func_output->output_set_dpms)
1934 ret = func_output->output_set_dpms(private_output->output_backend, dpms_value);
1936 /* LCOV_EXCL_START */
1937 ret = TDM_ERROR_NONE;
1938 TDM_WRN("DPMS not implemented!!");
1939 /* LCOV_EXCL_STOP */
1943 if (ret == TDM_ERROR_NONE) {
1944 if (private_output->current_dpms_value != dpms_value) {
1945 private_output->current_dpms_value = dpms_value;
1946 _tdm_output_call_thread_cb_dpms(private_output, dpms_value);
1948 TDM_INFO("output(%d) DPMS '%s' done", private_output->pipe, tdm_dpms_str(dpms_value));
1950 tdm_output_dpms temp = TDM_OUTPUT_DPMS_OFF;
1952 /* update current_dpms_value forcely */
1953 tdm_output_get_dpms_internal(output, &temp);
1955 TDM_ERR("output(%d) set DPMS failed: dpms '%s'", private_output->pipe, tdm_dpms_str(temp));
1958 _pthread_mutex_unlock(&private_display->lock);
1963 /* LCOV_EXCL_START */
1965 tdm_output_set_dpms_async(tdm_output *output, tdm_output_dpms dpms_value)
1967 tdm_private_module *private_module;
1968 tdm_func_output *func_output;
1970 OUTPUT_FUNC_ENTRY();
1972 if (!(private_output->caps.capabilities & TDM_OUTPUT_CAPABILITY_ASYNC_DPMS)) {
1973 TDM_ERR("output doesn't support the asynchronous DPMS control!");
1974 return TDM_ERROR_BAD_REQUEST;
1977 if (dpms_value > TDM_OUTPUT_DPMS_OFF) {
1978 if (dpms_value & TDM_OUTPUT_DPMS_DEFAULT_MASK) {
1979 TDM_ERR("Don't use the low-4bit for an extended DPMS mode: dpms_value(%x)", dpms_value);
1980 return TDM_ERROR_BAD_REQUEST;
1983 if (!(private_output->caps.capabilities & TDM_OUTPUT_CAPABILITY_EXTENDED_DPMS)) {
1984 TDM_ERR("output(%d) doesn't support the extended DPMS control: '%s'",
1985 private_output->pipe, tdm_dpms_str(dpms_value));
1986 return TDM_ERROR_BAD_REQUEST;
1990 _pthread_mutex_lock(&private_display->lock);
1992 if (private_output->waiting_dpms_change) {
1993 TDM_ERR("DPMS is not changed yet. Can't be changed twice");
1994 _pthread_mutex_unlock(&private_display->lock);
1995 return TDM_ERROR_BAD_REQUEST;
1998 private_module = private_output->private_module;
1999 func_output = &private_module->func_output;
2000 if (!private_module->use_hal_tdm) {
2001 if (!func_output->output_set_dpms_handler) {
2002 TDM_WRN("not implemented DPMS: output_set_dpms_handler");
2003 _pthread_mutex_unlock(&private_display->lock);
2004 return TDM_ERROR_NOT_IMPLEMENTED;
2007 if (!func_output->output_set_dpms_async) {
2008 TDM_WRN("not implemented DPMS: output_set_dpms_async");
2009 _pthread_mutex_unlock(&private_display->lock);
2010 return TDM_ERROR_NOT_IMPLEMENTED;
2014 if (!private_output->regist_dpms_cb) {
2015 private_output->regist_dpms_cb = 1;
2016 if (private_module->use_hal_tdm)
2017 ret = (tdm_error)hal_tdm_output_set_dpms_handler(private_output->output_backend,
2018 tdm_output_cb_dpms_hal_tdm, private_output);
2020 ret = func_output->output_set_dpms_handler(private_output->output_backend,
2021 tdm_output_cb_dpms, private_output);
2022 if (ret != TDM_ERROR_NONE) {
2023 _pthread_mutex_unlock(&private_display->lock);
2024 TDM_ERR("Can't set the DPMS handler!!");
2029 TDM_INFO("output(%d) DPMS async '%s'", private_output->pipe, tdm_dpms_str(dpms_value));
2031 if (private_module->use_hal_tdm)
2032 ret = (tdm_error)hal_tdm_output_set_dpms_async(private_output->output_backend, (hal_tdm_output_dpms)dpms_value, &sync);
2034 ret = func_output->output_set_dpms_async(private_output->output_backend, dpms_value, &sync);
2036 if (ret == TDM_ERROR_NONE) {
2038 tdm_output_dpms temp = TDM_OUTPUT_DPMS_OFF;
2040 tdm_output_get_dpms_internal(output, &temp);
2041 TDM_INFO("output(%d) DPMS async '%s'(%s) done", private_output->pipe, tdm_dpms_str(dpms_value), tdm_dpms_str(temp));
2043 private_output->waiting_dpms_change = 1;
2044 TDM_INFO("output(%d) DPMS async '%s' waiting", private_output->pipe, tdm_dpms_str(dpms_value));
2047 tdm_output_dpms temp = TDM_OUTPUT_DPMS_OFF;
2049 /* update current_dpms_value forcely */
2050 tdm_output_get_dpms_internal(output, &temp);
2052 TDM_ERR("output(%d) set DPMS async failed: dpms '%s'", private_output->pipe, tdm_dpms_str(temp));
2055 _pthread_mutex_unlock(&private_display->lock);
2059 /* LCOV_EXCL_STOP */
2062 tdm_output_get_dpms_internal(tdm_output *output, tdm_output_dpms *dpms_value)
2064 tdm_private_output *private_output;
2065 tdm_private_module *private_module;
2066 tdm_func_output *func_output;
2067 tdm_error ret = TDM_ERROR_NONE;
2069 TDM_RETURN_VAL_IF_FAIL(output != NULL, TDM_ERROR_INVALID_PARAMETER);
2071 private_output = (tdm_private_output*)output;
2073 /* TODO: this is ugly. But before calling backend's output_get_dpms(), we have
2074 * to check if all backends's DPMS operation has no problem. In future, we'd
2075 * better use new env instead of using commit_per_vblank variable to distinguish
2076 * whether we use the stored value or backend's output_get_dpms.
2078 if (!private_output->commit_per_vblank) {
2079 *dpms_value = private_output->current_dpms_value;
2080 return TDM_ERROR_NONE;
2083 private_module = private_output->private_module;
2084 func_output = &private_module->func_output;
2086 if (private_module->use_hal_tdm) {
2087 ret = (tdm_error)hal_tdm_output_get_dpms(private_output->output_backend, (hal_tdm_output_dpms *)dpms_value);
2089 if (!func_output->output_get_dpms) {
2090 /* LCOV_EXCL_START */
2091 *dpms_value = private_output->current_dpms_value;
2092 TDM_WRN("DPMS get not implemented!!");
2093 return TDM_ERROR_NONE;
2094 /* LCOV_EXCL_STOP */
2097 ret = func_output->output_get_dpms(private_output->output_backend, dpms_value);
2099 if (ret != TDM_ERROR_NONE) {
2100 /* LCOV_EXCL_START */
2101 TDM_ERR("output get DPMS failed");
2102 *dpms_value = TDM_OUTPUT_DPMS_OFF;
2103 /* LCOV_EXCL_STOP */
2106 /* checking with backend's value */
2107 if (*dpms_value != private_output->current_dpms_value) {
2108 TDM_ERR("output(%d) DPMS changed suddenly: %s -> %s",
2109 private_output->pipe, tdm_dpms_str(private_output->current_dpms_value),
2110 tdm_dpms_str(*dpms_value));
2111 private_output->current_dpms_value = *dpms_value;
2112 _tdm_output_call_thread_cb_dpms(private_output, *dpms_value);
2119 tdm_output_get_dpms_changing(tdm_output *output, int *changing)
2121 tdm_private_output *private_output;
2123 TDM_RETURN_VAL_IF_FAIL(output != NULL, TDM_ERROR_INVALID_PARAMETER);
2124 TDM_RETURN_VAL_IF_FAIL(changing != NULL, TDM_ERROR_INVALID_PARAMETER);
2126 private_output = (tdm_private_output*)output;
2128 *changing = private_output->waiting_dpms_change;
2130 return TDM_ERROR_NONE;
2135 tdm_output_get_dpms(tdm_output *output, tdm_output_dpms *dpms_value)
2137 OUTPUT_FUNC_ENTRY();
2139 TDM_RETURN_VAL_IF_FAIL(dpms_value != NULL, TDM_ERROR_INVALID_PARAMETER);
2141 _pthread_mutex_lock(&private_display->lock);
2143 ret = tdm_output_get_dpms_internal(output, dpms_value);
2145 _pthread_mutex_unlock(&private_display->lock);
2151 tdm_output_has_capture_capability(tdm_output *output, unsigned int *has_capability)
2153 tdm_private_module *private_module;
2155 OUTPUT_FUNC_ENTRY();
2157 TDM_RETURN_VAL_IF_FAIL(has_capability != NULL, TDM_ERROR_INVALID_PARAMETER);
2159 _pthread_mutex_lock(&private_display->lock);
2161 private_module = private_output->private_module;
2163 if (!(private_module->capabilities & TDM_DISPLAY_CAPABILITY_CAPTURE))
2164 *has_capability = 0;
2165 else if (!(private_module->caps_capture.capabilities & TDM_CAPTURE_CAPABILITY_OUTPUT))
2166 *has_capability = 0;
2168 *has_capability = 1;
2170 _pthread_mutex_unlock(&private_display->lock);
2175 EXTERN tdm_capture *
2176 tdm_output_create_capture(tdm_output *output, tdm_error *error)
2178 tdm_capture *capture = NULL;
2180 OUTPUT_FUNC_ENTRY_ERROR();
2182 _pthread_mutex_lock(&private_display->lock);
2184 capture = (tdm_capture *)tdm_capture_create_output_internal(private_output, error);
2186 _pthread_mutex_unlock(&private_display->lock);
2192 tdm_output_get_hwc(tdm_output *output, tdm_error *error)
2194 tdm_private_hwc *private_hwc = NULL;
2196 OUTPUT_FUNC_ENTRY_ERROR();
2198 _pthread_mutex_lock(&private_display->lock);
2200 private_hwc = private_output->private_hwc;
2203 *error = TDM_ERROR_BAD_REQUEST;
2204 _pthread_mutex_unlock(&private_display->lock);
2209 *error = TDM_ERROR_NONE;
2211 _pthread_mutex_unlock(&private_display->lock);
2217 tdm_output_set_mirror(tdm_output *output, tdm_output *src_output, tdm_transform transform)
2219 /* LCOV_EXCL_START */
2220 tdm_private_module *private_module;
2221 tdm_func_output *func_output;
2222 tdm_private_output *private_src_output;
2224 OUTPUT_FUNC_ENTRY();
2226 TDM_RETURN_VAL_IF_FAIL(src_output != NULL, TDM_ERROR_INVALID_PARAMETER);
2228 _pthread_mutex_lock(&private_display->lock);
2230 private_module = private_output->private_module;
2231 func_output = &private_module->func_output;
2232 private_src_output = (tdm_private_output*)src_output;
2234 if (!(private_output->caps.capabilities & TDM_OUTPUT_CAPABILITY_MIRROR)) {
2235 TDM_INFO("output(%d) doesn't support the mirror.", private_output->pipe);
2236 _pthread_mutex_unlock(&private_display->lock);
2237 return TDM_ERROR_BAD_REQUEST;
2240 if (private_module->use_hal_tdm) {
2241 ret = (tdm_error)hal_tdm_output_set_mirror((hal_tdm_output *)private_output->output_backend,
2242 (hal_tdm_output *)private_src_output->output_backend, (hal_tdm_transform)transform);
2245 if (!func_output->output_set_mirror) {
2246 TDM_WRN("not implemented!!");
2247 _pthread_mutex_unlock(&private_display->lock);
2248 return TDM_ERROR_NOT_IMPLEMENTED;
2251 ret = func_output->output_set_mirror(private_output->output_backend,
2252 private_src_output->output_backend,
2255 if (ret != TDM_ERROR_NONE) {
2256 TDM_ERR("output(%p) fails to set MIRROR.", private_output);
2257 _pthread_mutex_unlock(&private_display->lock);
2258 return TDM_ERROR_BAD_REQUEST;
2261 _pthread_mutex_unlock(&private_display->lock);
2264 /* LCOV_EXCL_STOP */
2268 tdm_output_unset_mirror(tdm_output *output)
2270 /* LCOV_EXCL_START */
2271 tdm_private_module *private_module;
2272 tdm_func_output *func_output;
2274 OUTPUT_FUNC_ENTRY();
2276 _pthread_mutex_lock(&private_display->lock);
2278 private_module = private_output->private_module;
2279 func_output = &private_module->func_output;
2281 if (!(private_output->caps.capabilities & TDM_OUTPUT_CAPABILITY_MIRROR)) {
2282 TDM_INFO("output(%d) doesn't support the mirror.", private_output->pipe);
2283 _pthread_mutex_unlock(&private_display->lock);
2284 return TDM_ERROR_BAD_REQUEST;
2287 if (private_module->use_hal_tdm) {
2288 ret = (tdm_error)hal_tdm_output_unset_mirror((hal_tdm_output *)private_output->output_backend);
2290 if (!func_output->output_unset_mirror) {
2291 TDM_WRN("not implemented!!");
2292 _pthread_mutex_unlock(&private_display->lock);
2293 return TDM_ERROR_NOT_IMPLEMENTED;
2296 ret = func_output->output_unset_mirror(private_output->output_backend);
2298 if (ret != TDM_ERROR_NONE) {
2299 TDM_ERR("output(%p) fails to unset MIRROR.", private_output);
2300 _pthread_mutex_unlock(&private_display->lock);
2301 return TDM_ERROR_BAD_REQUEST;
2304 _pthread_mutex_unlock(&private_display->lock);
2307 /* LCOV_EXCL_STOP */
2311 tdm_output_choose_commit_per_vblank_mode(tdm_private_output *private_output, int mode)
2313 if (!private_output)
2314 return TDM_ERROR_INVALID_PARAMETER;
2316 if (mode < 0 || mode > 2)
2317 return TDM_ERROR_INVALID_PARAMETER;
2319 private_output->commit_per_vblank = mode;
2321 if (private_output->commit_per_vblank == 0)
2322 TDM_INFO("commit per vblank: disable");
2323 else if (private_output->commit_per_vblank == 1)
2324 TDM_INFO("commit per vblank: enable (1 layer)");
2325 else if (private_output->commit_per_vblank == 2)
2326 TDM_INFO("commit per vblank: enable (previous commit)");
2328 return TDM_ERROR_NONE;
2331 /* LCOV_EXCL_START */
2333 tdm_voutput_destroy(tdm_voutput *voutput)
2335 tdm_private_module *private_module = NULL;
2336 tdm_voutput *voutput_backend = NULL;
2337 tdm_func_voutput *func_voutput = NULL;
2339 tdm_private_display *private_display;
2340 tdm_private_voutput *private_voutput;
2341 tdm_private_output *private_output;
2342 tdm_error ret = TDM_ERROR_NONE;
2343 TDM_RETURN_VAL_IF_FAIL(voutput != NULL, TDM_ERROR_INVALID_PARAMETER);
2344 private_voutput = (tdm_private_voutput*)voutput;
2345 private_display = private_voutput->private_display;
2346 private_module = private_voutput->private_module;
2347 TDM_RETURN_VAL_IF_FAIL(private_module == private_display->virtual_module, TDM_ERROR_BAD_MODULE);
2349 _pthread_mutex_lock(&private_display->lock);
2351 func_voutput = &private_module->func_voutput;
2352 voutput_backend = private_voutput->voutput_backend;
2353 private_output = private_voutput->private_output;
2354 tdm_display_destroy_private_output(private_output);
2355 LIST_DEL(&private_voutput->link);
2356 free(private_voutput);
2357 if (func_voutput->voutput_destroy)
2358 ret = func_voutput->voutput_destroy(voutput_backend);
2360 _pthread_mutex_unlock(&private_display->lock);
2366 tdm_voutput_set_available_mode(tdm_voutput *voutput, const tdm_output_mode *modes, int count)
2368 tdm_private_display *private_display;
2369 tdm_private_module *private_module = NULL;
2370 tdm_private_voutput *private_voutput;
2371 tdm_func_voutput *func_voutput = NULL;
2372 tdm_error ret = TDM_ERROR_NONE;
2374 TDM_RETURN_VAL_IF_FAIL(voutput != NULL, TDM_ERROR_INVALID_PARAMETER);
2375 TDM_RETURN_VAL_IF_FAIL(modes != NULL, TDM_ERROR_INVALID_PARAMETER);
2376 TDM_RETURN_VAL_IF_FAIL(count != 0, TDM_ERROR_INVALID_PARAMETER);
2378 private_voutput = (tdm_private_voutput*)voutput;
2379 private_display = private_voutput->private_display;
2380 private_module = private_voutput->private_module;
2381 TDM_RETURN_VAL_IF_FAIL(private_module == private_display->virtual_module, TDM_ERROR_BAD_MODULE);
2383 _pthread_mutex_lock(&private_display->lock);
2385 if (private_module->use_hal_tdm) {
2386 ret = (tdm_error)hal_tdm_voutput_set_available_mode((hal_tdm_voutput *)private_voutput->voutput_backend,
2387 (const hal_tdm_output_mode *)modes, count);
2389 func_voutput = &private_module->func_voutput;
2390 if (func_voutput->voutput_set_available_mode)
2391 ret = func_voutput->voutput_set_available_mode(private_voutput->voutput_backend, modes, count);
2393 ret = TDM_ERROR_NOT_IMPLEMENTED;
2395 _pthread_mutex_unlock(&private_display->lock);
2401 tdm_voutput_set_physical_size(tdm_voutput *voutput, unsigned int mmwidth, unsigned int mmheight)
2403 tdm_private_display *private_display;
2404 tdm_private_module *private_module = NULL;
2405 tdm_private_voutput *private_voutput;
2406 tdm_func_voutput *func_voutput = NULL;
2407 tdm_error ret = TDM_ERROR_NONE;
2409 TDM_RETURN_VAL_IF_FAIL(voutput != NULL, TDM_ERROR_INVALID_PARAMETER);
2410 TDM_RETURN_VAL_IF_FAIL(mmwidth != 0, TDM_ERROR_INVALID_PARAMETER);
2411 TDM_RETURN_VAL_IF_FAIL(mmheight != 0, TDM_ERROR_INVALID_PARAMETER);
2413 private_voutput = (tdm_private_voutput*)voutput;
2414 private_display = private_voutput->private_display;
2415 private_module = private_voutput->private_module;
2416 TDM_RETURN_VAL_IF_FAIL(private_module == private_display->virtual_module, TDM_ERROR_BAD_MODULE);
2418 _pthread_mutex_lock(&private_display->lock);
2420 if (private_module->use_hal_tdm) {
2421 ret = (tdm_error)hal_tdm_voutput_set_physical_size((hal_tdm_voutput *)private_voutput->voutput_backend, mmwidth, mmheight);
2423 func_voutput = &private_module->func_voutput;
2424 if (func_voutput->voutput_set_physical_size)
2425 ret = func_voutput->voutput_set_physical_size(private_voutput->voutput_backend, mmwidth, mmheight);
2427 ret = TDM_ERROR_NOT_IMPLEMENTED;
2429 _pthread_mutex_unlock(&private_display->lock);
2435 tdm_voutput_connect(tdm_voutput *voutput)
2437 tdm_private_display *private_display;
2438 tdm_private_module *private_module = NULL;
2439 tdm_private_voutput *private_voutput;
2440 tdm_func_voutput *func_voutput = NULL;
2441 tdm_error ret = TDM_ERROR_NONE;
2443 TDM_RETURN_VAL_IF_FAIL(voutput != NULL, TDM_ERROR_INVALID_PARAMETER);
2445 private_voutput = (tdm_private_voutput*)voutput;
2446 private_display = private_voutput->private_display;
2447 private_module = private_voutput->private_module;
2448 TDM_RETURN_VAL_IF_FAIL(private_module == private_display->virtual_module, TDM_ERROR_BAD_MODULE);
2450 _pthread_mutex_lock(&private_display->lock);
2452 if (private_module->use_hal_tdm) {
2453 ret = (tdm_error)hal_tdm_voutput_connect((hal_tdm_voutput *)private_voutput->voutput_backend);
2455 func_voutput = &private_module->func_voutput;
2456 if (func_voutput->voutput_connect)
2457 ret = func_voutput->voutput_connect(private_voutput->voutput_backend);
2459 ret = TDM_ERROR_NOT_IMPLEMENTED;
2461 _pthread_mutex_unlock(&private_display->lock);
2467 tdm_voutput_disconnect(tdm_voutput *voutput)
2469 tdm_private_display *private_display;
2470 tdm_private_module *private_module = NULL;
2471 tdm_private_voutput *private_voutput;
2472 tdm_func_voutput *func_voutput = NULL;
2473 tdm_error ret = TDM_ERROR_NONE;
2475 TDM_RETURN_VAL_IF_FAIL(voutput != NULL, TDM_ERROR_INVALID_PARAMETER);
2477 private_voutput = (tdm_private_voutput*)voutput;
2478 private_display = private_voutput->private_display;
2479 private_module = private_voutput->private_module;
2480 TDM_RETURN_VAL_IF_FAIL(private_module == private_display->virtual_module, TDM_ERROR_BAD_MODULE);
2482 _pthread_mutex_lock(&private_display->lock);
2484 if (private_module->use_hal_tdm) {
2485 ret = (tdm_error)hal_tdm_voutput_disconnect((hal_tdm_voutput *)private_voutput->voutput_backend);
2487 func_voutput = &private_module->func_voutput;
2488 if (func_voutput->voutput_disconnect)
2489 ret = func_voutput->voutput_disconnect(private_voutput->voutput_backend);
2491 ret = TDM_ERROR_NOT_IMPLEMENTED;
2493 _pthread_mutex_unlock(&private_display->lock);
2499 tdm_voutput_set_commit_func(tdm_voutput *voutput, tdm_voutput_commit_handler func)
2501 tdm_private_display *private_display;
2502 tdm_private_module *private_module = NULL;
2503 tdm_private_voutput *private_voutput;
2504 tdm_func_voutput *func_voutput = NULL;
2505 tdm_error ret = TDM_ERROR_NONE;
2507 TDM_RETURN_VAL_IF_FAIL(voutput != NULL, TDM_ERROR_INVALID_PARAMETER);
2509 private_voutput = (tdm_private_voutput*)voutput;
2510 private_display = private_voutput->private_display;
2511 private_module = private_voutput->private_module;
2512 TDM_RETURN_VAL_IF_FAIL(private_module == private_display->virtual_module, TDM_ERROR_BAD_MODULE);
2514 if (private_module->use_hal_tdm) {
2515 ret = (tdm_error)hal_tdm_voutput_set_commit_func((hal_tdm_voutput *)private_voutput->voutput_backend,
2516 (hal_tdm_voutput_commit_handler)func);
2518 func_voutput = &private_module->func_voutput;
2519 if (func_voutput->voutput_set_commit_func)
2520 ret = func_voutput->voutput_set_commit_func(private_voutput->voutput_backend, func);
2522 ret = TDM_ERROR_NOT_IMPLEMENTED;
2528 tdm_voutput_commit_done(tdm_voutput *voutput)
2530 tdm_private_display *private_display;
2531 tdm_private_module *private_module = NULL;
2532 tdm_private_voutput *private_voutput;
2533 tdm_func_voutput *func_voutput = NULL;
2534 tdm_error ret = TDM_ERROR_NONE;
2536 TDM_RETURN_VAL_IF_FAIL(voutput != NULL, TDM_ERROR_INVALID_PARAMETER);
2538 private_voutput = (tdm_private_voutput*)voutput;
2539 private_display = private_voutput->private_display;
2540 private_module = private_voutput->private_module;
2541 TDM_RETURN_VAL_IF_FAIL(private_module == private_display->virtual_module, TDM_ERROR_BAD_MODULE);
2543 _pthread_mutex_lock(&private_display->lock);
2545 if (private_module->use_hal_tdm) {
2546 ret = (tdm_error)hal_tdm_voutput_commit_done((hal_tdm_voutput *)private_voutput->voutput_backend);
2548 func_voutput = &private_module->func_voutput;
2549 if (func_voutput->voutput_commit_done)
2550 ret = func_voutput->voutput_commit_done(private_voutput->voutput_backend);
2552 ret = TDM_ERROR_NOT_IMPLEMENTED;
2554 _pthread_mutex_unlock(&private_display->lock);
2558 /* LCOV_EXCL_STOP */