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_check_hwc_commit_handler_validation(tdm_private_hwc *private_hwc, tdm_private_hwc_commit_handler *hwc_commit_handler)
92 tdm_private_hwc_commit_handler *commit_handler = NULL;
94 if (LIST_IS_EMPTY(&private_hwc->hwc_commit_handler_list))
95 return TDM_ERROR_INVALID_PARAMETER;
97 LIST_FOR_EACH_ENTRY(commit_handler, &private_hwc->hwc_commit_handler_list, link) {
98 if (commit_handler == hwc_commit_handler)
99 return TDM_ERROR_NONE;
102 return TDM_ERROR_INVALID_PARAMETER;
106 _tdm_hwc_thread_cb_commit(tdm_private_display *private_display, void *object,
107 tdm_thread_cb_base *cb_base, void *user_data)
109 tdm_thread_cb_hwc_commit *hwc_commit = (tdm_thread_cb_hwc_commit *)cb_base;
110 tdm_private_hwc_commit_handler *hwc_commit_handler = hwc_commit->base.data;
111 tdm_private_hwc *private_hwc = object;
113 TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED());
115 if (!hwc_commit_handler)
118 assert(hwc_commit_handler->owner_tid == syscall(SYS_gettid));
120 tdm_thread_cb_remove(private_hwc, TDM_THREAD_CB_HWC_COMMIT, hwc_commit_handler,
121 _tdm_hwc_thread_cb_commit, NULL);
123 TDM_RETURN_IF_FAIL(_tdm_hwc_check_hwc_commit_handler_validation(private_hwc, hwc_commit_handler) == TDM_ERROR_NONE)
125 LIST_DEL(&hwc_commit_handler->link);
127 if (tdm_debug_module & TDM_DEBUG_COMMIT) {
128 TDM_INFO("----------------------------------------- hwc(%d) committed", private_hwc->index);
129 TDM_INFO("handler(%p)", hwc_commit_handler);
132 /* LCOV_EXCL_START */
133 if (private_display->print_fps) {
134 double curr = tdm_helper_get_time();
135 if (private_hwc->fps_stamp == 0) {
136 private_hwc->fps_stamp = curr;
137 } else if ((curr - private_hwc->fps_stamp) > 1.0) {
138 TDM_INFO("hwc(%p,%d) fps: %d",
139 private_hwc, private_hwc->index, private_hwc->fps_count);
140 private_hwc->fps_count = 0;
141 private_hwc->fps_stamp = curr;
143 private_hwc->fps_count++;
144 } else if (private_hwc->fps_stamp != 0) {
145 private_hwc->fps_stamp = 0;
146 private_hwc->fps_count = 0;
150 if (hwc_commit_handler->func) {
151 _pthread_mutex_unlock(&private_display->lock);
152 hwc_commit_handler->func(private_hwc,
153 hwc_commit->sequence,
156 hwc_commit_handler->user_data);
157 _pthread_mutex_lock(&private_display->lock);
160 free(hwc_commit_handler);
162 if (tdm_debug_module & TDM_DEBUG_COMMIT)
163 TDM_INFO("-----------------------------------------...");
167 _tdm_hwc_cb_commit(tdm_hwc *hwc_backend, unsigned int sequence,
168 unsigned int tv_sec, unsigned int tv_usec, void *user_data)
170 tdm_private_hwc_commit_handler *hwc_commit_handler = user_data;
171 tdm_private_hwc *private_hwc;
172 tdm_thread_cb_hwc_commit hwc_commit;
175 if (hwc_commit_handler && hwc_commit_handler->use_vblank)
178 if (hwc_commit_handler)
179 private_hwc = hwc_commit_handler->private_hwc;
181 private_hwc = tdm_display_find_private_hwc(tdm_display_get(), hwc_backend);
183 memset(&hwc_commit, 0, sizeof hwc_commit);
184 hwc_commit.base.type = TDM_THREAD_CB_HWC_COMMIT;
185 hwc_commit.base.length = sizeof hwc_commit;
186 hwc_commit.base.object_stamp = private_hwc->stamp;
187 hwc_commit.base.data = hwc_commit_handler;
188 hwc_commit.base.sync = 0;
189 hwc_commit.sequence = sequence;
190 hwc_commit.tv_sec = tv_sec;
191 hwc_commit.tv_usec = tv_usec;
193 ret = tdm_thread_cb_call(private_hwc, &hwc_commit.base, 1);
194 TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
198 _tdm_hwc_cb_commit_hal_tdm(hal_tdm_hwc *hwc_backend, unsigned int sequence,
199 unsigned int tv_sec, unsigned int tv_usec, void *user_data)
201 tdm_private_hwc_commit_handler *hwc_commit_handler = user_data;
202 tdm_private_hwc *private_hwc;
203 tdm_thread_cb_hwc_commit hwc_commit;
206 if (hwc_commit_handler && hwc_commit_handler->use_vblank)
209 if (hwc_commit_handler)
210 private_hwc = hwc_commit_handler->private_hwc;
212 private_hwc = tdm_display_find_private_hwc(tdm_display_get(), (tdm_hwc *)hwc_backend);
214 memset(&hwc_commit, 0, sizeof hwc_commit);
215 hwc_commit.base.type = TDM_THREAD_CB_HWC_COMMIT;
216 hwc_commit.base.length = sizeof hwc_commit;
217 hwc_commit.base.object_stamp = private_hwc->stamp;
218 hwc_commit.base.data = hwc_commit_handler;
219 hwc_commit.base.sync = 0;
220 hwc_commit.sequence = sequence;
221 hwc_commit.tv_sec = tv_sec;
222 hwc_commit.tv_usec = tv_usec;
224 ret = tdm_thread_cb_call(private_hwc, &hwc_commit.base, 1);
225 TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
228 /* LCOV_EXCL_START */
230 _tdm_hwc_got_wait_vblank(unsigned int sequence,
231 unsigned int tv_sec, unsigned int tv_usec, void *user_data)
233 tdm_private_hwc_commit_handler *hwc_commit_handler = user_data;
234 tdm_private_hwc *private_hwc;
235 tdm_thread_cb_hwc_commit hwc_commit;
237 private_hwc = hwc_commit_handler->private_hwc;
238 private_hwc->private_output->layer_waiting_vblank = 0;
240 memset(&hwc_commit, 0, sizeof hwc_commit);
241 hwc_commit.base.type = TDM_THREAD_CB_HWC_COMMIT;
242 hwc_commit.base.length = sizeof hwc_commit;
243 hwc_commit.base.object_stamp = private_hwc->stamp;
244 hwc_commit.base.data = hwc_commit_handler;
245 hwc_commit.base.sync = 0;
246 hwc_commit.sequence = sequence;
247 hwc_commit.tv_sec = tv_sec;
248 hwc_commit.tv_usec = tv_usec;
250 _tdm_hwc_thread_cb_commit(private_hwc->private_output->private_display, private_hwc, &hwc_commit.base, user_data);
254 _tdm_hwc_cb_wait_vblank(tdm_vblank *vblank, tdm_error error, unsigned int sequence,
255 unsigned int tv_sec, unsigned int tv_usec, void *user_data)
257 tdm_private_hwc_commit_handler *hwc_commit_handler = user_data;
258 tdm_private_output *private_output = NULL;
259 tdm_private_display *private_display;
261 if (!hwc_commit_handler->use_vblank)
264 TDM_RETURN_IF_FAIL(hwc_commit_handler != NULL);
265 TDM_RETURN_IF_FAIL(hwc_commit_handler->private_hwc != NULL);
267 private_output = hwc_commit_handler->private_hwc->private_output;
268 TDM_RETURN_IF_FAIL(private_output != NULL);
270 private_display = private_output->private_display;
272 _pthread_mutex_lock(&private_display->lock);
274 _tdm_hwc_got_wait_vblank(sequence, tv_sec, tv_usec, user_data);
276 _pthread_mutex_unlock(&private_display->lock);
280 _tdm_hwc_vblank(tdm_private_hwc *private_hwc, tdm_private_hwc_commit_handler *hwc_commit_handler)
282 tdm_private_display *private_display;
283 tdm_private_output *private_output;
284 tdm_error ret = TDM_ERROR_NONE;
286 private_output = private_hwc->private_output;
287 TDM_RETURN_VAL_IF_FAIL(private_output != NULL, TDM_ERROR_INVALID_PARAMETER);
288 private_display = private_output->private_display;
290 if (!private_output->vblank) {
291 /* tdm_vblank APIs is for server. it should be called in unlock status*/
292 _pthread_mutex_unlock(&private_display->lock);
293 private_output->vblank = tdm_vblank_create(private_display, private_output, NULL);
294 _pthread_mutex_lock(&private_display->lock);
295 TDM_RETURN_VAL_IF_FAIL(private_output->vblank != NULL, TDM_ERROR_OPERATION_FAILED);
298 if (!private_output->layer_waiting_vblank) {
299 ret = tdm_vblank_set_fps(private_output->vblank, hwc_vblank_fps);
300 if (ret != TDM_ERROR_NONE)
303 private_output->layer_waiting_vblank = 1;
305 /* tdm_vblank APIs is for server. it should be called in unlock status*/
306 _pthread_mutex_unlock(&private_display->lock);
307 ret = tdm_vblank_wait(private_output->vblank, 0, 0, 1, _tdm_hwc_cb_wait_vblank, hwc_commit_handler);
308 _pthread_mutex_lock(&private_display->lock);
309 if (ret != TDM_ERROR_NONE) {
310 if (!TDM_OUTPUT_DPMS_VSYNC_IS_OFF(private_output->current_dpms_value)) {
311 private_output->layer_waiting_vblank = 0;
322 tdm_hwc_init(tdm_private_display *private_display)
324 tdm_thread_cb_set_find_func(TDM_THREAD_CB_HWC_COMMIT, tdm_display_find_hwc_stamp);
326 return TDM_ERROR_NONE;
330 tdm_hwc_set_vblank(unsigned int fps)
333 hwc_vblank_fps = fps;
337 tdm_hwc_unset_vblank(void)
343 EXTERN tdm_hwc_window *
344 tdm_hwc_create_window(tdm_hwc *hwc, tdm_error *error)
346 tdm_hwc_window *hwc_window = NULL;
348 HWC_FUNC_ENTRY_ERROR();
350 _pthread_mutex_lock(&private_display->lock);
352 hwc_window = (tdm_hwc_window *)tdm_hwc_window_create_internal(private_hwc, error);
354 _pthread_mutex_unlock(&private_display->lock);
360 tdm_hwc_get_video_supported_formats(tdm_hwc *hwc, const tbm_format **formats, int *count)
362 tdm_private_module *private_module;
363 tdm_func_hwc *func_hwc;
367 TDM_RETURN_VAL_IF_FAIL(formats != NULL, TDM_ERROR_INVALID_PARAMETER);
368 TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
370 _pthread_mutex_lock(&private_display->lock);
372 private_module = private_output->private_module;
373 func_hwc = &private_module->func_hwc;
375 if (private_module->use_hal_tdm) {
376 ret = (tdm_error)hal_tdm_hwc_get_video_supported_formats((hal_tdm_hwc *)private_hwc->hwc_backend, formats, count);
378 if (!func_hwc->hwc_get_video_supported_formats) {
379 /* LCOV_EXCL_START */
380 _pthread_mutex_unlock(&private_display->lock);
381 TDM_WRN("not implemented!!");
382 return TDM_ERROR_NOT_IMPLEMENTED;
386 ret = func_hwc->hwc_get_video_supported_formats(private_hwc->hwc_backend, formats, count);
388 _pthread_mutex_unlock(&private_display->lock);
394 tdm_hwc_get_video_available_properties(tdm_hwc *hwc, const tdm_prop **props, int *count)
396 tdm_private_module *private_module;
397 tdm_func_hwc *func_hwc = NULL;
401 TDM_RETURN_VAL_IF_FAIL(props != NULL, TDM_ERROR_INVALID_PARAMETER);
402 TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
404 _pthread_mutex_lock(&private_display->lock);
406 private_module = private_output->private_module;
407 func_hwc = &private_module->func_hwc;
409 if (private_module->use_hal_tdm) {
410 ret = (tdm_error)hal_tdm_hwc_get_video_available_properties((hal_tdm_hwc *)private_hwc->hwc_backend,
411 (const hal_tdm_prop **)props, count);
413 if (!func_hwc->hwc_get_video_available_properties) {
414 /* LCOV_EXCL_START */
415 _pthread_mutex_unlock(&private_display->lock);
416 TDM_WRN("not implemented!!");
417 return TDM_ERROR_NOT_IMPLEMENTED;
421 ret = func_hwc->hwc_get_video_available_properties(private_hwc->hwc_backend, props, count);
423 _pthread_mutex_unlock(&private_display->lock);
429 tdm_hwc_get_capabilities(tdm_hwc *hwc, tdm_hwc_capability *capabilities)
431 tdm_private_module *private_module;
432 tdm_func_hwc *func_hwc;
436 _pthread_mutex_lock(&private_display->lock);
438 private_module = private_output->private_module;
439 func_hwc = &private_module->func_hwc;
441 if (private_module->use_hal_tdm) {
442 ret = (tdm_error)hal_tdm_hwc_get_capabilities((hal_tdm_hwc *)private_hwc->hwc_backend, (hal_tdm_hwc_capability *)capabilities);
444 if (!func_hwc->hwc_get_capabilities) {
445 _pthread_mutex_unlock(&private_display->lock);
446 TDM_WRN("not implemented!!");
447 return TDM_ERROR_NOT_IMPLEMENTED;
450 ret = func_hwc->hwc_get_capabilities(private_hwc->hwc_backend, capabilities);
452 _pthread_mutex_unlock(&private_display->lock);
458 tdm_hwc_get_available_properties(tdm_hwc *hwc, const tdm_prop **props, int *count)
460 tdm_private_module *private_module;
461 tdm_func_hwc *func_hwc = NULL;
465 TDM_RETURN_VAL_IF_FAIL(props != NULL, TDM_ERROR_INVALID_PARAMETER);
466 TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
468 _pthread_mutex_lock(&private_display->lock);
470 private_module = private_output->private_module;
471 func_hwc = &private_module->func_hwc;
473 if (private_module->use_hal_tdm) {
474 ret = (tdm_error)hal_tdm_hwc_get_available_properties((hal_tdm_hwc *)private_hwc->hwc_backend, (const hal_tdm_prop **)props, count);
476 if (!func_hwc->hwc_get_available_properties) {
477 /* LCOV_EXCL_START */
478 _pthread_mutex_unlock(&private_display->lock);
479 TDM_WRN("not implemented!!");
480 return TDM_ERROR_NOT_IMPLEMENTED;
484 ret = func_hwc->hwc_get_available_properties(private_hwc->hwc_backend, props, count);
486 _pthread_mutex_unlock(&private_display->lock);
491 EXTERN tbm_surface_queue_h
492 tdm_hwc_get_client_target_buffer_queue(tdm_hwc *hwc, tdm_error *error)
494 tdm_private_module *private_module;
495 tdm_func_hwc *func_hwc = NULL;
496 tbm_surface_queue_h queue = NULL;
498 HWC_FUNC_ENTRY_ERROR();
500 _pthread_mutex_lock(&private_display->lock);
502 private_module = private_hwc->private_module;
503 func_hwc = &private_module->func_hwc;
505 if (private_module->use_hal_tdm) {
506 queue = hal_tdm_hwc_get_client_target_buffer_queue((hal_tdm_hwc *)private_hwc->hwc_backend, (hal_tdm_error *)error);
508 if (!func_hwc->hwc_get_client_target_buffer_queue) {
509 /* LCOV_EXCL_START */
510 _pthread_mutex_unlock(&private_display->lock);
511 TDM_WRN("not implemented!!");
516 queue = func_hwc->hwc_get_client_target_buffer_queue(private_hwc->hwc_backend, error);
518 _pthread_mutex_unlock(&private_display->lock);
524 tdm_hwc_set_client_target_buffer_info(tdm_hwc *hwc, tdm_hwc_window_info *info)
526 tdm_private_module *private_module;
527 tdm_func_hwc *func_hwc = NULL;
531 _pthread_mutex_lock(&private_display->lock);
533 private_module = private_hwc->private_module;
534 func_hwc = &private_module->func_hwc;
536 if (private_module->use_hal_tdm) {
537 ret = (tdm_error)hal_tdm_hwc_set_client_target_buffer_info((hal_tdm_hwc *)private_hwc->hwc_backend, (hal_tdm_hwc_window_info *)info);
539 if (!func_hwc->hwc_set_client_target_buffer_info) {
540 /* LCOV_EXCL_START */
541 _pthread_mutex_unlock(&private_display->lock);
542 return TDM_ERROR_NOT_IMPLEMENTED;
546 ret = func_hwc->hwc_set_client_target_buffer_info(private_hwc->hwc_backend, info);
549 _pthread_mutex_unlock(&private_display->lock);
555 tdm_hwc_set_client_target_buffer(tdm_hwc *hwc, tbm_surface_h target_buffer, tdm_region damage)
557 tdm_private_module *private_module;
558 tdm_func_hwc *func_hwc = NULL;
562 _pthread_mutex_lock(&private_display->lock);
564 if (tdm_debug_dump & TDM_DUMP_FLAG_WINDOW) {
565 /* LCOV_EXCL_START */
566 char str[TDM_PATH_LEN];
568 snprintf(str, TDM_PATH_LEN, "target_window_%03d", i++);
569 tdm_helper_dump_buffer_str(target_buffer, tdm_debug_dump_dir, str);
573 private_module = private_hwc->private_module;
574 func_hwc = &private_module->func_hwc;
576 if (private_module->use_hal_tdm) {
577 hal_tdm_region hdamage;
578 memcpy(&hdamage, &damage, sizeof(hal_tdm_region));
579 ret = (tdm_error)hal_tdm_hwc_set_client_target_buffer((hal_tdm_hwc *)private_hwc->hwc_backend, target_buffer, hdamage);
581 if (!func_hwc->hwc_set_client_target_buffer) {
582 /* LCOV_EXCL_START */
583 _pthread_mutex_unlock(&private_display->lock);
584 TDM_WRN("not implemented!!");
585 return TDM_ERROR_NOT_IMPLEMENTED;
589 ret = func_hwc->hwc_set_client_target_buffer(private_hwc->hwc_backend, target_buffer, damage);
591 if (private_hwc->display_target_buffer) {
592 if (private_hwc->display_target_buffer != target_buffer) {
593 tbm_surface_internal_unref(private_hwc->display_target_buffer);
594 private_hwc->display_target_buffer = target_buffer;
596 tbm_surface_internal_ref(private_hwc->display_target_buffer);
600 private_hwc->display_target_buffer = target_buffer;
601 tbm_surface_internal_ref(private_hwc->display_target_buffer);
605 _pthread_mutex_unlock(&private_display->lock);
611 tdm_hwc_set_client_target_acquire_fence(tdm_hwc *hwc, int acquire_fence)
613 tdm_private_module *private_module;
614 tdm_func_hwc *func_hwc = NULL;
618 _pthread_mutex_lock(&private_display->lock);
620 private_module = private_hwc->private_module;
621 func_hwc = &private_module->func_hwc;
623 if (private_module->use_hal_tdm) {
624 ret = (tdm_error)hal_tdm_hwc_set_client_target_acquire_fence((hal_tdm_hwc *)private_hwc->hwc_backend, acquire_fence);
626 if (!func_hwc->hwc_set_client_target_acquire_fence) {
627 /* LCOV_EXCL_START */
628 _pthread_mutex_unlock(&private_display->lock);
629 TDM_WRN("not implemented!!");
630 return TDM_ERROR_NOT_IMPLEMENTED;
634 ret = func_hwc->hwc_set_client_target_acquire_fence(private_hwc->hwc_backend, acquire_fence);
636 _pthread_mutex_unlock(&private_display->lock);
642 tdm_hwc_validate(tdm_hwc *hwc, tdm_hwc_window **composited_wnds, uint32_t num_wnds, uint32_t *num_types)
644 tdm_private_module *private_module;
645 tdm_func_hwc *func_hwc = NULL;
646 tdm_private_hwc_window **composited_wnds_frontend = NULL;
647 tdm_hwc_window **composited_wnds_backend = NULL;
652 TDM_RETURN_VAL_IF_FAIL(num_types != NULL, TDM_ERROR_INVALID_PARAMETER);
654 _pthread_mutex_lock(&private_display->lock);
656 private_module = private_hwc->private_module;
657 func_hwc = &private_module->func_hwc;
659 if (private_module->use_hal_tdm) {
661 ret = (tdm_error)hal_tdm_hwc_validate((hal_tdm_hwc *)private_hwc->hwc_backend, NULL, 0, num_types);
663 _pthread_mutex_unlock(&private_display->lock);
667 if (!func_hwc->hwc_validate) {
668 /* LCOV_EXCL_START */
669 _pthread_mutex_unlock(&private_display->lock);
670 TDM_WRN("not implemented!!");
671 return TDM_ERROR_NOT_IMPLEMENTED;
676 ret = func_hwc->hwc_validate(private_hwc->hwc_backend, NULL, 0, num_types);
678 _pthread_mutex_unlock(&private_display->lock);
682 composited_wnds_backend = calloc(num_wnds, sizeof(tdm_hwc_window *));
683 if (!composited_wnds_backend) {
684 /* LCOV_EXCL_START */
685 _pthread_mutex_unlock(&private_display->lock);
686 return TDM_ERROR_OUT_OF_MEMORY;
690 composited_wnds_frontend = (tdm_private_hwc_window **)composited_wnds;
692 for (i = 0; i < num_wnds; i++)
693 composited_wnds_backend[i] = composited_wnds_frontend[i]->hwc_window_backend;
695 if (private_module->use_hal_tdm)
696 ret = (tdm_error)hal_tdm_hwc_validate((hal_tdm_hwc *)private_hwc->hwc_backend, (hal_tdm_hwc_window **)composited_wnds_backend,
697 num_wnds, num_types);
699 ret = func_hwc->hwc_validate(private_hwc->hwc_backend, composited_wnds_backend,
700 num_wnds, num_types);
702 free(composited_wnds_backend);
704 _pthread_mutex_unlock(&private_display->lock);
710 tdm_hwc_get_changed_composition_types(tdm_hwc *hwc, uint32_t *num_elements,
711 tdm_hwc_window **hwc_window,
712 tdm_hwc_window_composition *composition_types)
714 tdm_private_module *private_module;
715 tdm_func_hwc *func_hwc = NULL;
716 tdm_private_hwc_window * private_hwc_window = NULL;
721 TDM_RETURN_VAL_IF_FAIL(num_elements != NULL, TDM_ERROR_INVALID_PARAMETER);
723 _pthread_mutex_lock(&private_display->lock);
725 private_module = private_hwc->private_module;
726 func_hwc = &private_module->func_hwc;
728 if (private_module->use_hal_tdm) {
729 ret = (tdm_error)hal_tdm_hwc_get_changed_composition_types((hal_tdm_hwc *)private_hwc->hwc_backend, num_elements,
730 (hal_tdm_hwc_window **)hwc_window,
731 (hal_tdm_hwc_window_composition *)composition_types);
733 if (!func_hwc->hwc_get_changed_composition_types) {
734 /* LCOV_EXCL_START */
735 _pthread_mutex_unlock(&private_display->lock);
736 TDM_WRN("not implemented!!");
737 return TDM_ERROR_NOT_IMPLEMENTED;
741 ret = func_hwc->hwc_get_changed_composition_types(private_hwc->hwc_backend,
742 num_elements, hwc_window, composition_types);
744 if (ret != TDM_ERROR_NONE) {
745 /* LCOV_EXCL_START */
746 _pthread_mutex_unlock(&private_display->lock);
751 if (hwc_window == NULL || composition_types == NULL) {
752 _pthread_mutex_unlock(&private_display->lock);
753 return TDM_ERROR_NONE;
756 for (i = 0; i < *num_elements; i++) {
757 private_hwc_window = _tdm_hwc_find_private_hwc_window(private_hwc, hwc_window[i]);
758 if (private_hwc_window == NULL) {
759 /* LCOV_EXCL_START */
760 TDM_ERR("failed! This should never happen!");
761 tdm_hwc_window_destroy_internal(private_hwc_window);
763 _pthread_mutex_unlock(&private_display->lock);
764 return TDM_ERROR_OPERATION_FAILED;
768 hwc_window[i] = (tdm_hwc_window*)private_hwc_window;
771 _pthread_mutex_unlock(&private_display->lock);
777 tdm_hwc_accept_validation(tdm_hwc *hwc)
779 tdm_private_module *private_module;
780 tdm_func_hwc *func_hwc = NULL;
784 _pthread_mutex_lock(&private_display->lock);
786 private_module = private_hwc->private_module;
787 func_hwc = &private_module->func_hwc;
789 if (private_module->use_hal_tdm) {
790 ret = (tdm_error)hal_tdm_hwc_accept_validation((hal_tdm_hwc *)private_hwc->hwc_backend);
792 if (!func_hwc->hwc_validate) {
793 /* LCOV_EXCL_START */
794 _pthread_mutex_unlock(&private_display->lock);
795 TDM_WRN("not implemented!!");
796 return TDM_ERROR_NOT_IMPLEMENTED;
800 ret = func_hwc->hwc_accept_validation(private_hwc->hwc_backend);
802 _pthread_mutex_unlock(&private_display->lock);
808 tdm_hwc_commit(tdm_hwc *hwc, int sync, tdm_hwc_commit_handler func, void *user_data)
810 tdm_private_module *private_module;
811 tdm_func_hwc *func_hwc = NULL;
812 tdm_private_hwc_commit_handler *hwc_commit_handler = NULL;
813 tdm_private_voutput *private_voutput = NULL;
814 tdm_private_voutput_commit_handler *voutput_commit_handler = NULL;
818 _pthread_mutex_lock(&private_display->lock);
820 private_module = private_hwc->private_module;
821 func_hwc = &private_module->func_hwc;
823 if (!private_module->use_hal_tdm) {
824 if (!func_hwc->hwc_commit) {
825 /* LCOV_EXCL_START */
826 TDM_WRN("not implemented!!");
827 _pthread_mutex_unlock(&private_display->lock);
828 return TDM_ERROR_NOT_IMPLEMENTED;
833 //TODO: I am not sure yet whether we have to check the dpms at hwc_commit.
835 /* check if the dpms is off */
836 if (TDM_OUTPUT_DPMS_VSYNC_IS_OFF(private_output->current_dpms_value)) {
837 TDM_ERR("hwc(%d) dpms: %s", private_hwc->index,
838 tdm_dpms_str(private_output->current_dpms_value));
839 _pthread_mutex_unlock(&private_display->lock);
840 return TDM_ERROR_DPMS_OFF;
844 if (tdm_debug_module & TDM_DEBUG_COMMIT)
845 TDM_INFO("hwc(%d) commit", private_hwc->index);
847 if (private_module == private_display->virtual_module) {
848 if (!private_output->private_voutput) {
849 TDM_ERR("virtual module but don't have voutput");
850 _pthread_mutex_unlock(&private_display->lock);
851 return TDM_ERROR_BAD_MODULE;
855 if (!private_hwc->regist_commit_cb) {
856 private_hwc->regist_commit_cb = 1;
857 if (private_module->use_hal_tdm)
858 ret = (tdm_error)hal_tdm_hwc_set_commit_handler((hal_tdm_hwc *)private_hwc->hwc_backend, _tdm_hwc_cb_commit_hal_tdm);
860 ret = func_hwc->hwc_set_commit_handler(private_hwc->hwc_backend, _tdm_hwc_cb_commit);
861 /* LCOV_EXCL_START */
862 if (ret != TDM_ERROR_NONE) {
863 private_hwc->regist_commit_cb = 0;
864 TDM_ERR("hwc(%d) fail to set hwc_set_commit_handler", private_hwc->index);
865 _pthread_mutex_unlock(&private_display->lock);
871 hwc_commit_handler = calloc(1, sizeof(tdm_private_hwc_commit_handler));
872 if (!hwc_commit_handler) {
873 /* LCOV_EXCL_START */
874 TDM_ERR("failed: alloc memory");
875 _pthread_mutex_unlock(&private_display->lock);
876 return TDM_ERROR_OUT_OF_MEMORY;
880 ret = tdm_thread_cb_add(private_hwc, TDM_THREAD_CB_HWC_COMMIT, hwc_commit_handler,
881 _tdm_hwc_thread_cb_commit, NULL);
882 if (ret != TDM_ERROR_NONE) {
883 TDM_ERR("tdm_thread_cb_add failed");
884 free(hwc_commit_handler);
885 _pthread_mutex_unlock(&private_display->lock);
889 LIST_ADDTAIL(&hwc_commit_handler->link, &private_hwc->hwc_commit_handler_list);
890 hwc_commit_handler->private_hwc = private_hwc;
891 hwc_commit_handler->func = func;
892 hwc_commit_handler->user_data = user_data;
893 hwc_commit_handler->owner_tid = syscall(SYS_gettid);
895 hwc_commit_handler->use_vblank = 1;
897 if (private_module == private_display->virtual_module) {
898 private_voutput = private_output->private_voutput;
900 if (LIST_LENGTH(&private_voutput->voutput_commit_handler_list) != 0) {
901 voutput_commit_handler = LIST_FIRST_ENTRY(&private_voutput->voutput_commit_handler_list, tdm_private_voutput_commit_handler, link);
902 voutput_commit_handler->user_data = private_hwc->display_target_buffer;
906 if (private_module->use_hal_tdm)
907 ret = (tdm_error)hal_tdm_hwc_commit((hal_tdm_hwc *)private_hwc->hwc_backend, sync, hwc_commit_handler);
909 ret = func_hwc->hwc_commit(private_hwc->hwc_backend, sync, hwc_commit_handler);
910 TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, commit_failed);
912 if (hwc_use_vblank) {
913 /* LCOV_EXCL_START */
914 ret = _tdm_hwc_vblank(private_hwc, hwc_commit_handler);
915 if (ret == TDM_ERROR_NONE) {
916 if (tdm_debug_module & TDM_DEBUG_COMMIT)
917 TDM_INFO("hwc(%d) backend commit: wait vblank handle(%p) func(%p) user_data(%p)",
918 private_hwc->index, hwc_commit_handler, func, user_data);
923 if (tdm_debug_module & TDM_DEBUG_COMMIT)
924 TDM_INFO("hwc(%d) backend commit: handle(%p) func(%p) user_data(%p)",
925 private_hwc->index, hwc_commit_handler, func, user_data);
928 _pthread_mutex_unlock(&private_display->lock);
933 /* LCOV_EXCL_START */
934 if (hwc_commit_handler) {
935 tdm_thread_cb_remove(private_hwc, TDM_THREAD_CB_HWC_COMMIT, hwc_commit_handler,
936 _tdm_hwc_thread_cb_commit, NULL);
937 LIST_DEL(&hwc_commit_handler->link);
938 free(hwc_commit_handler);
941 _pthread_mutex_unlock(&private_display->lock);
948 tdm_hwc_get_commit_fence(tdm_hwc *hwc, int *commit_fence)
950 tdm_private_module *private_module;
951 tdm_func_hwc *func_hwc = NULL;
955 _pthread_mutex_lock(&private_display->lock);
957 private_module = private_hwc->private_module;
958 func_hwc = &private_module->func_hwc;
960 if (private_module->use_hal_tdm) {
961 ret = (tdm_error)hal_tdm_hwc_get_commit_fence((hal_tdm_hwc *)private_hwc->hwc_backend, commit_fence);
963 if (!func_hwc->hwc_get_commit_fence) {
964 /* LCOV_EXCL_START */
965 _pthread_mutex_unlock(&private_display->lock);
966 TDM_WRN("not implemented!!");
967 return TDM_ERROR_NOT_IMPLEMENTED;
971 ret = func_hwc->hwc_get_commit_fence(private_hwc->hwc_backend, commit_fence);
973 _pthread_mutex_unlock(&private_display->lock);
979 tdm_hwc_get_release_fences(tdm_hwc *hwc, uint32_t *num_elements,
980 tdm_hwc_window **hwc_windows, int *fences)
982 tdm_private_module *private_module;
983 tdm_func_hwc *func_hwc = NULL;
984 tdm_private_hwc_window *private_hwc_window = NULL;
989 _pthread_mutex_lock(&private_display->lock);
991 private_module = private_hwc->private_module;
992 func_hwc = &private_module->func_hwc;
994 if (private_module->use_hal_tdm) {
995 ret = (tdm_error)hal_tdm_hwc_get_release_fences((hal_tdm_hwc *)private_hwc->hwc_backend, num_elements,
996 (hal_tdm_hwc_window **)hwc_windows, fences);
998 if (!func_hwc->hwc_get_release_fences) {
999 /* LCOV_EXCL_START */
1000 _pthread_mutex_unlock(&private_display->lock);
1001 TDM_WRN("not implemented!!");
1002 return TDM_ERROR_NOT_IMPLEMENTED;
1003 /* LCOV_EXCL_STOP */
1006 ret = func_hwc->hwc_get_release_fences(private_hwc->hwc_backend, num_elements,
1007 hwc_windows, fences);
1009 if (hwc_windows == NULL || fences == NULL) {
1010 _pthread_mutex_unlock(&private_display->lock);
1011 return TDM_ERROR_NONE;
1014 for (i = 0; i < *num_elements; i++) {
1015 private_hwc_window = _tdm_hwc_find_private_hwc_window(private_hwc, hwc_windows[i]);
1016 if (private_hwc_window == NULL) {
1017 /* LCOV_EXCL_START */
1018 TDM_ERR("failed! This should never happen!");
1019 tdm_hwc_window_destroy_internal(private_hwc_window);
1021 _pthread_mutex_unlock(&private_display->lock);
1022 return TDM_ERROR_OPERATION_FAILED;
1023 /* LCOV_EXCL_STOP */
1026 hwc_windows[i] = (tdm_hwc_window*)private_hwc_window;
1029 _pthread_mutex_unlock(&private_display->lock);
1035 tdm_hwc_set_property(tdm_hwc *hwc, uint32_t id, tdm_value value)
1037 tdm_private_module *private_module;
1038 tdm_func_hwc *func_hwc = NULL;
1042 _pthread_mutex_lock(&private_display->lock);
1044 private_module = private_hwc->private_module;
1045 func_hwc = &private_module->func_hwc;
1047 if (private_module->use_hal_tdm) {
1048 hal_tdm_value hvalue;
1049 memcpy(&hvalue.ptr, &value.ptr, sizeof(hal_tdm_value));
1050 ret = (tdm_error)hal_tdm_hwc_set_property((hal_tdm_hwc *)private_hwc->hwc_backend, id, hvalue);
1052 if (!func_hwc->hwc_set_property) {
1053 /* LCOV_EXCL_START */
1054 _pthread_mutex_unlock(&private_display->lock);
1055 TDM_WRN("not implemented!!");
1056 return TDM_ERROR_NOT_IMPLEMENTED;
1057 /* LCOV_EXCL_STOP */
1060 ret = func_hwc->hwc_set_property(private_hwc->hwc_backend, id, value);
1062 _pthread_mutex_unlock(&private_display->lock);
1068 tdm_hwc_get_property(tdm_hwc *hwc, uint32_t id, tdm_value *value)
1070 tdm_private_module *private_module;
1071 tdm_func_hwc *func_hwc = NULL;
1075 _pthread_mutex_lock(&private_display->lock);
1077 private_module = private_hwc->private_module;
1078 func_hwc = &private_module->func_hwc;
1080 if (private_module->use_hal_tdm) {
1081 hal_tdm_value hvalue;
1082 ret = (tdm_error)hal_tdm_hwc_get_property((hal_tdm_hwc *)private_hwc->hwc_backend, id, &hvalue);
1083 if (ret == TDM_ERROR_NONE)
1084 memcpy(&value->ptr, &hvalue.ptr, sizeof(tdm_value));
1086 if (!func_hwc->hwc_get_property) {
1087 /* LCOV_EXCL_START */
1088 _pthread_mutex_unlock(&private_display->lock);
1089 TDM_WRN("not implemented!!");
1090 return TDM_ERROR_NOT_IMPLEMENTED;
1091 /* LCOV_EXCL_STOP */
1094 ret = func_hwc->hwc_get_property(private_hwc->hwc_backend, id, value);
1096 _pthread_mutex_unlock(&private_display->lock);
1102 tdm_hwc_get_commit_interval(tdm_hwc *hwc, tdm_hwc_commit_interval *refresh)
1104 tdm_private_module *private_module;
1105 tdm_func_hwc *func_hwc = NULL;
1109 _pthread_mutex_lock(&private_display->lock);
1111 private_module = private_hwc->private_module;
1112 func_hwc = &private_module->func_hwc;
1114 if (private_module->use_hal_tdm) {
1115 ret = (tdm_error)hal_tdm_hwc_get_commit_interval((hal_tdm_hwc *)private_hwc->hwc_backend, (hal_tdm_hwc_commit_interval *)refresh);
1117 /* LCOV_EXCL_START */
1118 if (!func_hwc->hwc_get_commit_interval) {
1119 _pthread_mutex_unlock(&private_display->lock);
1120 return TDM_ERROR_NOT_IMPLEMENTED;
1123 ret = func_hwc->hwc_get_commit_interval(private_hwc->hwc_backend, refresh);
1124 /* LCOV_EXCL_STOP */
1126 _pthread_mutex_unlock(&private_display->lock);