backend-drm: reset CRTC_GAMMA_LUT

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

Unfortunately, we have old drm_output_set_gamma() API that cms-static
and cms-colord plugins are using. To avoid trampling over them, do not
touch gamma after they did. Those plugins are deprecated, so there is no
reason to make set_gamma work through atomic.

drm_output_set_gamma() is called from weston_compositor_add_output()
through the output_created_signal. This is after drm_output_enable() and
before any KMS modeset or atomic commit on the CRTC. Therefore it is not
possible that there would be any KMS action in flight when
drm_output_set_gamma() is called, and so setting deprecated_gamma_is_set
should be non-racy - like setting CRTC_GAMMA_LUT itself.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
This commit is contained in:
Pekka Paalanen 2022-07-01 13:48:49 +03:00 committed by Daniel Stone
parent dbce396c7c
commit debfeb3049
2 changed files with 42 additions and 0 deletions

View file

@ -236,6 +236,8 @@ enum wdrm_content_type {
enum wdrm_crtc_property {
WDRM_CRTC_MODE_ID = 0,
WDRM_CRTC_ACTIVE,
WDRM_CRTC_GAMMA_LUT,
WDRM_CRTC_GAMMA_LUT_SIZE,
WDRM_CRTC__COUNT
};
@ -573,6 +575,8 @@ struct drm_output {
unsigned max_bpc;
bool deprecated_gamma_is_set;
/* Plane being displayed directly on the CRTC */
struct drm_plane *scanout_plane;

View file

@ -165,6 +165,8 @@ const struct drm_property_info connector_props[] = {
const struct drm_property_info crtc_props[] = {
[WDRM_CRTC_MODE_ID] = { .name = "MODE_ID", },
[WDRM_CRTC_ACTIVE] = { .name = "ACTIVE", },
[WDRM_CRTC_GAMMA_LUT] = { .name = "GAMMA_LUT", },
[WDRM_CRTC_GAMMA_LUT_SIZE] = { .name = "GAMMA_LUT_SIZE", },
};
@ -507,6 +509,7 @@ drm_output_set_gamma(struct weston_output *output_base,
if (output_base->gamma_size != size)
return;
output->deprecated_gamma_is_set = true;
rc = drmModeCrtcSetGamma(device->drm.fd,
output->crtc->crtc_id,
size, r, g, b);
@ -796,6 +799,36 @@ crtc_add_prop(drmModeAtomicReq *req, struct drm_crtc *crtc,
return (ret <= 0) ? -1 : 0;
}
/** Set a CRTC property, allowing zero value for non-existing property
*
* \param req The atomic KMS request to append to.
* \param crtc The CRTC whose property to set.
* \param prop Which CRTC property to set.
* \param val The value, cast to u64, to set to the CRTC property.
* \return 0 on succcess, -1 on failure.
*
* If the property does not exist, attempting to set it to value
* zero is ok, because the property with value zero has the same
* KMS effect as the property not existing.
*
* However, trying to set a non-existing property to a non-zero value
* must fail, because that would not achieve the desired KMS effect.
*
* It is up to the caller to understand which KMS properties work
* like this and which do not.
*/
static int
crtc_add_prop_zero_ok(drmModeAtomicReq *req, struct drm_crtc *crtc,
enum wdrm_crtc_property prop, uint64_t val)
{
struct drm_property_info *info = &crtc->props_crtc[prop];
if (info->prop_id == 0 && val == 0)
return 0;
return crtc_add_prop(req, crtc, prop, val);
}
static int
connector_add_prop(drmModeAtomicReq *req, struct drm_connector *connector,
enum wdrm_connector_property prop, uint64_t val)
@ -1005,6 +1038,11 @@ drm_output_apply_state_atomic(struct drm_output_state *state,
current_mode->blob_id);
ret |= crtc_add_prop(req, crtc, WDRM_CRTC_ACTIVE, 1);
if (!output->deprecated_gamma_is_set) {
ret |= crtc_add_prop_zero_ok(req, crtc,
WDRM_CRTC_GAMMA_LUT, 0);
}
/* No need for the DPMS property, since it is implicit in
* routing and CRTC activity. */
wl_list_for_each(head, &output->base.head_list, base.output_link) {