backend-drm: reset gamma on legacy KMS

We are assuming that gamma LUT is pass-through, so better ensure it
really is pass-through rather than whatever the previous KMS client left
there.

Unfortunately the legacy ioctl does not offer any way to reset the LUT
without actually crafting an identity LUT.

If the legacy gamma libdrm function indicates the feature is not
supported, do not try to use it again. This avoids hammering the legacy
gamma every frame when deprecated drm_output_set_gamma() is not used.

drm_output_set_gamma() is not updated to check/set this flag in order to
maintain its old behavior.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
This commit is contained in:
Pekka Paalanen 2022-07-01 15:28:04 +03:00 committed by Daniel Stone
parent debfeb3049
commit 1acf69ac2f
2 changed files with 39 additions and 0 deletions

View File

@ -576,6 +576,7 @@ struct drm_output {
unsigned max_bpc;
bool deprecated_gamma_is_set;
bool legacy_gamma_not_supported;
/* Plane being displayed directly on the CRTC */
struct drm_plane *scanout_plane;

View File

@ -636,6 +636,41 @@ err:
drmModeSetCursor(device->drm.fd, crtc->crtc_id, 0, 0, 0);
}
static void
drm_output_reset_legacy_gamma(struct drm_output *output)
{
uint32_t len = output->base.gamma_size;
uint16_t *lut;
uint32_t i;
int ret;
if (len == 0)
return;
if (output->legacy_gamma_not_supported)
return;
lut = calloc(len, sizeof(uint16_t));
if (!lut)
return;
/* Identity curve */
for (i = 0; i < len; i++)
lut[i] = 0xffff * i / (len - 1);
ret = drmModeCrtcSetGamma(output->device->drm.fd,
output->crtc->crtc_id,
len, lut, lut, lut);
if (ret == -EOPNOTSUPP || ret == -ENOSYS)
output->legacy_gamma_not_supported = true;
else if (ret < 0) {
weston_log("%s failed for %s: %s\n", __func__,
output->base.name, strerror(-ret));
}
free(lut);
}
static int
drm_output_apply_state_legacy(struct drm_output_state *state)
{
@ -728,6 +763,9 @@ drm_output_apply_state_legacy(struct drm_output_state *state)
weston_log("set mode failed: %s\n", strerror(errno));
goto err;
}
if (!output->deprecated_gamma_is_set)
drm_output_reset_legacy_gamma(output);
}
pinfo = scanout_state->fb->format;