X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Ftdm_hwc.c;h=9238b29c5aade1fa1e3a233ec446571cb77335dc;hb=refs%2Fheads%2Fsandbox%2Fcyeon%2Fdevel;hp=bd7428c438cb08671a7093be3249aa11c40ed3d1;hpb=111235f88e860ec2b11d876ee185dfedf117c4b2;p=platform%2Fcore%2Fuifw%2Flibtdm.git diff --git a/src/tdm_hwc.c b/src/tdm_hwc.c index bd7428c..9238b29 100644 --- a/src/tdm_hwc.c +++ b/src/tdm_hwc.c @@ -70,6 +70,8 @@ TDM_RETURN_IF_FAIL(private_output != NULL); \ private_display = private_output->private_display +static int hwc_use_vblank; +static unsigned int hwc_vblank_fps; static tdm_private_hwc_window * _tdm_hwc_find_private_hwc_window(tdm_private_hwc *private_hwc, tdm_hwc_window *hwc_window_backend) @@ -84,6 +86,22 @@ _tdm_hwc_find_private_hwc_window(tdm_private_hwc *private_hwc, tdm_hwc_window *h return NULL; } +static tdm_error +_tdm_hwc_check_hwc_commit_handler_validation(tdm_private_hwc *private_hwc, tdm_private_hwc_commit_handler *hwc_commit_handler) +{ + tdm_private_hwc_commit_handler *commit_handler = NULL; + + if (LIST_IS_EMPTY(&private_hwc->hwc_commit_handler_list)) + return TDM_ERROR_INVALID_PARAMETER; + + LIST_FOR_EACH_ENTRY(commit_handler, &private_hwc->hwc_commit_handler_list, link) { + if (commit_handler == hwc_commit_handler) + return TDM_ERROR_NONE; + } + + return TDM_ERROR_INVALID_PARAMETER; +} + static void _tdm_hwc_thread_cb_commit(tdm_private_display *private_display, void *object, tdm_thread_cb_base *cb_base, void *user_data) @@ -102,6 +120,8 @@ _tdm_hwc_thread_cb_commit(tdm_private_display *private_display, void *object, tdm_thread_cb_remove(private_hwc, TDM_THREAD_CB_HWC_COMMIT, hwc_commit_handler, _tdm_hwc_thread_cb_commit, NULL); + TDM_RETURN_IF_FAIL(_tdm_hwc_check_hwc_commit_handler_validation(private_hwc, hwc_commit_handler) == TDM_ERROR_NONE) + LIST_DEL(&hwc_commit_handler->link); if (tdm_debug_module & TDM_DEBUG_COMMIT) { @@ -109,6 +129,24 @@ _tdm_hwc_thread_cb_commit(tdm_private_display *private_display, void *object, TDM_INFO("handler(%p)", hwc_commit_handler); } + /* LCOV_EXCL_START */ + if (private_display->print_fps) { + double curr = tdm_helper_get_time(); + if (private_hwc->fps_stamp == 0) { + private_hwc->fps_stamp = curr; + } else if ((curr - private_hwc->fps_stamp) > 1.0) { + TDM_INFO("hwc(%p,%d) fps: %d", + private_hwc, private_hwc->index, private_hwc->fps_count); + private_hwc->fps_count = 0; + private_hwc->fps_stamp = curr; + } else + private_hwc->fps_count++; + } else if (private_hwc->fps_stamp != 0) { + private_hwc->fps_stamp = 0; + private_hwc->fps_count = 0; + } + /* LCOV_EXCL_STOP */ + if (hwc_commit_handler->func) { _pthread_mutex_unlock(&private_display->lock); hwc_commit_handler->func(private_hwc, @@ -134,6 +172,9 @@ _tdm_hwc_cb_commit(tdm_hwc *hwc_backend, unsigned int sequence, tdm_thread_cb_hwc_commit hwc_commit; tdm_error ret; + if (hwc_commit_handler && hwc_commit_handler->use_vblank) + return; + if (hwc_commit_handler) private_hwc = hwc_commit_handler->private_hwc; else @@ -153,6 +194,99 @@ _tdm_hwc_cb_commit(tdm_hwc *hwc_backend, unsigned int sequence, TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE); } +static void +_tdm_hwc_got_wait_vblank(unsigned int sequence, + unsigned int tv_sec, unsigned int tv_usec, void *user_data) +{ + tdm_private_hwc_commit_handler *hwc_commit_handler = user_data; + tdm_private_hwc *private_hwc; + tdm_thread_cb_hwc_commit hwc_commit; + + private_hwc = hwc_commit_handler->private_hwc; + private_hwc->private_output->layer_waiting_vblank = 0; + + memset(&hwc_commit, 0, sizeof hwc_commit); + hwc_commit.base.type = TDM_THREAD_CB_HWC_COMMIT; + hwc_commit.base.length = sizeof hwc_commit; + hwc_commit.base.object_stamp = private_hwc->stamp; + hwc_commit.base.data = hwc_commit_handler; + hwc_commit.base.sync = 0; + hwc_commit.sequence = sequence; + hwc_commit.tv_sec = tv_sec; + hwc_commit.tv_usec = tv_usec; + + _tdm_hwc_thread_cb_commit(private_hwc->private_output->private_display, private_hwc, &hwc_commit.base, user_data); +} + +static void +_tdm_hwc_cb_wait_vblank(tdm_vblank *vblank, tdm_error error, unsigned int sequence, + unsigned int tv_sec, unsigned int tv_usec, void *user_data) +{ + tdm_private_hwc_commit_handler *hwc_commit_handler = user_data; + tdm_private_output *private_output = NULL; + tdm_private_display *private_display; + + if (!hwc_commit_handler->use_vblank) + return; + + TDM_RETURN_IF_FAIL(hwc_commit_handler != NULL); + TDM_RETURN_IF_FAIL(hwc_commit_handler->private_hwc != NULL); + + private_output = hwc_commit_handler->private_hwc->private_output; + TDM_RETURN_IF_FAIL(private_output != NULL); + + private_display = private_output->private_display; + + _pthread_mutex_lock(&private_display->lock); + + _tdm_hwc_got_wait_vblank(sequence, tv_sec, tv_usec, user_data); + + _pthread_mutex_unlock(&private_display->lock); +} + +static tdm_error +_tdm_hwc_vblank(tdm_private_hwc *private_hwc, tdm_private_hwc_commit_handler *hwc_commit_handler) +{ + tdm_private_display *private_display; + tdm_private_output *private_output; + tdm_error ret = TDM_ERROR_NONE; + + private_output = private_hwc->private_output; + TDM_RETURN_VAL_IF_FAIL(private_output != NULL, TDM_ERROR_INVALID_PARAMETER); + private_display = private_output->private_display; + + if (!private_output->vblank) { + /* tdm_vblank APIs is for server. it should be called in unlock status*/ + _pthread_mutex_unlock(&private_display->lock); + private_output->vblank = tdm_vblank_create(private_display, private_output, NULL); + _pthread_mutex_lock(&private_display->lock); + TDM_RETURN_VAL_IF_FAIL(private_output->vblank != NULL, TDM_ERROR_OPERATION_FAILED); + } + + if (!private_output->layer_waiting_vblank) { + ret = tdm_vblank_set_fps(private_output->vblank, hwc_vblank_fps); + if (ret != TDM_ERROR_NONE) + goto done; + + hwc_commit_handler->use_vblank = 1; + private_output->layer_waiting_vblank = 1; + + /* tdm_vblank APIs is for server. it should be called in unlock status*/ + _pthread_mutex_unlock(&private_display->lock); + ret = tdm_vblank_wait(private_output->vblank, 0, 0, 1, _tdm_hwc_cb_wait_vblank, hwc_commit_handler); + _pthread_mutex_lock(&private_display->lock); + if (ret != TDM_ERROR_NONE) { + if (!TDM_OUTPUT_DPMS_VSYNC_IS_OFF(private_output->current_dpms_value)) { + hwc_commit_handler->use_vblank = 0; + private_output->layer_waiting_vblank = 0; + } + } + } + +done: + return ret; +} + INTERN tdm_error tdm_hwc_init(tdm_private_display *private_display) { @@ -161,6 +295,20 @@ tdm_hwc_init(tdm_private_display *private_display) return TDM_ERROR_NONE; } +INTERN void +tdm_hwc_set_vblank(unsigned int fps) +{ + hwc_use_vblank = 1; + hwc_vblank_fps = fps; +} + +INTERN void +tdm_hwc_unset_vblank(void) +{ + hwc_use_vblank = 0; + hwc_vblank_fps = 0; +} + EXTERN tdm_hwc_window * tdm_hwc_create_window(tdm_hwc *hwc, tdm_error *error) { @@ -240,8 +388,7 @@ tdm_hwc_get_video_available_properties(tdm_hwc *hwc, const tdm_prop **props, int } EXTERN tdm_error -tdm_hwc_get_video_capability(tdm_hwc *hwc, - tdm_hwc_video_capability *video_capability) +tdm_hwc_get_capabilities(tdm_hwc *hwc, tdm_hwc_capability *capabilities) { tdm_private_module *private_module; tdm_func_hwc *func_hwc; @@ -253,14 +400,13 @@ tdm_hwc_get_video_capability(tdm_hwc *hwc, private_module = private_output->private_module; func_hwc = &private_module->func_hwc; - if (!func_hwc->hwc_get_video_capability) { + if (!func_hwc->hwc_get_capabilities) { _pthread_mutex_unlock(&private_display->lock); TDM_WRN("not implemented!!"); return TDM_ERROR_NOT_IMPLEMENTED; } - ret = func_hwc->hwc_get_video_capability(private_hwc->hwc_backend, - video_capability); + ret = func_hwc->hwc_get_capabilities(private_hwc->hwc_backend, capabilities); _pthread_mutex_unlock(&private_display->lock); @@ -359,11 +505,52 @@ tdm_hwc_set_client_target_buffer(tdm_hwc *hwc, tbm_surface_h target_buffer, tdm_ ret = func_hwc->hwc_set_client_target_buffer(private_hwc->hwc_backend, target_buffer, damage); + if (private_hwc->display_target_buffer) { + if (private_hwc->display_target_buffer != target_buffer) { + tbm_surface_internal_unref(private_hwc->display_target_buffer); + private_hwc->display_target_buffer = target_buffer; + if (target_buffer) + tbm_surface_internal_ref(private_hwc->display_target_buffer); + } + } else { + if (target_buffer) { + private_hwc->display_target_buffer = target_buffer; + tbm_surface_internal_ref(private_hwc->display_target_buffer); + } + } + _pthread_mutex_unlock(&private_display->lock); return ret; } +EXTERN tdm_error +tdm_hwc_set_client_target_acquire_fence(tdm_hwc *hwc, int acquire_fence) +{ + tdm_private_module *private_module; + tdm_func_hwc *func_hwc = NULL; + + HWC_FUNC_ENTRY(); + + _pthread_mutex_lock(&private_display->lock); + + private_module = private_hwc->private_module; + func_hwc = &private_module->func_hwc; + + if (!func_hwc->hwc_set_client_target_acquire_fence) { + /* LCOV_EXCL_START */ + _pthread_mutex_unlock(&private_display->lock); + TDM_WRN("not implemented!!"); + return TDM_ERROR_NOT_IMPLEMENTED; + /* LCOV_EXCL_STOP */ + } + + ret = func_hwc->hwc_set_client_target_acquire_fence(private_hwc->hwc_backend, acquire_fence); + + _pthread_mutex_unlock(&private_display->lock); + + return ret; +} EXTERN tdm_error tdm_hwc_validate(tdm_hwc *hwc, tdm_hwc_window **composited_wnds, uint32_t num_wnds, uint32_t *num_types) @@ -510,19 +697,14 @@ tdm_hwc_accept_validation(tdm_hwc *hwc) return ret; } -/* temporary prototype to avoid build break */ -tdm_error -tdm_hwc_accept_changes(tdm_hwc *hwc) -{ - return tdm_hwc_accept_validation(hwc); -} - EXTERN tdm_error tdm_hwc_commit(tdm_hwc *hwc, int sync, tdm_hwc_commit_handler func, void *user_data) { tdm_private_module *private_module; tdm_func_hwc *func_hwc = NULL; tdm_private_hwc_commit_handler *hwc_commit_handler = NULL; + tdm_private_voutput *private_voutput = NULL; + tdm_private_voutput_commit_handler *voutput_commit_handler = NULL; HWC_FUNC_ENTRY(); @@ -553,6 +735,14 @@ tdm_hwc_commit(tdm_hwc *hwc, int sync, tdm_hwc_commit_handler func, void *user_d if (tdm_debug_module & TDM_DEBUG_COMMIT) TDM_INFO("hwc(%d) commit", private_hwc->index); + if (private_module == private_display->virtual_module) { + if (!private_output->private_voutput) { + TDM_ERR("virtual module but don't have voutput"); + _pthread_mutex_unlock(&private_display->lock); + return TDM_ERROR_BAD_MODULE; + } + } + if (!private_hwc->regist_commit_cb) { private_hwc->regist_commit_cb = 1; ret = func_hwc->hwc_set_commit_handler(private_hwc->hwc_backend, _tdm_hwc_cb_commit); @@ -590,12 +780,31 @@ tdm_hwc_commit(tdm_hwc *hwc, int sync, tdm_hwc_commit_handler func, void *user_d hwc_commit_handler->user_data = user_data; hwc_commit_handler->owner_tid = syscall(SYS_gettid); + if (private_module == private_display->virtual_module) { + private_voutput = private_output->private_voutput; + + if (LIST_LENGTH(&private_voutput->voutput_commit_handler_list) != 0) { + voutput_commit_handler = LIST_FIRST_ENTRY(&private_voutput->voutput_commit_handler_list, tdm_private_voutput_commit_handler, link); + voutput_commit_handler->user_data = private_hwc->display_target_buffer; + } + } + ret = func_hwc->hwc_commit(private_hwc->hwc_backend, sync, hwc_commit_handler); TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, commit_failed); - if (tdm_debug_module & TDM_DEBUG_COMMIT) - TDM_INFO("hwc(%d) backend commit: handle(%p) func(%p) user_data(%p)", - private_hwc->index, hwc_commit_handler, func, user_data); + if (hwc_use_vblank) { + ret = _tdm_hwc_vblank(private_hwc, hwc_commit_handler); + if (ret == TDM_ERROR_NONE) { + if (tdm_debug_module & TDM_DEBUG_COMMIT) + TDM_INFO("hwc(%d) backend commit: wait vblank handle(%p) func(%p) user_data(%p)", + private_hwc->index, hwc_commit_handler, func, user_data); + } else + goto commit_failed; + } else { + if (tdm_debug_module & TDM_DEBUG_COMMIT) + TDM_INFO("hwc(%d) backend commit: handle(%p) func(%p) user_data(%p)", + private_hwc->index, hwc_commit_handler, func, user_data); + } _pthread_mutex_unlock(&private_display->lock); @@ -614,4 +823,88 @@ commit_failed: return ret; /* LCOV_EXCL_STOP */ -} \ No newline at end of file +} + +EXTERN tdm_error +tdm_hwc_get_commit_fence(tdm_hwc *hwc, int *commit_fence) +{ + tdm_private_module *private_module; + tdm_func_hwc *func_hwc = NULL; + + HWC_FUNC_ENTRY(); + + _pthread_mutex_lock(&private_display->lock); + + private_module = private_hwc->private_module; + func_hwc = &private_module->func_hwc; + + if (!func_hwc->hwc_get_commit_fence) { + /* LCOV_EXCL_START */ + _pthread_mutex_unlock(&private_display->lock); + TDM_WRN("not implemented!!"); + return TDM_ERROR_NOT_IMPLEMENTED; + /* LCOV_EXCL_STOP */ + } + + ret = func_hwc->hwc_get_commit_fence(private_hwc->hwc_backend, commit_fence); + + _pthread_mutex_unlock(&private_display->lock); + + return ret; +} + +tdm_error +tdm_hwc_set_property(tdm_hwc *hwc, uint32_t id, tdm_value value) +{ + tdm_private_module *private_module; + tdm_func_hwc *func_hwc = NULL; + + HWC_FUNC_ENTRY(); + + _pthread_mutex_lock(&private_display->lock); + + private_module = private_hwc->private_module; + func_hwc = &private_module->func_hwc; + + if (!func_hwc->hwc_set_property) { + /* LCOV_EXCL_START */ + _pthread_mutex_unlock(&private_display->lock); + TDM_WRN("not implemented!!"); + return TDM_ERROR_NOT_IMPLEMENTED; + /* LCOV_EXCL_STOP */ + } + + ret = func_hwc->hwc_set_property(private_hwc->hwc_backend, id, value); + + _pthread_mutex_unlock(&private_display->lock); + + return ret; +} + +tdm_error +tdm_hwc_get_property(tdm_hwc *hwc, uint32_t id, tdm_value *value) +{ + tdm_private_module *private_module; + tdm_func_hwc *func_hwc = NULL; + + HWC_FUNC_ENTRY(); + + _pthread_mutex_lock(&private_display->lock); + + private_module = private_hwc->private_module; + func_hwc = &private_module->func_hwc; + + if (!func_hwc->hwc_get_property) { + /* LCOV_EXCL_START */ + _pthread_mutex_unlock(&private_display->lock); + TDM_WRN("not implemented!!"); + return TDM_ERROR_NOT_IMPLEMENTED; + /* LCOV_EXCL_STOP */ + } + + ret = func_hwc->hwc_get_property(private_hwc->hwc_backend, id, value); + + _pthread_mutex_unlock(&private_display->lock); + + return ret; +}