From 24ee61445c70b62f73988c6a90aed129ea830c9e Mon Sep 17 00:00:00 2001 From: vanfanel Date: Wed, 7 Sep 2022 16:34:17 +0100 Subject: [PATCH] Don't change the max_bpc connector prop if mode=current. As things are, even when mode=current is specified on the .ini file, a full modeset is needed (and done), which causes a very noticeable screen blinking. That is because setting the max_bpc on a connector needs full modesetting. The idea here is that if mode=current on the .ini, no modesetting should be done, so the current max_bpc is programmed into the connector. But if a custom max-bpc=... is specified, that will be used instead, even if mode=current on the .ini Fixes: https://gitlab.freedesktop.org/wayland/weston/-/issues/660 Signed-off-by: vanfanel (cherry picked from commit 3240ccc69d1488003c1cfc36d23750145d4f13f7) --- compositor/main.c | 14 ++++++++++---- include/libweston/backend-drm.h | 3 ++- libweston/backend-drm/drm-internal.h | 1 + libweston/backend-drm/drm.c | 6 ++++++ libweston/backend-drm/kms.c | 23 ++++++++++++++++------- man/weston-drm.man | 2 +- 6 files changed, 36 insertions(+), 13 deletions(-) diff --git a/compositor/main.c b/compositor/main.c index 2eb0a03c..73f70b22 100644 --- a/compositor/main.c +++ b/compositor/main.c @@ -2051,7 +2051,8 @@ drm_backend_output_configure(struct weston_output *output, enum weston_drm_backend_output_mode mode = WESTON_DRM_BACKEND_OUTPUT_PREFERRED; uint32_t transform = WL_OUTPUT_TRANSFORM_NORMAL; - uint32_t max_bpc; + uint32_t max_bpc = 0; + bool max_bpc_specified = false; char *s; char *modeline = NULL; char *gbm_format = NULL; @@ -2063,16 +2064,19 @@ drm_backend_output_configure(struct weston_output *output, return -1; } - weston_config_section_get_uint(section, "max-bpc", &max_bpc, 16); - api->set_max_bpc(output, max_bpc); - weston_config_section_get_string(section, "mode", &s, "preferred"); + if (weston_config_section_get_uint(section, "max-bpc", &max_bpc, 16) == 0) + max_bpc_specified = true; if (strcmp(s, "off") == 0) { assert(0 && "off was supposed to be pruned"); return -1; } else if (wet->drm_use_current_mode || strcmp(s, "current") == 0) { mode = WESTON_DRM_BACKEND_OUTPUT_CURRENT; + /* If mode=current and no max-bpc was specfied on the .ini file, + use current max_bpc so full modeset is not done. */ + if (!max_bpc_specified) + max_bpc = 0; } else if (strcmp(s, "preferred") != 0) { modeline = s; s = NULL; @@ -2086,6 +2090,8 @@ drm_backend_output_configure(struct weston_output *output, } free(modeline); + api->set_max_bpc(output, max_bpc); + if (count_remaining_heads(output, NULL) == 1) { struct weston_head *head = weston_output_get_first_head(output); transform = weston_head_get_transform(head); diff --git a/include/libweston/backend-drm.h b/include/libweston/backend-drm.h index 548940ab..071125fa 100644 --- a/include/libweston/backend-drm.h +++ b/include/libweston/backend-drm.h @@ -84,7 +84,8 @@ struct weston_drm_output_api { * The property is used for working around faulty sink hardware like * monitors or media converters that mishandle the kernel driver * chosen bits-per-channel on the physical link. When having trouble, - * try a lower value like 8. + * try a lower value like 8. A value of 0 means that the current max + * bpc will be reprogrammed. * * The value actually used in KMS is silently clamped to the range the * KMS driver claims to support. The default value is 16. diff --git a/libweston/backend-drm/drm-internal.h b/libweston/backend-drm/drm-internal.h index f6c1617f..1ee1974c 100644 --- a/libweston/backend-drm/drm-internal.h +++ b/libweston/backend-drm/drm-internal.h @@ -517,6 +517,7 @@ struct drm_head { struct backlight *backlight; drmModeModeInfo inherited_mode; /**< Original mode on the connector */ + uint32_t inherited_max_bpc; /**< Original max_bpc on the connector */ uint32_t inherited_crtc_id; /**< Original CRTC assignment */ }; diff --git a/libweston/backend-drm/drm.c b/libweston/backend-drm/drm.c index 962cc284..7d607ca6 100644 --- a/libweston/backend-drm/drm.c +++ b/libweston/backend-drm/drm.c @@ -1388,6 +1388,12 @@ drm_head_read_current_setup(struct drm_head *head, struct drm_device *device) drmModeFreeCrtc(crtc); } + /* Get the current max_bpc that's currently configured to + * this connector. */ + head->inherited_max_bpc = drm_property_get_value( + &head->connector.props[WDRM_CONNECTOR_MAX_BPC], + head->connector.props_drm, 0); + return 0; } diff --git a/libweston/backend-drm/kms.c b/libweston/backend-drm/kms.c index 54010b97..0118efa1 100644 --- a/libweston/backend-drm/kms.c +++ b/libweston/backend-drm/kms.c @@ -912,20 +912,29 @@ drm_connector_set_max_bpc(struct drm_connector *connector, drmModeAtomicReq *req) { const struct drm_property_info *info; + struct drm_head *head; + struct drm_backend *backend = output->device->backend; uint64_t max_bpc; uint64_t a, b; if (!drm_connector_has_prop(connector, WDRM_CONNECTOR_MAX_BPC)) return 0; - info = &connector->props[WDRM_CONNECTOR_MAX_BPC]; - assert(info->flags & DRM_MODE_PROP_RANGE); - assert(info->num_range_values == 2); - a = info->range_values[0]; - b = info->range_values[1]; - assert(a <= b); + if (output->max_bpc == 0) { + /* A value of 0 means that the current max_bpc must be programmed. */ + head = drm_head_find_by_connector(backend, connector->connector_id); + max_bpc = head->inherited_max_bpc; + } else { + info = &connector->props[WDRM_CONNECTOR_MAX_BPC]; + assert(info->flags & DRM_MODE_PROP_RANGE); + assert(info->num_range_values == 2); + a = info->range_values[0]; + b = info->range_values[1]; + assert(a <= b); + + max_bpc = MAX(a, MIN(output->max_bpc, b)); + } - max_bpc = MAX(a, MIN(output->max_bpc, b)); return connector_add_prop(req, connector, WDRM_CONNECTOR_MAX_BPC, max_bpc); } diff --git a/man/weston-drm.man b/man/weston-drm.man index eaaf311c..383715d3 100644 --- a/man/weston-drm.man +++ b/man/weston-drm.man @@ -172,7 +172,7 @@ silenty clamped to the hardware driver supported range. This artificially limits the driver chosen link bits-per-channel which may be useful for working around sink hardware (e.g. monitor) limitations. The default is 16 which is practically unlimited. If you need to work around hardware issues, try a lower -value like 8. +value like 8. A value of 0 means that the current max bpc will be reprogrammed. .SS Section remote-output .TP