(resending with dri-devel in cc)
Support conversion from RGB565 and RGB888 to XRGB8888. This enables simpledrm to work with framebuffers of such formats.
UEFI and/or Grub will usually set 32-bit output in XRGB8888 format. The issue can be reproduced by enabling simpledrm and requesting a console framebuffer of different format on the kernel command line; for example
nomodeset video=1024x768-16
or
nomodeset video=1024x768-24
Conversion helpers will do nothing in this case.
Make this work by implementing the rsp conversion helpers. Also add a warning about unsupported format conversions. The patchset should also enable odd userspace configurations, such as running Xorg with 16- or 24-bit color depth.
Thomas Zimmermann (3): drm/format-helper: Print warning on missing format conversion drm/format-helper: Add RGB888-to-XRGB8888 conversion drm/format-helper: Add RGB565-to-XRGB8888 conversion
drivers/gpu/drm/drm_format_helper.c | 95 +++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+)
base-commit: d97978df553d768e457cb68c637b2b0a6188b87c
Not all possible format conversions are supported yet. Print a warning on unsupported combinations.
Signed-off-by: Thomas Zimmermann tzimmermann@suse.de --- drivers/gpu/drm/drm_format_helper.c | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/drivers/gpu/drm/drm_format_helper.c b/drivers/gpu/drm/drm_format_helper.c index 0e7135114728..b648f29b21b6 100644 --- a/drivers/gpu/drm/drm_format_helper.c +++ b/drivers/gpu/drm/drm_format_helper.c @@ -590,6 +590,9 @@ int drm_fb_blit_toio(void __iomem *dst, unsigned int dst_pitch, uint32_t dst_for } }
+ drm_warn_once(fb->dev, "No conversion helper from %p4cc to %p4cc found.\n", + &fb_format, &dst_format); + return -EINVAL; } EXPORT_SYMBOL(drm_fb_blit_toio);
Hello Thomas,
On 4/21/22 20:17, Thomas Zimmermann wrote:
Not all possible format conversions are supported yet. Print a warning on unsupported combinations.
Signed-off-by: Thomas Zimmermann tzimmermann@suse.de
Reviewed-by: Javier Martinez Canillas javierm@redhat.com
Add a format helper that converts RGB888 to XRGB8888. Use this function in drm_fb_blit_toio(). Fixes simpledrm output for this combination of formats.
Signed-off-by: Thomas Zimmermann tzimmermann@suse.de --- drivers/gpu/drm/drm_format_helper.c | 46 +++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+)
diff --git a/drivers/gpu/drm/drm_format_helper.c b/drivers/gpu/drm/drm_format_helper.c index b648f29b21b6..c107ff75ef78 100644 --- a/drivers/gpu/drm/drm_format_helper.c +++ b/drivers/gpu/drm/drm_format_helper.c @@ -411,6 +411,47 @@ void drm_fb_xrgb8888_to_rgb888_toio(void __iomem *dst, unsigned int dst_pitch, } EXPORT_SYMBOL(drm_fb_xrgb8888_to_rgb888_toio);
+static void drm_fb_rgb888_to_xrgb8888_line(void *dbuf, const void *sbuf, unsigned int pixels) +{ + u32 *dbuf32 = dbuf; + const u8 *sbuf8 = sbuf; + unsigned int x; + + for (x = 0; x < pixels; x++) { + u8 r = *sbuf8++; + u8 g = *sbuf8++; + u8 b = *sbuf8++; + *dbuf32++ = 0xff000000 | (r << 16) | (g << 8) | b; + } +} + +static void drm_fb_rgb888_to_xrgb8888_toio(void __iomem *dst, unsigned int dst_pitch, + const void *vaddr, const struct drm_framebuffer *fb, + const struct drm_rect *clip) +{ + size_t linepixels = clip->x2 - clip->x1; + size_t dst_len = linepixels * 4; + unsigned int y, lines = clip->y2 - clip->y1; + void *dbuf; + + if (!dst_pitch) + dst_pitch = dst_len; + + dbuf = kmalloc(dst_len, GFP_KERNEL); + if (!dbuf) + return; + + vaddr += clip_offset(clip, fb->pitches[0], 3); + for (y = 0; y < lines; y++) { + drm_fb_rgb888_to_xrgb8888_line(dbuf, vaddr, linepixels); + memcpy_toio(dst, dbuf, dst_len); + vaddr += fb->pitches[0]; + dst += dst_pitch; + } + + kfree(dbuf); +} + static void drm_fb_xrgb8888_to_xrgb2101010_line(u32 *dbuf, const u32 *sbuf, unsigned int pixels) { @@ -583,6 +624,11 @@ int drm_fb_blit_toio(void __iomem *dst, unsigned int dst_pitch, uint32_t dst_for drm_fb_xrgb8888_to_rgb888_toio(dst, dst_pitch, vmap, fb, clip); return 0; } + } else if (dst_format == DRM_FORMAT_XRGB8888) { + if (fb_format == DRM_FORMAT_RGB888) { + drm_fb_rgb888_to_xrgb8888_toio(dst, dst_pitch, vmap, fb, clip); + return 0; + } } else if (dst_format == DRM_FORMAT_XRGB2101010) { if (fb_format == DRM_FORMAT_XRGB8888) { drm_fb_xrgb8888_to_xrgb2101010_toio(dst, dst_pitch, vmap, fb, clip);
On 4/21/22 20:17, Thomas Zimmermann wrote:
Add a format helper that converts RGB888 to XRGB8888. Use this function in drm_fb_blit_toio(). Fixes simpledrm output for this combination of formats.
I think the examples you have in the cover letter are quite illustrative, maybe I would mention an example in the commit description as well.
Signed-off-by: Thomas Zimmermann tzimmermann@suse.de
[snip]
+static void drm_fb_rgb888_to_xrgb8888_toio(void __iomem *dst, unsigned int dst_pitch,
const void *vaddr, const struct drm_framebuffer *fb,
const struct drm_rect *clip)
+{
- size_t linepixels = clip->x2 - clip->x1;
drm_rect_width(clip) instead ?
- size_t dst_len = linepixels * 4;
- unsigned int y, lines = clip->y2 - clip->y1;
and drm_rect_height(clip) ?
- void *dbuf;
Reviewed-by: Javier Martinez Canillas javierm@redhat.com
Add a format helper that converts RGB565 to XRGB8888. Use this function in drm_fb_blit_toio(). Fixes simpledrm output for this combination of formats.
Signed-off-by: Thomas Zimmermann tzimmermann@suse.de --- drivers/gpu/drm/drm_format_helper.c | 46 +++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+)
diff --git a/drivers/gpu/drm/drm_format_helper.c b/drivers/gpu/drm/drm_format_helper.c index c107ff75ef78..3b3b48ba5e85 100644 --- a/drivers/gpu/drm/drm_format_helper.c +++ b/drivers/gpu/drm/drm_format_helper.c @@ -411,6 +411,49 @@ void drm_fb_xrgb8888_to_rgb888_toio(void __iomem *dst, unsigned int dst_pitch, } EXPORT_SYMBOL(drm_fb_xrgb8888_to_rgb888_toio);
+static void drm_fb_rgb565_to_xrgb8888_line(void *dbuf, const void *sbuf, unsigned int pixels) +{ + u32 *dbuf32 = dbuf; + const u16 *sbuf16 = sbuf; + unsigned int x; + + for (x = 0; x < pixels; x++, ++sbuf16, ++dbuf32) { + u32 val32 = ((*sbuf16 & 0xf800) << 8) | + ((*sbuf16 & 0x07e0) << 5) | + ((*sbuf16 & 0x001f) << 3); + *dbuf32 = 0xff000000 | val32 | + ((val32 >> 3) & 0x00070007) | + ((val32 >> 2) & 0x00000300); + } +} + +static void drm_fb_rgb565_to_xrgb8888_toio(void __iomem *dst, unsigned int dst_pitch, + const void *vaddr, const struct drm_framebuffer *fb, + const struct drm_rect *clip) +{ + size_t linepixels = clip->x2 - clip->x1; + size_t dst_len = linepixels * 4; + unsigned int y, lines = clip->y2 - clip->y1; + void *dbuf; + + if (!dst_pitch) + dst_pitch = dst_len; + + dbuf = kmalloc(dst_len, GFP_KERNEL); + if (!dbuf) + return; + + vaddr += clip_offset(clip, fb->pitches[0], 2); + for (y = 0; y < lines; y++) { + drm_fb_rgb565_to_xrgb8888_line(dbuf, vaddr, linepixels); + memcpy_toio(dst, dbuf, dst_len); + vaddr += fb->pitches[0]; + dst += dst_pitch; + } + + kfree(dbuf); +} + static void drm_fb_rgb888_to_xrgb8888_line(void *dbuf, const void *sbuf, unsigned int pixels) { u32 *dbuf32 = dbuf; @@ -628,6 +671,9 @@ int drm_fb_blit_toio(void __iomem *dst, unsigned int dst_pitch, uint32_t dst_for if (fb_format == DRM_FORMAT_RGB888) { drm_fb_rgb888_to_xrgb8888_toio(dst, dst_pitch, vmap, fb, clip); return 0; + } else if (fb_format == DRM_FORMAT_RGB565) { + drm_fb_rgb565_to_xrgb8888_toio(dst, dst_pitch, vmap, fb, clip); + return 0; } } else if (dst_format == DRM_FORMAT_XRGB2101010) { if (fb_format == DRM_FORMAT_XRGB8888) {
On 4/21/22 20:17, Thomas Zimmermann wrote:
Add a format helper that converts RGB565 to XRGB8888. Use this function in drm_fb_blit_toio(). Fixes simpledrm output for this combination of formats.
Signed-off-by: Thomas Zimmermann tzimmermann@suse.de
drivers/gpu/drm/drm_format_helper.c | 46 +++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+)
Same comments than for patch 2/3.
Reviewed-by: Javier Martinez Canillas javierm@redhat.com
dri-devel@lists.freedesktop.org