Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/vkms: Use s32 for internal color pipeline precision

Certain operations require us to preserve values below 0.0 and
above 1.0 (0x0 and 0xffff respectively in 16 bpc unorm). One
such operation is a BT709 encoding operation followed by its
decoding operation, or the reverse.

We'll use s32 values as intermediate in and outputs of our
color operations, for the operations where it matters.

For now this won't apply to LUT operations. We might want to
update those to work on s32 as well, but it's unclear how
that should work for unorm LUT definitions. We'll revisit
that once we add LUT + CTM tests.

Reviewed-by: Louis Chauvet <louis.chauvet@bootlin.com>
Signed-off-by: Alex Hung <alex.hung@amd.com>
Signed-off-by: Harry Wentland <harry.wentland@amd.com>
Reviewed-by: Daniel Stone <daniels@collabora.com>
Signed-off-by: Simon Ser <contact@emersion.fr>
Link: https://patch.msgid.link/20251115000237.3561250-20-alex.hung@amd.com

authored by

Harry Wentland and committed by
Simon Ser
bff4d3cd e5719e7f

+29 -2
+25 -2
drivers/gpu/drm/vkms/vkms_composer.c
··· 128 128 } 129 129 } 130 130 131 - static void apply_colorop(struct pixel_argb_u16 *pixel, struct drm_colorop *colorop) 131 + static void apply_colorop(struct pixel_argb_s32 *pixel, struct drm_colorop *colorop) 132 132 { 133 133 struct drm_colorop_state *colorop_state = colorop->state; 134 134 struct drm_device *dev = colorop->dev; ··· 157 157 static void pre_blend_color_transform(const struct vkms_plane_state *plane_state, 158 158 struct line_buffer *output_buffer) 159 159 { 160 + struct pixel_argb_s32 pixel; 161 + 160 162 for (size_t x = 0; x < output_buffer->n_pixels; x++) { 161 163 struct drm_colorop *colorop = plane_state->base.base.color_pipeline; 164 + 165 + /* 166 + * Some operations, such as applying a BT709 encoding matrix, 167 + * followed by a decoding matrix, require that we preserve 168 + * values above 1.0 and below 0.0 until the end of the pipeline. 169 + * 170 + * Pack the 16-bit UNORM values into s32 to give us head-room to 171 + * avoid clipping until we're at the end of the pipeline. Clip 172 + * intentionally at the end of the pipeline before packing 173 + * UNORM values back into u16. 174 + */ 175 + pixel.a = output_buffer->pixels[x].a; 176 + pixel.r = output_buffer->pixels[x].r; 177 + pixel.g = output_buffer->pixels[x].g; 178 + pixel.b = output_buffer->pixels[x].b; 162 179 163 180 while (colorop) { 164 181 struct drm_colorop_state *colorop_state; ··· 186 169 return; 187 170 188 171 if (!colorop_state->bypass) 189 - apply_colorop(&output_buffer->pixels[x], colorop); 172 + apply_colorop(&pixel, colorop); 190 173 191 174 colorop = colorop->next; 192 175 } 176 + 177 + /* clamp values */ 178 + output_buffer->pixels[x].a = clamp_val(pixel.a, 0, 0xffff); 179 + output_buffer->pixels[x].r = clamp_val(pixel.r, 0, 0xffff); 180 + output_buffer->pixels[x].g = clamp_val(pixel.g, 0, 0xffff); 181 + output_buffer->pixels[x].b = clamp_val(pixel.b, 0, 0xffff); 193 182 } 194 183 } 195 184
+4
drivers/gpu/drm/vkms/vkms_drv.h
··· 45 45 unsigned int rotation; 46 46 }; 47 47 48 + struct pixel_argb_s32 { 49 + s32 a, r, g, b; 50 + }; 51 + 48 52 /** 49 53 * struct pixel_argb_u16 - Internal representation of a pixel color. 50 54 * @a: Alpha component value, stored in 16 bits, without padding, using