Skip to content

Commit

Permalink
drm/vkms: Isolate writeback pixel conversion functions
Browse files Browse the repository at this point in the history
All convertions from the ARGB16161616 format follow the same structure.
Instead of repeting the same structure for each supported format, create
a function to encapsulate the common logic and isolate the pixel
conversion functions in a callback function.

Suggested-by: Melissa Wen <[email protected]>
Signed-off-by: Maíra Canal <[email protected]>
Reviewed-by: Arthur Grillo <[email protected]>
Signed-off-by: Maíra Canal <[email protected]>
Link: https://patchwork.freedesktop.org/patch/msgid/[email protected]
  • Loading branch information
mairacanal committed Jun 24, 2023
1 parent e2a4721 commit cc4fd29
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 89 deletions.
4 changes: 2 additions & 2 deletions drivers/gpu/drm/vkms/vkms_composer.c
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ static void blend(struct vkms_writeback_job *wb,
*crc32 = crc32_le(*crc32, (void *)output_buffer->pixels, row_size);

if (wb)
wb->wb_write(&wb->wb_frame_info, output_buffer, y_pos);
vkms_writeback_row(wb, output_buffer, y_pos);
}
}

Expand All @@ -147,7 +147,7 @@ static int check_format_funcs(struct vkms_crtc_state *crtc_state,
if (!planes[i]->pixel_read)
return -1;

if (active_wb && !active_wb->wb_write)
if (active_wb && !active_wb->pixel_write)
return -1;

return 0;
Expand Down
4 changes: 2 additions & 2 deletions drivers/gpu/drm/vkms/vkms_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,7 @@ struct line_buffer {
struct vkms_writeback_job {
struct iosys_map data[DRM_FORMAT_MAX_PLANES];
struct vkms_frame_info wb_frame_info;
void (*wb_write)(struct vkms_frame_info *frame_info,
const struct line_buffer *buffer, int y);
void (*pixel_write)(u8 *dst_pixels, struct pixel_argb_u16 *in_pixel);
};

/**
Expand Down Expand Up @@ -157,6 +156,7 @@ int vkms_verify_crc_source(struct drm_crtc *crtc, const char *source_name,
void vkms_composer_worker(struct work_struct *work);
void vkms_set_composer(struct vkms_output *out, bool enabled);
void vkms_compose_row(struct line_buffer *stage_buffer, struct vkms_plane_state *plane, int y);
void vkms_writeback_row(struct vkms_writeback_job *wb, const struct line_buffer *src_buffer, int y);

/* Writeback */
int vkms_enable_writeback_connector(struct vkms_device *vkmsdev);
Expand Down
140 changes: 57 additions & 83 deletions drivers/gpu/drm/vkms/vkms_formats.c
Original file line number Diff line number Diff line change
Expand Up @@ -150,107 +150,81 @@ void vkms_compose_row(struct line_buffer *stage_buffer, struct vkms_plane_state
* They are used in the `compose_active_planes` to convert and store a line
* from the src_buffer to the writeback buffer.
*/
static void argb_u16_to_ARGB8888(struct vkms_frame_info *frame_info,
const struct line_buffer *src_buffer, int y)
static void argb_u16_to_ARGB8888(u8 *dst_pixels, struct pixel_argb_u16 *in_pixel)
{
int x_dst = frame_info->dst.x1;
u8 *dst_pixels = packed_pixels_addr(frame_info, x_dst, y);
struct pixel_argb_u16 *in_pixels = src_buffer->pixels;
int x_limit = min_t(size_t, drm_rect_width(&frame_info->dst),
src_buffer->n_pixels);

for (size_t x = 0; x < x_limit; x++, dst_pixels += 4) {
/*
* This sequence below is important because the format's byte order is
* in little-endian. In the case of the ARGB8888 the memory is
* organized this way:
*
* | Addr | = blue channel
* | Addr + 1 | = green channel
* | Addr + 2 | = Red channel
* | Addr + 3 | = Alpha channel
*/
dst_pixels[3] = DIV_ROUND_CLOSEST(in_pixels[x].a, 257);
dst_pixels[2] = DIV_ROUND_CLOSEST(in_pixels[x].r, 257);
dst_pixels[1] = DIV_ROUND_CLOSEST(in_pixels[x].g, 257);
dst_pixels[0] = DIV_ROUND_CLOSEST(in_pixels[x].b, 257);
}
/*
* This sequence below is important because the format's byte order is
* in little-endian. In the case of the ARGB8888 the memory is
* organized this way:
*
* | Addr | = blue channel
* | Addr + 1 | = green channel
* | Addr + 2 | = Red channel
* | Addr + 3 | = Alpha channel
*/
dst_pixels[3] = DIV_ROUND_CLOSEST(in_pixel->a, 257);
dst_pixels[2] = DIV_ROUND_CLOSEST(in_pixel->r, 257);
dst_pixels[1] = DIV_ROUND_CLOSEST(in_pixel->g, 257);
dst_pixels[0] = DIV_ROUND_CLOSEST(in_pixel->b, 257);
}

static void argb_u16_to_XRGB8888(struct vkms_frame_info *frame_info,
const struct line_buffer *src_buffer, int y)
static void argb_u16_to_XRGB8888(u8 *dst_pixels, struct pixel_argb_u16 *in_pixel)
{
int x_dst = frame_info->dst.x1;
u8 *dst_pixels = packed_pixels_addr(frame_info, x_dst, y);
struct pixel_argb_u16 *in_pixels = src_buffer->pixels;
int x_limit = min_t(size_t, drm_rect_width(&frame_info->dst),
src_buffer->n_pixels);

for (size_t x = 0; x < x_limit; x++, dst_pixels += 4) {
dst_pixels[3] = 0xff;
dst_pixels[2] = DIV_ROUND_CLOSEST(in_pixels[x].r, 257);
dst_pixels[1] = DIV_ROUND_CLOSEST(in_pixels[x].g, 257);
dst_pixels[0] = DIV_ROUND_CLOSEST(in_pixels[x].b, 257);
}
dst_pixels[3] = 0xff;
dst_pixels[2] = DIV_ROUND_CLOSEST(in_pixel->r, 257);
dst_pixels[1] = DIV_ROUND_CLOSEST(in_pixel->g, 257);
dst_pixels[0] = DIV_ROUND_CLOSEST(in_pixel->b, 257);
}

static void argb_u16_to_ARGB16161616(struct vkms_frame_info *frame_info,
const struct line_buffer *src_buffer, int y)
static void argb_u16_to_ARGB16161616(u8 *dst_pixels, struct pixel_argb_u16 *in_pixel)
{
int x_dst = frame_info->dst.x1;
u16 *dst_pixels = packed_pixels_addr(frame_info, x_dst, y);
struct pixel_argb_u16 *in_pixels = src_buffer->pixels;
int x_limit = min_t(size_t, drm_rect_width(&frame_info->dst),
src_buffer->n_pixels);

for (size_t x = 0; x < x_limit; x++, dst_pixels += 4) {
dst_pixels[3] = cpu_to_le16(in_pixels[x].a);
dst_pixels[2] = cpu_to_le16(in_pixels[x].r);
dst_pixels[1] = cpu_to_le16(in_pixels[x].g);
dst_pixels[0] = cpu_to_le16(in_pixels[x].b);
}
u16 *pixels = (u16 *)dst_pixels;

pixels[3] = cpu_to_le16(in_pixel->a);
pixels[2] = cpu_to_le16(in_pixel->r);
pixels[1] = cpu_to_le16(in_pixel->g);
pixels[0] = cpu_to_le16(in_pixel->b);
}

static void argb_u16_to_XRGB16161616(struct vkms_frame_info *frame_info,
const struct line_buffer *src_buffer, int y)
static void argb_u16_to_XRGB16161616(u8 *dst_pixels, struct pixel_argb_u16 *in_pixel)
{
int x_dst = frame_info->dst.x1;
u16 *dst_pixels = packed_pixels_addr(frame_info, x_dst, y);
struct pixel_argb_u16 *in_pixels = src_buffer->pixels;
int x_limit = min_t(size_t, drm_rect_width(&frame_info->dst),
src_buffer->n_pixels);

for (size_t x = 0; x < x_limit; x++, dst_pixels += 4) {
dst_pixels[3] = 0xffff;
dst_pixels[2] = cpu_to_le16(in_pixels[x].r);
dst_pixels[1] = cpu_to_le16(in_pixels[x].g);
dst_pixels[0] = cpu_to_le16(in_pixels[x].b);
}
u16 *pixels = (u16 *)dst_pixels;

pixels[3] = 0xffff;
pixels[2] = cpu_to_le16(in_pixel->r);
pixels[1] = cpu_to_le16(in_pixel->g);
pixels[0] = cpu_to_le16(in_pixel->b);
}

static void argb_u16_to_RGB565(struct vkms_frame_info *frame_info,
const struct line_buffer *src_buffer, int y)
static void argb_u16_to_RGB565(u8 *dst_pixels, struct pixel_argb_u16 *in_pixel)
{
int x_dst = frame_info->dst.x1;
u16 *dst_pixels = packed_pixels_addr(frame_info, x_dst, y);
struct pixel_argb_u16 *in_pixels = src_buffer->pixels;
int x_limit = min_t(size_t, drm_rect_width(&frame_info->dst),
src_buffer->n_pixels);
u16 *pixels = (u16 *)dst_pixels;

s64 fp_rb_ratio = drm_fixp_div(drm_int2fixp(65535), drm_int2fixp(31));
s64 fp_g_ratio = drm_fixp_div(drm_int2fixp(65535), drm_int2fixp(63));

for (size_t x = 0; x < x_limit; x++, dst_pixels++) {
s64 fp_r = drm_int2fixp(in_pixels[x].r);
s64 fp_g = drm_int2fixp(in_pixels[x].g);
s64 fp_b = drm_int2fixp(in_pixels[x].b);
s64 fp_r = drm_int2fixp(in_pixel->r);
s64 fp_g = drm_int2fixp(in_pixel->g);
s64 fp_b = drm_int2fixp(in_pixel->b);

u16 r = drm_fixp2int_round(drm_fixp_div(fp_r, fp_rb_ratio));
u16 g = drm_fixp2int_round(drm_fixp_div(fp_g, fp_g_ratio));
u16 b = drm_fixp2int_round(drm_fixp_div(fp_b, fp_rb_ratio));
u16 r = drm_fixp2int(drm_fixp_div(fp_r, fp_rb_ratio));
u16 g = drm_fixp2int(drm_fixp_div(fp_g, fp_g_ratio));
u16 b = drm_fixp2int(drm_fixp_div(fp_b, fp_rb_ratio));

*dst_pixels = cpu_to_le16(r << 11 | g << 5 | b);
}
*pixels = cpu_to_le16(r << 11 | g << 5 | b);
}

void vkms_writeback_row(struct vkms_writeback_job *wb,
const struct line_buffer *src_buffer, int y)
{
struct vkms_frame_info *frame_info = &wb->wb_frame_info;
int x_dst = frame_info->dst.x1;
u8 *dst_pixels = packed_pixels_addr(frame_info, x_dst, y);
struct pixel_argb_u16 *in_pixels = src_buffer->pixels;
int x_limit = min_t(size_t, drm_rect_width(&frame_info->dst), src_buffer->n_pixels);

for (size_t x = 0; x < x_limit; x++, dst_pixels += frame_info->cpp)
wb->pixel_write(dst_pixels, &in_pixels[x]);
}

void *get_pixel_conversion_function(u32 format)
Expand All @@ -271,7 +245,7 @@ void *get_pixel_conversion_function(u32 format)
}
}

void *get_line_to_frame_function(u32 format)
void *get_pixel_write_function(u32 format)
{
switch (format) {
case DRM_FORMAT_ARGB8888:
Expand Down
2 changes: 1 addition & 1 deletion drivers/gpu/drm/vkms/vkms_formats.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@

void *get_pixel_conversion_function(u32 format);

void *get_line_to_frame_function(u32 format);
void *get_pixel_write_function(u32 format);

#endif /* _VKMS_FORMATS_H_ */
2 changes: 1 addition & 1 deletion drivers/gpu/drm/vkms/vkms_writeback.c
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ static void vkms_wb_atomic_commit(struct drm_connector *conn,
wb_frame_info->cpp = fb->format->cpp[0];

drm_writeback_queue_job(wb_conn, connector_state);
active_wb->wb_write = get_line_to_frame_function(wb_format);
active_wb->pixel_write = get_pixel_write_function(wb_format);
drm_rect_init(&wb_frame_info->src, 0, 0, crtc_width, crtc_height);
drm_rect_init(&wb_frame_info->dst, 0, 0, crtc_width, crtc_height);
}
Expand Down

0 comments on commit cc4fd29

Please sign in to comment.