1 /**************************************************************************
5 * Copyright 2018 Samsung Electronics co., Ltd. All Rights Reserved.
7 * Contact: SooChan Lim <sc1.lim@samsung.com>,
8 * Boram Park <boram1288.park@samsung.com>,
9 * Changyeon Lee <cyeon.lee@samsung.com>,
10 * Sangjin Lee <lsj119@samsung.com>
12 * Permission is hereby granted, free of charge, to any person obtaining a
13 * copy of this software and associated documentation files (the
14 * "Software"), to deal in the Software without restriction, including
15 * without limitation the rights to use, copy, modify, merge, publish,
16 * distribute, sub license, and/or sell copies of the Software, and to
17 * permit persons to whom the Software is furnished to do so, subject to
18 * the following conditions:
20 * The above copyright notice and this permission notice (including the
21 * next paragraph) shall be included in all copies or substantial portions
24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
25 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
27 * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
28 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
29 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
30 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 **************************************************************************/
38 #include "tdm_private.h"
40 #define HWC_FUNC_ENTRY() \
41 tdm_private_display *private_display; \
42 tdm_private_output *private_output; \
43 tdm_private_hwc *private_hwc; \
44 tdm_error ret = TDM_ERROR_NONE; /* default TDM_ERROR_NONE */\
45 TDM_RETURN_VAL_IF_FAIL(hwc != NULL, TDM_ERROR_INVALID_PARAMETER); \
46 private_hwc = (tdm_private_hwc*)hwc; \
47 private_output = private_hwc->private_output; \
48 TDM_RETURN_VAL_IF_FAIL(private_output != NULL, TDM_ERROR_INVALID_PARAMETER); \
49 private_display = private_output->private_display
51 #define HWC_FUNC_ENTRY_ERROR() \
52 tdm_private_display *private_display; \
53 tdm_private_output *private_output; \
54 tdm_private_hwc *private_hwc; \
55 tdm_error ret = TDM_ERROR_NONE; /* default TDM_ERROR_NONE */\
56 TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(hwc != NULL, TDM_ERROR_INVALID_PARAMETER, NULL); \
57 private_hwc = (tdm_private_hwc*)hwc; \
58 private_output = private_hwc->private_output; \
59 TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(private_output != NULL, TDM_ERROR_INVALID_PARAMETER, NULL); \
60 private_display = private_output->private_display
62 #define HWC_FUNC_ENTRY_VOID_RETURN() \
63 tdm_private_display *private_display; \
64 tdm_private_output *private_output; \
65 tdm_private_hwc *private_hwc; \
66 tdm_error ret = TDM_ERROR_NONE; /* default TDM_ERROR_NONE */\
67 TDM_RETURN_IF_FAIL(hwc != NULL); \
68 private_hwc = (tdm_private_hwc*)hwc; \
69 private_output = private_hwc->private_output; \
70 TDM_RETURN_IF_FAIL(private_output != NULL); \
71 private_display = private_output->private_display
73 static int hwc_use_vblank;
74 static unsigned int hwc_vblank_fps;
76 static tdm_private_hwc_window *
77 _tdm_hwc_find_private_hwc_window(tdm_private_hwc *private_hwc, tdm_hwc_window *hwc_window_backend)
79 tdm_private_hwc_window *private_hwc_window = NULL;
81 LIST_FOR_EACH_ENTRY(private_hwc_window, &private_hwc->hwc_window_list, link) {
82 if (private_hwc_window->hwc_window_backend == hwc_window_backend)
83 return private_hwc_window;
90 _tdm_hwc_thread_cb_commit(tdm_private_display *private_display, void *object,
91 tdm_thread_cb_base *cb_base, void *user_data)
93 tdm_thread_cb_hwc_commit *hwc_commit = (tdm_thread_cb_hwc_commit *)cb_base;
94 tdm_private_hwc_commit_handler *hwc_commit_handler = hwc_commit->base.data;
95 tdm_private_hwc *private_hwc = object;
97 TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED());
99 if (!hwc_commit_handler)
102 assert(hwc_commit_handler->owner_tid == syscall(SYS_gettid));
104 tdm_thread_cb_remove(private_hwc, TDM_THREAD_CB_HWC_COMMIT, hwc_commit_handler,
105 _tdm_hwc_thread_cb_commit, NULL);
107 LIST_DEL(&hwc_commit_handler->link);
109 if (tdm_debug_module & TDM_DEBUG_COMMIT) {
110 TDM_INFO("----------------------------------------- hwc(%d) committed", private_hwc->index);
111 TDM_INFO("handler(%p)", hwc_commit_handler);
114 /* LCOV_EXCL_START */
115 if (private_display->print_fps) {
116 double curr = tdm_helper_get_time();
117 if (private_hwc->fps_stamp == 0) {
118 private_hwc->fps_stamp = curr;
119 } else if ((curr - private_hwc->fps_stamp) > 1.0) {
120 TDM_INFO("hwc(%p,%d) fps: %d",
121 private_hwc, private_hwc->index, private_hwc->fps_count);
122 private_hwc->fps_count = 0;
123 private_hwc->fps_stamp = curr;
125 private_hwc->fps_count++;
126 } else if (private_hwc->fps_stamp != 0) {
127 private_hwc->fps_stamp = 0;
128 private_hwc->fps_count = 0;
132 if (hwc_commit_handler->func) {
133 _pthread_mutex_unlock(&private_display->lock);
134 hwc_commit_handler->func(private_hwc,
135 hwc_commit->sequence,
138 hwc_commit_handler->user_data);
139 _pthread_mutex_lock(&private_display->lock);
142 free(hwc_commit_handler);
144 if (tdm_debug_module & TDM_DEBUG_COMMIT)
145 TDM_INFO("-----------------------------------------...");
149 _tdm_hwc_cb_commit(tdm_hwc *hwc_backend, unsigned int sequence,
150 unsigned int tv_sec, unsigned int tv_usec, void *user_data)
152 tdm_private_hwc_commit_handler *hwc_commit_handler = user_data;
153 tdm_private_hwc *private_hwc;
154 tdm_thread_cb_hwc_commit hwc_commit;
157 if (hwc_commit_handler && hwc_commit_handler->use_vblank)
160 if (hwc_commit_handler)
161 private_hwc = hwc_commit_handler->private_hwc;
163 private_hwc = tdm_display_find_private_hwc(tdm_display_get(), hwc_backend);
165 memset(&hwc_commit, 0, sizeof hwc_commit);
166 hwc_commit.base.type = TDM_THREAD_CB_HWC_COMMIT;
167 hwc_commit.base.length = sizeof hwc_commit;
168 hwc_commit.base.object_stamp = private_hwc->stamp;
169 hwc_commit.base.data = hwc_commit_handler;
170 hwc_commit.base.sync = 0;
171 hwc_commit.sequence = sequence;
172 hwc_commit.tv_sec = tv_sec;
173 hwc_commit.tv_usec = tv_usec;
175 ret = tdm_thread_cb_call(private_hwc, &hwc_commit.base, 1);
176 TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
180 _tdm_hwc_got_wait_vblank(unsigned int sequence,
181 unsigned int tv_sec, unsigned int tv_usec, void *user_data)
183 tdm_private_hwc_commit_handler *hwc_commit_handler = user_data;
184 tdm_private_hwc *private_hwc;
185 tdm_thread_cb_hwc_commit hwc_commit;
187 private_hwc = hwc_commit_handler->private_hwc;
188 private_hwc->private_output->layer_waiting_vblank = 0;
190 memset(&hwc_commit, 0, sizeof hwc_commit);
191 hwc_commit.base.type = TDM_THREAD_CB_HWC_COMMIT;
192 hwc_commit.base.length = sizeof hwc_commit;
193 hwc_commit.base.object_stamp = private_hwc->stamp;
194 hwc_commit.base.data = hwc_commit_handler;
195 hwc_commit.base.sync = 0;
196 hwc_commit.sequence = sequence;
197 hwc_commit.tv_sec = tv_sec;
198 hwc_commit.tv_usec = tv_usec;
200 _tdm_hwc_thread_cb_commit(private_hwc->private_output->private_display, private_hwc, &hwc_commit.base, user_data);
204 _tdm_hwc_cb_wait_vblank(tdm_vblank *vblank, tdm_error error, unsigned int sequence,
205 unsigned int tv_sec, unsigned int tv_usec, void *user_data)
207 tdm_private_hwc_commit_handler *hwc_commit_handler = user_data;
208 tdm_private_output *private_output = NULL;
209 tdm_private_display *private_display;
211 if (!hwc_commit_handler->use_vblank)
214 TDM_RETURN_IF_FAIL(hwc_commit_handler != NULL);
216 private_output = hwc_commit_handler->private_hwc->private_output;
217 TDM_RETURN_IF_FAIL(private_output != NULL);
219 private_display = private_output->private_display;
221 _pthread_mutex_lock(&private_display->lock);
223 _tdm_hwc_got_wait_vblank(sequence, tv_sec, tv_usec, user_data);
225 _pthread_mutex_unlock(&private_display->lock);
229 _tdm_hwc_vblank(tdm_private_hwc *private_hwc, tdm_private_hwc_commit_handler *hwc_commit_handler)
231 tdm_private_display *private_display;
232 tdm_private_output *private_output;
233 tdm_error ret = TDM_ERROR_NONE;
235 private_output = private_hwc->private_output;
236 TDM_RETURN_VAL_IF_FAIL(private_output != NULL, TDM_ERROR_INVALID_PARAMETER);
237 private_display = private_output->private_display;
239 if (!private_output->vblank) {
240 /* tdm_vblank APIs is for server. it should be called in unlock status*/
241 _pthread_mutex_unlock(&private_display->lock);
242 private_output->vblank = tdm_vblank_create(private_display, private_output, NULL);
243 _pthread_mutex_lock(&private_display->lock);
244 TDM_RETURN_VAL_IF_FAIL(private_output->vblank != NULL, TDM_ERROR_OPERATION_FAILED);
247 if (!private_output->layer_waiting_vblank) {
248 ret = tdm_vblank_set_fps(private_output->vblank, hwc_vblank_fps);
249 if (ret != TDM_ERROR_NONE)
252 /* tdm_vblank APIs is for server. it should be called in unlock status*/
253 _pthread_mutex_unlock(&private_display->lock);
254 ret = tdm_vblank_wait(private_output->vblank, 0, 0, 1, _tdm_hwc_cb_wait_vblank, hwc_commit_handler);
255 _pthread_mutex_lock(&private_display->lock);
256 if (ret != TDM_ERROR_NONE) {
257 if (!TDM_OUTPUT_DPMS_VSYNC_IS_OFF(private_output->current_dpms_value))
261 hwc_commit_handler->use_vblank = 1;
262 private_output->layer_waiting_vblank = 1;
270 tdm_hwc_init(tdm_private_display *private_display)
272 tdm_thread_cb_set_find_func(TDM_THREAD_CB_HWC_COMMIT, tdm_display_find_hwc_stamp);
274 return TDM_ERROR_NONE;
278 tdm_hwc_set_vblank(unsigned int fps)
281 hwc_vblank_fps = fps;
285 tdm_hwc_unset_vblank(void)
291 EXTERN tdm_hwc_window *
292 tdm_hwc_create_window(tdm_hwc *hwc, tdm_error *error)
294 tdm_hwc_window *hwc_window = NULL;
296 HWC_FUNC_ENTRY_ERROR();
298 _pthread_mutex_lock(&private_display->lock);
300 hwc_window = (tdm_hwc_window *)tdm_hwc_window_create_internal(private_hwc, error);
302 _pthread_mutex_unlock(&private_display->lock);
308 tdm_hwc_get_video_supported_formats(tdm_hwc *hwc, const tbm_format **formats, int *count)
310 tdm_private_module *private_module;
311 tdm_func_hwc *func_hwc;
315 TDM_RETURN_VAL_IF_FAIL(formats != NULL, TDM_ERROR_INVALID_PARAMETER);
316 TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
318 _pthread_mutex_lock(&private_display->lock);
320 private_module = private_output->private_module;
321 func_hwc = &private_module->func_hwc;
323 if (!func_hwc->hwc_get_video_supported_formats) {
324 /* LCOV_EXCL_START */
325 _pthread_mutex_unlock(&private_display->lock);
326 TDM_WRN("not implemented!!");
327 return TDM_ERROR_NOT_IMPLEMENTED;
331 ret = func_hwc->hwc_get_video_supported_formats(private_hwc->hwc_backend, formats, count);
333 _pthread_mutex_unlock(&private_display->lock);
339 tdm_hwc_get_video_available_properties(tdm_hwc *hwc, const tdm_prop **props, int *count)
341 tdm_private_module *private_module;
342 tdm_func_hwc *func_hwc = NULL;
346 TDM_RETURN_VAL_IF_FAIL(props != NULL, TDM_ERROR_INVALID_PARAMETER);
347 TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
349 _pthread_mutex_lock(&private_display->lock);
351 private_module = private_output->private_module;
352 func_hwc = &private_module->func_hwc;
354 if (!func_hwc->hwc_get_video_available_properties) {
355 /* LCOV_EXCL_START */
356 _pthread_mutex_unlock(&private_display->lock);
357 TDM_WRN("not implemented!!");
358 return TDM_ERROR_NOT_IMPLEMENTED;
362 ret = func_hwc->hwc_get_video_available_properties(private_hwc->hwc_backend, props, count);
364 _pthread_mutex_unlock(&private_display->lock);
370 tdm_hwc_get_capabilities(tdm_hwc *hwc, tdm_hwc_capability *capabilities)
372 tdm_private_module *private_module;
373 tdm_func_hwc *func_hwc;
377 _pthread_mutex_lock(&private_display->lock);
379 private_module = private_output->private_module;
380 func_hwc = &private_module->func_hwc;
382 if (!func_hwc->hwc_get_capabilities) {
383 _pthread_mutex_unlock(&private_display->lock);
384 TDM_WRN("not implemented!!");
385 return TDM_ERROR_NOT_IMPLEMENTED;
388 ret = func_hwc->hwc_get_capabilities(private_hwc->hwc_backend, capabilities);
390 _pthread_mutex_unlock(&private_display->lock);
396 tdm_hwc_get_available_properties(tdm_hwc *hwc, const tdm_prop **props, int *count)
398 tdm_private_module *private_module;
399 tdm_func_hwc *func_hwc = NULL;
403 TDM_RETURN_VAL_IF_FAIL(props != NULL, TDM_ERROR_INVALID_PARAMETER);
404 TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
406 _pthread_mutex_lock(&private_display->lock);
408 private_module = private_output->private_module;
409 func_hwc = &private_module->func_hwc;
411 if (!func_hwc->hwc_get_available_properties) {
412 /* LCOV_EXCL_START */
413 _pthread_mutex_unlock(&private_display->lock);
414 TDM_WRN("not implemented!!");
415 return TDM_ERROR_NOT_IMPLEMENTED;
419 ret = func_hwc->hwc_get_available_properties(private_hwc->hwc_backend, props, count);
421 _pthread_mutex_unlock(&private_display->lock);
426 EXTERN tbm_surface_queue_h
427 tdm_hwc_get_client_target_buffer_queue(tdm_hwc *hwc, tdm_error *error)
429 tdm_private_module *private_module;
430 tdm_func_hwc *func_hwc = NULL;
431 tbm_surface_queue_h queue = NULL;
433 HWC_FUNC_ENTRY_ERROR();
435 _pthread_mutex_lock(&private_display->lock);
437 private_module = private_hwc->private_module;
438 func_hwc = &private_module->func_hwc;
440 if (!func_hwc->hwc_get_client_target_buffer_queue) {
441 /* LCOV_EXCL_START */
442 _pthread_mutex_unlock(&private_display->lock);
443 TDM_WRN("not implemented!!");
448 queue = func_hwc->hwc_get_client_target_buffer_queue(private_hwc->hwc_backend, error);
450 _pthread_mutex_unlock(&private_display->lock);
456 tdm_hwc_set_client_target_buffer(tdm_hwc *hwc, tbm_surface_h target_buffer, tdm_region damage)
458 tdm_private_module *private_module;
459 tdm_func_hwc *func_hwc = NULL;
463 _pthread_mutex_lock(&private_display->lock);
465 if (tdm_debug_dump & TDM_DUMP_FLAG_WINDOW) {
466 /* LCOV_EXCL_START */
467 char str[TDM_PATH_LEN];
469 snprintf(str, TDM_PATH_LEN, "target_window_%03d", i++);
470 tdm_helper_dump_buffer_str(target_buffer, tdm_debug_dump_dir, str);
474 private_module = private_hwc->private_module;
475 func_hwc = &private_module->func_hwc;
477 if (!func_hwc->hwc_set_client_target_buffer) {
478 /* LCOV_EXCL_START */
479 _pthread_mutex_unlock(&private_display->lock);
480 TDM_WRN("not implemented!!");
481 return TDM_ERROR_NOT_IMPLEMENTED;
485 ret = func_hwc->hwc_set_client_target_buffer(private_hwc->hwc_backend, target_buffer, damage);
487 if (private_hwc->display_target_buffer) {
488 if (private_hwc->display_target_buffer != target_buffer) {
489 tbm_surface_internal_unref(private_hwc->display_target_buffer);
490 private_hwc->display_target_buffer = target_buffer;
492 tbm_surface_internal_ref(private_hwc->display_target_buffer);
496 private_hwc->display_target_buffer = target_buffer;
497 tbm_surface_internal_ref(private_hwc->display_target_buffer);
501 _pthread_mutex_unlock(&private_display->lock);
507 tdm_hwc_set_client_target_acquire_fence(tdm_hwc *hwc, int acquire_fence)
509 tdm_private_module *private_module;
510 tdm_func_hwc *func_hwc = NULL;
514 _pthread_mutex_lock(&private_display->lock);
516 private_module = private_hwc->private_module;
517 func_hwc = &private_module->func_hwc;
519 if (!func_hwc->hwc_set_client_target_acquire_fence) {
520 /* LCOV_EXCL_START */
521 _pthread_mutex_unlock(&private_display->lock);
522 TDM_WRN("not implemented!!");
523 return TDM_ERROR_NOT_IMPLEMENTED;
527 ret = func_hwc->hwc_set_client_target_acquire_fence(private_hwc->hwc_backend, acquire_fence);
529 _pthread_mutex_unlock(&private_display->lock);
535 tdm_hwc_validate(tdm_hwc *hwc, tdm_hwc_window **composited_wnds, uint32_t num_wnds, uint32_t *num_types)
537 tdm_private_module *private_module;
538 tdm_func_hwc *func_hwc = NULL;
539 tdm_private_hwc_window **composited_wnds_frontend = NULL;
540 tdm_hwc_window **composited_wnds_backend = NULL;
545 TDM_RETURN_VAL_IF_FAIL(num_types != NULL, TDM_ERROR_INVALID_PARAMETER);
547 _pthread_mutex_lock(&private_display->lock);
549 private_module = private_hwc->private_module;
550 func_hwc = &private_module->func_hwc;
552 if (!func_hwc->hwc_validate) {
553 /* LCOV_EXCL_START */
554 _pthread_mutex_unlock(&private_display->lock);
555 TDM_WRN("not implemented!!");
556 return TDM_ERROR_NOT_IMPLEMENTED;
561 ret = func_hwc->hwc_validate(private_hwc->hwc_backend, NULL, 0, num_types);
563 _pthread_mutex_unlock(&private_display->lock);
567 composited_wnds_backend = calloc(num_wnds, sizeof(tdm_hwc_window *));
568 if (!composited_wnds_backend) {
569 /* LCOV_EXCL_START */
570 _pthread_mutex_unlock(&private_display->lock);
571 return TDM_ERROR_OUT_OF_MEMORY;
575 composited_wnds_frontend = (tdm_private_hwc_window **)composited_wnds;
577 for (i = 0; i < num_wnds; i++)
578 composited_wnds_backend[i] = composited_wnds_frontend[i]->hwc_window_backend;
580 ret = func_hwc->hwc_validate(private_hwc->hwc_backend, composited_wnds_backend,
581 num_wnds, num_types);
583 free(composited_wnds_backend);
585 _pthread_mutex_unlock(&private_display->lock);
591 tdm_hwc_get_changed_composition_types(tdm_hwc *hwc, uint32_t *num_elements,
592 tdm_hwc_window **hwc_window,
593 tdm_hwc_window_composition *composition_types)
595 tdm_private_module *private_module;
596 tdm_func_hwc *func_hwc = NULL;
597 tdm_private_hwc_window * private_hwc_window = NULL;
602 TDM_RETURN_VAL_IF_FAIL(num_elements != NULL, TDM_ERROR_INVALID_PARAMETER);
604 _pthread_mutex_lock(&private_display->lock);
606 private_module = private_hwc->private_module;
607 func_hwc = &private_module->func_hwc;
609 if (!func_hwc->hwc_get_changed_composition_types) {
610 /* LCOV_EXCL_START */
611 _pthread_mutex_unlock(&private_display->lock);
612 TDM_WRN("not implemented!!");
613 return TDM_ERROR_NOT_IMPLEMENTED;
617 ret = func_hwc->hwc_get_changed_composition_types(private_hwc->hwc_backend,
618 num_elements, hwc_window, composition_types);
619 if (ret != TDM_ERROR_NONE) {
620 /* LCOV_EXCL_START */
621 _pthread_mutex_unlock(&private_display->lock);
626 if (hwc_window == NULL || composition_types == NULL) {
627 _pthread_mutex_unlock(&private_display->lock);
628 return TDM_ERROR_NONE;
631 for (i = 0; i < *num_elements; i++) {
632 private_hwc_window = _tdm_hwc_find_private_hwc_window(private_hwc, hwc_window[i]);
633 if (private_hwc_window == NULL) {
634 /* LCOV_EXCL_START */
635 TDM_ERR("failed! This should never happen!");
636 tdm_hwc_window_destroy_internal(private_hwc_window);
638 _pthread_mutex_unlock(&private_display->lock);
639 return TDM_ERROR_OPERATION_FAILED;
643 hwc_window[i] = (tdm_hwc_window*)private_hwc_window;
646 _pthread_mutex_unlock(&private_display->lock);
652 tdm_hwc_accept_validation(tdm_hwc *hwc)
654 tdm_private_module *private_module;
655 tdm_func_hwc *func_hwc = NULL;
659 _pthread_mutex_lock(&private_display->lock);
661 private_module = private_hwc->private_module;
662 func_hwc = &private_module->func_hwc;
664 if (!func_hwc->hwc_validate) {
665 /* LCOV_EXCL_START */
666 _pthread_mutex_unlock(&private_display->lock);
667 TDM_WRN("not implemented!!");
668 return TDM_ERROR_NOT_IMPLEMENTED;
672 ret = func_hwc->hwc_accept_validation(private_hwc->hwc_backend);
674 _pthread_mutex_unlock(&private_display->lock);
680 tdm_hwc_commit(tdm_hwc *hwc, int sync, tdm_hwc_commit_handler func, void *user_data)
682 tdm_private_module *private_module;
683 tdm_func_hwc *func_hwc = NULL;
684 tdm_private_hwc_commit_handler *hwc_commit_handler = NULL;
685 tdm_private_voutput *private_voutput = NULL;
686 tdm_private_voutput_commit_handler *voutput_commit_handler = NULL;
690 _pthread_mutex_lock(&private_display->lock);
692 private_module = private_hwc->private_module;
693 func_hwc = &private_module->func_hwc;
695 if (!func_hwc->hwc_commit) {
696 /* LCOV_EXCL_START */
697 TDM_WRN("not implemented!!");
698 _pthread_mutex_unlock(&private_display->lock);
699 return TDM_ERROR_NOT_IMPLEMENTED;
703 //TODO: I am not sure yet whether we have to check the dpms at hwc_commit.
705 /* check if the dpms is off */
706 if (TDM_OUTPUT_DPMS_VSYNC_IS_OFF(private_output->current_dpms_value)) {
707 TDM_ERR("hwc(%d) dpms: %s", private_hwc->index,
708 tdm_dpms_str(private_output->current_dpms_value));
709 _pthread_mutex_unlock(&private_display->lock);
710 return TDM_ERROR_DPMS_OFF;
714 if (tdm_debug_module & TDM_DEBUG_COMMIT)
715 TDM_INFO("hwc(%d) commit", private_hwc->index);
717 if (private_module == private_display->virtual_module) {
718 if (!private_output->private_voutput) {
719 TDM_ERR("virtual module but don't have voutput");
720 _pthread_mutex_unlock(&private_display->lock);
721 return TDM_ERROR_BAD_MODULE;
725 if (!private_hwc->regist_commit_cb) {
726 private_hwc->regist_commit_cb = 1;
727 ret = func_hwc->hwc_set_commit_handler(private_hwc->hwc_backend, _tdm_hwc_cb_commit);
728 /* LCOV_EXCL_START */
729 if (ret != TDM_ERROR_NONE) {
730 private_hwc->regist_commit_cb = 0;
731 TDM_ERR("hwc(%d) fail to set hwc_set_commit_handler", private_hwc->index);
732 _pthread_mutex_unlock(&private_display->lock);
738 hwc_commit_handler = calloc(1, sizeof(tdm_private_hwc_commit_handler));
739 if (!hwc_commit_handler) {
740 /* LCOV_EXCL_START */
741 TDM_ERR("failed: alloc memory");
742 _pthread_mutex_unlock(&private_display->lock);
743 return TDM_ERROR_OUT_OF_MEMORY;
747 ret = tdm_thread_cb_add(private_hwc, TDM_THREAD_CB_HWC_COMMIT, hwc_commit_handler,
748 _tdm_hwc_thread_cb_commit, NULL);
749 if (ret != TDM_ERROR_NONE) {
750 TDM_ERR("tdm_thread_cb_add failed");
751 free(hwc_commit_handler);
752 _pthread_mutex_unlock(&private_display->lock);
756 LIST_ADDTAIL(&hwc_commit_handler->link, &private_hwc->hwc_commit_handler_list);
757 hwc_commit_handler->private_hwc = private_hwc;
758 hwc_commit_handler->func = func;
759 hwc_commit_handler->user_data = user_data;
760 hwc_commit_handler->owner_tid = syscall(SYS_gettid);
762 if (private_module == private_display->virtual_module) {
763 private_voutput = private_output->private_voutput;
765 if (LIST_LENGTH(&private_voutput->voutput_commit_handler_list) != 0) {
766 voutput_commit_handler = LIST_FIRST_ENTRY(&private_voutput->voutput_commit_handler_list, tdm_private_voutput_commit_handler, link);
767 voutput_commit_handler->user_data = private_hwc->display_target_buffer;
771 ret = func_hwc->hwc_commit(private_hwc->hwc_backend, sync, hwc_commit_handler);
772 TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, commit_failed);
774 if (hwc_use_vblank) {
775 ret = _tdm_hwc_vblank(private_hwc, hwc_commit_handler);
776 if (ret == TDM_ERROR_NONE) {
777 if (tdm_debug_module & TDM_DEBUG_COMMIT)
778 TDM_INFO("hwc(%d) backend commit: wait vblank handle(%p) func(%p) user_data(%p)",
779 private_hwc->index, hwc_commit_handler, func, user_data);
783 if (tdm_debug_module & TDM_DEBUG_COMMIT)
784 TDM_INFO("hwc(%d) backend commit: handle(%p) func(%p) user_data(%p)",
785 private_hwc->index, hwc_commit_handler, func, user_data);
788 _pthread_mutex_unlock(&private_display->lock);
793 /* LCOV_EXCL_START */
794 if (hwc_commit_handler) {
795 tdm_thread_cb_remove(private_hwc, TDM_THREAD_CB_HWC_COMMIT, hwc_commit_handler,
796 _tdm_hwc_thread_cb_commit, NULL);
797 LIST_DEL(&hwc_commit_handler->link);
798 free(hwc_commit_handler);
801 _pthread_mutex_unlock(&private_display->lock);
808 tdm_hwc_get_commit_fence(tdm_hwc *hwc, int *commit_fence)
810 tdm_private_module *private_module;
811 tdm_func_hwc *func_hwc = NULL;
815 _pthread_mutex_lock(&private_display->lock);
817 private_module = private_hwc->private_module;
818 func_hwc = &private_module->func_hwc;
820 if (!func_hwc->hwc_get_commit_fence) {
821 /* LCOV_EXCL_START */
822 _pthread_mutex_unlock(&private_display->lock);
823 TDM_WRN("not implemented!!");
824 return TDM_ERROR_NOT_IMPLEMENTED;
828 ret = func_hwc->hwc_get_commit_fence(private_hwc->hwc_backend, commit_fence);
830 _pthread_mutex_unlock(&private_display->lock);
836 tdm_hwc_set_property(tdm_hwc *hwc, uint32_t id, tdm_value value)
838 tdm_private_module *private_module;
839 tdm_func_hwc *func_hwc = NULL;
843 _pthread_mutex_lock(&private_display->lock);
845 private_module = private_hwc->private_module;
846 func_hwc = &private_module->func_hwc;
848 if (!func_hwc->hwc_set_property) {
849 /* LCOV_EXCL_START */
850 _pthread_mutex_unlock(&private_display->lock);
851 TDM_WRN("not implemented!!");
852 return TDM_ERROR_NOT_IMPLEMENTED;
856 ret = func_hwc->hwc_set_property(private_hwc->hwc_backend, id, value);
858 _pthread_mutex_unlock(&private_display->lock);
864 tdm_hwc_get_property(tdm_hwc *hwc, uint32_t id, tdm_value *value)
866 tdm_private_module *private_module;
867 tdm_func_hwc *func_hwc = NULL;
871 _pthread_mutex_lock(&private_display->lock);
873 private_module = private_hwc->private_module;
874 func_hwc = &private_module->func_hwc;
876 if (!func_hwc->hwc_get_property) {
877 /* LCOV_EXCL_START */
878 _pthread_mutex_unlock(&private_display->lock);
879 TDM_WRN("not implemented!!");
880 return TDM_ERROR_NOT_IMPLEMENTED;
884 ret = func_hwc->hwc_get_property(private_hwc->hwc_backend, id, value);
886 _pthread_mutex_unlock(&private_display->lock);