From 4f9aca7f1408c27945c451e68b02013519e719ea Mon Sep 17 00:00:00 2001 From: SooChan Lim Date: Sun, 11 Feb 2018 17:22:06 +0900 Subject: [PATCH] hwc:window_commit Change-Id: Icf4e5e4935fb014b0c44649030d2c33f7fa049d8 --- include/tdm.h | 12 +++++++ include/tdm_backend.h | 23 +++++++++++++ include/tdm_types.h | 14 ++++++++ src/tdm_hwc_window.c | 91 +++++++++++++++++++++++++++++++++++++++++++++++++ src/tdm_layer.c | 71 +++++++++++++++++++++++++------------- src/tdm_output.c | 81 +++++++++++++++++++++++++++++++++++++++++++ src/tdm_private.h | 2 ++ src/tdm_private_types.h | 19 ++++++++++- 8 files changed, 289 insertions(+), 24 deletions(-) diff --git a/include/tdm.h b/include/tdm.h index d6bc82a..402d31d 100644 --- a/include/tdm.h +++ b/include/tdm.h @@ -1059,6 +1059,18 @@ tdm_error tdm_hwc_window_unset_flags(tdm_hwc_window *hwc_window, tdm_hwc_window_flag flags); /** + * @brief Commit changes for a window object + * @details After all change of a window object are applied, a user commit handler + * will be called. + * @param[in] hwc_window A window object + * @param[in] func A user commit handler + * @param[in] user_data The user data + * @return #TDM_ERROR_NONE if success. Otherwise, error value. + */ +tdm_error +tdm_hwc_window_commit(tdm_hwc_window *hwc_window, tdm_hwc_window_commit_handler func, void *user_data); + +/** * @brief Get the available property array of a video hwc window object. * @param[in] hwc window A video hwc window object * @param[out] props The available property array diff --git a/include/tdm_backend.h b/include/tdm_backend.h index 297c74a..62ac805 100644 --- a/include/tdm_backend.h +++ b/include/tdm_backend.h @@ -595,6 +595,16 @@ typedef struct _tdm_func_output { tdm_error (*output_hwc_set_client_target_buffer)(tdm_output *output, tbm_surface_h target_buffer, tdm_hwc_region damage); /** + * @brief Get the layer associated with the client target buffer + * @details TODO: + * @param[in] output A output object + * @param[out] error #TDM_ERROR_NONE if success. Otherwise, error value. + * @return A layer object. + * @since 2.0.0 + */ + tdm_layer *(*output_hwc_get_target_buffer_layer)(tdm_output *output, tdm_error *error); + + /** * @brief Validate the output * @details Instructs the device to inspect all of the layer state and * determine if there are any composition type changes necessary before @@ -896,6 +906,19 @@ typedef struct _tdm_func_window { tbm_surface_h buffer); /** + * @brief Get a layer associated with a window object + * @param[in] hwc_window A window object + * @param[out] error #TDM_ERROR_NONE if success. Otherwise, error value. + * @return A layer which is @b assigend to a window object + * @remark + * A backend module @b SHOULD implement this function. The backend should + * return the tdm_layer assoicated with a hwc_window which must be assigend + * hw overlay.\n + */ + tdm_layer *(*hwc_window_get_layer)(tdm_hwc_window *hwc_window, + tdm_error *error); + + /** * @brief Set a flags to a window object * @param[in] hwc_window A window object * @param[in] flags A hwc_window flags diff --git a/include/tdm_types.h b/include/tdm_types.h index a20049f..8567149 100644 --- a/include/tdm_types.h +++ b/include/tdm_types.h @@ -260,6 +260,13 @@ typedef void (*tdm_output_commit_handler)(tdm_output *output, unsigned int seque void *user_data); /** + * @brief The output target_buffer commit handler + */ +typedef void (*tdm_output_hwc_target_buffer_commit_handler)(tdm_output *output, unsigned int sequence, + unsigned int tv_sec, unsigned int tv_usec, + void *user_data); + +/** * @brief The layer commit handler */ typedef void (*tdm_layer_commit_handler)(tdm_layer *layer, unsigned int sequence, @@ -267,6 +274,13 @@ typedef void (*tdm_layer_commit_handler)(tdm_layer *layer, unsigned int sequence void *user_data); /** + * @brief The hwc_window commit handler + */ +typedef void (*tdm_hwc_window_commit_handler)(tdm_hwc_window *hwc_window, unsigned int sequence, + unsigned int tv_sec, unsigned int tv_usec, + void *user_data); + +/** * @brief The done handler of a pp object */ typedef void (*tdm_pp_done_handler)(tdm_pp *pp, tbm_surface_h src, diff --git a/src/tdm_hwc_window.c b/src/tdm_hwc_window.c index 73f92c0..342b9db 100644 --- a/src/tdm_hwc_window.c +++ b/src/tdm_hwc_window.c @@ -195,6 +195,10 @@ tdm_hwc_window_set_info(tdm_hwc_window *hwc_window, tdm_hwc_window_info *info) info->transform); ret = func_hwc_window->hwc_window_set_info(private_hwc_window->hwc_window_backend, info); + if (ret == TDM_ERROR_NONE) { + if (memcmp(&private_hwc_window->info, info, sizeof(tdm_hwc_window_info)) != 0) + private_hwc_window->info = *info; + } _pthread_mutex_unlock(&private_display->lock); @@ -230,6 +234,8 @@ tdm_hwc_window_set_buffer(tdm_hwc_window *hwc_window, tbm_surface_h buffer) } ret = func_hwc_window->hwc_window_set_buffer(private_hwc_window->hwc_window_backend, buffer); + if (ret == TDM_ERROR_NONE) + private_hwc_window->buffer = buffer; _pthread_mutex_unlock(&private_display->lock); @@ -383,6 +389,91 @@ tdm_hwc_window_unset_flags(tdm_hwc_window *hwc_window, tdm_hwc_window_flag flags return ret; } +static +void _tdm_hwc_window_layer_commit_handler(tdm_layer *layer, unsigned int sequence, + unsigned int tv_sec, unsigned int tv_usec, + void *user_data) +{ + tdm_private_hwc_window_commit_handler *hwc_window_commit_handler = (tdm_private_hwc_window_commit_handler *)user_data; + tdm_hwc_window_commit_handler func = hwc_window_commit_handler->func; + tdm_hwc_window *hwc_window = (tdm_hwc_window *)hwc_window_commit_handler->private_hwc_window; + void *data = hwc_window_commit_handler->user_data; + + func(hwc_window, sequence, tv_sec, tv_usec, data); + + free(hwc_window_commit_handler); +} + +tdm_error +tdm_hwc_window_commit(tdm_hwc_window *hwc_window, tdm_hwc_window_commit_handler func, void *user_data) +{ + tdm_func_hwc_window *func_hwc_window = NULL; + tdm_private_hwc_window_commit_handler *hwc_window_commit_handler; + tdm_layer *layer = NULL; + tdm_private_layer *private_layer; + + HWC_WINDOW_FUNC_ENTRY(); + + _pthread_mutex_lock(&private_display->lock); + + func_hwc_window = &private_display->func_hwc_window; + + if (!func_hwc_window->hwc_window_get_layer) { + /* LCOV_EXCL_START */ + _pthread_mutex_unlock(&private_display->lock); + TDM_ERR("not implemented!!"); + return TDM_ERROR_NOT_IMPLEMENTED; + /* LCOV_EXCL_STOP */ + } + + layer = func_hwc_window->hwc_window_get_layer(private_hwc_window->hwc_window_backend, + &ret); + if (!layer) { + /* LCOV_EXCL_START */ + _pthread_mutex_unlock(&private_display->lock); + TDM_ERR("no assigned layer!!"); + return TDM_ERROR_INVALID_PARAMETER; + /* LCOV_EXCL_STOP */ + } + + layer = func_hwc_window->hwc_window_get_layer(private_hwc_window->hwc_window_backend, + &ret); + if (!layer) { + /* LCOV_EXCL_START */ + _pthread_mutex_unlock(&private_display->lock); + TDM_ERR("no assigned layer!!"); + return TDM_ERROR_INVALID_PARAMETER; + /* LCOV_EXCL_STOP */ + } + + private_layer = (tdm_private_layer*)layer; + + hwc_window_commit_handler = calloc(1, sizeof(tdm_private_hwc_window_commit_handler)); + if (!hwc_window_commit_handler) { + /* LCOV_EXCL_START */ + TDM_ERR("failed: alloc memory"); + return TDM_ERROR_OUT_OF_MEMORY; + /* LCOV_EXCL_STOP */ + } + + hwc_window_commit_handler->private_hwc_window = private_hwc_window; + hwc_window_commit_handler->func = func; + hwc_window_commit_handler->user_data = user_data; + + ret = tdm_layer_commit_internal(private_layer, _tdm_hwc_window_layer_commit_handler, user_data); + if (ret != TDM_ERROR_NONE) { + /* LCOV_EXCL_START */ + TDM_ERR("failed: commit layer(window)"); + free(hwc_window_commit_handler); + /* LCOV_EXCL_STOP */ + return ret; + } + + _pthread_mutex_unlock(&private_display->lock); + + return ret; +} + EXTERN tdm_error tdm_hwc_window_video_get_capability(tdm_hwc_window *hwc_window, tdm_hwc_window_video_capability *video_capability) diff --git a/src/tdm_layer.c b/src/tdm_layer.c index 8ef46a6..6787258 100644 --- a/src/tdm_layer.c +++ b/src/tdm_layer.c @@ -406,17 +406,11 @@ _tdm_layer_free_all_buffers(tdm_private_layer *private_layer) } } -EXTERN tdm_error -tdm_layer_set_buffer(tdm_layer *layer, tbm_surface_h buffer) +INTERN tdm_error +tdm_layer_set_buffer_internal(tdm_private_layer *private_layer, tbm_surface_h buffer) { tdm_func_layer *func_layer; - LAYER_FUNC_ENTRY(); - - TDM_RETURN_VAL_IF_FAIL(buffer != NULL, TDM_ERROR_INVALID_PARAMETER); - - _pthread_mutex_lock(&private_display->lock); - /* LCOV_EXCL_START */ /* dump buffer */ if (tdm_dump_enable && !(private_layer->caps.capabilities & TDM_LAYER_CAPABILITY_VIDEO)) @@ -441,7 +435,6 @@ tdm_layer_set_buffer(tdm_layer *layer, tbm_surface_h buffer) if (!func_layer->layer_set_buffer) { /* LCOV_EXCL_START */ - _pthread_mutex_unlock(&private_display->lock); TDM_ERR("not implemented!!"); return TDM_ERROR_NOT_IMPLEMENTED; /* LCOV_EXCL_START */ @@ -475,19 +468,31 @@ tdm_layer_set_buffer(tdm_layer *layer, tbm_surface_h buffer) TDM_TRACE_ASYNC_BEGIN((intptr_t)private_layer, "[LAYER] %d", tbm_bo_export(bo)); } + return TDM_ERROR_NONE; +} + +EXTERN tdm_error +tdm_layer_set_buffer(tdm_layer *layer, tbm_surface_h buffer) +{ + LAYER_FUNC_ENTRY(); + + TDM_RETURN_VAL_IF_FAIL(buffer != NULL, TDM_ERROR_INVALID_PARAMETER); + + _pthread_mutex_lock(&private_display->lock); + + ret = tdm_layer_set_buffer_internal(private_layer, buffer); + _pthread_mutex_unlock(&private_display->lock); return ret; } -EXTERN tdm_error -tdm_layer_unset_buffer(tdm_layer *layer) +INTERN tdm_error +tdm_layer_unset_buffer_internal(tdm_private_layer *private_layer) { tdm_func_layer *func_layer; LAYER_FUNC_ENTRY(); - _pthread_mutex_lock(&private_display->lock); - func_layer = &private_display->func_layer; _tdm_layer_free_all_buffers(private_layer); @@ -499,7 +504,6 @@ tdm_layer_unset_buffer(tdm_layer *layer) if (!func_layer->layer_unset_buffer) { /* LCOV_EXCL_START */ - _pthread_mutex_unlock(&private_display->lock); TDM_ERR("not implemented!!"); return TDM_ERROR_NOT_IMPLEMENTED; /* LCOV_EXCL_START */ @@ -508,6 +512,18 @@ tdm_layer_unset_buffer(tdm_layer *layer) ret = func_layer->layer_unset_buffer(private_layer->layer_backend); TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE); + return ret; +} + +EXTERN tdm_error +tdm_layer_unset_buffer(tdm_layer *layer) +{ + LAYER_FUNC_ENTRY(); + + _pthread_mutex_lock(&private_display->lock); + + ret = tdm_layer_unset_buffer_internal(private_layer); + _pthread_mutex_unlock(&private_display->lock); return ret; @@ -934,12 +950,11 @@ commit_failed: return ret; } -EXTERN tdm_error -tdm_layer_commit(tdm_layer *layer, tdm_layer_commit_handler func, void *user_data) +INTERN tdm_error +tdm_layer_commit_internal(tdm_private_layer *private_layer, tdm_layer_commit_handler func, void *user_data) { - LAYER_FUNC_ENTRY(); - - _pthread_mutex_lock(&private_display->lock); + tdm_private_output *private_output = private_layer->private_output; + tdm_error ret = TDM_ERROR_NONE; /* default TDM_ERROR_NONE */ if (private_output->commit_type == TDM_COMMIT_TYPE_NONE) { if (!private_output->commit_per_vblank) @@ -949,22 +964,32 @@ tdm_layer_commit(tdm_layer *layer, tdm_layer_commit_handler func, void *user_dat } if (TDM_OUTPUT_DPMS_VSYNC_IS_OFF(private_output->current_dpms_value)) { - TDM_ERR("layer(%p)'s output(%d) dpms: %s", layer, private_output->pipe, + TDM_ERR("layer(%p)'s output(%d) dpms: %s", private_layer, private_output->pipe, tdm_dpms_str(private_output->current_dpms_value)); - _pthread_mutex_unlock(&private_display->lock); return TDM_ERROR_DPMS_OFF; } /* don't call this inside of _tdm_layer_commit */ ret = tdm_layer_commit_pending_data(private_layer); if (ret != TDM_ERROR_NONE) { - TDM_ERR("layer(%p) committing pending data failed", layer); - _pthread_mutex_unlock(&private_display->lock); + TDM_ERR("layer(%p) committing pending data failed", private_layer); return ret; } ret = _tdm_layer_commit(private_layer, func, user_data); + return ret; +} + +EXTERN tdm_error +tdm_layer_commit(tdm_layer *layer, tdm_layer_commit_handler func, void *user_data) +{ + LAYER_FUNC_ENTRY(); + + _pthread_mutex_lock(&private_display->lock); + + ret = tdm_layer_commit_internal(private_layer, func, user_data); + _pthread_mutex_unlock(&private_display->lock); return ret; diff --git a/src/tdm_output.c b/src/tdm_output.c index 63fe459..1595cce 100644 --- a/src/tdm_output.c +++ b/src/tdm_output.c @@ -1826,6 +1826,87 @@ tdm_output_hwc_set_client_target_buffer(tdm_output *output, tbm_surface_h target return ret; } +static +void _tdm_output_hwc_layer_commit_handler(tdm_layer *layer, unsigned int sequence, + unsigned int tv_sec, unsigned int tv_usec, + void *user_data) +{ + tdm_private_output_hwc_target_buffer_commit_handler *output_hwc_target_buffer_commit_handler = (tdm_private_output_hwc_target_buffer_commit_handler *)user_data; + tdm_output_hwc_target_buffer_commit_handler func = output_hwc_target_buffer_commit_handler->func; + tdm_output *output = (tdm_output *)output_hwc_target_buffer_commit_handler->private_output; + void *data = output_hwc_target_buffer_commit_handler->user_data; + + func(output, sequence, tv_sec, tv_usec, data); + + free(output_hwc_target_buffer_commit_handler); +} + +tdm_error +tdm_output_hwc_commit_target_buffer(tdm_output *output, tdm_output_hwc_target_buffer_commit_handler func, void *user_data) +{ + tdm_func_output *func_output; + tdm_private_output_hwc_target_buffer_commit_handler *output_hwc_target_buffer_commit_handler; + tdm_layer *layer = NULL; + tdm_private_layer *private_layer; + + OUTPUT_FUNC_ENTRY(); + + _pthread_mutex_lock(&private_display->lock); + + if (!(private_output->caps.capabilities & TDM_OUTPUT_CAPABILITY_HWC)) { + TDM_ERR("output(%p) not support HWC", private_output); + _pthread_mutex_unlock(&private_display->lock); + return TDM_ERROR_BAD_REQUEST; + } + + func_output = &private_display->func_output; + + if (!func_output->output_hwc_get_target_buffer_layer) { + /* LCOV_EXCL_START */ + _pthread_mutex_unlock(&private_display->lock); + TDM_ERR("not implemented!!"); + return TDM_ERROR_NOT_IMPLEMENTED; + /* LCOV_EXCL_STOP */ + } + + layer = func_output->output_hwc_get_target_buffer_layer(private_output->output_backend, + &ret); + if (!layer) { + /* LCOV_EXCL_START */ + _pthread_mutex_unlock(&private_display->lock); + TDM_ERR("no assigned layer!!"); + return TDM_ERROR_INVALID_PARAMETER; + /* LCOV_EXCL_STOP */ + } + + private_layer = (tdm_private_layer*)layer; + + output_hwc_target_buffer_commit_handler = calloc(1, sizeof(tdm_private_output_hwc_target_buffer_commit_handler)); + if (!output_hwc_target_buffer_commit_handler) { + /* LCOV_EXCL_START */ + TDM_ERR("failed: alloc memory"); + return TDM_ERROR_OUT_OF_MEMORY; + /* LCOV_EXCL_STOP */ + } + + output_hwc_target_buffer_commit_handler->private_output = private_output; + output_hwc_target_buffer_commit_handler->func = func; + output_hwc_target_buffer_commit_handler->user_data = user_data; + + ret = tdm_layer_commit_internal(private_layer, _tdm_output_hwc_layer_commit_handler, user_data); + if (ret != TDM_ERROR_NONE) { + /* LCOV_EXCL_START */ + TDM_ERR("failed: commit layer(target buffer)"); + free(output_hwc_target_buffer_commit_handler); + /* LCOV_EXCL_STOP */ + return ret; + } + + _pthread_mutex_unlock(&private_display->lock); + + return ret; +} + tdm_error tdm_output_hwc_get_video_supported_formats(tdm_output *output, const tbm_format **formats, int *count) diff --git a/src/tdm_private.h b/src/tdm_private.h index 6cf2a6d..eea36d4 100644 --- a/src/tdm_private.h +++ b/src/tdm_private.h @@ -136,6 +136,8 @@ void tdm_layer_remove_commit_handler_internal(tdm_layer *layer, tdm_layer_commit_handler func, void *user_data); tdm_error +tdm_layer_commit_internal(tdm_private_layer *private_layer, tdm_layer_commit_handler func, void *user_data); +tdm_error tdm_layer_commit_pending_data(tdm_private_layer *private_layer); void tdm_layer_committed(tdm_private_layer *private_layer, tdm_private_layer_buffer **committed_buffer); diff --git a/src/tdm_private_types.h b/src/tdm_private_types.h index 8f7fb7d..7a1829d 100644 --- a/src/tdm_private_types.h +++ b/src/tdm_private_types.h @@ -106,7 +106,9 @@ typedef struct _tdm_private_server tdm_private_server; typedef struct _tdm_private_thread tdm_private_thread; typedef struct _tdm_private_vblank_handler tdm_private_vblank_handler; typedef struct _tdm_private_output_commit_handler tdm_private_output_commit_handler; +typedef struct _tdm_private_output_hwc_target_buffer_window_commit_handler tdm_private_output_hwc_target_buffer_commit_handler; typedef struct _tdm_private_layer_commit_handler tdm_private_layer_commit_handler; +typedef struct _tdm_private_hwc_window_commit_handler tdm_private_hwc_window_commit_handler; typedef struct _tdm_private_change_handler tdm_private_change_handler; typedef struct _tdm_private_layer_buffer tdm_private_layer_buffer; @@ -251,11 +253,14 @@ struct _tdm_private_hwc_window { struct list_head link; int index; - uint32_t zpos; tdm_private_display *private_display; tdm_private_output *private_output; + uint32_t zpos; + tdm_hwc_window_info info; + tbm_surface_h buffer; + tdm_hwc_window *hwc_window_backend; }; @@ -358,6 +363,12 @@ struct _tdm_private_output_commit_handler { pid_t owner_tid; }; +struct _tdm_private_output_hwc_target_buffer_window_commit_handler { + tdm_private_output *private_output; + tdm_output_hwc_target_buffer_commit_handler func; + void *user_data; +}; + struct _tdm_private_layer_commit_handler { struct list_head link; @@ -368,6 +379,12 @@ struct _tdm_private_layer_commit_handler { tdm_private_layer_buffer *committed_buffer; /* for layer_commit */ }; +struct _tdm_private_hwc_window_commit_handler { + tdm_private_hwc_window *private_hwc_window; + tdm_hwc_window_commit_handler func; + void *user_data; +}; + struct _tdm_private_change_handler { struct list_head link; -- 2.7.4