Introduce some infrastructure to handle format conversions:

 * New struct drm_format_convert containing the cpp for src
   and dst with a function pointer to actually convert a
   single scanline.
 * generic convert_lines() function which uses a struct
   drm_format_convert pointer to convert a rectangle.

drm_fb_swab16() has been switched over to the new
convert_lines() function as showcase.

Signed-off-by: Gerd Hoffmann <kra...@redhat.com>
---
 drivers/gpu/drm/drm_format_helper.c | 84 +++++++++++++++++++++--------
 1 file changed, 63 insertions(+), 21 deletions(-)

diff --git a/drivers/gpu/drm/drm_format_helper.c 
b/drivers/gpu/drm/drm_format_helper.c
index 00d716f14173..f32e0173600c 100644
--- a/drivers/gpu/drm/drm_format_helper.c
+++ b/drivers/gpu/drm/drm_format_helper.c
@@ -16,6 +16,61 @@
 #include <drm/drm_fourcc.h>
 #include <drm/drm_rect.h>
 
+struct drm_format_convert {
+       u32 dst_cpp;
+       u32 src_cpp;
+       void (*func)(void *dst, void *src, u32 pixels);
+};
+
+static void convert_swab16_fn(void *dst, void *src, u32 pixels)
+{
+       u16 *sbuf = src;
+       u16 *dbuf = dst;
+       u32 x;
+
+       for (x = 0; x < pixels; x++)
+               dbuf[x] = swab16(sbuf[16]);
+}
+
+static struct drm_format_convert convert_swab16 = {
+       .dst_cpp = 2,
+       .src_cpp = 2,
+       .func = convert_swab16_fn,
+};
+
+static void convert_lines(void *dst, unsigned int dst_pitch,
+                         void *src, unsigned int src_pitch,
+                         unsigned int pixels,
+                         unsigned int lines,
+                         struct drm_format_convert *conv)
+{
+       u32 src_linelength = pixels * conv->src_cpp;
+       u32 y;
+       void *sbuf;
+
+       /*
+        * The cma memory is write-combined so reads are uncached.
+        * Speed up by fetching one line at a time.
+        */
+       sbuf = kmalloc(src_linelength, GFP_KERNEL);
+       if (!sbuf)
+               return;
+
+       for (y = 0; y < lines; y++) {
+               memcpy(sbuf, src, src_linelength);
+               conv->func(dst, sbuf, pixels);
+               src += src_pitch;
+               dst += dst_pitch;
+       }
+
+       kfree(sbuf);
+}
+
+static u32 clip_offset(struct drm_rect *clip, u32 pitch, u32 cpp)
+{
+       return (clip->y1 * pitch) + (clip->x1 * cpp);
+}
+
 static void drm_fb_memcpy_lines(void *dst, unsigned int dst_pitch,
                                void *src, unsigned int src_pitch,
                                unsigned int linelength, unsigned int lines)
@@ -85,28 +140,15 @@ EXPORT_SYMBOL(drm_fb_memcpy_dstclip);
 void drm_fb_swab16(u16 *dst, void *vaddr, struct drm_framebuffer *fb,
                   struct drm_rect *clip)
 {
-       size_t len = (clip->x2 - clip->x1) * sizeof(u16);
-       unsigned int x, y;
-       u16 *src, *buf;
+       struct drm_format_convert *conv = &convert_swab16;
+       unsigned int src_offset =
+               clip_offset(clip, fb->pitches[0], conv->src_cpp);
+       size_t pixels = (clip->x2 - clip->x1);
+       size_t lines = (clip->y2 - clip->y1);
 
-       /*
-        * The cma memory is write-combined so reads are uncached.
-        * Speed up by fetching one line at a time.
-        */
-       buf = kmalloc(len, GFP_KERNEL);
-       if (!buf)
-               return;
-
-       for (y = clip->y1; y < clip->y2; y++) {
-               src = vaddr + (y * fb->pitches[0]);
-               src += clip->x1;
-               memcpy(buf, src, len);
-               src = buf;
-               for (x = clip->x1; x < clip->x2; x++)
-                       *dst++ = swab16(*src++);
-       }
-
-       kfree(buf);
+       convert_lines(dst, pixels * conv->dst_cpp,
+                     vaddr + src_offset, fb->pitches[0],
+                     pixels, lines, conv);
 }
 EXPORT_SYMBOL(drm_fb_swab16);
 
-- 
2.18.1

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

Reply via email to