Skip to content

Commit 966a0d4

Browse files
author
Thomas Zimmermann
committed
drm/ast: cursor: Move format conversion to shared helper
User-space cursor-image data is encoded in ARBG8888, while hardware supports ARGB4444. Implement the format conversion as part of the format-helper framework, so that other drivers can benefit. This allows to respect the damage area of the cursor update. In previous code, all cursor image data had to be converted on each update. Now, only the changed areas require an update. The hardware image is always updated completely, as it is required for the checksum update. The format-conversion helper still contains the old implementation's optimization of writing 2 output pixels at the same time. Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Reviewed-by: Jocelyn Falempe <jfalempe@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20250217122336.230067-3-tzimmermann@suse.de
1 parent 6ec054a commit 966a0d4

File tree

4 files changed

+92
-55
lines changed

4 files changed

+92
-55
lines changed

drivers/gpu/drm/ast/ast_drv.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,9 @@ enum ast_config_mode {
113113
#define AST_MAX_HWC_WIDTH 64
114114
#define AST_MAX_HWC_HEIGHT 64
115115

116-
#define AST_HWC_SIZE (AST_MAX_HWC_WIDTH * AST_MAX_HWC_HEIGHT * 2)
116+
#define AST_HWC_PITCH (AST_MAX_HWC_WIDTH * SZ_2)
117+
#define AST_HWC_SIZE (AST_MAX_HWC_HEIGHT * AST_HWC_PITCH)
118+
117119
#define AST_HWC_SIGNATURE_SIZE 32
118120

119121
/* define for signature structure */

drivers/gpu/drm/ast/ast_mode.c

Lines changed: 17 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -659,61 +659,16 @@ static u32 ast_cursor_calculate_checksum(const void *src, unsigned int width, un
659659
return csum;
660660
}
661661

662-
static void ast_update_cursor_image(u8 __iomem *dst, const u8 *src, u8 *tmp, int width, int height)
662+
static void ast_set_cursor_image(struct ast_device *ast, const u8 *src,
663+
unsigned int width, unsigned int height)
663664
{
664-
union {
665-
u32 ul;
666-
u8 b[4];
667-
} srcdata32[2], data32;
668-
union {
669-
u16 us;
670-
u8 b[2];
671-
} data16;
665+
u8 __iomem *dst = ast->cursor_plane.base.vaddr;
672666
u32 csum;
673-
s32 alpha_dst_delta, last_alpha_dst_delta;
674-
u8 *dstxor;
675-
const u8 *srcxor;
676-
int i, j;
677-
u32 per_pixel_copy, two_pixel_copy;
678-
679-
alpha_dst_delta = AST_MAX_HWC_WIDTH << 1;
680-
last_alpha_dst_delta = alpha_dst_delta - (width << 1);
681-
682-
srcxor = src;
683-
dstxor = tmp + last_alpha_dst_delta + (AST_MAX_HWC_HEIGHT - height) * alpha_dst_delta;
684-
per_pixel_copy = width & 1;
685-
two_pixel_copy = width >> 1;
686-
687-
for (j = 0; j < height; j++) {
688-
for (i = 0; i < two_pixel_copy; i++) {
689-
srcdata32[0].ul = *((u32 *)srcxor) & 0xf0f0f0f0;
690-
srcdata32[1].ul = *((u32 *)(srcxor + 4)) & 0xf0f0f0f0;
691-
data32.b[0] = srcdata32[0].b[1] | (srcdata32[0].b[0] >> 4);
692-
data32.b[1] = srcdata32[0].b[3] | (srcdata32[0].b[2] >> 4);
693-
data32.b[2] = srcdata32[1].b[1] | (srcdata32[1].b[0] >> 4);
694-
data32.b[3] = srcdata32[1].b[3] | (srcdata32[1].b[2] >> 4);
695-
memcpy(dstxor, &data32, 4);
696-
697-
dstxor += 4;
698-
srcxor += 8;
699-
}
700-
701-
for (i = 0; i < per_pixel_copy; i++) {
702-
srcdata32[0].ul = *((u32 *)srcxor) & 0xf0f0f0f0;
703-
data16.b[0] = srcdata32[0].b[1] | (srcdata32[0].b[0] >> 4);
704-
data16.b[1] = srcdata32[0].b[3] | (srcdata32[0].b[2] >> 4);
705-
memcpy(dstxor, &data16, 2);
706-
707-
dstxor += 2;
708-
srcxor += 4;
709-
}
710-
dstxor += last_alpha_dst_delta;
711-
}
712667

713-
csum = ast_cursor_calculate_checksum(tmp, width, height);
668+
csum = ast_cursor_calculate_checksum(src, width, height);
714669

715670
/* write pixel data */
716-
memcpy_toio(dst, tmp, AST_HWC_SIZE);
671+
memcpy_toio(dst, src, AST_HWC_SIZE);
717672

718673
/* write checksum + signature */
719674
dst += AST_HWC_SIZE;
@@ -802,9 +757,7 @@ static void ast_cursor_plane_helper_atomic_update(struct drm_plane *plane,
802757
struct drm_framebuffer *fb = plane_state->fb;
803758
struct drm_plane_state *old_plane_state = drm_atomic_get_old_plane_state(state, plane);
804759
struct ast_device *ast = to_ast_device(plane->dev);
805-
struct iosys_map src_map = shadow_plane_state->data[0];
806760
struct drm_rect damage;
807-
const u8 *src = src_map.vaddr; /* TODO: Use mapping abstraction properly */
808761
u64 dst_off = ast_plane->offset;
809762
u8 __iomem *dst = ast_plane->vaddr; /* TODO: Use mapping abstraction properly */
810763
u8 __iomem *sig = dst + AST_HWC_SIZE; /* TODO: Use mapping abstraction properly */
@@ -818,8 +771,18 @@ static void ast_cursor_plane_helper_atomic_update(struct drm_plane *plane,
818771
*/
819772

820773
if (drm_atomic_helper_damage_merged(old_plane_state, plane_state, &damage)) {
821-
ast_update_cursor_image(dst, src, ast_cursor_plane->argb4444,
822-
fb->width, fb->height);
774+
u8 *argb4444 = ast_cursor_plane->argb4444;
775+
struct iosys_map argb4444_dst[DRM_FORMAT_MAX_PLANES] = {
776+
IOSYS_MAP_INIT_VADDR(argb4444),
777+
};
778+
unsigned int argb4444_dst_pitch[DRM_FORMAT_MAX_PLANES] = {
779+
AST_HWC_PITCH,
780+
};
781+
782+
drm_fb_argb8888_to_argb4444(argb4444_dst, argb4444_dst_pitch,
783+
shadow_plane_state->data, fb, &damage,
784+
&shadow_plane_state->fmtcnv_state);
785+
ast_set_cursor_image(ast, argb4444, fb->width, fb->height);
823786
ast_set_cursor_base(ast, dst_off);
824787
}
825788

drivers/gpu/drm/drm_format_helper.c

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -978,6 +978,75 @@ void drm_fb_xrgb8888_to_gray8(struct iosys_map *dst, const unsigned int *dst_pit
978978
}
979979
EXPORT_SYMBOL(drm_fb_xrgb8888_to_gray8);
980980

981+
static void drm_fb_argb8888_to_argb4444_line(void *dbuf, const void *sbuf, unsigned int pixels)
982+
{
983+
unsigned int pixels2 = pixels & ~GENMASK_ULL(0, 0);
984+
__le32 *dbuf32 = dbuf;
985+
__le16 *dbuf16 = dbuf + pixels2 * sizeof(*dbuf16);
986+
const __le32 *sbuf32 = sbuf;
987+
unsigned int x;
988+
u32 val32;
989+
u16 val16;
990+
u32 pix[2];
991+
992+
for (x = 0; x < pixels2; x += 2, ++dbuf32) {
993+
pix[0] = le32_to_cpu(sbuf32[x]);
994+
pix[1] = le32_to_cpu(sbuf32[x + 1]);
995+
val32 = ((pix[0] & 0xf0000000) >> 16) |
996+
((pix[0] & 0x00f00000) >> 12) |
997+
((pix[0] & 0x0000f000) >> 8) |
998+
((pix[0] & 0x000000f0) >> 4) |
999+
((pix[1] & 0xf0000000) >> 0) |
1000+
((pix[1] & 0x00f00000) << 4) |
1001+
((pix[1] & 0x0000f000) << 8) |
1002+
((pix[1] & 0x000000f0) << 12);
1003+
*dbuf32 = cpu_to_le32(val32);
1004+
}
1005+
for (; x < pixels; x++) {
1006+
pix[0] = le32_to_cpu(sbuf32[x]);
1007+
val16 = ((pix[0] & 0xf0000000) >> 16) |
1008+
((pix[0] & 0x00f00000) >> 12) |
1009+
((pix[0] & 0x0000f000) >> 8) |
1010+
((pix[0] & 0x000000f0) >> 4);
1011+
dbuf16[x] = cpu_to_le16(val16);
1012+
}
1013+
}
1014+
1015+
/**
1016+
* drm_fb_argb8888_to_argb4444 - Convert ARGB8888 to ARGB4444 clip buffer
1017+
* @dst: Array of ARGB4444 destination buffers
1018+
* @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines
1019+
* within @dst; can be NULL if scanlines are stored next to each other.
1020+
* @src: Array of ARGB8888 source buffer
1021+
* @fb: DRM framebuffer
1022+
* @clip: Clip rectangle area to copy
1023+
* @state: Transform and conversion state
1024+
*
1025+
* This function copies parts of a framebuffer to display memory and converts
1026+
* the color format during the process. The parameters @dst, @dst_pitch and
1027+
* @src refer to arrays. Each array must have at least as many entries as
1028+
* there are planes in @fb's format. Each entry stores the value for the
1029+
* format's respective color plane at the same index.
1030+
*
1031+
* This function does not apply clipping on @dst (i.e. the destination is at the
1032+
* top-left corner).
1033+
*
1034+
* Drivers can use this function for ARGB4444 devices that don't support
1035+
* ARGB8888 natively.
1036+
*/
1037+
void drm_fb_argb8888_to_argb4444(struct iosys_map *dst, const unsigned int *dst_pitch,
1038+
const struct iosys_map *src, const struct drm_framebuffer *fb,
1039+
const struct drm_rect *clip, struct drm_format_conv_state *state)
1040+
{
1041+
static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = {
1042+
2,
1043+
};
1044+
1045+
drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, state,
1046+
drm_fb_argb8888_to_argb4444_line);
1047+
}
1048+
EXPORT_SYMBOL(drm_fb_argb8888_to_argb4444);
1049+
9811050
/**
9821051
* drm_fb_blit - Copy parts of a framebuffer to display memory
9831052
* @dst: Array of display-memory addresses to copy to

include/drm/drm_format_helper.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,9 @@ void drm_fb_xrgb8888_to_argb2101010(struct iosys_map *dst, const unsigned int *d
110110
void drm_fb_xrgb8888_to_gray8(struct iosys_map *dst, const unsigned int *dst_pitch,
111111
const struct iosys_map *src, const struct drm_framebuffer *fb,
112112
const struct drm_rect *clip, struct drm_format_conv_state *state);
113+
void drm_fb_argb8888_to_argb4444(struct iosys_map *dst, const unsigned int *dst_pitch,
114+
const struct iosys_map *src, const struct drm_framebuffer *fb,
115+
const struct drm_rect *clip, struct drm_format_conv_state *state);
113116

114117
int drm_fb_blit(struct iosys_map *dst, const unsigned int *dst_pitch, uint32_t dst_format,
115118
const struct iosys_map *src, const struct drm_framebuffer *fb,

0 commit comments

Comments
 (0)