[PATCH 1/4] drm/vkms: use the gamma LUT of the state being composed
From: Oarora Etimis
Date: Sun Nov 08 2026 - 14:36:52 EST
The worker can fall behind a commit, so crtc->state may be newer than the
state the frame is built from, and the frame would mix planes of one state
with the LUT of another. Take the LUT from crtc_state->base.gamma_lut.
Clear lut_length and channel_value2index_ratio in the else branch as well,
so that gamma_lut is either complete or entirely empty. Nothing reads them
while base is NULL - apply_lut() returns on that - but the next patch
decides whether to rebuild its table from lut_length alone, and a non-zero
length next to a NULL base would have it build from a NULL LUT.
A zero-length blob takes that branch too. It used to leave lut_length at 0
and channel_value2index_ratio at drm_fixp_div(-1, 0xffff), which nothing
read either.
Fixes: db1f254f2cfa ("drm/vkms: Add support to 1D gamma LUT")
Signed-off-by: Oarora Etimis <oaroraetimis@xxxxxxxxx>
---
drivers/gpu/drm/vkms/vkms_composer.c | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/vkms/vkms_composer.c b/drivers/gpu/drm/vkms/vkms_composer.c
index 0fc915a954ba..1d5658bbd493 100644
--- a/drivers/gpu/drm/vkms/vkms_composer.c
+++ b/drivers/gpu/drm/vkms/vkms_composer.c
@@ -609,6 +609,7 @@ void vkms_composer_worker(struct work_struct *work)
struct vkms_crtc_state,
composer_work);
struct drm_crtc *crtc = crtc_state->base.crtc;
+ struct drm_property_blob *gamma_lut = crtc_state->base.gamma_lut;
struct vkms_writeback_job *active_wb = crtc_state->active_writeback;
struct vkms_output *out = drm_crtc_to_vkms_output(crtc);
bool crc_pending, wb_pending;
@@ -625,19 +626,22 @@ void vkms_composer_worker(struct work_struct *work)
crtc_state->frame_end = 0;
crtc_state->crc_pending = false;
- if (crtc->state->gamma_lut) {
+ /* crtc->state may be newer than the state this frame is built from. */
+ if (gamma_lut && gamma_lut->length) {
s64 max_lut_index_fp;
s64 u16_max_fp = drm_int2fixp(0xffff);
- crtc_state->gamma_lut.base = (struct drm_color_lut *)crtc->state->gamma_lut->data;
+ crtc_state->gamma_lut.base = (struct drm_color_lut *)gamma_lut->data;
crtc_state->gamma_lut.lut_length =
- crtc->state->gamma_lut->length / sizeof(struct drm_color_lut);
+ gamma_lut->length / sizeof(struct drm_color_lut);
max_lut_index_fp = drm_int2fixp(crtc_state->gamma_lut.lut_length - 1);
crtc_state->gamma_lut.channel_value2index_ratio = drm_fixp_div(max_lut_index_fp,
u16_max_fp);
} else {
crtc_state->gamma_lut.base = NULL;
+ crtc_state->gamma_lut.lut_length = 0;
+ crtc_state->gamma_lut.channel_value2index_ratio = 0;
}
spin_unlock_irq(&out->composer_lock);
--
2.55.0