From b7f500389f1e731ccd764b26b48ff133563460d8 Mon Sep 17 00:00:00 2001 From: Sergey Sizonov Date: Fri, 20 Oct 2017 14:17:38 +0300 Subject: [PATCH] [hwc] add the ability to ask a client(E20) about the revalidation The backends may need to ask E20 for revalidation for some reason (power consumption, performance,...). So we need some way to let backend do this. The new TDM API function: tdm_output_set_need_validate_handler(); and TDM/backend interface API function: tdm_backend_trigger_need_validate_event(); have been added to let backend ask client(E20) for the revalidation. Change-Id: Ife266a55043cbf420702098b06223e46ef67c041 Signed-off-by: Sergey Sizonov --- include/tdm.h | 16 ++++++++++++ include/tdm_backend.h | 9 +++++++ include/tdm_types.h | 5 ++++ src/tdm.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/tdm_backend.c | 20 +++++++++++++++ src/tdm_output.c | 24 ++++++++++++++++++ src/tdm_private.h | 16 ++++++++++++ src/tdm_thread.c | 5 ++++ 8 files changed, 162 insertions(+) diff --git a/include/tdm.h b/include/tdm.h index b7fb89e..50fe717 100644 --- a/include/tdm.h +++ b/include/tdm.h @@ -635,6 +635,22 @@ tdm_error tdm_output_validate(tdm_output *output, uint32_t *num_types); /** + * @brief Set the 'need to validate' handler for the 'output' + * + * @details During backend's work it may need to ask for the revalidation + * (make client (E20) do tdm_output_validate() again), so a 'hndl' will + * be called as such need happen. Only one handler per output is supported. + * + * @param[in] output The output object a hndl is going to be registered for. + * @param[in] hndl The handler which will be called on the 'need to validate' event. + * + * @return #TDM_ERROR_NONE if success. Otherwise, error value. + */ +tdm_error +tdm_output_set_need_validate_handler(tdm_output *output, + tdm_output_need_validate_handler hndl); + +/** * @brief Get changed composition types * @details Retrieves the windows for which the device requires a different * composition type than had been set prior to the last call to tdm_output_validate(). diff --git a/include/tdm_backend.h b/include/tdm_backend.h index 6411f61..f78a3a7 100644 --- a/include/tdm_backend.h +++ b/include/tdm_backend.h @@ -1317,6 +1317,15 @@ tdm_event_loop_source_timer_update(tdm_event_loop_source *source, unsigned int m void tdm_event_loop_source_remove(tdm_event_loop_source *source); +/** + * @brief Trigger a 'need to validate' event. + * @param[in] output The output the event should be triggered for. + * @note The global display lock has to be locked before the call to this function. + * @see #tdm_output_set_need_validate_handler + */ +tdm_error +tdm_backend_trigger_need_validate_event(tdm_output *output); + #ifdef __cplusplus } #endif diff --git a/include/tdm_types.h b/include/tdm_types.h index 7602b84..5b537c6 100644 --- a/include/tdm_types.h +++ b/include/tdm_types.h @@ -293,6 +293,11 @@ typedef void (*tdm_pp_done_handler)(tdm_pp *pp, tbm_surface_h src, typedef void (*tdm_capture_done_handler)(tdm_capture *capture, tbm_surface_h buffer, void *user_data); +/** + * @brief The 'need to validate' handler of an output object + */ +typedef void (*tdm_output_need_validate_handler)(tdm_output *output); + #ifdef __cplusplus } #endif diff --git a/src/tdm.c b/src/tdm.c index 315b027..cb397b8 100644 --- a/src/tdm.c +++ b/src/tdm.c @@ -669,6 +669,70 @@ int tdm_debug_dump; static tdm_private_display *g_private_display; static pthread_mutex_t gLock = PTHREAD_MUTEX_INITIALIZER; +/* gets called on behalf of the ecore-main-loop thread */ +INTERN tdm_error +tdm_handle_need_validate_event(tdm_thread_cb_need_validate *ev) +{ + tdm_private_output *private_output; + + TDM_RETURN_VAL_IF_FAIL(ev != NULL, TDM_ERROR_INVALID_PARAMETER); + TDM_RETURN_VAL_IF_FAIL(ev->o != NULL, TDM_ERROR_OPERATION_FAILED); + + private_output = ev->o; + + TDM_INFO("tdm-backend asks for revalidation for the output:%p.", private_output); + + if (private_output->need_validate.hndl) + private_output->need_validate.hndl((tdm_output*)private_output); + + return TDM_ERROR_NONE; +} + +/* gets called on behalf of the tdm-thread */ +static tdm_error +_need_validate_handler(int fd, tdm_event_loop_mask mask, void *user_data) +{ + tdm_thread_cb_need_validate ev; + tdm_private_output *private_output; + tdm_error ret; + + private_output = (tdm_private_output *)user_data; + + ev.base.type = TDM_THREAD_CB_NEED_VALIDATE; + ev.base.length = sizeof ev; + ev.o = private_output; + + ret = tdm_thread_send_cb(private_output->private_display->private_loop, &ev.base); + TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE); + + TDM_INFO("tdm-thread: get a 'need to revalidate' event for the ouptut:%p.", private_output); + + /* who cares about this? */ + return TDM_ERROR_NONE; +} + +static void +_tdm_backend_events_init(tdm_private_display *priv_dsp) +{ + tdm_private_output *o; + tdm_error err = TDM_ERROR_NONE; + int fd; + + /* build in eventfd fds into event_loop listened & handled by the tdm-thread */ + LIST_FOR_EACH_ENTRY(o, &priv_dsp->output_list, link) { + fd = eventfd(0, 0); + TDM_WARNING_IF_FAIL(fd >= 0); + + tdm_event_loop_add_fd_handler(priv_dsp, fd, TDM_EVENT_LOOP_READABLE, + _need_validate_handler, o, &err); + TDM_WARNING_IF_FAIL(err == TDM_ERROR_NONE); + + o->need_validate.event_fd = fd; + + TDM_INFO("register an output:%p for the revalidation, event_fd:%d.", o, fd); + } +} + static tdm_error _tdm_display_check_module(tdm_backend_module *module) { @@ -1008,6 +1072,9 @@ tdm_display_init(tdm_error *error) private_display->init_count = 1; private_display->commit_type = TDM_COMMIT_TYPE_NONE; + if (private_display->hwc_enable) + _tdm_backend_events_init(private_display); + g_private_display = private_display; if (error) diff --git a/src/tdm_backend.c b/src/tdm_backend.c index d25066f..94aca18 100644 --- a/src/tdm_backend.c +++ b/src/tdm_backend.c @@ -181,3 +181,23 @@ tdm_backend_register_func_capture(tdm_display *dpy, return TDM_ERROR_NONE; } +EXTERN tdm_error +tdm_backend_trigger_need_validate_event(tdm_output *output) +{ + tdm_private_output *private_output; + uint64_t value; + int res; + + TDM_RETURN_VAL_IF_FAIL(output != NULL, TDM_ERROR_INVALID_PARAMETER); + + private_output = (tdm_private_output*)output; + value = 1; + + /* do not lock the global display lock here */ + + res = write(private_output->need_validate.event_fd, &value, sizeof(value)); + if (res < 0) + return TDM_ERROR_OPERATION_FAILED; + + return TDM_ERROR_NONE; +} diff --git a/src/tdm_output.c b/src/tdm_output.c index dc8c87a..b7ae3be 100644 --- a/src/tdm_output.c +++ b/src/tdm_output.c @@ -1397,6 +1397,30 @@ tdm_output_validate(tdm_output *output, uint32_t *num_types) } EXTERN tdm_error +tdm_output_set_need_validate_handler(tdm_output *output, + tdm_output_need_validate_handler hndl) +{ + OUTPUT_FUNC_ENTRY(); + + TDM_RETURN_VAL_IF_FAIL(hndl != NULL, TDM_ERROR_INVALID_PARAMETER); + + _pthread_mutex_lock(&private_display->lock); + + /* there's no reason to allow this */ + if (private_output->need_validate.hndl) { + + _pthread_mutex_unlock(&private_display->lock); + return TDM_ERROR_OPERATION_FAILED; + } + + private_output->need_validate.hndl = hndl; + + _pthread_mutex_unlock(&private_display->lock); + + return ret; +} + +EXTERN tdm_error tdm_output_get_changed_composition_types(tdm_output *output, uint32_t *num_elements, tdm_hwc_window **hwc_window, diff --git a/src/tdm_private.h b/src/tdm_private.h index 691d4d9..01d2e48 100644 --- a/src/tdm_private.h +++ b/src/tdm_private.h @@ -52,6 +52,7 @@ #include #include #include +#include #include #include @@ -226,6 +227,12 @@ struct _tdm_private_output { /* TODO: temp solution for handling DPMS things in sub-htread */ tdm_event_loop_source *dpms_changed_timer; + + struct { + /* look at the tdm_output_set_need_revalidate_handler() declaration for the details */ + tdm_output_need_validate_handler hndl; + int event_fd; + } need_validate; }; struct _tdm_private_layer { @@ -539,6 +546,7 @@ typedef enum { TDM_THREAD_CB_PP_DONE, TDM_THREAD_CB_CAPTURE_DONE, TDM_THREAD_CB_VBLANK_SW, + TDM_THREAD_CB_NEED_VALIDATE, } tdm_thread_cb_type; typedef struct _tdm_thread_cb_base tdm_thread_cb_base; @@ -549,6 +557,7 @@ typedef struct _tdm_thread_cb_output_dpms tdm_thread_cb_output_dpms; typedef struct _tdm_thread_cb_pp_done tdm_thread_cb_pp_done; typedef struct _tdm_thread_cb_capture_done tdm_thread_cb_capture_done; typedef struct _tdm_thread_cb_vblank_sw tdm_thread_cb_vblank_sw; +typedef struct _tdm_thread_cb_need_validate tdm_thread_cb_need_validate; struct _tdm_thread_cb_base { tdm_thread_cb_type type; @@ -598,6 +607,11 @@ struct _tdm_thread_cb_vblank_sw { double vblank_stamp; }; +struct _tdm_thread_cb_need_validate { + tdm_thread_cb_base base; + tdm_private_output *o; +}; + tdm_error tdm_thread_init(tdm_private_loop *private_loop); void @@ -722,6 +736,8 @@ tdm_display_enable_fps(tdm_private_display *private_display, int enable); void tdm_monitor_server_command(tdm_display *dpy, const char *options, char *reply, int *len); +tdm_error +tdm_handle_need_validate_event(tdm_thread_cb_need_validate *ev); struct argument_details { char type; diff --git a/src/tdm_thread.c b/src/tdm_thread.c index 4659740..c6f3007 100644 --- a/src/tdm_thread.c +++ b/src/tdm_thread.c @@ -356,6 +356,11 @@ tdm_thread_handle_cb(tdm_private_loop *private_loop) tdm_vblank_cb_vblank_SW(NULL, vblank_sw->vblank_stamp); break; } + case TDM_THREAD_CB_NEED_VALIDATE: { + tdm_thread_cb_need_validate *ev = (tdm_thread_cb_need_validate*)base; + tdm_handle_need_validate_event(ev); + break; + } default: break; } -- 2.7.4