From c61e3aaef986c13175c299570e8bc3ef09a4d50a Mon Sep 17 00:00:00 2001 From: Sergey Sizonov Date: Thu, 9 Nov 2017 12:04:24 +0300 Subject: [PATCH] [hwc] adopt COMMIT_PER_VBLANK functionality for each ouptut The new TDM HWC API made us to provide the COMMIT_PER_VBLANK functionality for each output independently. An output tdm-backend provides the hwc capability for isn't intended to be managed by tdm_layer_xxx functions, so there's no need to have the COMMIT_PER_VBLANK functionality turned on for such output, in contrast to outputs tdm-backend doesn't provide the hwc capability for. So now the COMMIT_PER_VBLANK functionality for the outputs which don't support hwc behaves depend on a TDM_COMMIT_PER_VBLANK env variable while outputs which support are always have this functionality turned off (like they read TDM_COMMIT_PER_VBLANK as '0') Change-Id: I8454915d635016edfcb2dca3ac4bd455c48f4c44 Signed-off-by: Sergey Sizonov --- include/tdm_helper.h | 10 ++++++++++ src/tdm.c | 44 ++++++++++++++++---------------------------- src/tdm_helper.c | 14 ++++++++++---- src/tdm_layer.c | 23 +++++++++++------------ src/tdm_monitor_server.c | 31 +++++++++++++++++++++---------- src/tdm_output.c | 35 ++++++++++++++++++++++++++++------- src/tdm_private.h | 12 ++++++------ 7 files changed, 102 insertions(+), 67 deletions(-) diff --git a/include/tdm_helper.h b/include/tdm_helper.h index 3d1d252..8bae8fa 100644 --- a/include/tdm_helper.h +++ b/include/tdm_helper.h @@ -221,10 +221,20 @@ tdm_helper_get_display_information(tdm_display *dpy, char *reply, int *len); * @brief Get whether the commit-per-vblank functionality is enabled or not. * @param[in] dpy A display object * @return 1 if enabled. Otherwise, 0. + * + * @deprecated use @c tdm_helper_output_commit_per_vblank_enabled instead */ int tdm_helper_commit_per_vblank_enabled(tdm_display *dpy); +/** + * @brief Get whether the commit-per-vblank functionality is enabled or not for the output. + * @param[in] output An output the functionality has to be checked for + * @return -1 if error occurred, 1 if enabled, 0 if disabled. + */ +int +tdm_helper_output_commit_per_vblank_enabled(tdm_output *output); + #ifdef __cplusplus } #endif diff --git a/src/tdm.c b/src/tdm.c index 7c12dfe..2246fc4 100644 --- a/src/tdm.c +++ b/src/tdm.c @@ -943,14 +943,6 @@ tdm_display_init(tdm_error *error) if (str) tdm_display_enable_path(str); - str = getenv("TDM_COMMIT_PER_VBLANK"); - if (str) { - char *end; - int enable = strtol(str, &end, 10); - - tdm_display_enable_commit_per_vblank(private_display, enable); - } - if (pthread_mutex_init(&private_display->lock, NULL)) { ret = TDM_ERROR_OPERATION_FAILED; TDM_ERR("mutex init failed: %m"); @@ -1010,7 +1002,6 @@ tdm_display_init(tdm_error *error) tdm_event_loop_create_backend_source(private_display); private_display->init_count = 1; - private_display->commit_type = TDM_COMMIT_TYPE_NONE; tdm_private_output *o = NULL; LIST_FOR_EACH_ENTRY(o, &private_display->output_list, link) { @@ -1018,6 +1009,22 @@ tdm_display_init(tdm_error *error) tdm_output_need_validate_event_init(o); } + /* the COMMIT_PER_VBLANK functionality is ability of an output to support + * several operational modes (commit_per_vblank modes) related to tdm_commit; + * this functionality can be turned off which means a default mode */ + str = getenv("TDM_COMMIT_PER_VBLANK"); + if (str) { + tdm_private_output *o = NULL; + char *end; + int mode = strtol(str, &end, 10); + + /* outputs which support hwc capability can work only + * if commit_per_vblank mode is '0' (default mode) */ + LIST_FOR_EACH_ENTRY(o, &private_display->output_list, link) + if (!(o->caps.capabilities & TDM_OUTPUT_CAPABILITY_HWC)) + tdm_output_choose_commit_per_vblank_mode(o, mode); + } + g_private_display = private_display; if (error) @@ -1331,25 +1338,6 @@ enable_fail: } INTERN tdm_error -tdm_display_enable_commit_per_vblank(tdm_private_display *private_display, int enable) -{ - private_display->commit_per_vblank = enable; - - if (private_display->commit_per_vblank == 0) - TDM_INFO("commit per vblank: disable"); - else if (private_display->commit_per_vblank == 1) - TDM_INFO("commit per vblank: enable (1 layer)"); - else if (private_display->commit_per_vblank == 2) - TDM_INFO("commit per vblank: enable (previous commit)"); - else { - private_display->commit_per_vblank = 1; - TDM_INFO("commit per vblank: enable (changed to 1 layer)"); - } - - return TDM_ERROR_NONE; -} - -INTERN tdm_error tdm_display_enable_fps(tdm_private_display *private_display, int enable) { private_display->print_fps = enable; diff --git a/src/tdm_helper.c b/src/tdm_helper.c index a22e0cc..bcd7aec 100644 --- a/src/tdm_helper.c +++ b/src/tdm_helper.c @@ -1064,12 +1064,18 @@ tdm_helper_get_display_information(tdm_display *dpy, char *reply, int *len) EXTERN int tdm_helper_commit_per_vblank_enabled(tdm_display *dpy) { - tdm_private_display *private_display; + TDM_ERR("the deprecated function, use 'tdm_helper_output_commit_per_vblank_enabled' instead."); - TDM_RETURN_VAL_IF_FAIL(dpy != NULL, 0); + return 0; +} - private_display = dpy; +EXTERN int +tdm_helper_output_commit_per_vblank_enabled(tdm_output *output) +{ + tdm_private_output *private_output = output; + + TDM_RETURN_VAL_IF_FAIL(private_output != NULL, -1); - return private_display->commit_per_vblank; + return !!private_output->commit_per_vblank; } diff --git a/src/tdm_layer.c b/src/tdm_layer.c index cb4ef55..c1a5d6b 100644 --- a/src/tdm_layer.c +++ b/src/tdm_layer.c @@ -713,9 +713,8 @@ static int _tdm_layer_commit_possible(tdm_private_layer *private_layer) { tdm_private_output *private_output = private_layer->private_output; - tdm_private_display *private_display = private_output->private_display; - TDM_RETURN_VAL_IF_FAIL(private_display->commit_per_vblank > 0, 1); + TDM_RETURN_VAL_IF_FAIL(private_output->commit_per_vblank > 0, 1); /* There is a previous commit request which is not done and displayed on screen yet. * We can't commit at this time. @@ -726,7 +725,7 @@ _tdm_layer_commit_possible(tdm_private_layer *private_layer) return 0; } - if (private_display->commit_per_vblank == 1 && _tdm_lauer_get_output_used_layer_count(private_output) > 1) { + if (private_output->commit_per_vblank == 1 && _tdm_lauer_get_output_used_layer_count(private_output) > 1) { if (tdm_debug_module & TDM_DEBUG_COMMIT) TDM_INFO("layer(%p) commit: not possible(more than 2 layers)", private_layer); return 0; @@ -836,8 +835,8 @@ _tdm_layer_commit(tdm_layer *layer, tdm_layer_commit_handler func, void *user_da private_layer, private_layer->waiting_buffer, (layer_commit_handler->committed_buffer) ? layer_commit_handler->committed_buffer->buffer : NULL); - if (!private_display->commit_per_vblank) { - TDM_GOTO_IF_FAIL(private_display->commit_type == TDM_COMMIT_TYPE_OUTPUT, commit_failed); + if (!private_output->commit_per_vblank) { + TDM_GOTO_IF_FAIL(private_output->commit_type == TDM_COMMIT_TYPE_OUTPUT, commit_failed); LIST_ADDTAIL(&layer_commit_handler->link, &private_output->layer_commit_handler_list); ret = tdm_output_commit_internal(private_layer->private_output, 0, _tdm_layer_cb_output_commit, layer_commit_handler); @@ -846,7 +845,7 @@ _tdm_layer_commit(tdm_layer *layer, tdm_layer_commit_handler func, void *user_da if (tdm_debug_module & TDM_DEBUG_COMMIT) TDM_INFO("layer(%p) commit: no commit-per-vblank", private_layer); } else { - TDM_GOTO_IF_FAIL(private_display->commit_type == TDM_COMMIT_TYPE_LAYER, commit_failed); + TDM_GOTO_IF_FAIL(private_output->commit_type == TDM_COMMIT_TYPE_LAYER, commit_failed); if (private_layer->committing) TDM_WRN("layer(%d) too many commit", private_layer->index); @@ -908,11 +907,11 @@ tdm_layer_commit(tdm_layer *layer, tdm_layer_commit_handler func, void *user_dat _pthread_mutex_lock(&private_display->lock); - if (private_display->commit_type == TDM_COMMIT_TYPE_NONE) { - if (!private_display->commit_per_vblank) - private_display->commit_type = TDM_COMMIT_TYPE_OUTPUT; + if (private_output->commit_type == TDM_COMMIT_TYPE_NONE) { + if (!private_output->commit_per_vblank) + private_output->commit_type = TDM_COMMIT_TYPE_OUTPUT; else - private_display->commit_type = TDM_COMMIT_TYPE_LAYER; + private_output->commit_type = TDM_COMMIT_TYPE_LAYER; } if (private_output->current_dpms_value > TDM_OUTPUT_DPMS_ON) { @@ -1077,11 +1076,11 @@ _tbm_layer_queue_acquirable_cb(tbm_surface_queue_h surface_queue, void *data) TDM_INFO("layer(%p) waiting_buffer(%p)", private_layer, private_layer->waiting_buffer->buffer); - if (private_display->commit_type == TDM_COMMIT_TYPE_OUTPUT) { + if (private_output->commit_type == TDM_COMMIT_TYPE_OUTPUT) { ret = tdm_output_commit_internal(private_layer->private_output, 0, NULL, NULL); if (ret != TDM_ERROR_NONE) TDM_ERR("tdm_output_commit_internal() is fail"); - } else if (private_display->commit_type == TDM_COMMIT_TYPE_LAYER) { + } else if (private_output->commit_type == TDM_COMMIT_TYPE_LAYER) { ret = _tdm_layer_commit(private_layer, NULL, NULL); if (ret != TDM_ERROR_NONE) TDM_ERR("layer(%p) _tdm_layer_commit() is fail", private_layer); diff --git a/src/tdm_monitor_server.c b/src/tdm_monitor_server.c index e7844a5..07c2487 100644 --- a/src/tdm_monitor_server.c +++ b/src/tdm_monitor_server.c @@ -220,23 +220,34 @@ done: } static void -_tdm_monitor_server_commit_per_vblank(unsigned int pid, char *cwd, int argc, char *argv[], char *reply, int *len, tdm_display *dpy) +_tdm_monitor_server_choose_commit_per_vblank_mode(unsigned int pid, char *cwd, int argc, char *argv[], char *reply, int *len, tdm_display *dpy) { - int enable; + int output_idx; + int mode; char *arg; char *end; + tdm_error err; - if (argc < 3) { + /* TODO: do we have to provide an ability to choose commit_per_vblank mode outside? */ + + if (argc < 4) { _tdm_monitor_server_usage(argv[0], reply, len); return; } arg = argv[2]; - enable = strtol(arg, &end, 10); + output_idx = strtol(arg, &end, 10); - tdm_display_enable_commit_per_vblank(dpy, enable); + arg = argv[3]; + mode = strtol(arg, &end, 10); - TDM_SNPRINTF(reply, len, "%s the commit-per-vblank\n", (enable) ? "enable" : "disable"); + err = tdm_output_choose_commit_per_vblank_mode(tdm_display_get_output(dpy, output_idx, NULL), mode); + if (err != TDM_ERROR_NONE) { + TDM_SNPRINTF(reply, len, "an error: output_idx or mode is wrong\n"); + return; + } + + TDM_SNPRINTF(reply, len, "the mode's been set\n"); } static void @@ -539,10 +550,10 @@ static struct { "console" }, { - "commit_per_vblank", _tdm_monitor_server_commit_per_vblank, - "enable/disable the commit per vblank", - "", - "0 or 1" + "choose_commit_per_vblank_mode", _tdm_monitor_server_choose_commit_per_vblank_mode, + "choose a commit_per_vblank mode for the output", + " ", + "0 1 or 1 2 or 2 0" }, { "fps", _tdm_monitor_server_fps, diff --git a/src/tdm_output.c b/src/tdm_output.c index 3dd945c..d445914 100644 --- a/src/tdm_output.c +++ b/src/tdm_output.c @@ -690,7 +690,7 @@ tdm_output_cb_commit(tdm_output *output_backend, unsigned int sequence, TDM_INFO("handler(%p)", output_commit_handler); } - if (private_display->commit_type == TDM_COMMIT_TYPE_OUTPUT) { + if (private_output->commit_type == TDM_COMMIT_TYPE_OUTPUT) { /* In case of layer commit, the below will be handled in the layer commit callback */ LIST_FOR_EACH_ENTRY(private_layer, &private_output->layer_list, link) { if (private_layer->committed_buffer) @@ -922,7 +922,7 @@ tdm_output_commit_internal(tdm_output *output, int sync, tdm_output_commit_handl /* TODO: this is ugly. But before using tdm_output_get_dpms_internal, we have * to check if all backends's DPMS operation has no problem. */ - if (private_display->commit_per_vblank) + if (private_output->commit_per_vblank) tdm_output_get_dpms_internal(output, &dpms_value); else dpms_value = private_output->current_dpms_value; @@ -999,15 +999,15 @@ tdm_output_commit(tdm_output *output, int sync, tdm_output_commit_handler func, _pthread_mutex_lock(&private_display->lock); - if (private_display->commit_type == TDM_COMMIT_TYPE_NONE) - private_display->commit_type = TDM_COMMIT_TYPE_OUTPUT; - else if (private_display->commit_type == TDM_COMMIT_TYPE_LAYER) { + if (private_output->commit_type == TDM_COMMIT_TYPE_NONE) + private_output->commit_type = TDM_COMMIT_TYPE_OUTPUT; + else if (private_output->commit_type == TDM_COMMIT_TYPE_LAYER) { TDM_ERR("Can't supported. Use tdm_layer_commit"); _pthread_mutex_unlock(&private_display->lock); return TDM_ERROR_BAD_REQUEST; } - if (private_display->commit_per_vblank) { + if (private_output->commit_per_vblank) { TDM_ERR("Use tdm_layer_commit"); _pthread_mutex_unlock(&private_display->lock); return TDM_ERROR_BAD_REQUEST; @@ -1298,7 +1298,7 @@ tdm_output_get_dpms_internal(tdm_output *output, tdm_output_dpms *dpms_value) } /* TODO: this is ugly. But we have to check if all backends's DPMS operation has no problem. */ - if (private_display->commit_per_vblank) + if (private_output->commit_per_vblank) if (*dpms_value != private_output->current_dpms_value) { private_output->current_dpms_value = *dpms_value; TDM_ERR("output(%d) dpms changed suddenly: %s", @@ -1727,3 +1727,24 @@ tdm_output_need_validate_event_init(tdm_output *output) return ret; } + +INTERN tdm_error +tdm_output_choose_commit_per_vblank_mode(tdm_private_output *private_output, int mode) +{ + if (!private_output) + return TDM_ERROR_INVALID_PARAMETER; + + if (mode < 0 || mode > 2) + return TDM_ERROR_INVALID_PARAMETER; + + private_output->commit_per_vblank = mode; + + if (private_output->commit_per_vblank == 0) + TDM_INFO("commit per vblank: disable"); + else if (private_output->commit_per_vblank == 1) + TDM_INFO("commit per vblank: enable (1 layer)"); + else if (private_output->commit_per_vblank == 2) + TDM_INFO("commit per vblank: enable (previous commit)"); + + return TDM_ERROR_NONE; +} diff --git a/src/tdm_private.h b/src/tdm_private.h index e6c0801..2a927db 100644 --- a/src/tdm_private.h +++ b/src/tdm_private.h @@ -177,10 +177,6 @@ struct _tdm_private_display { /* output order */ tdm_output **outputs; - /* calling a output commit per a vblank */ - int commit_per_vblank; - tdm_commit_type commit_type; - int print_fps; }; @@ -231,6 +227,10 @@ struct _tdm_private_output { tdm_output_need_validate_handler hndl; int event_fd; } need_validate; + + /* calling a output commit per a vblank */ + int commit_per_vblank; + tdm_commit_type commit_type; }; struct _tdm_private_layer { @@ -464,6 +464,8 @@ tdm_output_get_dpms_internal(tdm_output *output, tdm_output_dpms *dpms_value); tdm_error tdm_output_need_validate_event_init(tdm_output *output); +tdm_error +tdm_output_choose_commit_per_vblank_mode(tdm_private_output *private_output, int mode); void tdm_output_remove_vblank_handler_internal(tdm_output *output, tdm_output_vblank_handler func, void *user_data); @@ -741,8 +743,6 @@ tdm_display_enable_path(const char *path); tdm_error tdm_display_enable_ttrace_vblank(tdm_display *dpy, tdm_output *output, int enable); tdm_error -tdm_display_enable_commit_per_vblank(tdm_private_display *private_display, int enable); -tdm_error tdm_display_enable_fps(tdm_private_display *private_display, int enable); void -- 2.7.4