From 7326e131df3d1373dd796d9e2d931e81a3536bad Mon Sep 17 00:00:00 2001 From: Mario Kleiner Date: Tue, 14 Sep 2021 07:51:46 +0200 Subject: [PATCH] xfree86: Let xf86RandR12CrtcComputeGamma() deal with non-power-of-2 sizes. The assumption in the upsampling code was that the crtc->gamma_size size of the crtc's gamma table is a power of two. This is true for almost all current driver + gpu combos at least on Linux, with typical sizes of 256, 512, 1024 or 4096 slots. However, Intel Gen-11 Icelake and later are outliers, as their gamma table has 2^18 + 1 slots, very big and not a power of two! Try to make upsampling behave at least reasonable: Replicate the last gamma value to fill up remaining crtc->gamma_red/green/blue slots, which would normally stay uninitialized. This is important, because while the intel display driver does not actually use all 2^18+1 values passed as part of a GAMMA_LUT, it does need the very last slot, which would not get initialized by the old code. This should hopefully create reasonable behaviour with Icelake+ but is untested on the actual Intel hw due to lack of suitable hw. Signed-off-by: Mario Kleiner --- hw/xfree86/modes/xf86RandR12.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/hw/xfree86/modes/xf86RandR12.c b/hw/xfree86/modes/xf86RandR12.c index df46fb32b..5b90f4bf1 100644 --- a/hw/xfree86/modes/xf86RandR12.c +++ b/hw/xfree86/modes/xf86RandR12.c @@ -1255,8 +1255,8 @@ xf86RandR12CrtcComputeGamma(xf86CrtcPtr crtc, LOCO *palette, { int gamma_slots; unsigned shift; - CARD32 value; int i, j; + CARD32 value = 0; for (shift = 0; (gamma_size << shift) < (1 << 16); shift++); @@ -1273,6 +1273,10 @@ xf86RandR12CrtcComputeGamma(xf86CrtcPtr crtc, LOCO *palette, for (j = 0; j < gamma_slots; j++) crtc->gamma_red[i * gamma_slots + j] = value; } + + /* Replicate last value until end of crtc for gamma_size not a power of 2 */ + for (j = i * gamma_slots; j < crtc->gamma_size; j++) + crtc->gamma_red[j] = value; } else { /* Downsampling of larger palette to smaller hw lut size */ for (i = 0; i < crtc->gamma_size; i++) { @@ -1299,6 +1303,10 @@ xf86RandR12CrtcComputeGamma(xf86CrtcPtr crtc, LOCO *palette, for (j = 0; j < gamma_slots; j++) crtc->gamma_green[i * gamma_slots + j] = value; } + + /* Replicate last value until end of crtc for gamma_size not a power of 2 */ + for (j = i * gamma_slots; j < crtc->gamma_size; j++) + crtc->gamma_green[j] = value; } else { /* Downsampling of larger palette to smaller hw lut size */ for (i = 0; i < crtc->gamma_size; i++) { @@ -1325,6 +1333,10 @@ xf86RandR12CrtcComputeGamma(xf86CrtcPtr crtc, LOCO *palette, for (j = 0; j < gamma_slots; j++) crtc->gamma_blue[i * gamma_slots + j] = value; } + + /* Replicate last value until end of crtc for gamma_size not a power of 2 */ + for (j = i * gamma_slots; j < crtc->gamma_size; j++) + crtc->gamma_blue[j] = value; } else { /* Downsampling of larger palette to smaller hw lut size */ for (i = 0; i < crtc->gamma_size; i++) {