drm/vkms: Add YUV support
authorArthur Grillo <arthurgrillo@riseup.net>
Tue, 15 Apr 2025 13:55:33 +0000 (15:55 +0200)
committerLouis Chauvet <louis.chauvet@bootlin.com>
Wed, 28 May 2025 14:19:13 +0000 (16:19 +0200)
commitfe22d21e93426294eb0ebdb0bf5f6d6b77481ecc
tree2a79d2ec49c00a0f8b5cce6bc9012f73eebac446
parentc76e2c78bc2a35ca04eead275f14b6d23ae9a89f
drm/vkms: Add YUV support

Add support to the YUV formats bellow:

- NV12/NV16/NV24
- NV21/NV61/NV42
- YUV420/YUV422/YUV444
- YVU420/YVU422/YVU444

The conversion from yuv to rgb is done with fixed-point arithmetic, using
32.32 fixed-point numbers and the drm_fixed helpers.

To do the conversion, a specific matrix must be used for each color range
(DRM_COLOR_*_RANGE) and encoding (DRM_COLOR_*). This matrix is stored in
the `conversion_matrix` struct, along with the specific y_offset needed.
This matrix is queried only once, in `vkms_plane_atomic_update` and
stored in a `vkms_plane_state`. Those conversion matrices of each
encoding and range were obtained by rounding the values of the original
conversion matrices multiplied by 2^32. This is done to avoid the use of
floating point operations.

The same reading function is used for YUV and YVU formats. As the only
difference between those two category of formats is the order of field, a
simple swap in conversion matrix columns allows using the same function.

[Louis Chauvet:
- Adapted Arthur's work
- Implemented the read_line_t callbacks for yuv
- add struct conversion_matrix
- store the whole conversion_matrix in the plane state
- remove struct pixel_yuv_u8
- update the commit message
- Merge the modifications from Arthur]

Signed-off-by: Arthur Grillo <arthurgrillo@riseup.net>
Acked-by: Maxime Ripard <mripard@kernel.org>
Link: https://lore.kernel.org/r/20250415-yuv-v18-2-f2918f71ec4b@bootlin.com
Signed-off-by: Louis Chauvet <louis.chauvet@bootlin.com>
drivers/gpu/drm/vkms/vkms_drv.h
drivers/gpu/drm/vkms/vkms_formats.c
drivers/gpu/drm/vkms/vkms_formats.h
drivers/gpu/drm/vkms/vkms_plane.c