diff options
Diffstat (limited to 'drivers/gpu/drm/drm_format_helper.c')
-rw-r--r-- | drivers/gpu/drm/drm_format_helper.c | 96 |
1 files changed, 92 insertions, 4 deletions
diff --git a/drivers/gpu/drm/drm_format_helper.c b/drivers/gpu/drm/drm_format_helper.c index c043ca364c86..0e885cd34107 100644 --- a/drivers/gpu/drm/drm_format_helper.c +++ b/drivers/gpu/drm/drm_format_helper.c @@ -52,6 +52,7 @@ EXPORT_SYMBOL(drm_fb_memcpy); /** * drm_fb_memcpy_dstclip - Copy clip buffer * @dst: Destination buffer (iomem) + * @dst_pitch: Number of bytes between two consecutive scanlines within dst * @vaddr: Source buffer * @fb: DRM framebuffer * @clip: Clip rectangle area to copy @@ -59,12 +60,12 @@ EXPORT_SYMBOL(drm_fb_memcpy); * 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_memcpy_dstclip(void __iomem *dst, void *vaddr, - struct drm_framebuffer *fb, +void drm_fb_memcpy_dstclip(void __iomem *dst, unsigned int dst_pitch, + void *vaddr, struct drm_framebuffer *fb, struct drm_rect *clip) { unsigned int cpp = fb->format->cpp[0]; - unsigned int offset = clip_offset(clip, fb->pitches[0], cpp); + unsigned int offset = clip_offset(clip, dst_pitch, cpp); size_t len = (clip->x2 - clip->x1) * cpp; unsigned int y, lines = clip->y2 - clip->y1; @@ -73,7 +74,7 @@ void drm_fb_memcpy_dstclip(void __iomem *dst, void *vaddr, for (y = 0; y < lines; y++) { memcpy_toio(dst, vaddr, len); vaddr += fb->pitches[0]; - dst += fb->pitches[0]; + dst += dst_pitch; } } EXPORT_SYMBOL(drm_fb_memcpy_dstclip); @@ -343,3 +344,90 @@ void drm_fb_xrgb8888_to_gray8(u8 *dst, void *vaddr, struct drm_framebuffer *fb, } EXPORT_SYMBOL(drm_fb_xrgb8888_to_gray8); +/** + * drm_fb_blit_rect_dstclip - Copy parts of a framebuffer to display memory + * @dst: The display memory to copy to + * @dst_pitch: Number of bytes between two consecutive scanlines within dst + * @dst_format: FOURCC code of the display's color format + * @vmap: The framebuffer memory to copy from + * @fb: The framebuffer to copy from + * @clip: Clip rectangle area to copy + * + * This function copies parts of a framebuffer to display memory. If the + * formats of the display and the framebuffer mismatch, the blit function + * will attempt to convert between them. + * + * Use drm_fb_blit_dstclip() to copy the full framebuffer. + * + * Returns: + * 0 on success, or + * -EINVAL if the color-format conversion failed, or + * a negative error code otherwise. + */ +int drm_fb_blit_rect_dstclip(void __iomem *dst, unsigned int dst_pitch, + uint32_t dst_format, void *vmap, + struct drm_framebuffer *fb, + struct drm_rect *clip) +{ + uint32_t fb_format = fb->format->format; + + /* treat alpha channel like filler bits */ + if (fb_format == DRM_FORMAT_ARGB8888) + fb_format = DRM_FORMAT_XRGB8888; + if (dst_format == DRM_FORMAT_ARGB8888) + dst_format = DRM_FORMAT_XRGB8888; + + if (dst_format == fb_format) { + drm_fb_memcpy_dstclip(dst, dst_pitch, vmap, fb, clip); + return 0; + + } 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); + 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); + return 0; + } + } + + return -EINVAL; +} +EXPORT_SYMBOL(drm_fb_blit_rect_dstclip); + +/** + * drm_fb_blit_dstclip - Copy framebuffer to display memory + * @dst: The display memory to copy to + * @dst_pitch: Number of bytes between two consecutive scanlines within dst + * @dst_format: FOURCC code of the display's color format + * @vmap: The framebuffer memory to copy from + * @fb: The framebuffer to copy from + * + * This function copies a full framebuffer to display memory. If the formats + * of the display and the framebuffer mismatch, the copy function will + * attempt to convert between them. + * + * See drm_fb_blit_rect_dstclip() for more inforamtion. + * + * Returns: + * 0 on success, or a negative error code otherwise. + */ +int drm_fb_blit_dstclip(void __iomem *dst, unsigned int dst_pitch, + uint32_t dst_format, void *vmap, + struct drm_framebuffer *fb) +{ + struct drm_rect fullscreen = { + .x1 = 0, + .x2 = fb->width, + .y1 = 0, + .y2 = fb->height, + }; + return drm_fb_blit_rect_dstclip(dst, dst_pitch, dst_format, vmap, fb, + &fullscreen); +} +EXPORT_SYMBOL(drm_fb_blit_dstclip); |