Message ID | 20250325110407.81107-5-tzimmermann@suse.de (mailing list archive) |
---|---|
State | New |
Headers | show |
Series | drm/format-helper: Add helpers for line conversion | expand |
On 25/03/2025 11:31, Thomas Zimmermann wrote: > Add drm_fb_xfrm_line_32to16() to implement conversion from 32-bit > pixels to 16-bit pixels. The pixel-conversion is specified by the > given callback parameter. Mark the helper as always_inline to avoid > overhead from function calls. > > Then implement all existing line-conversion functions with the new > generic call and the respective pixel-conversion helper. There's one > pixel-conversion helper that swaps output bytes. It is for gud and > requires refactoring, so don't move it into the header file. > Thanks, it looks good to me. Reviewed-by: Jocelyn Falempe <jfalempe@redhat.com> > Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> > --- > drivers/gpu/drm/drm_format_helper.c | 118 +++++--------------------- > drivers/gpu/drm/drm_format_internal.h | 12 +++ > 2 files changed, 34 insertions(+), 96 deletions(-) > > diff --git a/drivers/gpu/drm/drm_format_helper.c b/drivers/gpu/drm/drm_format_helper.c > index 5a2fe3d685a2..aecf55c1fc6b 100644 > --- a/drivers/gpu/drm/drm_format_helper.c > +++ b/drivers/gpu/drm/drm_format_helper.c > @@ -246,6 +246,18 @@ static int drm_fb_xfrm(struct iosys_map *dst, > xfrm_line); > } > > +static __always_inline void drm_fb_xfrm_line_32to16(void *dbuf, const void *sbuf, > + unsigned int pixels, > + u32 (*xfrm_pixel)(u32)) > +{ > + __le16 *dbuf16 = dbuf; > + const __le32 *sbuf32 = sbuf; > + const __le32 *send32 = sbuf32 + pixels; > + > + while (sbuf32 < send32) > + *dbuf16++ = cpu_to_le16(xfrm_pixel(le32_to_cpup(sbuf32++))); > +} > + > static __always_inline void drm_fb_xfrm_line_32to24(void *dbuf, const void *sbuf, > unsigned int pixels, > u32 (*xfrm_pixel)(u32)) > @@ -448,38 +460,19 @@ EXPORT_SYMBOL(drm_fb_xrgb8888_to_rgb332); > > static void drm_fb_xrgb8888_to_rgb565_line(void *dbuf, const void *sbuf, unsigned int pixels) > { > - __le16 *dbuf16 = dbuf; > - const __le32 *sbuf32 = sbuf; > - unsigned int x; > - u16 val16; > - u32 pix; > + drm_fb_xfrm_line_32to16(dbuf, sbuf, pixels, drm_pixel_xrgb8888_to_rgb565); > +} > > - for (x = 0; x < pixels; x++) { > - pix = le32_to_cpu(sbuf32[x]); > - val16 = ((pix & 0x00F80000) >> 8) | > - ((pix & 0x0000FC00) >> 5) | > - ((pix & 0x000000F8) >> 3); > - dbuf16[x] = cpu_to_le16(val16); > - } > +static __always_inline u32 drm_xrgb8888_to_rgb565_swab(u32 pix) > +{ > + return swab16(drm_pixel_xrgb8888_to_rgb565(pix)); > } > > /* TODO: implement this helper as conversion to RGB565|BIG_ENDIAN */ > static void drm_fb_xrgb8888_to_rgb565_swab_line(void *dbuf, const void *sbuf, > unsigned int pixels) > { > - __le16 *dbuf16 = dbuf; > - const __le32 *sbuf32 = sbuf; > - unsigned int x; > - u16 val16; > - u32 pix; > - > - for (x = 0; x < pixels; x++) { > - pix = le32_to_cpu(sbuf32[x]); > - val16 = ((pix & 0x00F80000) >> 8) | > - ((pix & 0x0000FC00) >> 5) | > - ((pix & 0x000000F8) >> 3); > - dbuf16[x] = cpu_to_le16(swab16(val16)); > - } > + drm_fb_xfrm_line_32to16(dbuf, sbuf, pixels, drm_xrgb8888_to_rgb565_swab); > } > > /** > @@ -526,19 +519,7 @@ EXPORT_SYMBOL(drm_fb_xrgb8888_to_rgb565); > > static void drm_fb_xrgb8888_to_xrgb1555_line(void *dbuf, const void *sbuf, unsigned int pixels) > { > - __le16 *dbuf16 = dbuf; > - const __le32 *sbuf32 = sbuf; > - unsigned int x; > - u16 val16; > - u32 pix; > - > - for (x = 0; x < pixels; x++) { > - pix = le32_to_cpu(sbuf32[x]); > - val16 = ((pix & 0x00f80000) >> 9) | > - ((pix & 0x0000f800) >> 6) | > - ((pix & 0x000000f8) >> 3); > - dbuf16[x] = cpu_to_le16(val16); > - } > + drm_fb_xfrm_line_32to16(dbuf, sbuf, pixels, drm_pixel_xrgb8888_to_xrgb1555); > } > > /** > @@ -578,20 +559,7 @@ EXPORT_SYMBOL(drm_fb_xrgb8888_to_xrgb1555); > > static void drm_fb_xrgb8888_to_argb1555_line(void *dbuf, const void *sbuf, unsigned int pixels) > { > - __le16 *dbuf16 = dbuf; > - const __le32 *sbuf32 = sbuf; > - unsigned int x; > - u16 val16; > - u32 pix; > - > - for (x = 0; x < pixels; x++) { > - pix = le32_to_cpu(sbuf32[x]); > - val16 = BIT(15) | /* set alpha bit */ > - ((pix & 0x00f80000) >> 9) | > - ((pix & 0x0000f800) >> 6) | > - ((pix & 0x000000f8) >> 3); > - dbuf16[x] = cpu_to_le16(val16); > - } > + drm_fb_xfrm_line_32to16(dbuf, sbuf, pixels, drm_pixel_xrgb8888_to_argb1555); > } > > /** > @@ -631,20 +599,7 @@ EXPORT_SYMBOL(drm_fb_xrgb8888_to_argb1555); > > static void drm_fb_xrgb8888_to_rgba5551_line(void *dbuf, const void *sbuf, unsigned int pixels) > { > - __le16 *dbuf16 = dbuf; > - const __le32 *sbuf32 = sbuf; > - unsigned int x; > - u16 val16; > - u32 pix; > - > - for (x = 0; x < pixels; x++) { > - pix = le32_to_cpu(sbuf32[x]); > - val16 = ((pix & 0x00f80000) >> 8) | > - ((pix & 0x0000f800) >> 5) | > - ((pix & 0x000000f8) >> 2) | > - BIT(0); /* set alpha bit */ > - dbuf16[x] = cpu_to_le16(val16); > - } > + drm_fb_xfrm_line_32to16(dbuf, sbuf, pixels, drm_pixel_xrgb8888_to_rgba5551); > } > > /** > @@ -980,36 +935,7 @@ EXPORT_SYMBOL(drm_fb_xrgb8888_to_gray8); > > static void drm_fb_argb8888_to_argb4444_line(void *dbuf, const void *sbuf, unsigned int pixels) > { > - unsigned int pixels2 = pixels & ~GENMASK_ULL(0, 0); > - __le32 *dbuf32 = dbuf; > - __le16 *dbuf16 = dbuf + pixels2 * sizeof(*dbuf16); > - const __le32 *sbuf32 = sbuf; > - unsigned int x; > - u32 val32; > - u16 val16; > - u32 pix[2]; > - > - for (x = 0; x < pixels2; x += 2, ++dbuf32) { > - pix[0] = le32_to_cpu(sbuf32[x]); > - pix[1] = le32_to_cpu(sbuf32[x + 1]); > - val32 = ((pix[0] & 0xf0000000) >> 16) | > - ((pix[0] & 0x00f00000) >> 12) | > - ((pix[0] & 0x0000f000) >> 8) | > - ((pix[0] & 0x000000f0) >> 4) | > - ((pix[1] & 0xf0000000) >> 0) | > - ((pix[1] & 0x00f00000) << 4) | > - ((pix[1] & 0x0000f000) << 8) | > - ((pix[1] & 0x000000f0) << 12); > - *dbuf32 = cpu_to_le32(val32); > - } > - for (; x < pixels; x++) { > - pix[0] = le32_to_cpu(sbuf32[x]); > - val16 = ((pix[0] & 0xf0000000) >> 16) | > - ((pix[0] & 0x00f00000) >> 12) | > - ((pix[0] & 0x0000f000) >> 8) | > - ((pix[0] & 0x000000f0) >> 4); > - dbuf16[x] = cpu_to_le16(val16); > - } > + drm_fb_xfrm_line_32to16(dbuf, sbuf, pixels, drm_pixel_argb8888_to_argb4444); > } > > /** > diff --git a/drivers/gpu/drm/drm_format_internal.h b/drivers/gpu/drm/drm_format_internal.h > index e7fcf260a914..4f20b63cb6f6 100644 > --- a/drivers/gpu/drm/drm_format_internal.h > +++ b/drivers/gpu/drm/drm_format_internal.h > @@ -128,4 +128,16 @@ static inline u32 drm_pixel_xrgb8888_to_abgr2101010(u32 pix) > drm_pixel_xrgb8888_to_xbgr2101010(pix); > } > > +/* > + * Conversion from ARGB8888 > + */ > + > +static inline u32 drm_pixel_argb8888_to_argb4444(u32 pix) > +{ > + return ((pix & 0xf0000000) >> 16) | > + ((pix & 0x00f00000) >> 12) | > + ((pix & 0x0000f000) >> 8) | > + ((pix & 0x000000f0) >> 4); > +} > + > #endif
diff --git a/drivers/gpu/drm/drm_format_helper.c b/drivers/gpu/drm/drm_format_helper.c index 5a2fe3d685a2..aecf55c1fc6b 100644 --- a/drivers/gpu/drm/drm_format_helper.c +++ b/drivers/gpu/drm/drm_format_helper.c @@ -246,6 +246,18 @@ static int drm_fb_xfrm(struct iosys_map *dst, xfrm_line); } +static __always_inline void drm_fb_xfrm_line_32to16(void *dbuf, const void *sbuf, + unsigned int pixels, + u32 (*xfrm_pixel)(u32)) +{ + __le16 *dbuf16 = dbuf; + const __le32 *sbuf32 = sbuf; + const __le32 *send32 = sbuf32 + pixels; + + while (sbuf32 < send32) + *dbuf16++ = cpu_to_le16(xfrm_pixel(le32_to_cpup(sbuf32++))); +} + static __always_inline void drm_fb_xfrm_line_32to24(void *dbuf, const void *sbuf, unsigned int pixels, u32 (*xfrm_pixel)(u32)) @@ -448,38 +460,19 @@ EXPORT_SYMBOL(drm_fb_xrgb8888_to_rgb332); static void drm_fb_xrgb8888_to_rgb565_line(void *dbuf, const void *sbuf, unsigned int pixels) { - __le16 *dbuf16 = dbuf; - const __le32 *sbuf32 = sbuf; - unsigned int x; - u16 val16; - u32 pix; + drm_fb_xfrm_line_32to16(dbuf, sbuf, pixels, drm_pixel_xrgb8888_to_rgb565); +} - for (x = 0; x < pixels; x++) { - pix = le32_to_cpu(sbuf32[x]); - val16 = ((pix & 0x00F80000) >> 8) | - ((pix & 0x0000FC00) >> 5) | - ((pix & 0x000000F8) >> 3); - dbuf16[x] = cpu_to_le16(val16); - } +static __always_inline u32 drm_xrgb8888_to_rgb565_swab(u32 pix) +{ + return swab16(drm_pixel_xrgb8888_to_rgb565(pix)); } /* TODO: implement this helper as conversion to RGB565|BIG_ENDIAN */ static void drm_fb_xrgb8888_to_rgb565_swab_line(void *dbuf, const void *sbuf, unsigned int pixels) { - __le16 *dbuf16 = dbuf; - const __le32 *sbuf32 = sbuf; - unsigned int x; - u16 val16; - u32 pix; - - for (x = 0; x < pixels; x++) { - pix = le32_to_cpu(sbuf32[x]); - val16 = ((pix & 0x00F80000) >> 8) | - ((pix & 0x0000FC00) >> 5) | - ((pix & 0x000000F8) >> 3); - dbuf16[x] = cpu_to_le16(swab16(val16)); - } + drm_fb_xfrm_line_32to16(dbuf, sbuf, pixels, drm_xrgb8888_to_rgb565_swab); } /** @@ -526,19 +519,7 @@ EXPORT_SYMBOL(drm_fb_xrgb8888_to_rgb565); static void drm_fb_xrgb8888_to_xrgb1555_line(void *dbuf, const void *sbuf, unsigned int pixels) { - __le16 *dbuf16 = dbuf; - const __le32 *sbuf32 = sbuf; - unsigned int x; - u16 val16; - u32 pix; - - for (x = 0; x < pixels; x++) { - pix = le32_to_cpu(sbuf32[x]); - val16 = ((pix & 0x00f80000) >> 9) | - ((pix & 0x0000f800) >> 6) | - ((pix & 0x000000f8) >> 3); - dbuf16[x] = cpu_to_le16(val16); - } + drm_fb_xfrm_line_32to16(dbuf, sbuf, pixels, drm_pixel_xrgb8888_to_xrgb1555); } /** @@ -578,20 +559,7 @@ EXPORT_SYMBOL(drm_fb_xrgb8888_to_xrgb1555); static void drm_fb_xrgb8888_to_argb1555_line(void *dbuf, const void *sbuf, unsigned int pixels) { - __le16 *dbuf16 = dbuf; - const __le32 *sbuf32 = sbuf; - unsigned int x; - u16 val16; - u32 pix; - - for (x = 0; x < pixels; x++) { - pix = le32_to_cpu(sbuf32[x]); - val16 = BIT(15) | /* set alpha bit */ - ((pix & 0x00f80000) >> 9) | - ((pix & 0x0000f800) >> 6) | - ((pix & 0x000000f8) >> 3); - dbuf16[x] = cpu_to_le16(val16); - } + drm_fb_xfrm_line_32to16(dbuf, sbuf, pixels, drm_pixel_xrgb8888_to_argb1555); } /** @@ -631,20 +599,7 @@ EXPORT_SYMBOL(drm_fb_xrgb8888_to_argb1555); static void drm_fb_xrgb8888_to_rgba5551_line(void *dbuf, const void *sbuf, unsigned int pixels) { - __le16 *dbuf16 = dbuf; - const __le32 *sbuf32 = sbuf; - unsigned int x; - u16 val16; - u32 pix; - - for (x = 0; x < pixels; x++) { - pix = le32_to_cpu(sbuf32[x]); - val16 = ((pix & 0x00f80000) >> 8) | - ((pix & 0x0000f800) >> 5) | - ((pix & 0x000000f8) >> 2) | - BIT(0); /* set alpha bit */ - dbuf16[x] = cpu_to_le16(val16); - } + drm_fb_xfrm_line_32to16(dbuf, sbuf, pixels, drm_pixel_xrgb8888_to_rgba5551); } /** @@ -980,36 +935,7 @@ EXPORT_SYMBOL(drm_fb_xrgb8888_to_gray8); static void drm_fb_argb8888_to_argb4444_line(void *dbuf, const void *sbuf, unsigned int pixels) { - unsigned int pixels2 = pixels & ~GENMASK_ULL(0, 0); - __le32 *dbuf32 = dbuf; - __le16 *dbuf16 = dbuf + pixels2 * sizeof(*dbuf16); - const __le32 *sbuf32 = sbuf; - unsigned int x; - u32 val32; - u16 val16; - u32 pix[2]; - - for (x = 0; x < pixels2; x += 2, ++dbuf32) { - pix[0] = le32_to_cpu(sbuf32[x]); - pix[1] = le32_to_cpu(sbuf32[x + 1]); - val32 = ((pix[0] & 0xf0000000) >> 16) | - ((pix[0] & 0x00f00000) >> 12) | - ((pix[0] & 0x0000f000) >> 8) | - ((pix[0] & 0x000000f0) >> 4) | - ((pix[1] & 0xf0000000) >> 0) | - ((pix[1] & 0x00f00000) << 4) | - ((pix[1] & 0x0000f000) << 8) | - ((pix[1] & 0x000000f0) << 12); - *dbuf32 = cpu_to_le32(val32); - } - for (; x < pixels; x++) { - pix[0] = le32_to_cpu(sbuf32[x]); - val16 = ((pix[0] & 0xf0000000) >> 16) | - ((pix[0] & 0x00f00000) >> 12) | - ((pix[0] & 0x0000f000) >> 8) | - ((pix[0] & 0x000000f0) >> 4); - dbuf16[x] = cpu_to_le16(val16); - } + drm_fb_xfrm_line_32to16(dbuf, sbuf, pixels, drm_pixel_argb8888_to_argb4444); } /** diff --git a/drivers/gpu/drm/drm_format_internal.h b/drivers/gpu/drm/drm_format_internal.h index e7fcf260a914..4f20b63cb6f6 100644 --- a/drivers/gpu/drm/drm_format_internal.h +++ b/drivers/gpu/drm/drm_format_internal.h @@ -128,4 +128,16 @@ static inline u32 drm_pixel_xrgb8888_to_abgr2101010(u32 pix) drm_pixel_xrgb8888_to_xbgr2101010(pix); } +/* + * Conversion from ARGB8888 + */ + +static inline u32 drm_pixel_argb8888_to_argb4444(u32 pix) +{ + return ((pix & 0xf0000000) >> 16) | + ((pix & 0x00f00000) >> 12) | + ((pix & 0x0000f000) >> 8) | + ((pix & 0x000000f0) >> 4); +} + #endif
Add drm_fb_xfrm_line_32to16() to implement conversion from 32-bit pixels to 16-bit pixels. The pixel-conversion is specified by the given callback parameter. Mark the helper as always_inline to avoid overhead from function calls. Then implement all existing line-conversion functions with the new generic call and the respective pixel-conversion helper. There's one pixel-conversion helper that swaps output bytes. It is for gud and requires refactoring, so don't move it into the header file. Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> --- drivers/gpu/drm/drm_format_helper.c | 118 +++++--------------------- drivers/gpu/drm/drm_format_internal.h | 12 +++ 2 files changed, 34 insertions(+), 96 deletions(-)