From: Boram Park Date: Wed, 19 Jul 2017 03:23:44 +0000 (+0900) Subject: add tdm_output_set_dpms_async X-Git-Tag: submit/tizen_3.0/20170719.053725~3 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=7f8c3b416f50b7a13d22f79cfc813d5ef8c34d79;p=platform%2Fcore%2Fuifw%2Flibtdm.git add tdm_output_set_dpms_async Change-Id: I9775ea2e5e78e8a4b11ec85b2b7481b670959b13 --- diff --git a/include/tdm.h b/include/tdm.h index 29c81930..a7695c16 100644 --- a/include/tdm.h +++ b/include/tdm.h @@ -524,14 +524,31 @@ tdm_error tdm_output_get_mode(tdm_output *output, const tdm_output_mode **mode); /** - * @brief Set DPMS of a output object + * @brief Set DPMS of a output object synchronously * @param[in] output A output object * @param[in] dpms_value DPMS value * @return #TDM_ERROR_NONE if success. Otherwise, error value. + * @see tdm_output_set_dpms_async */ tdm_error tdm_output_set_dpms(tdm_output *output, tdm_output_dpms dpms_value); +/** + * @brief Set DPMS of a output object asynchronously + * @details This function can be used when a output supports the asynchronous DPMS + * control. The output has #TDM_OUTPUT_CAPABILITY_ASYNC_DPMS flags which + * #tdm_output_get_capabilities returns. If an output change handler is added with + * #tdm_output_add_change_handler, the output change handler will be called when + * the DPMS status is changed indeed. + * @param[in] output A output object + * @param[in] dpms_value DPMS value + * @return #TDM_ERROR_NONE if success. Otherwise, error value. + * @see tdm_output_add_change_handler, tdm_output_set_dpms, + * tdm_output_get_capabilities, #TDM_OUTPUT_CAPABILITY_ASYNC_DPMS. + */ +tdm_error +tdm_output_set_dpms_async(tdm_output *output, tdm_output_dpms dpms_value); + /** * @brief Get DPMS of a output object * @param[in] output A output object diff --git a/include/tdm_backend.h b/include/tdm_backend.h index 0949372c..2de8c7b3 100644 --- a/include/tdm_backend.h +++ b/include/tdm_backend.h @@ -451,7 +451,7 @@ typedef struct _tdm_func_output { tdm_output_commit_handler func); /** - * @brief Set DPMS of a output object + * @brief Set DPMS of a output object synchronously * @param[in] output A output object * @param[in] dpms_value DPMS value * @return #TDM_ERROR_NONE if success. Otherwise, error value. @@ -512,18 +512,35 @@ typedef struct _tdm_func_output { /** * @brief Set a output dpms handler - * @details A backend module needs to call the output dpms handler when the - * output DPMS has been changed to let the TDM frontend know the change. + * @details This function can be NULL if an output doesn't support asynchronous + * DPMS control. Otherwise, a backend module needs to call the output dpms handler + * to let the TDM frontend know the output DPMS change indeed. * @param[in] output A output object * @param[in] func A output dpms handler * @param[in] user_data The user data * @return #TDM_ERROR_NONE if success. Otherwise, error value. + * @see #output_set_dpms_async, #TDM_OUTPUT_CAPABILITY_ASYNC_DPMS * @since 1.4.0 */ tdm_error (*output_set_dpms_handler)(tdm_output *output, tdm_output_dpms_handler func, void *user_data); - void (*reserved2)(void); + + /** + * @brief Set DPMS of a output object asynchronously + * @param[in] output A output object + * @details This function can be NULL if an output doesn't support asynchronous + * DPMS control. Otherwise, an output should have #TDM_OUTPUT_CAPABILITY_ASYNC_DPMS + * flags which #output_get_capability returns. And if a output dpms handler is added with + * #output_set_dpms_handler, a backend module needs to call the output dpms handler + * to let the TDM frontend know the output DPMS change indeed. + * @param[in] dpms_value DPMS value + * @return #TDM_ERROR_NONE if success. Otherwise, error value. + * @see #output_set_dpms_handler, #TDM_OUTPUT_CAPABILITY_ASYNC_DPMS + * @since 1.7.0 + */ + tdm_error (*output_set_dpms_async)(tdm_output *output, tdm_output_dpms dpms_value); + void (*reserved3)(void); void (*reserved4)(void); void (*reserved5)(void); diff --git a/src/tdm_output.c b/src/tdm_output.c index 62ba065a..8b7abd48 100644 --- a/src/tdm_output.c +++ b/src/tdm_output.c @@ -1087,6 +1087,7 @@ tdm_output_cb_dpms(tdm_output *output_backend, tdm_output_dpms dpms, void *user_ } private_output->current_dpms_value = dpms; + private_output->waiting_dpms_change = 0; TDM_INFO("output(%d) dpms %s", private_output->pipe, tdm_dpms_str(dpms)); @@ -1108,6 +1109,12 @@ tdm_output_set_dpms(tdm_output *output, tdm_output_dpms dpms_value) _pthread_mutex_lock(&private_display->lock); + if (private_output->waiting_dpms_change) { + TDM_ERR("DPMS is not changed yet. Can't be changed twice"); + _pthread_mutex_unlock(&private_display->lock); + return TDM_ERROR_BAD_REQUEST; + } + if (private_output->current_dpms_value == dpms_value) { _pthread_mutex_unlock(&private_display->lock); return TDM_ERROR_NONE; @@ -1132,30 +1139,16 @@ tdm_output_set_dpms(tdm_output *output, tdm_output_dpms dpms_value) func_output = &private_display->func_output; - if (!func_output->output_set_dpms) { - _pthread_mutex_unlock(&private_display->lock); - private_output->current_dpms_value = dpms_value; - TDM_INFO("output(%d) dpms %s", private_output->pipe, tdm_dpms_str(dpms_value)); + if (func_output->output_set_dpms) + ret = func_output->output_set_dpms(private_output->output_backend, dpms_value); + else { + ret = TDM_ERROR_NONE; TDM_WRN("not implemented!!"); - return TDM_ERROR_NONE; + goto done; } - if (func_output->output_set_dpms_handler) { - if (!private_output->regist_dpms_cb) { - private_output->regist_dpms_cb = 1; - ret = func_output->output_set_dpms_handler(private_output->output_backend, - tdm_output_cb_dpms, private_output); - if (ret != TDM_ERROR_NONE) { - _pthread_mutex_unlock(&private_display->lock); - TDM_ERR("Can't set the dpms handler!!"); - return ret; - } - } - } - - ret = func_output->output_set_dpms(private_output->output_backend, dpms_value); - - if (ret == TDM_ERROR_NONE && !func_output->output_set_dpms_handler) { +done: + if (ret == TDM_ERROR_NONE) { tdm_value value; private_output->current_dpms_value = dpms_value; @@ -1179,6 +1172,67 @@ tdm_output_set_dpms(tdm_output *output, tdm_output_dpms dpms_value) return ret; } +EXTERN tdm_error +tdm_output_set_dpms_async(tdm_output *output, tdm_output_dpms dpms_value) +{ + tdm_func_output *func_output; + OUTPUT_FUNC_ENTRY(); + + if (!(private_output->caps.capabilities & TDM_OUTPUT_CAPABILITY_ASYNC_DPMS)) { + TDM_ERR("output doesn't support the asynchronous DPMS control!"); + return TDM_ERROR_BAD_REQUEST; + } + + if (dpms_value > TDM_OUTPUT_DPMS_OFF) + dpms_value = TDM_OUTPUT_DPMS_OFF; + + _pthread_mutex_lock(&private_display->lock); + + if (private_output->waiting_dpms_change) { + TDM_ERR("DPMS is not changed yet. Can't be changed twice"); + _pthread_mutex_unlock(&private_display->lock); + return TDM_ERROR_BAD_REQUEST; + } + + if (private_output->current_dpms_value == dpms_value) { + _pthread_mutex_unlock(&private_display->lock); + return TDM_ERROR_NONE; + } + + func_output = &private_display->func_output; + if (!func_output->output_set_dpms_handler) { + TDM_ERR("not implemented: output_set_dpms_handler"); + _pthread_mutex_unlock(&private_display->lock); + return TDM_ERROR_NOT_IMPLEMENTED; + } + + if (!func_output->output_set_dpms_async) { + TDM_ERR("not implemented: output_set_dpms_async"); + _pthread_mutex_unlock(&private_display->lock); + return TDM_ERROR_NOT_IMPLEMENTED; + } + + if (!private_output->regist_dpms_cb) { + private_output->regist_dpms_cb = 1; + ret = func_output->output_set_dpms_handler(private_output->output_backend, + tdm_output_cb_dpms, private_output); + if (ret != TDM_ERROR_NONE) { + _pthread_mutex_unlock(&private_display->lock); + TDM_ERR("Can't set the dpms handler!!"); + return ret; + } + } + + ret = func_output->output_set_dpms_async(private_output->output_backend, dpms_value); + + if (ret == TDM_ERROR_NONE) + private_output->waiting_dpms_change = 1; + + _pthread_mutex_unlock(&private_display->lock); + + return ret; +} + INTERN tdm_error tdm_output_get_dpms_internal(tdm_output *output, tdm_output_dpms *dpms_value) { diff --git a/src/tdm_private.h b/src/tdm_private.h index 4ea122d6..12ac3857 100644 --- a/src/tdm_private.h +++ b/src/tdm_private.h @@ -193,6 +193,7 @@ struct _tdm_private_output { unsigned int pipe; tdm_output_dpms current_dpms_value; + unsigned int waiting_dpms_change; const tdm_output_mode *current_mode; int regist_vblank_cb;