On 9/30/24 8:31 AM, Louis Chauvet wrote: > From: Arthur Grillo <arthurgrillo@xxxxxxxxxx> > > 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. > > Signed-off-by: Arthur Grillo <arthurgrillo@xxxxxxxxxx> > [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: Louis Chauvet <louis.chauvet@xxxxxxxxxxx> > --- > drivers/gpu/drm/vkms/vkms_drv.h | 18 ++ > drivers/gpu/drm/vkms/vkms_formats.c | 353 ++++++++++++++++++++++++++++++++++++ > drivers/gpu/drm/vkms/vkms_formats.h | 4 + > drivers/gpu/drm/vkms/vkms_plane.c | 16 +- > 4 files changed, 390 insertions(+), 1 deletion(-) > > diff --git a/drivers/gpu/drm/vkms/vkms_formats.c b/drivers/gpu/drm/vkms/vkms_formats.c > index 0f6678420a11..adb1228e5201 100644 > --- a/drivers/gpu/drm/vkms/vkms_formats.c > +++ b/drivers/gpu/drm/vkms/vkms_formats.c > @@ -140,6 +140,51 @@ static void packed_pixels_addr_1x1(const struct vkms_frame_info *frame_info, > *addr = (u8 *)frame_info->map[0].vaddr + offset; > } > > +/** > + * get_subsampling() - Get the subsampling divisor value on a specific direction > + * > + * @format: format to extarct the subsampling from extract > + * @direction: direction of the subsampling requested > + */ > +static int get_subsampling(const struct drm_format_info *format, > + enum pixel_read_direction direction) > +{ > + switch (direction) { > + case READ_BOTTOM_TO_TOP: > + case READ_TOP_TO_BOTTOM: > + return format->vsub; > + case READ_RIGHT_TO_LEFT: > + case READ_LEFT_TO_RIGHT: > + return format->hsub; > + } > + WARN_ONCE(true, "Invalid direction for pixel reading: %d\n", direction); > + return 1; > +} > + > +/** > + * get_subsampling_offset() - An offset for keeping the chroma siting consistent regardless of > + * x_start and y_start values > + * > + * @direction: direction of the reading to properly compute this offset > + * @x_start: x coordinate of the starting point of the readed line read > + * @y_start: y coordinate of the starting point of the readed line read > + */ > +static int get_subsampling_offset(enum pixel_read_direction direction, int x_start, int y_start) > +{