Skip to content

Commit 9e6600e

Browse files
committed
drm/vkms: Create helper macro for YUV formats
The callback functions for line conversion are almost identical for semi-planar formats. The generic READ_LINE_YUV_SEMIPLANAR macro generate all the required boilerplate to process a line from a semi-planar format. Reviewed-by: Maíra Canal <mcanal@igalia.com> Acked-by: Daniel Stone <daniels@collabora.com> Link: https://lore.kernel.org/r/20250703-b4-new-color-formats-v7-7-15fd8fd2e15c@bootlin.com Signed-off-by: Louis Chauvet <louis.chauvet@bootlin.com>
1 parent 7766ae8 commit 9e6600e

1 file changed

Lines changed: 48 additions & 27 deletions

File tree

drivers/gpu/drm/vkms/vkms_formats.c

Lines changed: 48 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -479,35 +479,56 @@ READ_LINE(R8_read_line, px, u8, argb_u16_from_gray8, *px)
479479
* - Convert YUV and YVU with the same function (a column swap is needed when setting up
480480
* plane->conversion_matrix)
481481
*/
482-
static void semi_planar_yuv_read_line(const struct vkms_plane_state *plane, int x_start,
483-
int y_start, enum pixel_read_direction direction, int count,
484-
struct pixel_argb_u16 out_pixel[])
485-
{
486-
u8 *y_plane;
487-
u8 *uv_plane;
488-
489-
packed_pixels_addr_1x1(plane->frame_info, x_start, y_start, 0,
490-
&y_plane);
491-
packed_pixels_addr_1x1(plane->frame_info,
492-
x_start / plane->frame_info->fb->format->hsub,
493-
y_start / plane->frame_info->fb->format->vsub, 1,
494-
&uv_plane);
495-
int step_y = get_block_step_bytes(plane->frame_info->fb, direction, 0);
496-
int step_uv = get_block_step_bytes(plane->frame_info->fb, direction, 1);
497-
int subsampling = get_subsampling(plane->frame_info->fb->format, direction);
498-
int subsampling_offset = get_subsampling_offset(direction, x_start, y_start);
499-
const struct conversion_matrix *conversion_matrix = &plane->conversion_matrix;
500482

501-
for (int i = 0; i < count; i++) {
502-
*out_pixel = argb_u16_from_yuv161616(conversion_matrix, y_plane[0] * 257,
503-
uv_plane[0] * 257, uv_plane[1] * 257);
504-
out_pixel += 1;
505-
y_plane += step_y;
506-
if ((i + subsampling_offset + 1) % subsampling == 0)
507-
uv_plane += step_uv;
508-
}
483+
/**
484+
* READ_LINE_YUV_SEMIPLANAR() - Generic generator for a read_line function which can be used for yuv
485+
* formats with two planes and block_w == block_h == 1.
486+
*
487+
* @function_name: Function name to generate
488+
* @pixel_1_name: temporary pixel name for the first plane used in the @__VA_ARGS__ parameters
489+
* @pixel_2_name: temporary pixel name for the second plane used in the @__VA_ARGS__ parameters
490+
* @pixel_1_type: Used to specify the type you want to cast the pixel pointer on the plane 1
491+
* @pixel_2_type: Used to specify the type you want to cast the pixel pointer on the plane 2
492+
* @callback: Callback to call for each pixels. This function should take
493+
* (struct conversion_matrix*, @__VA_ARGS__) as parameter and return a pixel_argb_u16
494+
* __VA_ARGS__: Argument to pass inside the callback. You can use @pixel_1_name and @pixel_2_name
495+
* to access current pixel values
496+
*/
497+
#define READ_LINE_YUV_SEMIPLANAR(function_name, pixel_1_name, pixel_2_name, pixel_1_type, \
498+
pixel_2_type, callback, ...) \
499+
static void function_name(const struct vkms_plane_state *plane, int x_start, \
500+
int y_start, enum pixel_read_direction direction, int count, \
501+
struct pixel_argb_u16 out_pixel[]) \
502+
{ \
503+
u8 *plane_1; \
504+
u8 *plane_2; \
505+
\
506+
packed_pixels_addr_1x1(plane->frame_info, x_start, y_start, 0, \
507+
&plane_1); \
508+
packed_pixels_addr_1x1(plane->frame_info, \
509+
x_start / plane->frame_info->fb->format->hsub, \
510+
y_start / plane->frame_info->fb->format->vsub, 1, \
511+
&plane_2); \
512+
int step_1 = get_block_step_bytes(plane->frame_info->fb, direction, 0); \
513+
int step_2 = get_block_step_bytes(plane->frame_info->fb, direction, 1); \
514+
int subsampling = get_subsampling(plane->frame_info->fb->format, direction); \
515+
int subsampling_offset = get_subsampling_offset(direction, x_start, y_start); \
516+
const struct conversion_matrix *conversion_matrix = &plane->conversion_matrix; \
517+
\
518+
for (int i = 0; i < count; i++) { \
519+
pixel_1_type *(pixel_1_name) = (pixel_1_type *)plane_1; \
520+
pixel_2_type *(pixel_2_name) = (pixel_2_type *)plane_2; \
521+
*out_pixel = (callback)(conversion_matrix, __VA_ARGS__); \
522+
out_pixel += 1; \
523+
plane_1 += step_1; \
524+
if ((i + subsampling_offset + 1) % subsampling == 0) \
525+
plane_2 += step_2; \
526+
} \
509527
}
510528

529+
READ_LINE_YUV_SEMIPLANAR(YUV888_semiplanar_read_line, y, uv, u8, u8, argb_u16_from_yuv161616,
530+
y[0] * 257, uv[0] * 257, uv[1] * 257)
531+
511532
/*
512533
* This callback can be used for YUV format where each color component is
513534
* stored in a different plane (often called planar formats). It will
@@ -703,7 +724,7 @@ pixel_read_line_t get_pixel_read_line_function(u32 format)
703724
case DRM_FORMAT_NV21:
704725
case DRM_FORMAT_NV61:
705726
case DRM_FORMAT_NV42:
706-
return &semi_planar_yuv_read_line;
727+
return &YUV888_semiplanar_read_line;
707728
case DRM_FORMAT_YUV420:
708729
case DRM_FORMAT_YUV422:
709730
case DRM_FORMAT_YUV444:

0 commit comments

Comments
 (0)