Move destination-buffer clipping from all format-helper conversion functions into callers. Support destination-buffer pitch. Only distinguish between system and I/O memory, but use same logic everywhere. Simply harmonize the interface and semantics of the existing code. Not all conversion helpers support all combinations of parameters. We have to add additional features when we need them. v2: * fix default destination pitch in drm_fb_xrgb8888_to_gray8() (Noralf) Signed-off-by: Thomas Zimmermann <tzimmermann@xxxxxxx> Tested-by: Noralf Trønnes <noralf@xxxxxxxxxxx> Reviewed-by: Noralf Trønnes <noralf@xxxxxxxxxxx> --- drivers/gpu/drm/drm_format_helper.c | 131 +++++++++++++++------------- drivers/gpu/drm/drm_mipi_dbi.c | 2 +- drivers/gpu/drm/gud/gud_pipe.c | 10 +-- drivers/gpu/drm/tiny/cirrus.c | 10 +-- drivers/gpu/drm/tiny/repaper.c | 2 +- drivers/gpu/drm/tiny/st7586.c | 2 +- include/drm/drm_format_helper.h | 30 +++---- 7 files changed, 97 insertions(+), 90 deletions(-) diff --git a/drivers/gpu/drm/drm_format_helper.c b/drivers/gpu/drm/drm_format_helper.c index dac355320287..0c8933390fdd 100644 --- a/drivers/gpu/drm/drm_format_helper.c +++ b/drivers/gpu/drm/drm_format_helper.c @@ -165,7 +165,7 @@ void drm_fb_swab(void *dst, unsigned int dst_pitch, const void *src, } EXPORT_SYMBOL(drm_fb_swab); -static void drm_fb_xrgb8888_to_rgb332_line(u8 *dbuf, __le32 *sbuf, unsigned int pixels) +static void drm_fb_xrgb8888_to_rgb332_line(u8 *dbuf, const __le32 *sbuf, unsigned int pixels) { unsigned int x; u32 pix; @@ -181,23 +181,24 @@ static void drm_fb_xrgb8888_to_rgb332_line(u8 *dbuf, __le32 *sbuf, unsigned int /** * drm_fb_xrgb8888_to_rgb332 - Convert XRGB8888 to RGB332 clip buffer * @dst: RGB332 destination buffer + * @dst_pitch: Number of bytes between two consecutive scanlines within dst * @src: XRGB8888 source buffer * @fb: DRM framebuffer * @clip: Clip rectangle area to copy * * Drivers can use this function for RGB332 devices that don't natively support XRGB8888. - * - * This function does not apply clipping on dst, i.e. the destination is a small buffer - * containing the clip rect only. */ -void drm_fb_xrgb8888_to_rgb332(void *dst, void *src, struct drm_framebuffer *fb, - struct drm_rect *clip) +void drm_fb_xrgb8888_to_rgb332(void *dst, unsigned int dst_pitch, const void *src, + const struct drm_framebuffer *fb, const struct drm_rect *clip) { size_t width = drm_rect_width(clip); size_t src_len = width * sizeof(u32); unsigned int y; void *sbuf; + if (!dst_pitch) + dst_pitch = width; + /* Use a buffer to speed up access on buffers with uncached read mapping (i.e. WC) */ sbuf = kmalloc(src_len, GFP_KERNEL); if (!sbuf) @@ -208,14 +209,14 @@ void drm_fb_xrgb8888_to_rgb332(void *dst, void *src, struct drm_framebuffer *fb, memcpy(sbuf, src, src_len); drm_fb_xrgb8888_to_rgb332_line(dst, sbuf, width); src += fb->pitches[0]; - dst += width; + dst += dst_pitch; } kfree(sbuf); } EXPORT_SYMBOL(drm_fb_xrgb8888_to_rgb332); -static void drm_fb_xrgb8888_to_rgb565_line(u16 *dbuf, u32 *sbuf, +static void drm_fb_xrgb8888_to_rgb565_line(u16 *dbuf, const u32 *sbuf, unsigned int pixels, bool swab) { @@ -236,6 +237,7 @@ static void drm_fb_xrgb8888_to_rgb565_line(u16 *dbuf, u32 *sbuf, /** * drm_fb_xrgb8888_to_rgb565 - Convert XRGB8888 to RGB565 clip buffer * @dst: RGB565 destination buffer + * @dst_pitch: Number of bytes between two consecutive scanlines within dst * @vaddr: XRGB8888 source buffer * @fb: DRM framebuffer * @clip: Clip rectangle area to copy @@ -243,13 +245,10 @@ static void drm_fb_xrgb8888_to_rgb565_line(u16 *dbuf, u32 *sbuf, * * Drivers can use this function for RGB565 devices that don't natively * support XRGB8888. - * - * This function does not apply clipping on dst, i.e. the destination - * is a small buffer containing the clip rect only. */ -void drm_fb_xrgb8888_to_rgb565(void *dst, void *vaddr, - struct drm_framebuffer *fb, - struct drm_rect *clip, bool swab) +void drm_fb_xrgb8888_to_rgb565(void *dst, unsigned int dst_pitch, const void *vaddr, + const struct drm_framebuffer *fb, const struct drm_rect *clip, + bool swab) { size_t linepixels = clip->x2 - clip->x1; size_t src_len = linepixels * sizeof(u32); @@ -257,6 +256,9 @@ void drm_fb_xrgb8888_to_rgb565(void *dst, void *vaddr, unsigned y, lines = clip->y2 - clip->y1; void *sbuf; + if (!dst_pitch) + dst_pitch = dst_len; + /* * The cma memory is write-combined so reads are uncached. * Speed up by fetching one line at a time. @@ -270,7 +272,7 @@ void drm_fb_xrgb8888_to_rgb565(void *dst, void *vaddr, memcpy(sbuf, vaddr, src_len); drm_fb_xrgb8888_to_rgb565_line(dst, sbuf, linepixels, swab); vaddr += fb->pitches[0]; - dst += dst_len; + dst += dst_pitch; } kfree(sbuf); @@ -278,9 +280,9 @@ void drm_fb_xrgb8888_to_rgb565(void *dst, void *vaddr, EXPORT_SYMBOL(drm_fb_xrgb8888_to_rgb565); /** - * drm_fb_xrgb8888_to_rgb565_dstclip - Convert XRGB8888 to RGB565 clip buffer + * drm_fb_xrgb8888_to_rgb565_toio - Convert XRGB8888 to RGB565 clip buffer * @dst: RGB565 destination buffer (iomem) - * @dst_pitch: destination buffer pitch + * @dst_pitch: Number of bytes between two consecutive scanlines within dst * @vaddr: XRGB8888 source buffer * @fb: DRM framebuffer * @clip: Clip rectangle area to copy @@ -288,37 +290,36 @@ EXPORT_SYMBOL(drm_fb_xrgb8888_to_rgb565); * * Drivers can use this function for RGB565 devices that don't natively * support XRGB8888. - * - * This function applies clipping on dst, i.e. the destination is a - * full (iomem) framebuffer but only the clip rect content is copied over. */ -void drm_fb_xrgb8888_to_rgb565_dstclip(void __iomem *dst, unsigned int dst_pitch, - void *vaddr, struct drm_framebuffer *fb, - struct drm_rect *clip, bool swab) +void drm_fb_xrgb8888_to_rgb565_toio(void __iomem *dst, unsigned int dst_pitch, + const void *vaddr, const struct drm_framebuffer *fb, + const struct drm_rect *clip, bool swab) { size_t linepixels = clip->x2 - clip->x1; size_t dst_len = linepixels * sizeof(u16); unsigned 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], sizeof(u32)); - dst += clip_offset(clip, dst_pitch, sizeof(u16)); for (y = 0; y < lines; y++) { drm_fb_xrgb8888_to_rgb565_line(dbuf, vaddr, linepixels, swab); memcpy_toio(dst, dbuf, dst_len); vaddr += fb->pitches[0]; - dst += dst_len; + dst += dst_pitch; } kfree(dbuf); } -EXPORT_SYMBOL(drm_fb_xrgb8888_to_rgb565_dstclip); +EXPORT_SYMBOL(drm_fb_xrgb8888_to_rgb565_toio); -static void drm_fb_xrgb8888_to_rgb888_line(u8 *dbuf, u32 *sbuf, +static void drm_fb_xrgb8888_to_rgb888_line(u8 *dbuf, const u32 *sbuf, unsigned int pixels) { unsigned int x; @@ -333,24 +334,25 @@ static void drm_fb_xrgb8888_to_rgb888_line(u8 *dbuf, u32 *sbuf, /** * drm_fb_xrgb8888_to_rgb888 - Convert XRGB8888 to RGB888 clip buffer * @dst: RGB888 destination buffer + * @dst_pitch: Number of bytes between two consecutive scanlines within dst * @src: XRGB8888 source buffer * @fb: DRM framebuffer * @clip: Clip rectangle area to copy * * Drivers can use this function for RGB888 devices that don't natively * support XRGB8888. - * - * This function does not apply clipping on dst, i.e. the destination - * is a small buffer containing the clip rect only. */ -void drm_fb_xrgb8888_to_rgb888(void *dst, void *src, struct drm_framebuffer *fb, - struct drm_rect *clip) +void drm_fb_xrgb8888_to_rgb888(void *dst, unsigned int dst_pitch, const void *src, + const struct drm_framebuffer *fb, const struct drm_rect *clip) { size_t width = drm_rect_width(clip); size_t src_len = width * sizeof(u32); unsigned int y; void *sbuf; + if (!dst_pitch) + dst_pitch = width * 3; + /* Use a buffer to speed up access on buffers with uncached read mapping (i.e. WC) */ sbuf = kmalloc(src_len, GFP_KERNEL); if (!sbuf) @@ -361,7 +363,7 @@ void drm_fb_xrgb8888_to_rgb888(void *dst, void *src, struct drm_framebuffer *fb, memcpy(sbuf, src, src_len); drm_fb_xrgb8888_to_rgb888_line(dst, sbuf, width); src += fb->pitches[0]; - dst += width * 3; + dst += dst_pitch; } kfree(sbuf); @@ -369,48 +371,48 @@ void drm_fb_xrgb8888_to_rgb888(void *dst, void *src, struct drm_framebuffer *fb, EXPORT_SYMBOL(drm_fb_xrgb8888_to_rgb888); /** - * drm_fb_xrgb8888_to_rgb888_dstclip - Convert XRGB8888 to RGB888 clip buffer + * drm_fb_xrgb8888_to_rgb888_toio - Convert XRGB8888 to RGB888 clip buffer * @dst: RGB565 destination buffer (iomem) - * @dst_pitch: destination buffer pitch + * @dst_pitch: Number of bytes between two consecutive scanlines within dst * @vaddr: XRGB8888 source buffer * @fb: DRM framebuffer * @clip: Clip rectangle area to copy * * Drivers can use this function for RGB888 devices that don't natively * support XRGB8888. - * - * This function applies clipping on dst, i.e. the destination is a - * full (iomem) framebuffer but only the clip rect content is copied over. */ -void drm_fb_xrgb8888_to_rgb888_dstclip(void __iomem *dst, unsigned int dst_pitch, - void *vaddr, struct drm_framebuffer *fb, - struct drm_rect *clip) +void drm_fb_xrgb8888_to_rgb888_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 * 3; unsigned 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], sizeof(u32)); - dst += clip_offset(clip, dst_pitch, sizeof(u16)); for (y = 0; y < lines; y++) { drm_fb_xrgb8888_to_rgb888_line(dbuf, vaddr, linepixels); memcpy_toio(dst, dbuf, dst_len); vaddr += fb->pitches[0]; - dst += dst_len; + dst += dst_pitch; } kfree(dbuf); } -EXPORT_SYMBOL(drm_fb_xrgb8888_to_rgb888_dstclip); +EXPORT_SYMBOL(drm_fb_xrgb8888_to_rgb888_toio); /** * drm_fb_xrgb8888_to_gray8 - Convert XRGB8888 to grayscale * @dst: 8-bit grayscale destination buffer + * @dst_pitch: Number of bytes between two consecutive scanlines within dst * @vaddr: XRGB8888 source buffer * @fb: DRM framebuffer * @clip: Clip rectangle area to copy @@ -424,16 +426,21 @@ EXPORT_SYMBOL(drm_fb_xrgb8888_to_rgb888_dstclip); * * ITU BT.601 is used for the RGB -> luma (brightness) conversion. */ -void drm_fb_xrgb8888_to_gray8(u8 *dst, void *vaddr, struct drm_framebuffer *fb, - struct drm_rect *clip) +void drm_fb_xrgb8888_to_gray8(void *dst, unsigned int dst_pitch, const void *vaddr, + const struct drm_framebuffer *fb, const struct drm_rect *clip) { unsigned int len = (clip->x2 - clip->x1) * sizeof(u32); unsigned int x, y; void *buf; - u32 *src; + u8 *dst8; + u32 *src32; if (WARN_ON(fb->format->format != DRM_FORMAT_XRGB8888)) return; + + if (!dst_pitch) + dst_pitch = drm_rect_width(clip); + /* * The cma memory is write-combined so reads are uncached. * Speed up by fetching one line at a time. @@ -442,20 +449,22 @@ void drm_fb_xrgb8888_to_gray8(u8 *dst, void *vaddr, struct drm_framebuffer *fb, if (!buf) return; + vaddr += clip_offset(clip, fb->pitches[0], sizeof(u32)); for (y = clip->y1; y < clip->y2; y++) { - src = vaddr + (y * fb->pitches[0]); - src += clip->x1; - memcpy(buf, src, len); - src = buf; + dst8 = dst; + src32 = memcpy(buf, vaddr, len); for (x = clip->x1; x < clip->x2; x++) { - u8 r = (*src & 0x00ff0000) >> 16; - u8 g = (*src & 0x0000ff00) >> 8; - u8 b = *src & 0x000000ff; + u8 r = (*src32 & 0x00ff0000) >> 16; + u8 g = (*src32 & 0x0000ff00) >> 8; + u8 b = *src32 & 0x000000ff; /* ITU BT.601: Y = 0.299 R + 0.587 G + 0.114 B */ - *dst++ = (3 * r + 6 * g + b) / 10; - src++; + *dst8++ = (3 * r + 6 * g + b) / 10; + src32++; } + + vaddr += fb->pitches[0]; + dst += dst_pitch; } kfree(buf); @@ -502,15 +511,15 @@ int drm_fb_blit_rect_dstclip(void __iomem *dst, unsigned int dst_pitch, } else if (dst_format == DRM_FORMAT_RGB565) { if (fb_format == DRM_FORMAT_XRGB8888) { - drm_fb_xrgb8888_to_rgb565_dstclip(dst, dst_pitch, - vmap, fb, clip, - false); + dst += clip_offset(clip, dst_pitch, fb->format->cpp[0]); + drm_fb_xrgb8888_to_rgb565_toio(dst, dst_pitch, vmap, fb, clip, + false); return 0; } } else if (dst_format == DRM_FORMAT_RGB888) { if (fb_format == DRM_FORMAT_XRGB8888) { - drm_fb_xrgb8888_to_rgb888_dstclip(dst, dst_pitch, - vmap, fb, clip); + dst += clip_offset(clip, dst_pitch, fb->format->cpp[0]); + drm_fb_xrgb8888_to_rgb888_toio(dst, dst_pitch, vmap, fb, clip); return 0; } } diff --git a/drivers/gpu/drm/drm_mipi_dbi.c b/drivers/gpu/drm/drm_mipi_dbi.c index 7ce89917d761..b75403f3251a 100644 --- a/drivers/gpu/drm/drm_mipi_dbi.c +++ b/drivers/gpu/drm/drm_mipi_dbi.c @@ -216,7 +216,7 @@ int mipi_dbi_buf_copy(void *dst, struct drm_framebuffer *fb, drm_fb_memcpy(dst, 0, src, fb, clip); break; case DRM_FORMAT_XRGB8888: - drm_fb_xrgb8888_to_rgb565(dst, src, fb, clip, swap); + drm_fb_xrgb8888_to_rgb565(dst, 0, src, fb, clip, swap); break; default: drm_err_once(fb->dev, "Format is not supported: %p4cc\n", diff --git a/drivers/gpu/drm/gud/gud_pipe.c b/drivers/gpu/drm/gud/gud_pipe.c index e0b117b2559f..a150a5a4b5d4 100644 --- a/drivers/gpu/drm/gud/gud_pipe.c +++ b/drivers/gpu/drm/gud/gud_pipe.c @@ -74,7 +74,7 @@ static size_t gud_xrgb8888_to_r124(u8 *dst, const struct drm_format_info *format if (!buf) return 0; - drm_fb_xrgb8888_to_gray8(buf, src, fb, rect); + drm_fb_xrgb8888_to_gray8(buf, 0, src, fb, rect); pix8 = buf; for (y = 0; y < height; y++) { @@ -190,13 +190,13 @@ static int gud_prep_flush(struct gud_device *gdrm, struct drm_framebuffer *fb, goto end_cpu_access; } } else if (format->format == DRM_FORMAT_R8) { - drm_fb_xrgb8888_to_gray8(buf, vaddr, fb, rect); + drm_fb_xrgb8888_to_gray8(buf, 0, vaddr, fb, rect); } else if (format->format == DRM_FORMAT_RGB332) { - drm_fb_xrgb8888_to_rgb332(buf, vaddr, fb, rect); + drm_fb_xrgb8888_to_rgb332(buf, 0, vaddr, fb, rect); } else if (format->format == DRM_FORMAT_RGB565) { - drm_fb_xrgb8888_to_rgb565(buf, vaddr, fb, rect, gud_is_big_endian()); + drm_fb_xrgb8888_to_rgb565(buf, 0, vaddr, fb, rect, gud_is_big_endian()); } else if (format->format == DRM_FORMAT_RGB888) { - drm_fb_xrgb8888_to_rgb888(buf, vaddr, fb, rect); + drm_fb_xrgb8888_to_rgb888(buf, 0, vaddr, fb, rect); } else { len = gud_xrgb8888_to_color(buf, format, vaddr, fb, rect); } diff --git a/drivers/gpu/drm/tiny/cirrus.c b/drivers/gpu/drm/tiny/cirrus.c index 5344e506e8a9..9327001d35dd 100644 --- a/drivers/gpu/drm/tiny/cirrus.c +++ b/drivers/gpu/drm/tiny/cirrus.c @@ -329,14 +329,12 @@ static int cirrus_fb_blit_rect(struct drm_framebuffer *fb, const struct dma_buf_ drm_fb_memcpy_toio(dst, fb->pitches[0], vmap, fb, rect); } else if (fb->format->cpp[0] == 4 && cirrus->cpp == 2) { - drm_fb_xrgb8888_to_rgb565_dstclip(cirrus->vram, - cirrus->pitch, - vmap, fb, rect, false); + dst += drm_fb_clip_offset(cirrus->pitch, fb->format, rect); + drm_fb_xrgb8888_to_rgb565_toio(dst, cirrus->pitch, vmap, fb, rect, false); } else if (fb->format->cpp[0] == 4 && cirrus->cpp == 3) { - drm_fb_xrgb8888_to_rgb888_dstclip(cirrus->vram, - cirrus->pitch, - vmap, fb, rect); + dst += drm_fb_clip_offset(cirrus->pitch, fb->format, rect); + drm_fb_xrgb8888_to_rgb888_toio(dst, cirrus->pitch, vmap, fb, rect); } else { WARN_ON_ONCE("cpp mismatch"); diff --git a/drivers/gpu/drm/tiny/repaper.c b/drivers/gpu/drm/tiny/repaper.c index 4d07b21a16e6..97a775c48cea 100644 --- a/drivers/gpu/drm/tiny/repaper.c +++ b/drivers/gpu/drm/tiny/repaper.c @@ -560,7 +560,7 @@ static int repaper_fb_dirty(struct drm_framebuffer *fb) if (ret) goto out_free; - drm_fb_xrgb8888_to_gray8(buf, cma_obj->vaddr, fb, &clip); + drm_fb_xrgb8888_to_gray8(buf, 0, cma_obj->vaddr, fb, &clip); drm_gem_fb_end_cpu_access(fb, DMA_FROM_DEVICE); diff --git a/drivers/gpu/drm/tiny/st7586.c b/drivers/gpu/drm/tiny/st7586.c index ad0faa8723c2..51b9b9fb3ead 100644 --- a/drivers/gpu/drm/tiny/st7586.c +++ b/drivers/gpu/drm/tiny/st7586.c @@ -73,7 +73,7 @@ static void st7586_xrgb8888_to_gray332(u8 *dst, void *vaddr, if (!buf) return; - drm_fb_xrgb8888_to_gray8(buf, vaddr, fb, clip); + drm_fb_xrgb8888_to_gray8(buf, 0, vaddr, fb, clip); src = buf; for (y = clip->y1; y < clip->y2; y++) { diff --git a/include/drm/drm_format_helper.h b/include/drm/drm_format_helper.h index ddcba5abe306..6b366f422a24 100644 --- a/include/drm/drm_format_helper.h +++ b/include/drm/drm_format_helper.h @@ -20,21 +20,21 @@ void drm_fb_memcpy_toio(void __iomem *dst, unsigned int dst_pitch, const void *v void drm_fb_swab(void *dst, unsigned int dst_pitch, const void *src, const struct drm_framebuffer *fb, const struct drm_rect *clip, bool cached); -void drm_fb_xrgb8888_to_rgb332(void *dst, void *vaddr, struct drm_framebuffer *fb, - struct drm_rect *clip); -void drm_fb_xrgb8888_to_rgb565(void *dst, void *vaddr, - struct drm_framebuffer *fb, - struct drm_rect *clip, bool swab); -void drm_fb_xrgb8888_to_rgb565_dstclip(void __iomem *dst, unsigned int dst_pitch, - void *vaddr, struct drm_framebuffer *fb, - struct drm_rect *clip, bool swab); -void drm_fb_xrgb8888_to_rgb888(void *dst, void *src, struct drm_framebuffer *fb, - struct drm_rect *clip); -void drm_fb_xrgb8888_to_rgb888_dstclip(void __iomem *dst, unsigned int dst_pitch, - void *vaddr, struct drm_framebuffer *fb, - struct drm_rect *clip); -void drm_fb_xrgb8888_to_gray8(u8 *dst, void *vaddr, struct drm_framebuffer *fb, - struct drm_rect *clip); +void drm_fb_xrgb8888_to_rgb332(void *dst, unsigned int dst_pitch, const void *vaddr, + const struct drm_framebuffer *fb, const struct drm_rect *clip); +void drm_fb_xrgb8888_to_rgb565(void *dst, unsigned int dst_pitch, const void *vaddr, + const struct drm_framebuffer *fb, const struct drm_rect *clip, + bool swab); +void drm_fb_xrgb8888_to_rgb565_toio(void __iomem *dst, unsigned int dst_pitch, + const void *vaddr, const struct drm_framebuffer *fb, + const struct drm_rect *clip, bool swab); +void drm_fb_xrgb8888_to_rgb888(void *dst, unsigned int dst_pitch, const void *src, + const struct drm_framebuffer *fb, const struct drm_rect *clip); +void drm_fb_xrgb8888_to_rgb888_toio(void __iomem *dst, unsigned int dst_pitch, + const void *vaddr, const struct drm_framebuffer *fb, + const struct drm_rect *clip); +void drm_fb_xrgb8888_to_gray8(void *dst, unsigned int dst_pitch, const void *vaddr, + const struct drm_framebuffer *fb, const struct drm_rect *clip); int drm_fb_blit_rect_dstclip(void __iomem *dst, unsigned int dst_pitch, uint32_t dst_format, void *vmap, -- 2.33.1 _______________________________________________ Virtualization mailing list Virtualization@xxxxxxxxxxxxxxxxxxxxxxxxxx https://lists.linuxfoundation.org/mailman/listinfo/virtualization