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 <redwindwanderer@gmail.com>
(cherry picked from commit 3240ccc69d1488003c1cfc36d23750145d4f13f7)
dev
vanfanel 2 years ago committed by Marius Vlad
parent 870db9703c
commit 24ee61445c
  1. 14
      compositor/main.c
  2. 3
      include/libweston/backend-drm.h
  3. 1
      libweston/backend-drm/drm-internal.h
  4. 6
      libweston/backend-drm/drm.c
  5. 23
      libweston/backend-drm/kms.c
  6. 2
      man/weston-drm.man

@ -2051,7 +2051,8 @@ drm_backend_output_configure(struct weston_output *output,
enum weston_drm_backend_output_mode mode = enum weston_drm_backend_output_mode mode =
WESTON_DRM_BACKEND_OUTPUT_PREFERRED; WESTON_DRM_BACKEND_OUTPUT_PREFERRED;
uint32_t transform = WL_OUTPUT_TRANSFORM_NORMAL; uint32_t transform = WL_OUTPUT_TRANSFORM_NORMAL;
uint32_t max_bpc; uint32_t max_bpc = 0;
bool max_bpc_specified = false;
char *s; char *s;
char *modeline = NULL; char *modeline = NULL;
char *gbm_format = NULL; char *gbm_format = NULL;
@ -2063,16 +2064,19 @@ drm_backend_output_configure(struct weston_output *output,
return -1; 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"); 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) { if (strcmp(s, "off") == 0) {
assert(0 && "off was supposed to be pruned"); assert(0 && "off was supposed to be pruned");
return -1; return -1;
} else if (wet->drm_use_current_mode || strcmp(s, "current") == 0) { } else if (wet->drm_use_current_mode || strcmp(s, "current") == 0) {
mode = WESTON_DRM_BACKEND_OUTPUT_CURRENT; 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) { } else if (strcmp(s, "preferred") != 0) {
modeline = s; modeline = s;
s = NULL; s = NULL;
@ -2086,6 +2090,8 @@ drm_backend_output_configure(struct weston_output *output,
} }
free(modeline); free(modeline);
api->set_max_bpc(output, max_bpc);
if (count_remaining_heads(output, NULL) == 1) { if (count_remaining_heads(output, NULL) == 1) {
struct weston_head *head = weston_output_get_first_head(output); struct weston_head *head = weston_output_get_first_head(output);
transform = weston_head_get_transform(head); transform = weston_head_get_transform(head);

@ -84,7 +84,8 @@ struct weston_drm_output_api {
* The property is used for working around faulty sink hardware like * The property is used for working around faulty sink hardware like
* monitors or media converters that mishandle the kernel driver * monitors or media converters that mishandle the kernel driver
* chosen bits-per-channel on the physical link. When having trouble, * 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 * The value actually used in KMS is silently clamped to the range the
* KMS driver claims to support. The default value is 16. * KMS driver claims to support. The default value is 16.

@ -517,6 +517,7 @@ struct drm_head {
struct backlight *backlight; struct backlight *backlight;
drmModeModeInfo inherited_mode; /**< Original mode on the connector */ 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 */ uint32_t inherited_crtc_id; /**< Original CRTC assignment */
}; };

@ -1388,6 +1388,12 @@ drm_head_read_current_setup(struct drm_head *head, struct drm_device *device)
drmModeFreeCrtc(crtc); 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; return 0;
} }

@ -912,20 +912,29 @@ drm_connector_set_max_bpc(struct drm_connector *connector,
drmModeAtomicReq *req) drmModeAtomicReq *req)
{ {
const struct drm_property_info *info; const struct drm_property_info *info;
struct drm_head *head;
struct drm_backend *backend = output->device->backend;
uint64_t max_bpc; uint64_t max_bpc;
uint64_t a, b; uint64_t a, b;
if (!drm_connector_has_prop(connector, WDRM_CONNECTOR_MAX_BPC)) if (!drm_connector_has_prop(connector, WDRM_CONNECTOR_MAX_BPC))
return 0; return 0;
info = &connector->props[WDRM_CONNECTOR_MAX_BPC]; if (output->max_bpc == 0) {
assert(info->flags & DRM_MODE_PROP_RANGE); /* A value of 0 means that the current max_bpc must be programmed. */
assert(info->num_range_values == 2); head = drm_head_find_by_connector(backend, connector->connector_id);
a = info->range_values[0]; max_bpc = head->inherited_max_bpc;
b = info->range_values[1]; } else {
assert(a <= b); 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, return connector_add_prop(req, connector,
WDRM_CONNECTOR_MAX_BPC, max_bpc); WDRM_CONNECTOR_MAX_BPC, max_bpc);
} }

@ -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 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 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 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 .SS Section remote-output
.TP .TP

Loading…
Cancel
Save