From patchwork Sun Feb 2 12:40:16 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Zsolt Kajtar X-Patchwork-Id: 861466 Received: from c64.rulez.org (c64.rulez.org [79.139.58.36]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 777621DFDE for ; Sun, 2 Feb 2025 12:40:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=79.139.58.36 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738500022; cv=none; b=aGFhAG4itv8FdIKTwj6gNvnVvyixvteL+EGOhiDzNS792/iOYTs8h9j+eNXwkbYqbBOd/N5NlzWbV0wXC/T0Uy8afxrpRNhkXGGzfTF3xLw4MLqGTXXgoc89pP+V9o92AtFHcDpe3C4yXV21EL3D2+dOLGsWGkzw/WggLtkeZr4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738500022; c=relaxed/simple; bh=ggdaDmnMdP2zkYq6YsTuYl3zyA3wIV9cx3rS7rOxRdc=; h=Message-ID:Date:MIME-Version:Subject:From:To:References: In-Reply-To:Content-Type; b=MPGQwmxpEWFADlzmNcTIwv7j07+iQxjWd5MS7sMhFlDxDhc0OM4gxG1G/bdA23MRQrviinkD0sBy1Yw5eGZ/mLnfJPRYutftXTPdetjipluYX9bO6LK89gkWCZIBBZUia2xy/WGSbrsrkLcbWbwq2y1mcZlphY9muH6iLTq5dLU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=c64.rulez.org; spf=pass smtp.mailfrom=c64.rulez.org; arc=none smtp.client-ip=79.139.58.36 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=c64.rulez.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=c64.rulez.org Received: from [192.168.0.59] (unknown [89.134.12.53]) by c64.rulez.org (Postfix) with ESMTPSA id A2888100F6 for ; Sun, 2 Feb 2025 13:40:16 +0100 (CET) Message-ID: <0e2eba19-bc83-fd23-c9ff-59299a738bcf@c64.rulez.org> Date: Sun, 2 Feb 2025 13:40:16 +0100 Precedence: bulk X-Mailing-List: linux-fbdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Thunderbird/91.13.0 Subject: [RFC PATCH 01/12] Deduplicate cfb/sys drawing fbops Content-Language: en-GB From: =?utf-8?q?Kajt=C3=A1r_Zsolt?= To: linux-fbdev@vger.kernel.org References: In-Reply-To: Signed-off-by: Zsolt Kajtar Signed-off-by: Zsolt Kajtar --- drivers/video/fbdev/core/fb_copyarea.h | 440 +++++++++++++++++++++++++ 1 file changed, 440 insertions(+) create mode 100644 drivers/video/fbdev/core/fb_copyarea.h diff --git a/drivers/video/fbdev/core/fb_copyarea.h b/drivers/video/fbdev/core/fb_copyarea.h new file mode 100644 index 000000000..a271f57d9 --- /dev/null +++ b/drivers/video/fbdev/core/fb_copyarea.h @@ -0,0 +1,440 @@ +/* + * Generic function for frame buffer with packed pixels of any depth. + * + * Copyright (C) 1999-2005 James Simmons + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive for + * more details. + * + * NOTES: + * + * This is for cfb packed pixels. Iplan and such are incorporated in the + * drivers that need them. + * + * FIXME + * + * Also need to add code to deal with cards endians that are different than + * the native cpu endians. I also need to deal with MSB position in the word. + * + * The two functions or copying forward and backward could be split up like + * the ones for filling, i.e. in aligned and unaligned versions. This would + * help moving some redundant computations and branches out of the loop, too. + */ + +#include +#include +#include +#include +#include +#include +#include "fb_draw.h" + +#if BITS_PER_LONG == 32 +# define FB_WRITEL fb_writel +# define FB_READL fb_readl +#else +# define FB_WRITEL fb_writeq +# define FB_READL fb_readq +#endif + + /* + * Generic bitwise copy algorithm + */ + +static void +bitcpy(struct fb_info *p, unsigned long __iomem *dst, unsigned dst_idx, + const unsigned long __iomem *src, unsigned src_idx, int bits, + unsigned n, u32 bswapmask) +{ + unsigned long first, last; + int const shift = dst_idx-src_idx; + +#if 0 + /* + * If you suspect bug in this function, compare it with this simple + * memmove implementation. + */ + memmove((char *)dst + ((dst_idx & (bits - 1))) / 8, + (char *)src + ((src_idx & (bits - 1))) / 8, n / 8); + return; +#endif + + first = fb_shifted_pixels_mask_long(p, dst_idx, bswapmask); + last = ~fb_shifted_pixels_mask_long(p, (dst_idx+n) % bits, bswapmask); + + if (!shift) { + // Same alignment for source and dest + + if (dst_idx+n <= bits) { + // Single word + if (last) + first &= last; + FB_WRITEL( comp( FB_READL(src), FB_READL(dst), first), dst); + } else { + // Multiple destination words + + // Leading bits + if (first != ~0UL) { + FB_WRITEL( comp( FB_READL(src), FB_READL(dst), first), dst); + dst++; + src++; + n -= bits - dst_idx; + } + + // Main chunk + n /= bits; + while (n >= 8) { + FB_WRITEL(FB_READL(src++), dst++); + FB_WRITEL(FB_READL(src++), dst++); + FB_WRITEL(FB_READL(src++), dst++); + FB_WRITEL(FB_READL(src++), dst++); + FB_WRITEL(FB_READL(src++), dst++); + FB_WRITEL(FB_READL(src++), dst++); + FB_WRITEL(FB_READL(src++), dst++); + FB_WRITEL(FB_READL(src++), dst++); + n -= 8; + } + while (n--) + FB_WRITEL(FB_READL(src++), dst++); + + // Trailing bits + if (last) + FB_WRITEL( comp( FB_READL(src), FB_READL(dst), last), dst); + } + } else { + /* Different alignment for source and dest */ + unsigned long d0, d1; + int m; + + int const left = shift & (bits - 1); + int const right = -shift & (bits - 1); + + if (dst_idx+n <= bits) { + // Single destination word + if (last) + first &= last; + d0 = FB_READL(src); + d0 = fb_rev_pixels_in_long(d0, bswapmask); + if (shift > 0) { + // Single source word + d0 <<= left; + } else if (src_idx+n <= bits) { + // Single source word + d0 >>= right; + } else { + // 2 source words + d1 = FB_READL(src + 1); + d1 = fb_rev_pixels_in_long(d1, bswapmask); + d0 = d0 >> right | d1 << left; + } + d0 = fb_rev_pixels_in_long(d0, bswapmask); + FB_WRITEL(comp(d0, FB_READL(dst), first), dst); + } else { + // Multiple destination words + /** We must always remember the last value read, because in case + SRC and DST overlap bitwise (e.g. when moving just one pixel in + 1bpp), we always collect one full long for DST and that might + overlap with the current long from SRC. We store this value in + 'd0'. */ + d0 = FB_READL(src++); + d0 = fb_rev_pixels_in_long(d0, bswapmask); + // Leading bits + if (shift > 0) { + // Single source word + d1 = d0; + d0 <<= left; + n -= bits - dst_idx; + } else { + // 2 source words + d1 = FB_READL(src++); + d1 = fb_rev_pixels_in_long(d1, bswapmask); + + d0 = d0 >> right | d1 << left; + n -= bits - dst_idx; + } + d0 = fb_rev_pixels_in_long(d0, bswapmask); + FB_WRITEL(comp(d0, FB_READL(dst), first), dst); + d0 = d1; + dst++; + + // Main chunk + m = n % bits; + n /= bits; + while ((n >= 4) && !bswapmask) { + d1 = FB_READL(src++); + FB_WRITEL(d0 >> right | d1 << left, dst++); + d0 = d1; + d1 = FB_READL(src++); + FB_WRITEL(d0 >> right | d1 << left, dst++); + d0 = d1; + d1 = FB_READL(src++); + FB_WRITEL(d0 >> right | d1 << left, dst++); + d0 = d1; + d1 = FB_READL(src++); + FB_WRITEL(d0 >> right | d1 << left, dst++); + d0 = d1; + n -= 4; + } + while (n--) { + d1 = FB_READL(src++); + d1 = fb_rev_pixels_in_long(d1, bswapmask); + d0 = d0 >> right | d1 << left; + d0 = fb_rev_pixels_in_long(d0, bswapmask); + FB_WRITEL(d0, dst++); + d0 = d1; + } + + // Trailing bits + if (m) { + if (m <= bits - right) { + // Single source word + d0 >>= right; + } else { + // 2 source words + d1 = FB_READL(src); + d1 = fb_rev_pixels_in_long(d1, + bswapmask); + d0 = d0 >> right | d1 << left; + } + d0 = fb_rev_pixels_in_long(d0, bswapmask); + FB_WRITEL(comp(d0, FB_READL(dst), last), dst); + } + } + } +} + + /* + * Generic bitwise copy algorithm, operating backward + */ + +static void +bitcpy_rev(struct fb_info *p, unsigned long __iomem *dst, unsigned dst_idx, + const unsigned long __iomem *src, unsigned src_idx, int bits, + unsigned n, u32 bswapmask) +{ + unsigned long first, last; + int shift; + +#if 0 + /* + * If you suspect bug in this function, compare it with this simple + * memmove implementation. + */ + memmove((char *)dst + ((dst_idx & (bits - 1))) / 8, + (char *)src + ((src_idx & (bits - 1))) / 8, n / 8); + return; +#endif + + dst += (dst_idx + n - 1) / bits; + src += (src_idx + n - 1) / bits; + dst_idx = (dst_idx + n - 1) % bits; + src_idx = (src_idx + n - 1) % bits; + + shift = dst_idx-src_idx; + + first = ~fb_shifted_pixels_mask_long(p, (dst_idx + 1) % bits, bswapmask); + last = fb_shifted_pixels_mask_long(p, (bits + dst_idx + 1 - n) % bits, bswapmask); + + if (!shift) { + // Same alignment for source and dest + + if ((unsigned long)dst_idx+1 >= n) { + // Single word + if (first) + last &= first; + FB_WRITEL( comp( FB_READL(src), FB_READL(dst), last), dst); + } else { + // Multiple destination words + + // Leading bits + if (first) { + FB_WRITEL( comp( FB_READL(src), FB_READL(dst), first), dst); + dst--; + src--; + n -= dst_idx+1; + } + + // Main chunk + n /= bits; + while (n >= 8) { + FB_WRITEL(FB_READL(src--), dst--); + FB_WRITEL(FB_READL(src--), dst--); + FB_WRITEL(FB_READL(src--), dst--); + FB_WRITEL(FB_READL(src--), dst--); + FB_WRITEL(FB_READL(src--), dst--); + FB_WRITEL(FB_READL(src--), dst--); + FB_WRITEL(FB_READL(src--), dst--); + FB_WRITEL(FB_READL(src--), dst--); + n -= 8; + } + while (n--) + FB_WRITEL(FB_READL(src--), dst--); + + // Trailing bits + if (last != -1UL) + FB_WRITEL( comp( FB_READL(src), FB_READL(dst), last), dst); + } + } else { + // Different alignment for source and dest + unsigned long d0, d1; + int m; + + int const left = shift & (bits-1); + int const right = -shift & (bits-1); + + if ((unsigned long)dst_idx+1 >= n) { + // Single destination word + if (first) + last &= first; + d0 = FB_READL(src); + if (shift < 0) { + // Single source word + d0 >>= right; + } else if (1+(unsigned long)src_idx >= n) { + // Single source word + d0 <<= left; + } else { + // 2 source words + d1 = FB_READL(src - 1); + d1 = fb_rev_pixels_in_long(d1, bswapmask); + d0 = d0 << left | d1 >> right; + } + d0 = fb_rev_pixels_in_long(d0, bswapmask); + FB_WRITEL(comp(d0, FB_READL(dst), last), dst); + } else { + // Multiple destination words + /** We must always remember the last value read, because in case + SRC and DST overlap bitwise (e.g. when moving just one pixel in + 1bpp), we always collect one full long for DST and that might + overlap with the current long from SRC. We store this value in + 'd0'. */ + + d0 = FB_READL(src--); + d0 = fb_rev_pixels_in_long(d0, bswapmask); + // Leading bits + if (shift < 0) { + // Single source word + d1 = d0; + d0 >>= right; + } else { + // 2 source words + d1 = FB_READL(src--); + d1 = fb_rev_pixels_in_long(d1, bswapmask); + d0 = d0 << left | d1 >> right; + } + d0 = fb_rev_pixels_in_long(d0, bswapmask); + if (!first) + FB_WRITEL(d0, dst); + else + FB_WRITEL(comp(d0, FB_READL(dst), first), dst); + d0 = d1; + dst--; + n -= dst_idx+1; + + // Main chunk + m = n % bits; + n /= bits; + while ((n >= 4) && !bswapmask) { + d1 = FB_READL(src--); + FB_WRITEL(d0 << left | d1 >> right, dst--); + d0 = d1; + d1 = FB_READL(src--); + FB_WRITEL(d0 << left | d1 >> right, dst--); + d0 = d1; + d1 = FB_READL(src--); + FB_WRITEL(d0 << left | d1 >> right, dst--); + d0 = d1; + d1 = FB_READL(src--); + FB_WRITEL(d0 << left | d1 >> right, dst--); + d0 = d1; + n -= 4; + } + while (n--) { + d1 = FB_READL(src--); + d1 = fb_rev_pixels_in_long(d1, bswapmask); + d0 = d0 << left | d1 >> right; + d0 = fb_rev_pixels_in_long(d0, bswapmask); + FB_WRITEL(d0, dst--); + d0 = d1; + } + + // Trailing bits + if (m) { + if (m <= bits - left) { + // Single source word + d0 <<= left; + } else { + // 2 source words + d1 = FB_READL(src); + d1 = fb_rev_pixels_in_long(d1, + bswapmask); + d0 = d0 << left | d1 >> right; + } + d0 = fb_rev_pixels_in_long(d0, bswapmask); + FB_WRITEL(comp(d0, FB_READL(dst), last), dst); + } + } + } +} + +void cfb_copyarea(struct fb_info *p, const struct fb_copyarea *area) +{ + u32 dx = area->dx, dy = area->dy, sx = area->sx, sy = area->sy; + u32 height = area->height, width = area->width; + unsigned int const bits_per_line = p->fix.line_length * 8u; + unsigned long __iomem *base = NULL; + int bits = BITS_PER_LONG, bytes = bits >> 3; + unsigned dst_idx = 0, src_idx = 0, rev_copy = 0; + u32 bswapmask = fb_compute_bswapmask(p); + + if (p->state != FBINFO_STATE_RUNNING) + return; + + if (p->flags & FBINFO_VIRTFB) + fb_warn_once(p, "Framebuffer is not in I/O address space."); + + /* if the beginning of the target area might overlap with the end of + the source area, be have to copy the area reverse. */ + if ((dy == sy && dx > sx) || (dy > sy)) { + dy += height; + sy += height; + rev_copy = 1; + } + + // split the base of the framebuffer into a long-aligned address and the + // index of the first bit + base = (unsigned long __iomem *)((unsigned long)p->screen_base & ~(bytes-1)); + dst_idx = src_idx = 8*((unsigned long)p->screen_base & (bytes-1)); + // add offset of source and target area + dst_idx += dy*bits_per_line + dx*p->var.bits_per_pixel; + src_idx += sy*bits_per_line + sx*p->var.bits_per_pixel; + + if (p->fbops->fb_sync) + p->fbops->fb_sync(p); + + if (rev_copy) { + while (height--) { + dst_idx -= bits_per_line; + src_idx -= bits_per_line; + bitcpy_rev(p, base + (dst_idx / bits), dst_idx % bits, + base + (src_idx / bits), src_idx % bits, bits, + width*p->var.bits_per_pixel, bswapmask); + } + } else { + while (height--) { + bitcpy(p, base + (dst_idx / bits), dst_idx % bits, + base + (src_idx / bits), src_idx % bits, bits, + width*p->var.bits_per_pixel, bswapmask); + dst_idx += bits_per_line; + src_idx += bits_per_line; + } + } +} + +EXPORT_SYMBOL(cfb_copyarea); + +MODULE_AUTHOR("James Simmons "); +MODULE_DESCRIPTION("Generic software accelerated copyarea"); +MODULE_LICENSE("GPL"); + From patchwork Sun Feb 2 12:42:15 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Zsolt Kajtar X-Patchwork-Id: 861465 Received: from c64.rulez.org (c64.rulez.org [79.139.58.36]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 27FE51DFDE for ; Sun, 2 Feb 2025 12:42:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=79.139.58.36 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738500139; cv=none; b=V4Fmz8beS2TnO89f8fnR1c95tk1T+wU2R4BOs7E6QJj3FE10E+ay72Z+KTBwObwWwx69LCIWbeWb/fFMnGOC+Bp3Sa0DFtsLVbsZzZy9swvVxEDwle8rVMC5Jl19Mi4/zkNe8I927/twykDR2vbfJeIx4Cn3udO32MR9nQz7elQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738500139; c=relaxed/simple; bh=1k3RRIM8BQwrGtTbiEjL3qJ6NqhZZzK40wzxIRhiYhA=; h=Message-ID:Date:MIME-Version:Subject:From:To:References: In-Reply-To:Content-Type; b=AIlJ0YkPnj4ilkmqvPBUdxvtrPoyrxzOoJxAlCDHY6q6BlAZDa1SDL1c8WIsh4SGOEhMD5ZVlLPdIR0a71+ZqgQ1WL0J/fAQuVAH3KPS5ld4xJMLoo1ayIWvOE4lxnhehncFbZKT19lgZUFn2I4U2GTw7BRNZs5P+PbJMW1YEjk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=c64.rulez.org; spf=pass smtp.mailfrom=c64.rulez.org; arc=none smtp.client-ip=79.139.58.36 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=c64.rulez.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=c64.rulez.org Received: from [192.168.0.59] (unknown [89.134.12.53]) by c64.rulez.org (Postfix) with ESMTPSA id 5B244100F6 for ; Sun, 2 Feb 2025 13:42:15 +0100 (CET) Message-ID: <50c335f3-d3c9-3f1d-dd3b-e78818425662@c64.rulez.org> Date: Sun, 2 Feb 2025 13:42:15 +0100 Precedence: bulk X-Mailing-List: linux-fbdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Thunderbird/91.13.0 Subject: [RFC PATCH 03/12] Deduplicate cfb/sys drawing fbops Content-Language: en-GB From: =?utf-8?q?Kajt=C3=A1r_Zsolt?= To: linux-fbdev@vger.kernel.org References: <0e2eba19-bc83-fd23-c9ff-59299a738bcf@c64.rulez.org> In-Reply-To: fbdev: core: Use generic copyarea for as cfb_copyarea Signed-off-by: Zsolt Kajtar --- drivers/video/fbdev/core/cfbcopyarea.c | 425 +------------------------ 1 file changed, 10 insertions(+), 415 deletions(-) diff --git a/drivers/video/fbdev/core/cfbcopyarea.c b/drivers/video/fbdev/core/cfbcopyarea.c index a271f57d9..a32859b6d 100644 --- a/drivers/video/fbdev/core/cfbcopyarea.c +++ b/drivers/video/fbdev/core/cfbcopyarea.c @@ -7,430 +7,25 @@ * License. See the file COPYING in the main directory of this archive for * more details. * - * NOTES: - * - * This is for cfb packed pixels. Iplan and such are incorporated in the - * drivers that need them. - * - * FIXME - * - * Also need to add code to deal with cards endians that are different than - * the native cpu endians. I also need to deal with MSB position in the word. - * - * The two functions or copying forward and backward could be split up like - * the ones for filling, i.e. in aligned and unaligned versions. This would - * help moving some redundant computations and branches out of the loop, too. */ #include -#include -#include #include #include -#include -#include "fb_draw.h" #if BITS_PER_LONG == 32 -# define FB_WRITEL fb_writel -# define FB_READL fb_readl +# define FB_WRITEL fb_writel +# define FB_READL fb_readl #else -# define FB_WRITEL fb_writeq -# define FB_READL fb_readq +# define FB_WRITEL fb_writeq +# define FB_READL fb_readq #endif - - /* - * Generic bitwise copy algorithm - */ - -static void -bitcpy(struct fb_info *p, unsigned long __iomem *dst, unsigned dst_idx, - const unsigned long __iomem *src, unsigned src_idx, int bits, - unsigned n, u32 bswapmask) -{ - unsigned long first, last; - int const shift = dst_idx-src_idx; - -#if 0 - /* - * If you suspect bug in this function, compare it with this simple - * memmove implementation. - */ - memmove((char *)dst + ((dst_idx & (bits - 1))) / 8, - (char *)src + ((src_idx & (bits - 1))) / 8, n / 8); - return; -#endif - - first = fb_shifted_pixels_mask_long(p, dst_idx, bswapmask); - last = ~fb_shifted_pixels_mask_long(p, (dst_idx+n) % bits, bswapmask); - - if (!shift) { - // Same alignment for source and dest - - if (dst_idx+n <= bits) { - // Single word - if (last) - first &= last; - FB_WRITEL( comp( FB_READL(src), FB_READL(dst), first), dst); - } else { - // Multiple destination words - - // Leading bits - if (first != ~0UL) { - FB_WRITEL( comp( FB_READL(src), FB_READL(dst), first), dst); - dst++; - src++; - n -= bits - dst_idx; - } - - // Main chunk - n /= bits; - while (n >= 8) { - FB_WRITEL(FB_READL(src++), dst++); - FB_WRITEL(FB_READL(src++), dst++); - FB_WRITEL(FB_READL(src++), dst++); - FB_WRITEL(FB_READL(src++), dst++); - FB_WRITEL(FB_READL(src++), dst++); - FB_WRITEL(FB_READL(src++), dst++); - FB_WRITEL(FB_READL(src++), dst++); - FB_WRITEL(FB_READL(src++), dst++); - n -= 8; - } - while (n--) - FB_WRITEL(FB_READL(src++), dst++); - - // Trailing bits - if (last) - FB_WRITEL( comp( FB_READL(src), FB_READL(dst), last), dst); - } - } else { - /* Different alignment for source and dest */ - unsigned long d0, d1; - int m; - - int const left = shift & (bits - 1); - int const right = -shift & (bits - 1); - - if (dst_idx+n <= bits) { - // Single destination word - if (last) - first &= last; - d0 = FB_READL(src); - d0 = fb_rev_pixels_in_long(d0, bswapmask); - if (shift > 0) { - // Single source word - d0 <<= left; - } else if (src_idx+n <= bits) { - // Single source word - d0 >>= right; - } else { - // 2 source words - d1 = FB_READL(src + 1); - d1 = fb_rev_pixels_in_long(d1, bswapmask); - d0 = d0 >> right | d1 << left; - } - d0 = fb_rev_pixels_in_long(d0, bswapmask); - FB_WRITEL(comp(d0, FB_READL(dst), first), dst); - } else { - // Multiple destination words - /** We must always remember the last value read, because in case - SRC and DST overlap bitwise (e.g. when moving just one pixel in - 1bpp), we always collect one full long for DST and that might - overlap with the current long from SRC. We store this value in - 'd0'. */ - d0 = FB_READL(src++); - d0 = fb_rev_pixels_in_long(d0, bswapmask); - // Leading bits - if (shift > 0) { - // Single source word - d1 = d0; - d0 <<= left; - n -= bits - dst_idx; - } else { - // 2 source words - d1 = FB_READL(src++); - d1 = fb_rev_pixels_in_long(d1, bswapmask); - - d0 = d0 >> right | d1 << left; - n -= bits - dst_idx; - } - d0 = fb_rev_pixels_in_long(d0, bswapmask); - FB_WRITEL(comp(d0, FB_READL(dst), first), dst); - d0 = d1; - dst++; - - // Main chunk - m = n % bits; - n /= bits; - while ((n >= 4) && !bswapmask) { - d1 = FB_READL(src++); - FB_WRITEL(d0 >> right | d1 << left, dst++); - d0 = d1; - d1 = FB_READL(src++); - FB_WRITEL(d0 >> right | d1 << left, dst++); - d0 = d1; - d1 = FB_READL(src++); - FB_WRITEL(d0 >> right | d1 << left, dst++); - d0 = d1; - d1 = FB_READL(src++); - FB_WRITEL(d0 >> right | d1 << left, dst++); - d0 = d1; - n -= 4; - } - while (n--) { - d1 = FB_READL(src++); - d1 = fb_rev_pixels_in_long(d1, bswapmask); - d0 = d0 >> right | d1 << left; - d0 = fb_rev_pixels_in_long(d0, bswapmask); - FB_WRITEL(d0, dst++); - d0 = d1; - } - - // Trailing bits - if (m) { - if (m <= bits - right) { - // Single source word - d0 >>= right; - } else { - // 2 source words - d1 = FB_READL(src); - d1 = fb_rev_pixels_in_long(d1, - bswapmask); - d0 = d0 >> right | d1 << left; - } - d0 = fb_rev_pixels_in_long(d0, bswapmask); - FB_WRITEL(comp(d0, FB_READL(dst), last), dst); - } - } - } -} - - /* - * Generic bitwise copy algorithm, operating backward - */ - -static void -bitcpy_rev(struct fb_info *p, unsigned long __iomem *dst, unsigned dst_idx, - const unsigned long __iomem *src, unsigned src_idx, int bits, - unsigned n, u32 bswapmask) -{ - unsigned long first, last; - int shift; - -#if 0 - /* - * If you suspect bug in this function, compare it with this simple - * memmove implementation. - */ - memmove((char *)dst + ((dst_idx & (bits - 1))) / 8, - (char *)src + ((src_idx & (bits - 1))) / 8, n / 8); - return; -#endif - - dst += (dst_idx + n - 1) / bits; - src += (src_idx + n - 1) / bits; - dst_idx = (dst_idx + n - 1) % bits; - src_idx = (src_idx + n - 1) % bits; - - shift = dst_idx-src_idx; - - first = ~fb_shifted_pixels_mask_long(p, (dst_idx + 1) % bits, bswapmask); - last = fb_shifted_pixels_mask_long(p, (bits + dst_idx + 1 - n) % bits, bswapmask); - - if (!shift) { - // Same alignment for source and dest - - if ((unsigned long)dst_idx+1 >= n) { - // Single word - if (first) - last &= first; - FB_WRITEL( comp( FB_READL(src), FB_READL(dst), last), dst); - } else { - // Multiple destination words - - // Leading bits - if (first) { - FB_WRITEL( comp( FB_READL(src), FB_READL(dst), first), dst); - dst--; - src--; - n -= dst_idx+1; - } - - // Main chunk - n /= bits; - while (n >= 8) { - FB_WRITEL(FB_READL(src--), dst--); - FB_WRITEL(FB_READL(src--), dst--); - FB_WRITEL(FB_READL(src--), dst--); - FB_WRITEL(FB_READL(src--), dst--); - FB_WRITEL(FB_READL(src--), dst--); - FB_WRITEL(FB_READL(src--), dst--); - FB_WRITEL(FB_READL(src--), dst--); - FB_WRITEL(FB_READL(src--), dst--); - n -= 8; - } - while (n--) - FB_WRITEL(FB_READL(src--), dst--); - - // Trailing bits - if (last != -1UL) - FB_WRITEL( comp( FB_READL(src), FB_READL(dst), last), dst); - } - } else { - // Different alignment for source and dest - unsigned long d0, d1; - int m; - - int const left = shift & (bits-1); - int const right = -shift & (bits-1); - - if ((unsigned long)dst_idx+1 >= n) { - // Single destination word - if (first) - last &= first; - d0 = FB_READL(src); - if (shift < 0) { - // Single source word - d0 >>= right; - } else if (1+(unsigned long)src_idx >= n) { - // Single source word - d0 <<= left; - } else { - // 2 source words - d1 = FB_READL(src - 1); - d1 = fb_rev_pixels_in_long(d1, bswapmask); - d0 = d0 << left | d1 >> right; - } - d0 = fb_rev_pixels_in_long(d0, bswapmask); - FB_WRITEL(comp(d0, FB_READL(dst), last), dst); - } else { - // Multiple destination words - /** We must always remember the last value read, because in case - SRC and DST overlap bitwise (e.g. when moving just one pixel in - 1bpp), we always collect one full long for DST and that might - overlap with the current long from SRC. We store this value in - 'd0'. */ - - d0 = FB_READL(src--); - d0 = fb_rev_pixels_in_long(d0, bswapmask); - // Leading bits - if (shift < 0) { - // Single source word - d1 = d0; - d0 >>= right; - } else { - // 2 source words - d1 = FB_READL(src--); - d1 = fb_rev_pixels_in_long(d1, bswapmask); - d0 = d0 << left | d1 >> right; - } - d0 = fb_rev_pixels_in_long(d0, bswapmask); - if (!first) - FB_WRITEL(d0, dst); - else - FB_WRITEL(comp(d0, FB_READL(dst), first), dst); - d0 = d1; - dst--; - n -= dst_idx+1; - - // Main chunk - m = n % bits; - n /= bits; - while ((n >= 4) && !bswapmask) { - d1 = FB_READL(src--); - FB_WRITEL(d0 << left | d1 >> right, dst--); - d0 = d1; - d1 = FB_READL(src--); - FB_WRITEL(d0 << left | d1 >> right, dst--); - d0 = d1; - d1 = FB_READL(src--); - FB_WRITEL(d0 << left | d1 >> right, dst--); - d0 = d1; - d1 = FB_READL(src--); - FB_WRITEL(d0 << left | d1 >> right, dst--); - d0 = d1; - n -= 4; - } - while (n--) { - d1 = FB_READL(src--); - d1 = fb_rev_pixels_in_long(d1, bswapmask); - d0 = d0 << left | d1 >> right; - d0 = fb_rev_pixels_in_long(d0, bswapmask); - FB_WRITEL(d0, dst--); - d0 = d1; - } - - // Trailing bits - if (m) { - if (m <= bits - left) { - // Single source word - d0 <<= left; - } else { - // 2 source words - d1 = FB_READL(src); - d1 = fb_rev_pixels_in_long(d1, - bswapmask); - d0 = d0 << left | d1 >> right; - } - d0 = fb_rev_pixels_in_long(d0, bswapmask); - FB_WRITEL(comp(d0, FB_READL(dst), last), dst); - } - } - } -} - -void cfb_copyarea(struct fb_info *p, const struct fb_copyarea *area) -{ - u32 dx = area->dx, dy = area->dy, sx = area->sx, sy = area->sy; - u32 height = area->height, width = area->width; - unsigned int const bits_per_line = p->fix.line_length * 8u; - unsigned long __iomem *base = NULL; - int bits = BITS_PER_LONG, bytes = bits >> 3; - unsigned dst_idx = 0, src_idx = 0, rev_copy = 0; - u32 bswapmask = fb_compute_bswapmask(p); - - if (p->state != FBINFO_STATE_RUNNING) - return; - - if (p->flags & FBINFO_VIRTFB) - fb_warn_once(p, "Framebuffer is not in I/O address space."); - - /* if the beginning of the target area might overlap with the end of - the source area, be have to copy the area reverse. */ - if ((dy == sy && dx > sx) || (dy > sy)) { - dy += height; - sy += height; - rev_copy = 1; - } - - // split the base of the framebuffer into a long-aligned address and the - // index of the first bit - base = (unsigned long __iomem *)((unsigned long)p->screen_base & ~(bytes-1)); - dst_idx = src_idx = 8*((unsigned long)p->screen_base & (bytes-1)); - // add offset of source and target area - dst_idx += dy*bits_per_line + dx*p->var.bits_per_pixel; - src_idx += sy*bits_per_line + sx*p->var.bits_per_pixel; - - if (p->fbops->fb_sync) - p->fbops->fb_sync(p); - - if (rev_copy) { - while (height--) { - dst_idx -= bits_per_line; - src_idx -= bits_per_line; - bitcpy_rev(p, base + (dst_idx / bits), dst_idx % bits, - base + (src_idx / bits), src_idx % bits, bits, - width*p->var.bits_per_pixel, bswapmask); - } - } else { - while (height--) { - bitcpy(p, base + (dst_idx / bits), dst_idx % bits, - base + (src_idx / bits), src_idx % bits, bits, - width*p->var.bits_per_pixel, bswapmask); - dst_idx += bits_per_line; - src_idx += bits_per_line; - } - } -} +#define FB_MEM /* nothing */ +#define FB_COPYAREA cfb_copyarea +#define FB_SPACE 0 +#define FB_SPACE_NAME "I/O" +#define FB_SCREEN_BASE(a) ((a)->screen_base) +#include "fb_copyarea.h" EXPORT_SYMBOL(cfb_copyarea); From patchwork Sun Feb 2 12:42:57 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Zsolt Kajtar X-Patchwork-Id: 862208 Received: from c64.rulez.org (c64.rulez.org [79.139.58.36]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id F2AA61DFDE for ; Sun, 2 Feb 2025 12:42:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=79.139.58.36 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738500184; cv=none; b=p3gLs/QVwSqZSO2efJci6ajiUq020Qr3U08zGWZ06djE9LuKGeF/VIxhLYE2HfVJ108v7XBLolNan/+sX8LDDC3+O5TgDaeHQgqvJEHAdqbfngLP5G7X6RHrDPMOMV3oLHC/SfKLVN1De594bgTVn4oqyM4bzzCCZySMYZnAMZA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738500184; c=relaxed/simple; bh=G4qx893KhBVwJjFvGwXqIrwItvWFwjEEBMfuXI4lbWY=; h=Message-ID:Date:MIME-Version:Subject:From:To:References: In-Reply-To:Content-Type; b=RYJS4fXvJ8AlomMwcW8DQAAZCzgi2K/pXOZtweS10KTUXwqe1ag7NubrNCSeWp3KCp5NDABnR4RXsRajm5IbFqEVQt3N+gbJ7uZwPpoWIzPBujoiIiwVvh8e9mNkA/SIE+5z/rYpqLIT+Twkuo+zRyLEvpzPzxLD0QD3F48O3P8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=c64.rulez.org; spf=pass smtp.mailfrom=c64.rulez.org; arc=none smtp.client-ip=79.139.58.36 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=c64.rulez.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=c64.rulez.org Received: from [192.168.0.59] (unknown [89.134.12.53]) by c64.rulez.org (Postfix) with ESMTPSA id 88810100F6 for ; Sun, 2 Feb 2025 13:42:57 +0100 (CET) Message-ID: Date: Sun, 2 Feb 2025 13:42:57 +0100 Precedence: bulk X-Mailing-List: linux-fbdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Thunderbird/91.13.0 Subject: [RFC PATCH 04/12] Deduplicate cfb/sys drawing fbops Content-Language: en-GB From: =?utf-8?q?Kajt=C3=A1r_Zsolt?= To: linux-fbdev@vger.kernel.org References: <0e2eba19-bc83-fd23-c9ff-59299a738bcf@c64.rulez.org> <50c335f3-d3c9-3f1d-dd3b-e78818425662@c64.rulez.org> In-Reply-To: <50c335f3-d3c9-3f1d-dd3b-e78818425662@c64.rulez.org> fbdev: core: Use generic copyarea for as sys_copyarea Signed-off-by: Zsolt Kajtar --- drivers/video/fbdev/core/syscopyarea.c | 356 +------------------------ 1 file changed, 8 insertions(+), 348 deletions(-) diff --git a/drivers/video/fbdev/core/syscopyarea.c b/drivers/video/fbdev/core/syscopyarea.c index 75e7001e8..f720301e2 100644 --- a/drivers/video/fbdev/core/syscopyarea.c +++ b/drivers/video/fbdev/core/syscopyarea.c @@ -13,357 +13,17 @@ * */ #include -#include -#include #include #include -#include -#include "fb_draw.h" - /* - * Generic bitwise copy algorithm - */ - -static void -bitcpy(struct fb_info *p, unsigned long *dst, unsigned dst_idx, - const unsigned long *src, unsigned src_idx, int bits, unsigned n) -{ - unsigned long first, last; - int const shift = dst_idx-src_idx; - int left, right; - - first = FB_SHIFT_HIGH(p, ~0UL, dst_idx); - last = ~(FB_SHIFT_HIGH(p, ~0UL, (dst_idx+n) % bits)); - - if (!shift) { - /* Same alignment for source and dest */ - if (dst_idx+n <= bits) { - /* Single word */ - if (last) - first &= last; - *dst = comp(*src, *dst, first); - } else { - /* Multiple destination words */ - /* Leading bits */ - if (first != ~0UL) { - *dst = comp(*src, *dst, first); - dst++; - src++; - n -= bits - dst_idx; - } - - /* Main chunk */ - n /= bits; - while (n >= 8) { - *dst++ = *src++; - *dst++ = *src++; - *dst++ = *src++; - *dst++ = *src++; - *dst++ = *src++; - *dst++ = *src++; - *dst++ = *src++; - *dst++ = *src++; - n -= 8; - } - while (n--) - *dst++ = *src++; - - /* Trailing bits */ - if (last) - *dst = comp(*src, *dst, last); - } - } else { - unsigned long d0, d1; - int m; - - /* Different alignment for source and dest */ - right = shift & (bits - 1); - left = -shift & (bits - 1); - - if (dst_idx+n <= bits) { - /* Single destination word */ - if (last) - first &= last; - if (shift > 0) { - /* Single source word */ - *dst = comp(*src << left, *dst, first); - } else if (src_idx+n <= bits) { - /* Single source word */ - *dst = comp(*src >> right, *dst, first); - } else { - /* 2 source words */ - d0 = *src++; - d1 = *src; - *dst = comp(d0 >> right | d1 << left, *dst, - first); - } - } else { - /* Multiple destination words */ - /** We must always remember the last value read, - because in case SRC and DST overlap bitwise (e.g. - when moving just one pixel in 1bpp), we always - collect one full long for DST and that might - overlap with the current long from SRC. We store - this value in 'd0'. */ - d0 = *src++; - /* Leading bits */ - if (shift > 0) { - /* Single source word */ - *dst = comp(d0 << left, *dst, first); - dst++; - n -= bits - dst_idx; - } else { - /* 2 source words */ - d1 = *src++; - *dst = comp(d0 >> right | d1 << left, *dst, - first); - d0 = d1; - dst++; - n -= bits - dst_idx; - } - - /* Main chunk */ - m = n % bits; - n /= bits; - while (n >= 4) { - d1 = *src++; - *dst++ = d0 >> right | d1 << left; - d0 = d1; - d1 = *src++; - *dst++ = d0 >> right | d1 << left; - d0 = d1; - d1 = *src++; - *dst++ = d0 >> right | d1 << left; - d0 = d1; - d1 = *src++; - *dst++ = d0 >> right | d1 << left; - d0 = d1; - n -= 4; - } - while (n--) { - d1 = *src++; - *dst++ = d0 >> right | d1 << left; - d0 = d1; - } - - /* Trailing bits */ - if (m) { - if (m <= bits - right) { - /* Single source word */ - d0 >>= right; - } else { - /* 2 source words */ - d1 = *src; - d0 = d0 >> right | d1 << left; - } - *dst = comp(d0, *dst, last); - } - } - } -} - - /* - * Generic bitwise copy algorithm, operating backward - */ - -static void -bitcpy_rev(struct fb_info *p, unsigned long *dst, unsigned dst_idx, - const unsigned long *src, unsigned src_idx, unsigned bits, - unsigned n) -{ - unsigned long first, last; - int shift; - - dst += (dst_idx + n - 1) / bits; - src += (src_idx + n - 1) / bits; - dst_idx = (dst_idx + n - 1) % bits; - src_idx = (src_idx + n - 1) % bits; - - shift = dst_idx-src_idx; - - first = ~FB_SHIFT_HIGH(p, ~0UL, (dst_idx + 1) % bits); - last = FB_SHIFT_HIGH(p, ~0UL, (bits + dst_idx + 1 - n) % bits); - - if (!shift) { - /* Same alignment for source and dest */ - if ((unsigned long)dst_idx+1 >= n) { - /* Single word */ - if (first) - last &= first; - *dst = comp(*src, *dst, last); - } else { - /* Multiple destination words */ - - /* Leading bits */ - if (first) { - *dst = comp(*src, *dst, first); - dst--; - src--; - n -= dst_idx+1; - } - - /* Main chunk */ - n /= bits; - while (n >= 8) { - *dst-- = *src--; - *dst-- = *src--; - *dst-- = *src--; - *dst-- = *src--; - *dst-- = *src--; - *dst-- = *src--; - *dst-- = *src--; - *dst-- = *src--; - n -= 8; - } - while (n--) - *dst-- = *src--; - /* Trailing bits */ - if (last != -1UL) - *dst = comp(*src, *dst, last); - } - } else { - /* Different alignment for source and dest */ - - int const left = shift & (bits-1); - int const right = -shift & (bits-1); - - if ((unsigned long)dst_idx+1 >= n) { - /* Single destination word */ - if (first) - last &= first; - if (shift < 0) { - /* Single source word */ - *dst = comp(*src >> right, *dst, last); - } else if (1+(unsigned long)src_idx >= n) { - /* Single source word */ - *dst = comp(*src << left, *dst, last); - } else { - /* 2 source words */ - *dst = comp(*src << left | *(src-1) >> right, - *dst, last); - } - } else { - /* Multiple destination words */ - /** We must always remember the last value read, - because in case SRC and DST overlap bitwise (e.g. - when moving just one pixel in 1bpp), we always - collect one full long for DST and that might - overlap with the current long from SRC. We store - this value in 'd0'. */ - unsigned long d0, d1; - int m; - - d0 = *src--; - /* Leading bits */ - if (shift < 0) { - /* Single source word */ - d1 = d0; - d0 >>= right; - } else { - /* 2 source words */ - d1 = *src--; - d0 = d0 << left | d1 >> right; - } - if (!first) - *dst = d0; - else - *dst = comp(d0, *dst, first); - d0 = d1; - dst--; - n -= dst_idx+1; - - /* Main chunk */ - m = n % bits; - n /= bits; - while (n >= 4) { - d1 = *src--; - *dst-- = d0 << left | d1 >> right; - d0 = d1; - d1 = *src--; - *dst-- = d0 << left | d1 >> right; - d0 = d1; - d1 = *src--; - *dst-- = d0 << left | d1 >> right; - d0 = d1; - d1 = *src--; - *dst-- = d0 << left | d1 >> right; - d0 = d1; - n -= 4; - } - while (n--) { - d1 = *src--; - *dst-- = d0 << left | d1 >> right; - d0 = d1; - } - - /* Trailing bits */ - if (m) { - if (m <= bits - left) { - /* Single source word */ - d0 <<= left; - } else { - /* 2 source words */ - d1 = *src; - d0 = d0 << left | d1 >> right; - } - *dst = comp(d0, *dst, last); - } - } - } -} - -void sys_copyarea(struct fb_info *p, const struct fb_copyarea *area) -{ - u32 dx = area->dx, dy = area->dy, sx = area->sx, sy = area->sy; - u32 height = area->height, width = area->width; - unsigned int const bits_per_line = p->fix.line_length * 8u; - unsigned long *base = NULL; - int bits = BITS_PER_LONG, bytes = bits >> 3; - unsigned dst_idx = 0, src_idx = 0, rev_copy = 0; - - if (p->state != FBINFO_STATE_RUNNING) - return; - - if (!(p->flags & FBINFO_VIRTFB)) - fb_warn_once(p, "Framebuffer is not in virtual address space."); - - /* if the beginning of the target area might overlap with the end of - the source area, be have to copy the area reverse. */ - if ((dy == sy && dx > sx) || (dy > sy)) { - dy += height; - sy += height; - rev_copy = 1; - } - - /* split the base of the framebuffer into a long-aligned address and - the index of the first bit */ - base = (unsigned long *)((unsigned long)p->screen_base & ~(bytes-1)); - dst_idx = src_idx = 8*((unsigned long)p->screen_base & (bytes-1)); - /* add offset of source and target area */ - dst_idx += dy*bits_per_line + dx*p->var.bits_per_pixel; - src_idx += sy*bits_per_line + sx*p->var.bits_per_pixel; - - if (p->fbops->fb_sync) - p->fbops->fb_sync(p); - - if (rev_copy) { - while (height--) { - dst_idx -= bits_per_line; - src_idx -= bits_per_line; - bitcpy_rev(p, base + (dst_idx / bits), dst_idx % bits, - base + (src_idx / bits), src_idx % bits, bits, - width*p->var.bits_per_pixel); - } - } else { - while (height--) { - bitcpy(p, base + (dst_idx / bits), dst_idx % bits, - base + (src_idx / bits), src_idx % bits, bits, - width*p->var.bits_per_pixel); - dst_idx += bits_per_line; - src_idx += bits_per_line; - } - } -} +#define FB_READL(a) (*a) +#define FB_WRITEL(a,b) do { *(b) = (a); } while (false) +#define FB_MEM /* nothing */ +#define FB_COPYAREA sys_copyarea +#define FB_SPACE FBINFO_VIRTFB +#define FB_SPACE_NAME "virtual" +#define FB_SCREEN_BASE(a) ((a)->screen_buffer) +#include "fb_copyarea.h" EXPORT_SYMBOL(sys_copyarea); From patchwork Sun Feb 2 12:43:30 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Zsolt Kajtar X-Patchwork-Id: 861464 Received: from c64.rulez.org (c64.rulez.org [79.139.58.36]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 575CF1DFDE for ; Sun, 2 Feb 2025 12:43:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=79.139.58.36 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738500216; cv=none; b=SuulUJQX5vDi8K+fPS06Q0Mv5LybN/CkN/TT2GtTTCa1OJw0P70UAYycjkf90f1cYF4jIR9BgbBhyY8HJyTUy1kma/fgd45M2f734DpYe4QIByFY/QQ/6S5dkB1oFx0TJkc9V9uMFAp3wSdSWj24H6qBMeC0pe2CIncK2It90q4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738500216; c=relaxed/simple; bh=qeiUnr3S5o50ZlIc/DV8ZR8WTQOYeoE5tExn5gVcmYY=; h=Message-ID:Date:MIME-Version:Subject:From:To:References: In-Reply-To:Content-Type; b=qQDhCS6K5p/Hr8wxlO9Pqy/nyYnaHB5sxhuUgd3K4ot1CWH3KCXmuyMWDNawJJDJcNdASgO1YxHhO+byYEaost2NO3fls5qlvqy38mazAU6v4FWZfU0wV4UR22ILLLzTft+iun8YRfO6qOZPRC6WZtbCJhu3oUAA7pfya5oevcA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=c64.rulez.org; spf=pass smtp.mailfrom=c64.rulez.org; arc=none smtp.client-ip=79.139.58.36 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=c64.rulez.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=c64.rulez.org Received: from [192.168.0.59] (unknown [89.134.12.53]) by c64.rulez.org (Postfix) with ESMTPSA id BBF08100F6 for ; Sun, 2 Feb 2025 13:43:30 +0100 (CET) Message-ID: Date: Sun, 2 Feb 2025 13:43:30 +0100 Precedence: bulk X-Mailing-List: linux-fbdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Thunderbird/91.13.0 Subject: [RFC PATCH 05/12] Deduplicate cfb/sys drawing fbops Content-Language: en-GB From: =?utf-8?q?Kajt=C3=A1r_Zsolt?= To: linux-fbdev@vger.kernel.org References: <0e2eba19-bc83-fd23-c9ff-59299a738bcf@c64.rulez.org> <50c335f3-d3c9-3f1d-dd3b-e78818425662@c64.rulez.org> In-Reply-To: fbdev: core: Copy cfbfillrect to fb_fillrect Signed-off-by: Zsolt Kajtar --- drivers/video/fbdev/core/fb_fillrect.h | 374 +++++++++++++++++++++++++ 1 file changed, 374 insertions(+) create mode 100644 drivers/video/fbdev/core/fb_fillrect.h diff --git a/drivers/video/fbdev/core/fb_fillrect.h b/drivers/video/fbdev/core/fb_fillrect.h new file mode 100644 index 000000000..cbaa4c9e2 --- /dev/null +++ b/drivers/video/fbdev/core/fb_fillrect.h @@ -0,0 +1,374 @@ +/* + * Generic fillrect for frame buffers with packed pixels of any depth. + * + * Copyright (C) 2000 James Simmons (jsimmons@linux-fbdev.org) + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive for + * more details. + * + * NOTES: + * + * Also need to add code to deal with cards endians that are different than + * the native cpu endians. I also need to deal with MSB position in the word. + * + */ +#include +#include +#include +#include +#include "fb_draw.h" + +#if BITS_PER_LONG == 32 +# define FB_WRITEL fb_writel +# define FB_READL fb_readl +#else +# define FB_WRITEL fb_writeq +# define FB_READL fb_readq +#endif + + /* + * Aligned pattern fill using 32/64-bit memory accesses + */ + +static void +bitfill_aligned(struct fb_info *p, unsigned long __iomem *dst, int dst_idx, + unsigned long pat, unsigned n, int bits, u32 bswapmask) +{ + unsigned long first, last; + + if (!n) + return; + + first = fb_shifted_pixels_mask_long(p, dst_idx, bswapmask); + last = ~fb_shifted_pixels_mask_long(p, (dst_idx+n) % bits, bswapmask); + + if (dst_idx+n <= bits) { + // Single word + if (last) + first &= last; + FB_WRITEL(comp(pat, FB_READL(dst), first), dst); + } else { + // Multiple destination words + + // Leading bits + if (first!= ~0UL) { + FB_WRITEL(comp(pat, FB_READL(dst), first), dst); + dst++; + n -= bits - dst_idx; + } + + // Main chunk + n /= bits; + while (n >= 8) { + FB_WRITEL(pat, dst++); + FB_WRITEL(pat, dst++); + FB_WRITEL(pat, dst++); + FB_WRITEL(pat, dst++); + FB_WRITEL(pat, dst++); + FB_WRITEL(pat, dst++); + FB_WRITEL(pat, dst++); + FB_WRITEL(pat, dst++); + n -= 8; + } + while (n--) + FB_WRITEL(pat, dst++); + + // Trailing bits + if (last) + FB_WRITEL(comp(pat, FB_READL(dst), last), dst); + } +} + + + /* + * Unaligned generic pattern fill using 32/64-bit memory accesses + * The pattern must have been expanded to a full 32/64-bit value + * Left/right are the appropriate shifts to convert to the pattern to be + * used for the next 32/64-bit word + */ + +static void +bitfill_unaligned(struct fb_info *p, unsigned long __iomem *dst, int dst_idx, + unsigned long pat, int left, int right, unsigned n, int bits) +{ + unsigned long first, last; + + if (!n) + return; + + first = FB_SHIFT_HIGH(p, ~0UL, dst_idx); + last = ~(FB_SHIFT_HIGH(p, ~0UL, (dst_idx+n) % bits)); + + if (dst_idx+n <= bits) { + // Single word + if (last) + first &= last; + FB_WRITEL(comp(pat, FB_READL(dst), first), dst); + } else { + // Multiple destination words + // Leading bits + if (first) { + FB_WRITEL(comp(pat, FB_READL(dst), first), dst); + dst++; + pat = pat << left | pat >> right; + n -= bits - dst_idx; + } + + // Main chunk + n /= bits; + while (n >= 4) { + FB_WRITEL(pat, dst++); + pat = pat << left | pat >> right; + FB_WRITEL(pat, dst++); + pat = pat << left | pat >> right; + FB_WRITEL(pat, dst++); + pat = pat << left | pat >> right; + FB_WRITEL(pat, dst++); + pat = pat << left | pat >> right; + n -= 4; + } + while (n--) { + FB_WRITEL(pat, dst++); + pat = pat << left | pat >> right; + } + + // Trailing bits + if (last) + FB_WRITEL(comp(pat, FB_READL(dst), last), dst); + } +} + + /* + * Aligned pattern invert using 32/64-bit memory accesses + */ +static void +bitfill_aligned_rev(struct fb_info *p, unsigned long __iomem *dst, + int dst_idx, unsigned long pat, unsigned n, int bits, + u32 bswapmask) +{ + unsigned long val = pat, dat; + unsigned long first, last; + + if (!n) + return; + + first = fb_shifted_pixels_mask_long(p, dst_idx, bswapmask); + last = ~fb_shifted_pixels_mask_long(p, (dst_idx+n) % bits, bswapmask); + + if (dst_idx+n <= bits) { + // Single word + if (last) + first &= last; + dat = FB_READL(dst); + FB_WRITEL(comp(dat ^ val, dat, first), dst); + } else { + // Multiple destination words + // Leading bits + if (first!=0UL) { + dat = FB_READL(dst); + FB_WRITEL(comp(dat ^ val, dat, first), dst); + dst++; + n -= bits - dst_idx; + } + + // Main chunk + n /= bits; + while (n >= 8) { + FB_WRITEL(FB_READL(dst) ^ val, dst); + dst++; + FB_WRITEL(FB_READL(dst) ^ val, dst); + dst++; + FB_WRITEL(FB_READL(dst) ^ val, dst); + dst++; + FB_WRITEL(FB_READL(dst) ^ val, dst); + dst++; + FB_WRITEL(FB_READL(dst) ^ val, dst); + dst++; + FB_WRITEL(FB_READL(dst) ^ val, dst); + dst++; + FB_WRITEL(FB_READL(dst) ^ val, dst); + dst++; + FB_WRITEL(FB_READL(dst) ^ val, dst); + dst++; + n -= 8; + } + while (n--) { + FB_WRITEL(FB_READL(dst) ^ val, dst); + dst++; + } + // Trailing bits + if (last) { + dat = FB_READL(dst); + FB_WRITEL(comp(dat ^ val, dat, last), dst); + } + } +} + + + /* + * Unaligned generic pattern invert using 32/64-bit memory accesses + * The pattern must have been expanded to a full 32/64-bit value + * Left/right are the appropriate shifts to convert to the pattern to be + * used for the next 32/64-bit word + */ + +static void +bitfill_unaligned_rev(struct fb_info *p, unsigned long __iomem *dst, + int dst_idx, unsigned long pat, int left, int right, + unsigned n, int bits) +{ + unsigned long first, last, dat; + + if (!n) + return; + + first = FB_SHIFT_HIGH(p, ~0UL, dst_idx); + last = ~(FB_SHIFT_HIGH(p, ~0UL, (dst_idx+n) % bits)); + + if (dst_idx+n <= bits) { + // Single word + if (last) + first &= last; + dat = FB_READL(dst); + FB_WRITEL(comp(dat ^ pat, dat, first), dst); + } else { + // Multiple destination words + + // Leading bits + if (first != 0UL) { + dat = FB_READL(dst); + FB_WRITEL(comp(dat ^ pat, dat, first), dst); + dst++; + pat = pat << left | pat >> right; + n -= bits - dst_idx; + } + + // Main chunk + n /= bits; + while (n >= 4) { + FB_WRITEL(FB_READL(dst) ^ pat, dst); + dst++; + pat = pat << left | pat >> right; + FB_WRITEL(FB_READL(dst) ^ pat, dst); + dst++; + pat = pat << left | pat >> right; + FB_WRITEL(FB_READL(dst) ^ pat, dst); + dst++; + pat = pat << left | pat >> right; + FB_WRITEL(FB_READL(dst) ^ pat, dst); + dst++; + pat = pat << left | pat >> right; + n -= 4; + } + while (n--) { + FB_WRITEL(FB_READL(dst) ^ pat, dst); + dst++; + pat = pat << left | pat >> right; + } + + // Trailing bits + if (last) { + dat = FB_READL(dst); + FB_WRITEL(comp(dat ^ pat, dat, last), dst); + } + } +} + +void cfb_fillrect(struct fb_info *p, const struct fb_fillrect *rect) +{ + unsigned long pat, pat2, fg; + unsigned long width = rect->width, height = rect->height; + int bits = BITS_PER_LONG, bytes = bits >> 3; + u32 bpp = p->var.bits_per_pixel; + unsigned long __iomem *dst; + int dst_idx, left; + + if (p->state != FBINFO_STATE_RUNNING) + return; + + if (p->flags & FBINFO_VIRTFB) + fb_warn_once(p, "Framebuffer is not in I/O address space."); + + if (p->fix.visual == FB_VISUAL_TRUECOLOR || + p->fix.visual == FB_VISUAL_DIRECTCOLOR ) + fg = ((u32 *) (p->pseudo_palette))[rect->color]; + else + fg = rect->color; + + pat = pixel_to_pat(bpp, fg); + + dst = (unsigned long __iomem *)((unsigned long)p->screen_base & ~(bytes-1)); + dst_idx = ((unsigned long)p->screen_base & (bytes - 1))*8; + dst_idx += rect->dy*p->fix.line_length*8+rect->dx*bpp; + /* FIXME For now we support 1-32 bpp only */ + left = bits % bpp; + if (p->fbops->fb_sync) + p->fbops->fb_sync(p); + if (!left) { + u32 bswapmask = fb_compute_bswapmask(p); + void (*fill_op32)(struct fb_info *p, + unsigned long __iomem *dst, int dst_idx, + unsigned long pat, unsigned n, int bits, + u32 bswapmask) = NULL; + + switch (rect->rop) { + case ROP_XOR: + fill_op32 = bitfill_aligned_rev; + break; + case ROP_COPY: + fill_op32 = bitfill_aligned; + break; + default: + printk( KERN_ERR "cfb_fillrect(): unknown rop, defaulting to ROP_COPY\n"); + fill_op32 = bitfill_aligned; + break; + } + while (height--) { + dst += dst_idx >> (ffs(bits) - 1); + dst_idx &= (bits - 1); + fill_op32(p, dst, dst_idx, pat, width*bpp, bits, + bswapmask); + dst_idx += p->fix.line_length*8; + } + } else { + int right, r; + void (*fill_op)(struct fb_info *p, unsigned long __iomem *dst, + int dst_idx, unsigned long pat, int left, + int right, unsigned n, int bits) = NULL; +#ifdef __LITTLE_ENDIAN + right = left; + left = bpp - right; +#else + right = bpp - left; +#endif + switch (rect->rop) { + case ROP_XOR: + fill_op = bitfill_unaligned_rev; + break; + case ROP_COPY: + fill_op = bitfill_unaligned; + break; + default: + printk(KERN_ERR "cfb_fillrect(): unknown rop, defaulting to ROP_COPY\n"); + fill_op = bitfill_unaligned; + break; + } + while (height--) { + dst += dst_idx / bits; + dst_idx &= (bits - 1); + r = dst_idx % bpp; + /* rotate pattern to the correct start position */ + pat2 = le_long_to_cpu(rolx(cpu_to_le_long(pat), r, bpp)); + fill_op(p, dst, dst_idx, pat2, left, right, + width*bpp, bits); + dst_idx += p->fix.line_length*8; + } + } +} + +EXPORT_SYMBOL(cfb_fillrect); + +MODULE_AUTHOR("James Simmons "); +MODULE_DESCRIPTION("Generic software accelerated fill rectangle"); +MODULE_LICENSE("GPL"); From patchwork Sun Feb 2 12:44:26 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Zsolt Kajtar X-Patchwork-Id: 862207 Received: from c64.rulez.org (c64.rulez.org [79.139.58.36]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E62AE1DFDE for ; Sun, 2 Feb 2025 12:44:27 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=79.139.58.36 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738500270; cv=none; b=pcjN9udmpbVuNjL0oLOd+OWYwZhjvd7BMSpSu9L7oHDPR6xb0mINSbnrOrhsiA7aoK8j2IRjAzDxblHfQYh6hg0i5L16yjm37FtBpmU5l53JafbK/E/IYDWNZ8uCpvD+cmn8PoP9i3Qn84o5QUpepCzBSIJOqmvQiJWTDoW7gZM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738500270; c=relaxed/simple; bh=SyNqmKw3UnjhV+zg23p2W2qbzlXnVzcyMGhARp+6fVs=; h=Message-ID:Date:MIME-Version:Subject:From:To:References: In-Reply-To:Content-Type; b=Ip4eJGXelbo7uff9XVClZ0lSAC/RGebrzhFNjtAL0eZ0olLamUiLZWTGFDYVLxyZ4un69G1i2ampHWxkEM3Bko/rL72lvx9khDsV54hsrwoIwE/f25tF61a+6xPjkLUa6qI6ExWxQ8XyEncRvslDhHMtfOm9niqdwOVE+0nnb3o= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=c64.rulez.org; spf=pass smtp.mailfrom=c64.rulez.org; arc=none smtp.client-ip=79.139.58.36 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=c64.rulez.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=c64.rulez.org Received: from [192.168.0.59] (unknown [89.134.12.53]) by c64.rulez.org (Postfix) with ESMTPSA id 43F58100F6 for ; Sun, 2 Feb 2025 13:44:26 +0100 (CET) Message-ID: <65535c64-6f8e-95b4-e171-528176969983@c64.rulez.org> Date: Sun, 2 Feb 2025 13:44:26 +0100 Precedence: bulk X-Mailing-List: linux-fbdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Thunderbird/91.13.0 Subject: [RFC PATCH 06/12] fbdev: core: Make fb_fillrect generic Content-Language: en-GB From: =?utf-8?q?Kajt=C3=A1r_Zsolt?= To: linux-fbdev@vger.kernel.org References: <0e2eba19-bc83-fd23-c9ff-59299a738bcf@c64.rulez.org> <50c335f3-d3c9-3f1d-dd3b-e78818425662@c64.rulez.org> In-Reply-To: fbdev: core: Make fb_fillrect generic Signed-off-by: Zsolt Kajtar --- drivers/video/fbdev/core/fb_fillrect.h | 89 +++++++++++--------------- 1 file changed, 37 insertions(+), 52 deletions(-) diff --git a/drivers/video/fbdev/core/fb_fillrect.h b/drivers/video/fbdev/core/fb_fillrect.h index cbaa4c9e2..3ee29e56d 100644 --- a/drivers/video/fbdev/core/fb_fillrect.h +++ b/drivers/video/fbdev/core/fb_fillrect.h @@ -13,26 +13,14 @@ * the native cpu endians. I also need to deal with MSB position in the word. * */ -#include -#include -#include -#include #include "fb_draw.h" -#if BITS_PER_LONG == 32 -# define FB_WRITEL fb_writel -# define FB_READL fb_readl -#else -# define FB_WRITEL fb_writeq -# define FB_READL fb_readq -#endif - /* * Aligned pattern fill using 32/64-bit memory accesses */ static void -bitfill_aligned(struct fb_info *p, unsigned long __iomem *dst, int dst_idx, +bitfill_aligned(struct fb_info *p, unsigned long FB_MEM *dst, int dst_idx, unsigned long pat, unsigned n, int bits, u32 bswapmask) { unsigned long first, last; @@ -44,21 +32,21 @@ bitfill_aligned(struct fb_info *p, unsigned long __iomem *dst, int dst_idx, last = ~fb_shifted_pixels_mask_long(p, (dst_idx+n) % bits, bswapmask); if (dst_idx+n <= bits) { - // Single word + /* Single word */ if (last) first &= last; FB_WRITEL(comp(pat, FB_READL(dst), first), dst); } else { - // Multiple destination words + /* Multiple destination words */ - // Leading bits + /* Leading bits */ if (first!= ~0UL) { FB_WRITEL(comp(pat, FB_READL(dst), first), dst); dst++; n -= bits - dst_idx; } - // Main chunk + /* Main chunk */ n /= bits; while (n >= 8) { FB_WRITEL(pat, dst++); @@ -74,7 +62,7 @@ bitfill_aligned(struct fb_info *p, unsigned long __iomem *dst, int dst_idx, while (n--) FB_WRITEL(pat, dst++); - // Trailing bits + /* Trailing bits */ if (last) FB_WRITEL(comp(pat, FB_READL(dst), last), dst); } @@ -89,7 +77,7 @@ bitfill_aligned(struct fb_info *p, unsigned long __iomem *dst, int dst_idx, */ static void -bitfill_unaligned(struct fb_info *p, unsigned long __iomem *dst, int dst_idx, +bitfill_unaligned(struct fb_info *p, unsigned long FB_MEM *dst, int dst_idx, unsigned long pat, int left, int right, unsigned n, int bits) { unsigned long first, last; @@ -101,13 +89,13 @@ bitfill_unaligned(struct fb_info *p, unsigned long __iomem *dst, int dst_idx, last = ~(FB_SHIFT_HIGH(p, ~0UL, (dst_idx+n) % bits)); if (dst_idx+n <= bits) { - // Single word + /* Single word */ if (last) first &= last; FB_WRITEL(comp(pat, FB_READL(dst), first), dst); } else { - // Multiple destination words - // Leading bits + /* Multiple destination words */ + /* Leading bits */ if (first) { FB_WRITEL(comp(pat, FB_READL(dst), first), dst); dst++; @@ -115,7 +103,7 @@ bitfill_unaligned(struct fb_info *p, unsigned long __iomem *dst, int dst_idx, n -= bits - dst_idx; } - // Main chunk + /* Main chunk */ n /= bits; while (n >= 4) { FB_WRITEL(pat, dst++); @@ -133,7 +121,7 @@ bitfill_unaligned(struct fb_info *p, unsigned long __iomem *dst, int dst_idx, pat = pat << left | pat >> right; } - // Trailing bits + /* Trailing bits */ if (last) FB_WRITEL(comp(pat, FB_READL(dst), last), dst); } @@ -143,7 +131,7 @@ bitfill_unaligned(struct fb_info *p, unsigned long __iomem *dst, int dst_idx, * Aligned pattern invert using 32/64-bit memory accesses */ static void -bitfill_aligned_rev(struct fb_info *p, unsigned long __iomem *dst, +bitfill_aligned_rev(struct fb_info *p, unsigned long FB_MEM *dst, int dst_idx, unsigned long pat, unsigned n, int bits, u32 bswapmask) { @@ -157,14 +145,14 @@ bitfill_aligned_rev(struct fb_info *p, unsigned long __iomem *dst, last = ~fb_shifted_pixels_mask_long(p, (dst_idx+n) % bits, bswapmask); if (dst_idx+n <= bits) { - // Single word + /* Single word */ if (last) first &= last; dat = FB_READL(dst); FB_WRITEL(comp(dat ^ val, dat, first), dst); } else { - // Multiple destination words - // Leading bits + /* Multiple destination words */ + /* Leading bits */ if (first!=0UL) { dat = FB_READL(dst); FB_WRITEL(comp(dat ^ val, dat, first), dst); @@ -172,7 +160,7 @@ bitfill_aligned_rev(struct fb_info *p, unsigned long __iomem *dst, n -= bits - dst_idx; } - // Main chunk + /* Main chunk */ n /= bits; while (n >= 8) { FB_WRITEL(FB_READL(dst) ^ val, dst); @@ -197,7 +185,7 @@ bitfill_aligned_rev(struct fb_info *p, unsigned long __iomem *dst, FB_WRITEL(FB_READL(dst) ^ val, dst); dst++; } - // Trailing bits + /* Trailing bits */ if (last) { dat = FB_READL(dst); FB_WRITEL(comp(dat ^ val, dat, last), dst); @@ -214,7 +202,7 @@ bitfill_aligned_rev(struct fb_info *p, unsigned long __iomem *dst, */ static void -bitfill_unaligned_rev(struct fb_info *p, unsigned long __iomem *dst, +bitfill_unaligned_rev(struct fb_info *p, unsigned long FB_MEM *dst, int dst_idx, unsigned long pat, int left, int right, unsigned n, int bits) { @@ -227,15 +215,15 @@ bitfill_unaligned_rev(struct fb_info *p, unsigned long __iomem *dst, last = ~(FB_SHIFT_HIGH(p, ~0UL, (dst_idx+n) % bits)); if (dst_idx+n <= bits) { - // Single word + /* Single word */ if (last) first &= last; dat = FB_READL(dst); FB_WRITEL(comp(dat ^ pat, dat, first), dst); } else { - // Multiple destination words + /* Multiple destination words */ - // Leading bits + /* Leading bits */ if (first != 0UL) { dat = FB_READL(dst); FB_WRITEL(comp(dat ^ pat, dat, first), dst); @@ -244,7 +232,7 @@ bitfill_unaligned_rev(struct fb_info *p, unsigned long __iomem *dst, n -= bits - dst_idx; } - // Main chunk + /* Main chunk */ n /= bits; while (n >= 4) { FB_WRITEL(FB_READL(dst) ^ pat, dst); @@ -267,7 +255,7 @@ bitfill_unaligned_rev(struct fb_info *p, unsigned long __iomem *dst, pat = pat << left | pat >> right; } - // Trailing bits + /* Trailing bits */ if (last) { dat = FB_READL(dst); FB_WRITEL(comp(dat ^ pat, dat, last), dst); @@ -275,20 +263,21 @@ bitfill_unaligned_rev(struct fb_info *p, unsigned long __iomem *dst, } } -void cfb_fillrect(struct fb_info *p, const struct fb_fillrect *rect) +void FB_FILLRECT(struct fb_info *p, const struct fb_fillrect *rect) { unsigned long pat, pat2, fg; unsigned long width = rect->width, height = rect->height; int bits = BITS_PER_LONG, bytes = bits >> 3; u32 bpp = p->var.bits_per_pixel; - unsigned long __iomem *dst; + unsigned long FB_MEM *dst; int dst_idx, left; if (p->state != FBINFO_STATE_RUNNING) return; - if (p->flags & FBINFO_VIRTFB) - fb_warn_once(p, "Framebuffer is not in I/O address space."); + if ((p->flags & FBINFO_VIRTFB) != FB_SPACE) + fb_warn_once(p, "Framebuffer is not in " FB_SPACE_NAME + " address space."); if (p->fix.visual == FB_VISUAL_TRUECOLOR || p->fix.visual == FB_VISUAL_DIRECTCOLOR ) @@ -298,8 +287,8 @@ void cfb_fillrect(struct fb_info *p, const struct fb_fillrect *rect) pat = pixel_to_pat(bpp, fg); - dst = (unsigned long __iomem *)((unsigned long)p->screen_base & ~(bytes-1)); - dst_idx = ((unsigned long)p->screen_base & (bytes - 1))*8; + dst = (unsigned long FB_MEM *)((unsigned long)FB_SCREEN_BASE(p) & ~(bytes-1)); + dst_idx = ((unsigned long)FB_SCREEN_BASE(p) & (bytes - 1))*8; dst_idx += rect->dy*p->fix.line_length*8+rect->dx*bpp; /* FIXME For now we support 1-32 bpp only */ left = bits % bpp; @@ -308,7 +297,7 @@ void cfb_fillrect(struct fb_info *p, const struct fb_fillrect *rect) if (!left) { u32 bswapmask = fb_compute_bswapmask(p); void (*fill_op32)(struct fb_info *p, - unsigned long __iomem *dst, int dst_idx, + unsigned long FB_MEM *dst, int dst_idx, unsigned long pat, unsigned n, int bits, u32 bswapmask) = NULL; @@ -320,7 +309,8 @@ void cfb_fillrect(struct fb_info *p, const struct fb_fillrect *rect) fill_op32 = bitfill_aligned; break; default: - printk( KERN_ERR "cfb_fillrect(): unknown rop, defaulting to ROP_COPY\n"); + printk( KERN_ERR FB_FILLRECT_NAME "(): unknown rop, " + "defaulting to ROP_COPY\n"); fill_op32 = bitfill_aligned; break; } @@ -333,7 +323,7 @@ void cfb_fillrect(struct fb_info *p, const struct fb_fillrect *rect) } } else { int right, r; - void (*fill_op)(struct fb_info *p, unsigned long __iomem *dst, + void (*fill_op)(struct fb_info *p, unsigned long FB_MEM *dst, int dst_idx, unsigned long pat, int left, int right, unsigned n, int bits) = NULL; #ifdef __LITTLE_ENDIAN @@ -350,7 +340,8 @@ void cfb_fillrect(struct fb_info *p, const struct fb_fillrect *rect) fill_op = bitfill_unaligned; break; default: - printk(KERN_ERR "cfb_fillrect(): unknown rop, defaulting to ROP_COPY\n"); + printk(KERN_ERR FB_FILLRECT_NAME "(): unknown rop, " + "defaulting to ROP_COPY\n"); fill_op = bitfill_unaligned; break; } @@ -366,9 +357,3 @@ void cfb_fillrect(struct fb_info *p, const struct fb_fillrect *rect) } } } - -EXPORT_SYMBOL(cfb_fillrect); - -MODULE_AUTHOR("James Simmons "); -MODULE_DESCRIPTION("Generic software accelerated fill rectangle"); -MODULE_LICENSE("GPL"); From patchwork Sun Feb 2 12:44:59 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Zsolt Kajtar X-Patchwork-Id: 861463 Received: from c64.rulez.org (c64.rulez.org [79.139.58.36]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 914B01D6DDC for ; Sun, 2 Feb 2025 12:45:01 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=79.139.58.36 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738500303; cv=none; b=kDoxdCjbCh+bfEnkqTnKQPMStnoRy+nyt1H+a5nNcgCZTYN+EZiUdV2gqFaFaOAT5TwAkOSEqAqWTaqkFuNxRTq9aghkj6/hlla/JxTSsP6u+/6Ki28LszKZkP/60KURDYcGI2RCxzI2JQ1qEumULlWhGh8CL3nLYcc0FI60ll4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738500303; c=relaxed/simple; bh=SDa6Sqr4Ms7p/aO5OpjLS9VOywpODTTeXGX0BS0oLqM=; h=Message-ID:Date:MIME-Version:Subject:From:To:References: In-Reply-To:Content-Type; b=f5SkJiSILt+/zvo41YiP/zpJ2ac/GadA3AMSCTAntGVJRoF6v5shR6Wnm87qzJX5XAXQm9n5y6YeOK0u3NZ3F2rFI6RNSoA1IDOEWWpMzKiDIUQ2cnLrzB9z3b1LD0x3EC7pOvseHtTubCtkccYB5TK2nm78pk/HFzE6lzA0xD8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=c64.rulez.org; spf=pass smtp.mailfrom=c64.rulez.org; arc=none smtp.client-ip=79.139.58.36 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=c64.rulez.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=c64.rulez.org Received: from [192.168.0.59] (unknown [89.134.12.53]) by c64.rulez.org (Postfix) with ESMTPSA id DB9AC100F6 for ; Sun, 2 Feb 2025 13:44:59 +0100 (CET) Message-ID: <15ae6780-b3a9-abad-047b-a650d193aba3@c64.rulez.org> Date: Sun, 2 Feb 2025 13:44:59 +0100 Precedence: bulk X-Mailing-List: linux-fbdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Thunderbird/91.13.0 Subject: [RFC PATCH 07/12] fbdev: core: Use generic fillrect for as, cfb_fillrect Content-Language: en-GB From: =?utf-8?q?Kajt=C3=A1r_Zsolt?= To: linux-fbdev@vger.kernel.org References: <0e2eba19-bc83-fd23-c9ff-59299a738bcf@c64.rulez.org> <50c335f3-d3c9-3f1d-dd3b-e78818425662@c64.rulez.org> <65535c64-6f8e-95b4-e171-528176969983@c64.rulez.org> In-Reply-To: <65535c64-6f8e-95b4-e171-528176969983@c64.rulez.org> fbdev: core: Use generic fillrect for as cfb_fillrect Signed-off-by: Zsolt Kajtar --- drivers/video/fbdev/core/cfbfillrect.c | 362 +------------------------ 1 file changed, 11 insertions(+), 351 deletions(-) diff --git a/drivers/video/fbdev/core/cfbfillrect.c b/drivers/video/fbdev/core/cfbfillrect.c index cbaa4c9e2..116d56de2 100644 --- a/drivers/video/fbdev/core/cfbfillrect.c +++ b/drivers/video/fbdev/core/cfbfillrect.c @@ -7,365 +7,25 @@ * License. See the file COPYING in the main directory of this archive for * more details. * - * NOTES: - * - * Also need to add code to deal with cards endians that are different than - * the native cpu endians. I also need to deal with MSB position in the word. - * */ #include -#include #include #include -#include "fb_draw.h" #if BITS_PER_LONG == 32 -# define FB_WRITEL fb_writel -# define FB_READL fb_readl -#else -# define FB_WRITEL fb_writeq -# define FB_READL fb_readq -#endif - - /* - * Aligned pattern fill using 32/64-bit memory accesses - */ - -static void -bitfill_aligned(struct fb_info *p, unsigned long __iomem *dst, int dst_idx, - unsigned long pat, unsigned n, int bits, u32 bswapmask) -{ - unsigned long first, last; - - if (!n) - return; - - first = fb_shifted_pixels_mask_long(p, dst_idx, bswapmask); - last = ~fb_shifted_pixels_mask_long(p, (dst_idx+n) % bits, bswapmask); - - if (dst_idx+n <= bits) { - // Single word - if (last) - first &= last; - FB_WRITEL(comp(pat, FB_READL(dst), first), dst); - } else { - // Multiple destination words - - // Leading bits - if (first!= ~0UL) { - FB_WRITEL(comp(pat, FB_READL(dst), first), dst); - dst++; - n -= bits - dst_idx; - } - - // Main chunk - n /= bits; - while (n >= 8) { - FB_WRITEL(pat, dst++); - FB_WRITEL(pat, dst++); - FB_WRITEL(pat, dst++); - FB_WRITEL(pat, dst++); - FB_WRITEL(pat, dst++); - FB_WRITEL(pat, dst++); - FB_WRITEL(pat, dst++); - FB_WRITEL(pat, dst++); - n -= 8; - } - while (n--) - FB_WRITEL(pat, dst++); - - // Trailing bits - if (last) - FB_WRITEL(comp(pat, FB_READL(dst), last), dst); - } -} - - - /* - * Unaligned generic pattern fill using 32/64-bit memory accesses - * The pattern must have been expanded to a full 32/64-bit value - * Left/right are the appropriate shifts to convert to the pattern to be - * used for the next 32/64-bit word - */ - -static void -bitfill_unaligned(struct fb_info *p, unsigned long __iomem *dst, int dst_idx, - unsigned long pat, int left, int right, unsigned n, int bits) -{ - unsigned long first, last; - - if (!n) - return; - - first = FB_SHIFT_HIGH(p, ~0UL, dst_idx); - last = ~(FB_SHIFT_HIGH(p, ~0UL, (dst_idx+n) % bits)); - - if (dst_idx+n <= bits) { - // Single word - if (last) - first &= last; - FB_WRITEL(comp(pat, FB_READL(dst), first), dst); - } else { - // Multiple destination words - // Leading bits - if (first) { - FB_WRITEL(comp(pat, FB_READL(dst), first), dst); - dst++; - pat = pat << left | pat >> right; - n -= bits - dst_idx; - } - - // Main chunk - n /= bits; - while (n >= 4) { - FB_WRITEL(pat, dst++); - pat = pat << left | pat >> right; - FB_WRITEL(pat, dst++); - pat = pat << left | pat >> right; - FB_WRITEL(pat, dst++); - pat = pat << left | pat >> right; - FB_WRITEL(pat, dst++); - pat = pat << left | pat >> right; - n -= 4; - } - while (n--) { - FB_WRITEL(pat, dst++); - pat = pat << left | pat >> right; - } - - // Trailing bits - if (last) - FB_WRITEL(comp(pat, FB_READL(dst), last), dst); - } -} - - /* - * Aligned pattern invert using 32/64-bit memory accesses - */ -static void -bitfill_aligned_rev(struct fb_info *p, unsigned long __iomem *dst, - int dst_idx, unsigned long pat, unsigned n, int bits, - u32 bswapmask) -{ - unsigned long val = pat, dat; - unsigned long first, last; - - if (!n) - return; - - first = fb_shifted_pixels_mask_long(p, dst_idx, bswapmask); - last = ~fb_shifted_pixels_mask_long(p, (dst_idx+n) % bits, bswapmask); - - if (dst_idx+n <= bits) { - // Single word - if (last) - first &= last; - dat = FB_READL(dst); - FB_WRITEL(comp(dat ^ val, dat, first), dst); - } else { - // Multiple destination words - // Leading bits - if (first!=0UL) { - dat = FB_READL(dst); - FB_WRITEL(comp(dat ^ val, dat, first), dst); - dst++; - n -= bits - dst_idx; - } - - // Main chunk - n /= bits; - while (n >= 8) { - FB_WRITEL(FB_READL(dst) ^ val, dst); - dst++; - FB_WRITEL(FB_READL(dst) ^ val, dst); - dst++; - FB_WRITEL(FB_READL(dst) ^ val, dst); - dst++; - FB_WRITEL(FB_READL(dst) ^ val, dst); - dst++; - FB_WRITEL(FB_READL(dst) ^ val, dst); - dst++; - FB_WRITEL(FB_READL(dst) ^ val, dst); - dst++; - FB_WRITEL(FB_READL(dst) ^ val, dst); - dst++; - FB_WRITEL(FB_READL(dst) ^ val, dst); - dst++; - n -= 8; - } - while (n--) { - FB_WRITEL(FB_READL(dst) ^ val, dst); - dst++; - } - // Trailing bits - if (last) { - dat = FB_READL(dst); - FB_WRITEL(comp(dat ^ val, dat, last), dst); - } - } -} - - - /* - * Unaligned generic pattern invert using 32/64-bit memory accesses - * The pattern must have been expanded to a full 32/64-bit value - * Left/right are the appropriate shifts to convert to the pattern to be - * used for the next 32/64-bit word - */ - -static void -bitfill_unaligned_rev(struct fb_info *p, unsigned long __iomem *dst, - int dst_idx, unsigned long pat, int left, int right, - unsigned n, int bits) -{ - unsigned long first, last, dat; - - if (!n) - return; - - first = FB_SHIFT_HIGH(p, ~0UL, dst_idx); - last = ~(FB_SHIFT_HIGH(p, ~0UL, (dst_idx+n) % bits)); - - if (dst_idx+n <= bits) { - // Single word - if (last) - first &= last; - dat = FB_READL(dst); - FB_WRITEL(comp(dat ^ pat, dat, first), dst); - } else { - // Multiple destination words - - // Leading bits - if (first != 0UL) { - dat = FB_READL(dst); - FB_WRITEL(comp(dat ^ pat, dat, first), dst); - dst++; - pat = pat << left | pat >> right; - n -= bits - dst_idx; - } - - // Main chunk - n /= bits; - while (n >= 4) { - FB_WRITEL(FB_READL(dst) ^ pat, dst); - dst++; - pat = pat << left | pat >> right; - FB_WRITEL(FB_READL(dst) ^ pat, dst); - dst++; - pat = pat << left | pat >> right; - FB_WRITEL(FB_READL(dst) ^ pat, dst); - dst++; - pat = pat << left | pat >> right; - FB_WRITEL(FB_READL(dst) ^ pat, dst); - dst++; - pat = pat << left | pat >> right; - n -= 4; - } - while (n--) { - FB_WRITEL(FB_READL(dst) ^ pat, dst); - dst++; - pat = pat << left | pat >> right; - } - - // Trailing bits - if (last) { - dat = FB_READL(dst); - FB_WRITEL(comp(dat ^ pat, dat, last), dst); - } - } -} - -void cfb_fillrect(struct fb_info *p, const struct fb_fillrect *rect) -{ - unsigned long pat, pat2, fg; - unsigned long width = rect->width, height = rect->height; - int bits = BITS_PER_LONG, bytes = bits >> 3; - u32 bpp = p->var.bits_per_pixel; - unsigned long __iomem *dst; - int dst_idx, left; - - if (p->state != FBINFO_STATE_RUNNING) - return; - - if (p->flags & FBINFO_VIRTFB) - fb_warn_once(p, "Framebuffer is not in I/O address space."); - - if (p->fix.visual == FB_VISUAL_TRUECOLOR || - p->fix.visual == FB_VISUAL_DIRECTCOLOR ) - fg = ((u32 *) (p->pseudo_palette))[rect->color]; - else - fg = rect->color; - - pat = pixel_to_pat(bpp, fg); - - dst = (unsigned long __iomem *)((unsigned long)p->screen_base & ~(bytes-1)); - dst_idx = ((unsigned long)p->screen_base & (bytes - 1))*8; - dst_idx += rect->dy*p->fix.line_length*8+rect->dx*bpp; - /* FIXME For now we support 1-32 bpp only */ - left = bits % bpp; - if (p->fbops->fb_sync) - p->fbops->fb_sync(p); - if (!left) { - u32 bswapmask = fb_compute_bswapmask(p); - void (*fill_op32)(struct fb_info *p, - unsigned long __iomem *dst, int dst_idx, - unsigned long pat, unsigned n, int bits, - u32 bswapmask) = NULL; - - switch (rect->rop) { - case ROP_XOR: - fill_op32 = bitfill_aligned_rev; - break; - case ROP_COPY: - fill_op32 = bitfill_aligned; - break; - default: - printk( KERN_ERR "cfb_fillrect(): unknown rop, defaulting to ROP_COPY\n"); - fill_op32 = bitfill_aligned; - break; - } - while (height--) { - dst += dst_idx >> (ffs(bits) - 1); - dst_idx &= (bits - 1); - fill_op32(p, dst, dst_idx, pat, width*bpp, bits, - bswapmask); - dst_idx += p->fix.line_length*8; - } - } else { - int right, r; - void (*fill_op)(struct fb_info *p, unsigned long __iomem *dst, - int dst_idx, unsigned long pat, int left, - int right, unsigned n, int bits) = NULL; -#ifdef __LITTLE_ENDIAN - right = left; - left = bpp - right; +# define FB_WRITEL fb_writel +# define FB_READL fb_readl #else - right = bpp - left; +# define FB_WRITEL fb_writeq +# define FB_READL fb_readq #endif - switch (rect->rop) { - case ROP_XOR: - fill_op = bitfill_unaligned_rev; - break; - case ROP_COPY: - fill_op = bitfill_unaligned; - break; - default: - printk(KERN_ERR "cfb_fillrect(): unknown rop, defaulting to ROP_COPY\n"); - fill_op = bitfill_unaligned; - break; - } - while (height--) { - dst += dst_idx / bits; - dst_idx &= (bits - 1); - r = dst_idx % bpp; - /* rotate pattern to the correct start position */ - pat2 = le_long_to_cpu(rolx(cpu_to_le_long(pat), r, bpp)); - fill_op(p, dst, dst_idx, pat2, left, right, - width*bpp, bits); - dst_idx += p->fix.line_length*8; - } - } -} +#define FB_MEM __iomem +#define FB_FILLRECT cfb_fillrect +#define FB_FILLRECT_NAME "cfb_fillrect" +#define FB_SPACE 0 +#define FB_SPACE_NAME "I/O" +#define FB_SCREEN_BASE(a) ((a)->screen_base) +#include "fb_fillrect.h" EXPORT_SYMBOL(cfb_fillrect); From patchwork Sun Feb 2 12:45:34 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Zsolt Kajtar X-Patchwork-Id: 862206 Received: from c64.rulez.org (c64.rulez.org [79.139.58.36]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id EFE67156885 for ; Sun, 2 Feb 2025 12:45:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=79.139.58.36 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738500337; cv=none; b=LjD8fyfFSkMbBS8uTbrhcN4a+wjNPTxzuCAdZYzMKwCkhVgS2d0g7BdDae2aU71XECgIsrtkGRFF8L8kzmgBXFO9aKxB2tT/HPsDRUmTpia7R0hEW0dS8zfqUkabEjWRpCSE/m75e/pYxkUzqnuyl+zVryfZ+GC6sdTuvP4+TEU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738500337; c=relaxed/simple; bh=zXdGKZ8a88/91/7b2h63DQXRghmd/vVjiwcgfI+WrsI=; h=Message-ID:Date:MIME-Version:Subject:From:To:References: In-Reply-To:Content-Type; b=Tp4n8fMWGXjpx2CzSwTzR2VegILy40HhRlfHlcbUXRI3GAg00cgTTnCP36O6y8nU8j9JMYjXRV+yG31vqE815vNwoqibxcUh6bHvi5BK7XGBdtsae2+/etC+bXNS8tclIV4g935m6qmqTQ9daP6xUo48cTFMbedg2IZrduLE9ug= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=c64.rulez.org; spf=pass smtp.mailfrom=c64.rulez.org; arc=none smtp.client-ip=79.139.58.36 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=c64.rulez.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=c64.rulez.org Received: from [192.168.0.59] (unknown [89.134.12.53]) by c64.rulez.org (Postfix) with ESMTPSA id 6562F100F6 for ; Sun, 2 Feb 2025 13:45:34 +0100 (CET) Message-ID: <7f2cf3dc-ae1e-7b6c-9c71-717b6f4453ea@c64.rulez.org> Date: Sun, 2 Feb 2025 13:45:34 +0100 Precedence: bulk X-Mailing-List: linux-fbdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Thunderbird/91.13.0 Subject: [RFC PATCH 08/12] fbdev: core: Use generic fillrect for as, sys_fillrect Content-Language: en-GB From: =?utf-8?q?Kajt=C3=A1r_Zsolt?= To: linux-fbdev@vger.kernel.org References: <0e2eba19-bc83-fd23-c9ff-59299a738bcf@c64.rulez.org> <50c335f3-d3c9-3f1d-dd3b-e78818425662@c64.rulez.org> <65535c64-6f8e-95b4-e171-528176969983@c64.rulez.org> <15ae6780-b3a9-abad-047b-a650d193aba3@c64.rulez.org> In-Reply-To: <15ae6780-b3a9-abad-047b-a650d193aba3@c64.rulez.org> fbdev: core: Use generic fillrect for as sys_fillrect Signed-off-by: Zsolt Kajtar --- drivers/video/fbdev/core/sysfillrect.c | 314 +------------------------ 1 file changed, 9 insertions(+), 305 deletions(-) diff --git a/drivers/video/fbdev/core/sysfillrect.c b/drivers/video/fbdev/core/sysfillrect.c index e49221a88..48d0f0efb 100644 --- a/drivers/video/fbdev/core/sysfillrect.c +++ b/drivers/video/fbdev/core/sysfillrect.c @@ -12,314 +12,18 @@ * more details. */ #include -#include #include #include -#include "fb_draw.h" - /* - * Aligned pattern fill using 32/64-bit memory accesses - */ - -static void -bitfill_aligned(struct fb_info *p, unsigned long *dst, int dst_idx, - unsigned long pat, unsigned n, int bits) -{ - unsigned long first, last; - - if (!n) - return; - - first = FB_SHIFT_HIGH(p, ~0UL, dst_idx); - last = ~(FB_SHIFT_HIGH(p, ~0UL, (dst_idx+n) % bits)); - - if (dst_idx+n <= bits) { - /* Single word */ - if (last) - first &= last; - *dst = comp(pat, *dst, first); - } else { - /* Multiple destination words */ - - /* Leading bits */ - if (first!= ~0UL) { - *dst = comp(pat, *dst, first); - dst++; - n -= bits - dst_idx; - } - - /* Main chunk */ - n /= bits; - memset_l(dst, pat, n); - dst += n; - - /* Trailing bits */ - if (last) - *dst = comp(pat, *dst, last); - } -} - - - /* - * Unaligned generic pattern fill using 32/64-bit memory accesses - * The pattern must have been expanded to a full 32/64-bit value - * Left/right are the appropriate shifts to convert to the pattern to be - * used for the next 32/64-bit word - */ - -static void -bitfill_unaligned(struct fb_info *p, unsigned long *dst, int dst_idx, - unsigned long pat, int left, int right, unsigned n, int bits) -{ - unsigned long first, last; - - if (!n) - return; - - first = FB_SHIFT_HIGH(p, ~0UL, dst_idx); - last = ~(FB_SHIFT_HIGH(p, ~0UL, (dst_idx+n) % bits)); - - if (dst_idx+n <= bits) { - /* Single word */ - if (last) - first &= last; - *dst = comp(pat, *dst, first); - } else { - /* Multiple destination words */ - /* Leading bits */ - if (first) { - *dst = comp(pat, *dst, first); - dst++; - pat = pat << left | pat >> right; - n -= bits - dst_idx; - } - - /* Main chunk */ - n /= bits; - while (n >= 4) { - *dst++ = pat; - pat = pat << left | pat >> right; - *dst++ = pat; - pat = pat << left | pat >> right; - *dst++ = pat; - pat = pat << left | pat >> right; - *dst++ = pat; - pat = pat << left | pat >> right; - n -= 4; - } - while (n--) { - *dst++ = pat; - pat = pat << left | pat >> right; - } - - /* Trailing bits */ - if (last) - *dst = comp(pat, *dst, last); - } -} - - /* - * Aligned pattern invert using 32/64-bit memory accesses - */ -static void -bitfill_aligned_rev(struct fb_info *p, unsigned long *dst, int dst_idx, - unsigned long pat, unsigned n, int bits) -{ - unsigned long val = pat; - unsigned long first, last; - - if (!n) - return; - - first = FB_SHIFT_HIGH(p, ~0UL, dst_idx); - last = ~(FB_SHIFT_HIGH(p, ~0UL, (dst_idx+n) % bits)); - - if (dst_idx+n <= bits) { - /* Single word */ - if (last) - first &= last; - *dst = comp(*dst ^ val, *dst, first); - } else { - /* Multiple destination words */ - /* Leading bits */ - if (first!=0UL) { - *dst = comp(*dst ^ val, *dst, first); - dst++; - n -= bits - dst_idx; - } - - /* Main chunk */ - n /= bits; - while (n >= 8) { - *dst++ ^= val; - *dst++ ^= val; - *dst++ ^= val; - *dst++ ^= val; - *dst++ ^= val; - *dst++ ^= val; - *dst++ ^= val; - *dst++ ^= val; - n -= 8; - } - while (n--) - *dst++ ^= val; - /* Trailing bits */ - if (last) - *dst = comp(*dst ^ val, *dst, last); - } -} - - - /* - * Unaligned generic pattern invert using 32/64-bit memory accesses - * The pattern must have been expanded to a full 32/64-bit value - * Left/right are the appropriate shifts to convert to the pattern to be - * used for the next 32/64-bit word - */ - -static void -bitfill_unaligned_rev(struct fb_info *p, unsigned long *dst, int dst_idx, - unsigned long pat, int left, int right, unsigned n, - int bits) -{ - unsigned long first, last; - - if (!n) - return; - - first = FB_SHIFT_HIGH(p, ~0UL, dst_idx); - last = ~(FB_SHIFT_HIGH(p, ~0UL, (dst_idx+n) % bits)); - - if (dst_idx+n <= bits) { - /* Single word */ - if (last) - first &= last; - *dst = comp(*dst ^ pat, *dst, first); - } else { - /* Multiple destination words */ - - /* Leading bits */ - if (first != 0UL) { - *dst = comp(*dst ^ pat, *dst, first); - dst++; - pat = pat << left | pat >> right; - n -= bits - dst_idx; - } - - /* Main chunk */ - n /= bits; - while (n >= 4) { - *dst++ ^= pat; - pat = pat << left | pat >> right; - *dst++ ^= pat; - pat = pat << left | pat >> right; - *dst++ ^= pat; - pat = pat << left | pat >> right; - *dst++ ^= pat; - pat = pat << left | pat >> right; - n -= 4; - } - while (n--) { - *dst ^= pat; - pat = pat << left | pat >> right; - } - - /* Trailing bits */ - if (last) - *dst = comp(*dst ^ pat, *dst, last); - } -} - -void sys_fillrect(struct fb_info *p, const struct fb_fillrect *rect) -{ - unsigned long pat, pat2, fg; - unsigned long width = rect->width, height = rect->height; - int bits = BITS_PER_LONG, bytes = bits >> 3; - u32 bpp = p->var.bits_per_pixel; - unsigned long *dst; - int dst_idx, left; - - if (p->state != FBINFO_STATE_RUNNING) - return; - - if (!(p->flags & FBINFO_VIRTFB)) - fb_warn_once(p, "Framebuffer is not in virtual address space."); - - if (p->fix.visual == FB_VISUAL_TRUECOLOR || - p->fix.visual == FB_VISUAL_DIRECTCOLOR ) - fg = ((u32 *) (p->pseudo_palette))[rect->color]; - else - fg = rect->color; - - pat = pixel_to_pat( bpp, fg); - - dst = (unsigned long *)((unsigned long)p->screen_base & ~(bytes-1)); - dst_idx = ((unsigned long)p->screen_base & (bytes - 1))*8; - dst_idx += rect->dy*p->fix.line_length*8+rect->dx*bpp; - /* FIXME For now we support 1-32 bpp only */ - left = bits % bpp; - if (p->fbops->fb_sync) - p->fbops->fb_sync(p); - if (!left) { - void (*fill_op32)(struct fb_info *p, unsigned long *dst, - int dst_idx, unsigned long pat, unsigned n, - int bits) = NULL; - - switch (rect->rop) { - case ROP_XOR: - fill_op32 = bitfill_aligned_rev; - break; - case ROP_COPY: - fill_op32 = bitfill_aligned; - break; - default: - printk( KERN_ERR "cfb_fillrect(): unknown rop, " - "defaulting to ROP_COPY\n"); - fill_op32 = bitfill_aligned; - break; - } - while (height--) { - dst += dst_idx >> (ffs(bits) - 1); - dst_idx &= (bits - 1); - fill_op32(p, dst, dst_idx, pat, width*bpp, bits); - dst_idx += p->fix.line_length*8; - } - } else { - int right, r; - void (*fill_op)(struct fb_info *p, unsigned long *dst, - int dst_idx, unsigned long pat, int left, - int right, unsigned n, int bits) = NULL; -#ifdef __LITTLE_ENDIAN - right = left; - left = bpp - right; -#else - right = bpp - left; -#endif - switch (rect->rop) { - case ROP_XOR: - fill_op = bitfill_unaligned_rev; - break; - case ROP_COPY: - fill_op = bitfill_unaligned; - break; - default: - printk(KERN_ERR "sys_fillrect(): unknown rop, " - "defaulting to ROP_COPY\n"); - fill_op = bitfill_unaligned; - break; - } - while (height--) { - dst += dst_idx / bits; - dst_idx &= (bits - 1); - r = dst_idx % bpp; - /* rotate pattern to the correct start position */ - pat2 = le_long_to_cpu(rolx(cpu_to_le_long(pat), r, bpp)); - fill_op(p, dst, dst_idx, pat2, left, right, - width*bpp, bits); - dst_idx += p->fix.line_length*8; - } - } -} +#define FB_READL(a) (*a) +#define FB_WRITEL(a,b) do { *(b) = (a); } while (false) +#define FB_MEM /* nothing */ +#define FB_FILLRECT sys_fillrect +#define FB_FILLRECT_NAME "sys_fillrect" +#define FB_SPACE FBINFO_VIRTFB +#define FB_SPACE_NAME "virtual" +#define FB_SCREEN_BASE(a) ((a)->screen_buffer) +#include "fb_fillrect.h" EXPORT_SYMBOL(sys_fillrect); From patchwork Sun Feb 2 12:46:16 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Zsolt Kajtar X-Patchwork-Id: 861462 Received: from c64.rulez.org (c64.rulez.org [79.139.58.36]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7413C156885 for ; Sun, 2 Feb 2025 12:46:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=79.139.58.36 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738500379; cv=none; b=B76SoC1YT5nEaMwFWUPTYFMfRhCgrUIyzoVKILaBRuE+u0/MR6rBirz7LKDEIjUk8V7cCGKN0XPnlwSGUJIpDPjWBPkWllma1Zu00/vr2hbCOrZI2E6yYgCgYZGYnVPaX0mrKNIfpo4Bf/kxqs4J8ffWwCBC+ijB9L/p2fOPePM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738500379; c=relaxed/simple; bh=uCPurGa89QqM3AhM8sqSvBGMPl9Dyd1MsAcjN34/9tY=; h=Message-ID:Date:MIME-Version:Subject:From:To:References: In-Reply-To:Content-Type; b=Zqx0tiLFdUy5oJcL2FFxOmz/YzbrcssO/mchie/h56PJ+d1L29Z/Zt76mqHaRTzGYgXyRoanQsVNz/T6EtHFVjc018bA9JC4HdiNJsASMIcWrpWTV73ZQ2d2EzCgU44paFCdqINbp8KslUFxrlG8D5+oRNWpY4bBMbl5KTj0vgg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=c64.rulez.org; spf=pass smtp.mailfrom=c64.rulez.org; arc=none smtp.client-ip=79.139.58.36 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=c64.rulez.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=c64.rulez.org Received: from [192.168.0.59] (unknown [89.134.12.53]) by c64.rulez.org (Postfix) with ESMTPSA id 1F136100F6 for ; Sun, 2 Feb 2025 13:46:16 +0100 (CET) Message-ID: <6c0e4997-8215-a249-20ed-d353ca476cd4@c64.rulez.org> Date: Sun, 2 Feb 2025 13:46:16 +0100 Precedence: bulk X-Mailing-List: linux-fbdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Thunderbird/91.13.0 Subject: [RFC PATCH 09/12] fbdev: core: Copy cfbimgblt to fb_imageblit Content-Language: en-GB From: =?utf-8?q?Kajt=C3=A1r_Zsolt?= To: linux-fbdev@vger.kernel.org References: <0e2eba19-bc83-fd23-c9ff-59299a738bcf@c64.rulez.org> <50c335f3-d3c9-3f1d-dd3b-e78818425662@c64.rulez.org> <65535c64-6f8e-95b4-e171-528176969983@c64.rulez.org> <15ae6780-b3a9-abad-047b-a650d193aba3@c64.rulez.org> <7f2cf3dc-ae1e-7b6c-9c71-717b6f4453ea@c64.rulez.org> In-Reply-To: <7f2cf3dc-ae1e-7b6c-9c71-717b6f4453ea@c64.rulez.org> fbdev: core: Copy cfbimgblt to fb_imageblit Signed-off-by: Zsolt Kajtar --- drivers/video/fbdev/core/fb_imageblit.h | 369 ++++++++++++++++++++++++ 1 file changed, 369 insertions(+) create mode 100644 drivers/video/fbdev/core/fb_imageblit.h diff --git a/drivers/video/fbdev/core/fb_imageblit.h b/drivers/video/fbdev/core/fb_imageblit.h new file mode 100644 index 000000000..7d1d2f1a6 --- /dev/null +++ b/drivers/video/fbdev/core/fb_imageblit.h @@ -0,0 +1,369 @@ +/* + * Generic BitBLT function for frame buffer with packed pixels of any depth. + * + * Copyright (C) June 1999 James Simmons + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive for + * more details. + * + * NOTES: + * + * This function copys a image from system memory to video memory. The + * image can be a bitmap where each 0 represents the background color and + * each 1 represents the foreground color. Great for font handling. It can + * also be a color image. This is determined by image_depth. The color image + * must be laid out exactly in the same format as the framebuffer. Yes I know + * their are cards with hardware that coverts images of various depths to the + * framebuffer depth. But not every card has this. All images must be rounded + * up to the nearest byte. For example a bitmap 12 bits wide must be two + * bytes width. + * + * Tony: + * Incorporate mask tables similar to fbcon-cfb*.c in 2.4 API. This speeds + * up the code significantly. + * + * Code for depths not multiples of BITS_PER_LONG is still kludgy, which is + * still processed a bit at a time. + * + * Also need to add code to deal with cards endians that are different than + * the native cpu endians. I also need to deal with MSB position in the word. + */ +#include +#include +#include +#include +#include "fb_draw.h" + +#define DEBUG + +#ifdef DEBUG +#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt,__func__,## args) +#else +#define DPRINTK(fmt, args...) +#endif + +static const u32 cfb_tab8_be[] = { + 0x00000000,0x000000ff,0x0000ff00,0x0000ffff, + 0x00ff0000,0x00ff00ff,0x00ffff00,0x00ffffff, + 0xff000000,0xff0000ff,0xff00ff00,0xff00ffff, + 0xffff0000,0xffff00ff,0xffffff00,0xffffffff +}; + +static const u32 cfb_tab8_le[] = { + 0x00000000,0xff000000,0x00ff0000,0xffff0000, + 0x0000ff00,0xff00ff00,0x00ffff00,0xffffff00, + 0x000000ff,0xff0000ff,0x00ff00ff,0xffff00ff, + 0x0000ffff,0xff00ffff,0x00ffffff,0xffffffff +}; + +static const u32 cfb_tab16_be[] = { + 0x00000000, 0x0000ffff, 0xffff0000, 0xffffffff +}; + +static const u32 cfb_tab16_le[] = { + 0x00000000, 0xffff0000, 0x0000ffff, 0xffffffff +}; + +static const u32 cfb_tab32[] = { + 0x00000000, 0xffffffff +}; + +#define FB_WRITEL fb_writel +#define FB_READL fb_readl + +static inline void color_imageblit(const struct fb_image *image, + struct fb_info *p, u8 __iomem *dst1, + u32 start_index, + u32 pitch_index) +{ + /* Draw the penguin */ + u32 __iomem *dst, *dst2; + u32 color = 0, val, shift; + int i, n, bpp = p->var.bits_per_pixel; + u32 null_bits = 32 - bpp; + u32 *palette = (u32 *) p->pseudo_palette; + const u8 *src = image->data; + u32 bswapmask = fb_compute_bswapmask(p); + + dst2 = (u32 __iomem *) dst1; + for (i = image->height; i--; ) { + n = image->width; + dst = (u32 __iomem *) dst1; + shift = 0; + val = 0; + + if (start_index) { + u32 start_mask = ~fb_shifted_pixels_mask_u32(p, + start_index, bswapmask); + val = FB_READL(dst) & start_mask; + shift = start_index; + } + while (n--) { + if (p->fix.visual == FB_VISUAL_TRUECOLOR || + p->fix.visual == FB_VISUAL_DIRECTCOLOR ) + color = palette[*src]; + else + color = *src; + color <<= FB_LEFT_POS(p, bpp); + val |= FB_SHIFT_HIGH(p, color, shift ^ bswapmask); + if (shift >= null_bits) { + FB_WRITEL(val, dst++); + + val = (shift == null_bits) ? 0 : + FB_SHIFT_LOW(p, color, 32 - shift); + } + shift += bpp; + shift &= (32 - 1); + src++; + } + if (shift) { + u32 end_mask = fb_shifted_pixels_mask_u32(p, shift, + bswapmask); + + FB_WRITEL((FB_READL(dst) & end_mask) | val, dst); + } + dst1 += p->fix.line_length; + if (pitch_index) { + dst2 += p->fix.line_length; + dst1 = (u8 __iomem *)((long __force)dst2 & ~(sizeof(u32) - 1)); + + start_index += pitch_index; + start_index &= 32 - 1; + } + } +} + +static inline void slow_imageblit(const struct fb_image *image, struct fb_info *p, + u8 __iomem *dst1, u32 fgcolor, + u32 bgcolor, + u32 start_index, + u32 pitch_index) +{ + u32 shift, color = 0, bpp = p->var.bits_per_pixel; + u32 __iomem *dst, *dst2; + u32 val, pitch = p->fix.line_length; + u32 null_bits = 32 - bpp; + u32 spitch = (image->width+7)/8; + const u8 *src = image->data, *s; + u32 i, j, l; + u32 bswapmask = fb_compute_bswapmask(p); + + dst2 = (u32 __iomem *) dst1; + fgcolor <<= FB_LEFT_POS(p, bpp); + bgcolor <<= FB_LEFT_POS(p, bpp); + + for (i = image->height; i--; ) { + shift = val = 0; + l = 8; + j = image->width; + dst = (u32 __iomem *) dst1; + s = src; + + /* write leading bits */ + if (start_index) { + u32 start_mask = ~fb_shifted_pixels_mask_u32(p, + start_index, bswapmask); + val = FB_READL(dst) & start_mask; + shift = start_index; + } + + while (j--) { + l--; + color = (*s & (1 << l)) ? fgcolor : bgcolor; + val |= FB_SHIFT_HIGH(p, color, shift ^ bswapmask); + + /* Did the bitshift spill bits to the next long? */ + if (shift >= null_bits) { + FB_WRITEL(val, dst++); + val = (shift == null_bits) ? 0 : + FB_SHIFT_LOW(p, color, 32 - shift); + } + shift += bpp; + shift &= (32 - 1); + if (!l) { l = 8; s++; } + } + + /* write trailing bits */ + if (shift) { + u32 end_mask = fb_shifted_pixels_mask_u32(p, shift, + bswapmask); + + FB_WRITEL((FB_READL(dst) & end_mask) | val, dst); + } + + dst1 += pitch; + src += spitch; + if (pitch_index) { + dst2 += pitch; + dst1 = (u8 __iomem *)((long __force)dst2 & ~(sizeof(u32) - 1)); + start_index += pitch_index; + start_index &= 32 - 1; + } + + } +} + +/* + * fast_imageblit - optimized monochrome color expansion + * + * Only if: bits_per_pixel == 8, 16, or 32 + * image->width is divisible by pixel/dword (ppw); + * fix->line_legth is divisible by 4; + * beginning and end of a scanline is dword aligned + */ +static inline void fast_imageblit(const struct fb_image *image, struct fb_info *p, + u8 __iomem *dst1, u32 fgcolor, + u32 bgcolor) +{ + u32 fgx = fgcolor, bgx = bgcolor, bpp = p->var.bits_per_pixel; + u32 ppw = 32/bpp, spitch = (image->width + 7)/8; + u32 bit_mask, eorx, shift; + const char *s = image->data, *src; + u32 __iomem *dst; + const u32 *tab = NULL; + size_t tablen; + u32 colortab[16]; + int i, j, k; + + switch (bpp) { + case 8: + tab = fb_be_math(p) ? cfb_tab8_be : cfb_tab8_le; + tablen = 16; + break; + case 16: + tab = fb_be_math(p) ? cfb_tab16_be : cfb_tab16_le; + tablen = 4; + break; + case 32: + tab = cfb_tab32; + tablen = 2; + break; + default: + return; + } + + for (i = ppw-1; i--; ) { + fgx <<= bpp; + bgx <<= bpp; + fgx |= fgcolor; + bgx |= bgcolor; + } + + bit_mask = (1 << ppw) - 1; + eorx = fgx ^ bgx; + k = image->width/ppw; + + for (i = 0; i < tablen; ++i) + colortab[i] = (tab[i] & eorx) ^ bgx; + + for (i = image->height; i--; ) { + dst = (u32 __iomem *)dst1; + shift = 8; + src = s; + + /* + * Manually unroll the per-line copying loop for better + * performance. This works until we processed the last + * completely filled source byte (inclusive). + */ + switch (ppw) { + case 4: /* 8 bpp */ + for (j = k; j >= 2; j -= 2, ++src) { + FB_WRITEL(colortab[(*src >> 4) & bit_mask], dst++); + FB_WRITEL(colortab[(*src >> 0) & bit_mask], dst++); + } + break; + case 2: /* 16 bpp */ + for (j = k; j >= 4; j -= 4, ++src) { + FB_WRITEL(colortab[(*src >> 6) & bit_mask], dst++); + FB_WRITEL(colortab[(*src >> 4) & bit_mask], dst++); + FB_WRITEL(colortab[(*src >> 2) & bit_mask], dst++); + FB_WRITEL(colortab[(*src >> 0) & bit_mask], dst++); + } + break; + case 1: /* 32 bpp */ + for (j = k; j >= 8; j -= 8, ++src) { + FB_WRITEL(colortab[(*src >> 7) & bit_mask], dst++); + FB_WRITEL(colortab[(*src >> 6) & bit_mask], dst++); + FB_WRITEL(colortab[(*src >> 5) & bit_mask], dst++); + FB_WRITEL(colortab[(*src >> 4) & bit_mask], dst++); + FB_WRITEL(colortab[(*src >> 3) & bit_mask], dst++); + FB_WRITEL(colortab[(*src >> 2) & bit_mask], dst++); + FB_WRITEL(colortab[(*src >> 1) & bit_mask], dst++); + FB_WRITEL(colortab[(*src >> 0) & bit_mask], dst++); + } + break; + } + + /* + * For image widths that are not a multiple of 8, there + * are trailing pixels left on the current line. Print + * them as well. + */ + for (; j--; ) { + shift -= ppw; + FB_WRITEL(colortab[(*src >> shift) & bit_mask], dst++); + if (!shift) { + shift = 8; + ++src; + } + } + + dst1 += p->fix.line_length; + s += spitch; + } +} + +void cfb_imageblit(struct fb_info *p, const struct fb_image *image) +{ + u32 fgcolor, bgcolor, start_index, bitstart, pitch_index = 0; + u32 bpl = sizeof(u32), bpp = p->var.bits_per_pixel; + u32 width = image->width; + u32 dx = image->dx, dy = image->dy; + u8 __iomem *dst1; + + if (p->state != FBINFO_STATE_RUNNING) + return; + + if (p->flags & FBINFO_VIRTFB) + fb_warn_once(p, "Framebuffer is not in I/O address space."); + + bitstart = (dy * p->fix.line_length * 8) + (dx * bpp); + start_index = bitstart & (32 - 1); + pitch_index = (p->fix.line_length & (bpl - 1)) * 8; + + bitstart /= 8; + bitstart &= ~(bpl - 1); + dst1 = p->screen_base + bitstart; + + if (p->fbops->fb_sync) + p->fbops->fb_sync(p); + + if (image->depth == 1) { + if (p->fix.visual == FB_VISUAL_TRUECOLOR || + p->fix.visual == FB_VISUAL_DIRECTCOLOR) { + fgcolor = ((u32*)(p->pseudo_palette))[image->fg_color]; + bgcolor = ((u32*)(p->pseudo_palette))[image->bg_color]; + } else { + fgcolor = image->fg_color; + bgcolor = image->bg_color; + } + + if (32 % bpp == 0 && !start_index && !pitch_index && + ((width & (32/bpp-1)) == 0) && + bpp >= 8 && bpp <= 32) + fast_imageblit(image, p, dst1, fgcolor, bgcolor); + else + slow_imageblit(image, p, dst1, fgcolor, bgcolor, + start_index, pitch_index); + } else + color_imageblit(image, p, dst1, start_index, pitch_index); +} + +EXPORT_SYMBOL(cfb_imageblit); + +MODULE_AUTHOR("James Simmons "); +MODULE_DESCRIPTION("Generic software accelerated imaging drawing"); +MODULE_LICENSE("GPL"); + From patchwork Sun Feb 2 12:46:52 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Zsolt Kajtar X-Patchwork-Id: 862205 Received: from c64.rulez.org (c64.rulez.org [79.139.58.36]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3D11D1D6DB6 for ; Sun, 2 Feb 2025 12:46:54 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=79.139.58.36 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738500416; cv=none; b=jwai5Spf4S5G88sqyamKf4YVfMorPnX3ANGGc4As5z7jjNWFClpn3qyF8wpYdSVoJqdYqrJMZl6kAyZOfCCmpwxcukA8/jU9CWMfdL9G7/xvHZyverorGylRt4NBoTAuXqB4kBe8fAbJwD8WXiB+tTjCsNo3bkmKHRAyrOM1NFI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738500416; c=relaxed/simple; bh=UySuaKMdF+qDuWLBJcChIir92Q/vfWkpJw9YlW6ziNY=; h=Message-ID:Date:MIME-Version:Subject:From:To:References: In-Reply-To:Content-Type; b=qaPV0e00hFEut5oKZPcV69JbO3i5rsSecycgn6OZlI3jZMHIX9lOYIKsEiqqUCcrFtDiQHgxTwvIa2nXYrLla3FJww8i7dUbxwgWXxeSP71+AEQgPF7UQG7cp0HRBYrDy7sdCJQthQ5vfjtkcKOYczHU9MUa2KWE3Oin0E4LlLk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=c64.rulez.org; spf=pass smtp.mailfrom=c64.rulez.org; arc=none smtp.client-ip=79.139.58.36 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=c64.rulez.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=c64.rulez.org Received: from [192.168.0.59] (unknown [89.134.12.53]) by c64.rulez.org (Postfix) with ESMTPSA id AA605100F6 for ; Sun, 2 Feb 2025 13:46:52 +0100 (CET) Message-ID: <8ed1d74c-0757-6c6c-d619-9d9b4fea00c0@c64.rulez.org> Date: Sun, 2 Feb 2025 13:46:52 +0100 Precedence: bulk X-Mailing-List: linux-fbdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Thunderbird/91.13.0 Subject: [RFC PATCH 10/12] fbdev: core: Make fb_imageblit generic Content-Language: en-GB From: =?utf-8?q?Kajt=C3=A1r_Zsolt?= To: linux-fbdev@vger.kernel.org References: <0e2eba19-bc83-fd23-c9ff-59299a738bcf@c64.rulez.org> <50c335f3-d3c9-3f1d-dd3b-e78818425662@c64.rulez.org> <65535c64-6f8e-95b4-e171-528176969983@c64.rulez.org> <15ae6780-b3a9-abad-047b-a650d193aba3@c64.rulez.org> <7f2cf3dc-ae1e-7b6c-9c71-717b6f4453ea@c64.rulez.org> <6c0e4997-8215-a249-20ed-d353ca476cd4@c64.rulez.org> In-Reply-To: <6c0e4997-8215-a249-20ed-d353ca476cd4@c64.rulez.org> fbdev: core: Make fb_imageblit generic Signed-off-by: Zsolt Kajtar --- drivers/video/fbdev/core/fb_imageblit.h | 53 ++++++++++--------------- 1 file changed, 20 insertions(+), 33 deletions(-) diff --git a/drivers/video/fbdev/core/fb_imageblit.h b/drivers/video/fbdev/core/fb_imageblit.h index 7d1d2f1a6..d0308135e 100644 --- a/drivers/video/fbdev/core/fb_imageblit.h +++ b/drivers/video/fbdev/core/fb_imageblit.h @@ -29,10 +29,6 @@ * Also need to add code to deal with cards endians that are different than * the native cpu endians. I also need to deal with MSB position in the word. */ -#include -#include -#include -#include #include "fb_draw.h" #define DEBUG @@ -69,16 +65,13 @@ static const u32 cfb_tab32[] = { 0x00000000, 0xffffffff }; -#define FB_WRITEL fb_writel -#define FB_READL fb_readl - static inline void color_imageblit(const struct fb_image *image, - struct fb_info *p, u8 __iomem *dst1, + struct fb_info *p, u8 FB_MEM *dst1, u32 start_index, u32 pitch_index) { /* Draw the penguin */ - u32 __iomem *dst, *dst2; + u32 FB_MEM *dst, *dst2; u32 color = 0, val, shift; int i, n, bpp = p->var.bits_per_pixel; u32 null_bits = 32 - bpp; @@ -86,10 +79,10 @@ static inline void color_imageblit(const struct fb_image *image, const u8 *src = image->data; u32 bswapmask = fb_compute_bswapmask(p); - dst2 = (u32 __iomem *) dst1; + dst2 = (u32 FB_MEM *) dst1; for (i = image->height; i--; ) { n = image->width; - dst = (u32 __iomem *) dst1; + dst = (u32 FB_MEM *) dst1; shift = 0; val = 0; @@ -126,7 +119,7 @@ static inline void color_imageblit(const struct fb_image *image, dst1 += p->fix.line_length; if (pitch_index) { dst2 += p->fix.line_length; - dst1 = (u8 __iomem *)((long __force)dst2 & ~(sizeof(u32) - 1)); + dst1 = (u8 FB_MEM *)((long __force)dst2 & ~(sizeof(u32) - 1)); start_index += pitch_index; start_index &= 32 - 1; @@ -135,13 +128,13 @@ static inline void color_imageblit(const struct fb_image *image, } static inline void slow_imageblit(const struct fb_image *image, struct fb_info *p, - u8 __iomem *dst1, u32 fgcolor, + u8 FB_MEM *dst1, u32 fgcolor, u32 bgcolor, u32 start_index, u32 pitch_index) { u32 shift, color = 0, bpp = p->var.bits_per_pixel; - u32 __iomem *dst, *dst2; + u32 FB_MEM *dst, *dst2; u32 val, pitch = p->fix.line_length; u32 null_bits = 32 - bpp; u32 spitch = (image->width+7)/8; @@ -149,7 +142,7 @@ static inline void slow_imageblit(const struct fb_image *image, struct fb_info * u32 i, j, l; u32 bswapmask = fb_compute_bswapmask(p); - dst2 = (u32 __iomem *) dst1; + dst2 = (u32 FB_MEM *) dst1; fgcolor <<= FB_LEFT_POS(p, bpp); bgcolor <<= FB_LEFT_POS(p, bpp); @@ -157,7 +150,7 @@ static inline void slow_imageblit(const struct fb_image *image, struct fb_info * shift = val = 0; l = 8; j = image->width; - dst = (u32 __iomem *) dst1; + dst = (u32 FB_MEM *) dst1; s = src; /* write leading bits */ @@ -196,7 +189,7 @@ static inline void slow_imageblit(const struct fb_image *image, struct fb_info * src += spitch; if (pitch_index) { dst2 += pitch; - dst1 = (u8 __iomem *)((long __force)dst2 & ~(sizeof(u32) - 1)); + dst1 = (u8 FB_MEM *)((long __force)dst2 & ~(sizeof(u32) - 1)); start_index += pitch_index; start_index &= 32 - 1; } @@ -213,14 +206,14 @@ static inline void slow_imageblit(const struct fb_image *image, struct fb_info * * beginning and end of a scanline is dword aligned */ static inline void fast_imageblit(const struct fb_image *image, struct fb_info *p, - u8 __iomem *dst1, u32 fgcolor, + u8 FB_MEM *dst1, u32 fgcolor, u32 bgcolor) { u32 fgx = fgcolor, bgx = bgcolor, bpp = p->var.bits_per_pixel; u32 ppw = 32/bpp, spitch = (image->width + 7)/8; u32 bit_mask, eorx, shift; - const char *s = image->data, *src; - u32 __iomem *dst; + const u8 *s = image->data, *src; + u32 FB_MEM *dst; const u32 *tab = NULL; size_t tablen; u32 colortab[16]; @@ -258,7 +251,7 @@ static inline void fast_imageblit(const struct fb_image *image, struct fb_info * colortab[i] = (tab[i] & eorx) ^ bgx; for (i = image->height; i--; ) { - dst = (u32 __iomem *)dst1; + dst = (u32 FB_MEM *)dst1; shift = 8; src = s; @@ -315,19 +308,20 @@ static inline void fast_imageblit(const struct fb_image *image, struct fb_info * } } -void cfb_imageblit(struct fb_info *p, const struct fb_image *image) +void FB_IMAGEBLIT (struct fb_info *p, const struct fb_image *image) { u32 fgcolor, bgcolor, start_index, bitstart, pitch_index = 0; u32 bpl = sizeof(u32), bpp = p->var.bits_per_pixel; u32 width = image->width; u32 dx = image->dx, dy = image->dy; - u8 __iomem *dst1; + u8 FB_MEM *dst1; if (p->state != FBINFO_STATE_RUNNING) return; - if (p->flags & FBINFO_VIRTFB) - fb_warn_once(p, "Framebuffer is not in I/O address space."); + if ((p->flags & FBINFO_VIRTFB) != FB_SPACE) + fb_warn_once(p, "Framebuffer is not in " FB_SPACE_NAME + " address space."); bitstart = (dy * p->fix.line_length * 8) + (dx * bpp); start_index = bitstart & (32 - 1); @@ -335,7 +329,7 @@ void cfb_imageblit(struct fb_info *p, const struct fb_image *image) bitstart /= 8; bitstart &= ~(bpl - 1); - dst1 = p->screen_base + bitstart; + dst1 = (void __force *)FB_SCREEN_BASE(p) + bitstart; if (p->fbops->fb_sync) p->fbops->fb_sync(p); @@ -360,10 +354,3 @@ void cfb_imageblit(struct fb_info *p, const struct fb_image *image) } else color_imageblit(image, p, dst1, start_index, pitch_index); } - -EXPORT_SYMBOL(cfb_imageblit); - -MODULE_AUTHOR("James Simmons "); -MODULE_DESCRIPTION("Generic software accelerated imaging drawing"); -MODULE_LICENSE("GPL"); - From patchwork Sun Feb 2 12:47:27 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Zsolt Kajtar X-Patchwork-Id: 861461 Received: from c64.rulez.org (c64.rulez.org [79.139.58.36]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3214B1D6DB6 for ; Sun, 2 Feb 2025 12:47:29 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=79.139.58.36 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738500451; cv=none; b=YwwiBwQiExryvkH0RoARpDbhgbA31PJJVOKaN86hhC0f4Hc8ype+nhLzlRQslcvj8sjmmb8bbTCzztJj+xmtbAM6PUNcwJNw9zq12HHAWtGNQU15aMZxGAX+0AWGK7o8xSDRhRfi0A7GKaqIyUc4+wTWTlyPwafyZeaQSjMQRj0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738500451; c=relaxed/simple; bh=q4F9Cgp7aiwSWJpJDH5Kj+dR/GjxdgoIvK3SWOHs/2U=; h=Message-ID:Date:MIME-Version:Subject:From:To:References: In-Reply-To:Content-Type; b=IlbioVdTOT8aITJfIPAEsZSg3kmaTnLSOuh77IlPBFt1fF5A58WYpQfLilPmksyIqnelB0NyHdgKHrgfdcavevAmeMy5niy+2RkqAASkC4L6odRAAqMnslyGaUIjg0dDKZJwWcYCRPe2KuxeUeAW76dKDB4qjKu7Ci+SQUGHev0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=c64.rulez.org; spf=pass smtp.mailfrom=c64.rulez.org; arc=none smtp.client-ip=79.139.58.36 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=c64.rulez.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=c64.rulez.org Received: from [192.168.0.59] (unknown [89.134.12.53]) by c64.rulez.org (Postfix) with ESMTPSA id C1957100F6 for ; Sun, 2 Feb 2025 13:47:27 +0100 (CET) Message-ID: <4370d619-9567-d6e1-1d63-78f0a77ddbe6@c64.rulez.org> Date: Sun, 2 Feb 2025 13:47:27 +0100 Precedence: bulk X-Mailing-List: linux-fbdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Thunderbird/91.13.0 Subject: [RFC PATCH 11/12] fbdev: core: Use generic imageblit for as, cfb_imageblit Content-Language: en-GB From: =?utf-8?q?Kajt=C3=A1r_Zsolt?= To: linux-fbdev@vger.kernel.org References: <0e2eba19-bc83-fd23-c9ff-59299a738bcf@c64.rulez.org> <50c335f3-d3c9-3f1d-dd3b-e78818425662@c64.rulez.org> <65535c64-6f8e-95b4-e171-528176969983@c64.rulez.org> <15ae6780-b3a9-abad-047b-a650d193aba3@c64.rulez.org> <7f2cf3dc-ae1e-7b6c-9c71-717b6f4453ea@c64.rulez.org> <6c0e4997-8215-a249-20ed-d353ca476cd4@c64.rulez.org> <8ed1d74c-0757-6c6c-d619-9d9b4fea00c0@c64.rulez.org> In-Reply-To: <8ed1d74c-0757-6c6c-d619-9d9b4fea00c0@c64.rulez.org> fbdev: core: Use generic imageblit for as cfb_imageblit Signed-off-by: Zsolt Kajtar --- drivers/video/fbdev/core/cfbimgblt.c | 356 +-------------------------- 1 file changed, 8 insertions(+), 348 deletions(-) diff --git a/drivers/video/fbdev/core/cfbimgblt.c b/drivers/video/fbdev/core/cfbimgblt.c index 7d1d2f1a6..ff2eda62e 100644 --- a/drivers/video/fbdev/core/cfbimgblt.c +++ b/drivers/video/fbdev/core/cfbimgblt.c @@ -7,359 +7,19 @@ * License. See the file COPYING in the main directory of this archive for * more details. * - * NOTES: - * - * This function copys a image from system memory to video memory. The - * image can be a bitmap where each 0 represents the background color and - * each 1 represents the foreground color. Great for font handling. It can - * also be a color image. This is determined by image_depth. The color image - * must be laid out exactly in the same format as the framebuffer. Yes I know - * their are cards with hardware that coverts images of various depths to the - * framebuffer depth. But not every card has this. All images must be rounded - * up to the nearest byte. For example a bitmap 12 bits wide must be two - * bytes width. - * - * Tony: - * Incorporate mask tables similar to fbcon-cfb*.c in 2.4 API. This speeds - * up the code significantly. - * - * Code for depths not multiples of BITS_PER_LONG is still kludgy, which is - * still processed a bit at a time. - * - * Also need to add code to deal with cards endians that are different than - * the native cpu endians. I also need to deal with MSB position in the word. */ #include -#include #include #include -#include "fb_draw.h" - -#define DEBUG - -#ifdef DEBUG -#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt,__func__,## args) -#else -#define DPRINTK(fmt, args...) -#endif - -static const u32 cfb_tab8_be[] = { - 0x00000000,0x000000ff,0x0000ff00,0x0000ffff, - 0x00ff0000,0x00ff00ff,0x00ffff00,0x00ffffff, - 0xff000000,0xff0000ff,0xff00ff00,0xff00ffff, - 0xffff0000,0xffff00ff,0xffffff00,0xffffffff -}; - -static const u32 cfb_tab8_le[] = { - 0x00000000,0xff000000,0x00ff0000,0xffff0000, - 0x0000ff00,0xff00ff00,0x00ffff00,0xffffff00, - 0x000000ff,0xff0000ff,0x00ff00ff,0xffff00ff, - 0x0000ffff,0xff00ffff,0x00ffffff,0xffffffff -}; - -static const u32 cfb_tab16_be[] = { - 0x00000000, 0x0000ffff, 0xffff0000, 0xffffffff -}; - -static const u32 cfb_tab16_le[] = { - 0x00000000, 0xffff0000, 0x0000ffff, 0xffffffff -}; - -static const u32 cfb_tab32[] = { - 0x00000000, 0xffffffff -}; - -#define FB_WRITEL fb_writel -#define FB_READL fb_readl - -static inline void color_imageblit(const struct fb_image *image, - struct fb_info *p, u8 __iomem *dst1, - u32 start_index, - u32 pitch_index) -{ - /* Draw the penguin */ - u32 __iomem *dst, *dst2; - u32 color = 0, val, shift; - int i, n, bpp = p->var.bits_per_pixel; - u32 null_bits = 32 - bpp; - u32 *palette = (u32 *) p->pseudo_palette; - const u8 *src = image->data; - u32 bswapmask = fb_compute_bswapmask(p); - - dst2 = (u32 __iomem *) dst1; - for (i = image->height; i--; ) { - n = image->width; - dst = (u32 __iomem *) dst1; - shift = 0; - val = 0; - - if (start_index) { - u32 start_mask = ~fb_shifted_pixels_mask_u32(p, - start_index, bswapmask); - val = FB_READL(dst) & start_mask; - shift = start_index; - } - while (n--) { - if (p->fix.visual == FB_VISUAL_TRUECOLOR || - p->fix.visual == FB_VISUAL_DIRECTCOLOR ) - color = palette[*src]; - else - color = *src; - color <<= FB_LEFT_POS(p, bpp); - val |= FB_SHIFT_HIGH(p, color, shift ^ bswapmask); - if (shift >= null_bits) { - FB_WRITEL(val, dst++); - - val = (shift == null_bits) ? 0 : - FB_SHIFT_LOW(p, color, 32 - shift); - } - shift += bpp; - shift &= (32 - 1); - src++; - } - if (shift) { - u32 end_mask = fb_shifted_pixels_mask_u32(p, shift, - bswapmask); - - FB_WRITEL((FB_READL(dst) & end_mask) | val, dst); - } - dst1 += p->fix.line_length; - if (pitch_index) { - dst2 += p->fix.line_length; - dst1 = (u8 __iomem *)((long __force)dst2 & ~(sizeof(u32) - 1)); - - start_index += pitch_index; - start_index &= 32 - 1; - } - } -} - -static inline void slow_imageblit(const struct fb_image *image, struct fb_info *p, - u8 __iomem *dst1, u32 fgcolor, - u32 bgcolor, - u32 start_index, - u32 pitch_index) -{ - u32 shift, color = 0, bpp = p->var.bits_per_pixel; - u32 __iomem *dst, *dst2; - u32 val, pitch = p->fix.line_length; - u32 null_bits = 32 - bpp; - u32 spitch = (image->width+7)/8; - const u8 *src = image->data, *s; - u32 i, j, l; - u32 bswapmask = fb_compute_bswapmask(p); - - dst2 = (u32 __iomem *) dst1; - fgcolor <<= FB_LEFT_POS(p, bpp); - bgcolor <<= FB_LEFT_POS(p, bpp); - - for (i = image->height; i--; ) { - shift = val = 0; - l = 8; - j = image->width; - dst = (u32 __iomem *) dst1; - s = src; - - /* write leading bits */ - if (start_index) { - u32 start_mask = ~fb_shifted_pixels_mask_u32(p, - start_index, bswapmask); - val = FB_READL(dst) & start_mask; - shift = start_index; - } - - while (j--) { - l--; - color = (*s & (1 << l)) ? fgcolor : bgcolor; - val |= FB_SHIFT_HIGH(p, color, shift ^ bswapmask); - - /* Did the bitshift spill bits to the next long? */ - if (shift >= null_bits) { - FB_WRITEL(val, dst++); - val = (shift == null_bits) ? 0 : - FB_SHIFT_LOW(p, color, 32 - shift); - } - shift += bpp; - shift &= (32 - 1); - if (!l) { l = 8; s++; } - } - - /* write trailing bits */ - if (shift) { - u32 end_mask = fb_shifted_pixels_mask_u32(p, shift, - bswapmask); - - FB_WRITEL((FB_READL(dst) & end_mask) | val, dst); - } - - dst1 += pitch; - src += spitch; - if (pitch_index) { - dst2 += pitch; - dst1 = (u8 __iomem *)((long __force)dst2 & ~(sizeof(u32) - 1)); - start_index += pitch_index; - start_index &= 32 - 1; - } - - } -} - -/* - * fast_imageblit - optimized monochrome color expansion - * - * Only if: bits_per_pixel == 8, 16, or 32 - * image->width is divisible by pixel/dword (ppw); - * fix->line_legth is divisible by 4; - * beginning and end of a scanline is dword aligned - */ -static inline void fast_imageblit(const struct fb_image *image, struct fb_info *p, - u8 __iomem *dst1, u32 fgcolor, - u32 bgcolor) -{ - u32 fgx = fgcolor, bgx = bgcolor, bpp = p->var.bits_per_pixel; - u32 ppw = 32/bpp, spitch = (image->width + 7)/8; - u32 bit_mask, eorx, shift; - const char *s = image->data, *src; - u32 __iomem *dst; - const u32 *tab = NULL; - size_t tablen; - u32 colortab[16]; - int i, j, k; - - switch (bpp) { - case 8: - tab = fb_be_math(p) ? cfb_tab8_be : cfb_tab8_le; - tablen = 16; - break; - case 16: - tab = fb_be_math(p) ? cfb_tab16_be : cfb_tab16_le; - tablen = 4; - break; - case 32: - tab = cfb_tab32; - tablen = 2; - break; - default: - return; - } - - for (i = ppw-1; i--; ) { - fgx <<= bpp; - bgx <<= bpp; - fgx |= fgcolor; - bgx |= bgcolor; - } - - bit_mask = (1 << ppw) - 1; - eorx = fgx ^ bgx; - k = image->width/ppw; - - for (i = 0; i < tablen; ++i) - colortab[i] = (tab[i] & eorx) ^ bgx; - - for (i = image->height; i--; ) { - dst = (u32 __iomem *)dst1; - shift = 8; - src = s; - - /* - * Manually unroll the per-line copying loop for better - * performance. This works until we processed the last - * completely filled source byte (inclusive). - */ - switch (ppw) { - case 4: /* 8 bpp */ - for (j = k; j >= 2; j -= 2, ++src) { - FB_WRITEL(colortab[(*src >> 4) & bit_mask], dst++); - FB_WRITEL(colortab[(*src >> 0) & bit_mask], dst++); - } - break; - case 2: /* 16 bpp */ - for (j = k; j >= 4; j -= 4, ++src) { - FB_WRITEL(colortab[(*src >> 6) & bit_mask], dst++); - FB_WRITEL(colortab[(*src >> 4) & bit_mask], dst++); - FB_WRITEL(colortab[(*src >> 2) & bit_mask], dst++); - FB_WRITEL(colortab[(*src >> 0) & bit_mask], dst++); - } - break; - case 1: /* 32 bpp */ - for (j = k; j >= 8; j -= 8, ++src) { - FB_WRITEL(colortab[(*src >> 7) & bit_mask], dst++); - FB_WRITEL(colortab[(*src >> 6) & bit_mask], dst++); - FB_WRITEL(colortab[(*src >> 5) & bit_mask], dst++); - FB_WRITEL(colortab[(*src >> 4) & bit_mask], dst++); - FB_WRITEL(colortab[(*src >> 3) & bit_mask], dst++); - FB_WRITEL(colortab[(*src >> 2) & bit_mask], dst++); - FB_WRITEL(colortab[(*src >> 1) & bit_mask], dst++); - FB_WRITEL(colortab[(*src >> 0) & bit_mask], dst++); - } - break; - } - - /* - * For image widths that are not a multiple of 8, there - * are trailing pixels left on the current line. Print - * them as well. - */ - for (; j--; ) { - shift -= ppw; - FB_WRITEL(colortab[(*src >> shift) & bit_mask], dst++); - if (!shift) { - shift = 8; - ++src; - } - } - - dst1 += p->fix.line_length; - s += spitch; - } -} - -void cfb_imageblit(struct fb_info *p, const struct fb_image *image) -{ - u32 fgcolor, bgcolor, start_index, bitstart, pitch_index = 0; - u32 bpl = sizeof(u32), bpp = p->var.bits_per_pixel; - u32 width = image->width; - u32 dx = image->dx, dy = image->dy; - u8 __iomem *dst1; - - if (p->state != FBINFO_STATE_RUNNING) - return; - - if (p->flags & FBINFO_VIRTFB) - fb_warn_once(p, "Framebuffer is not in I/O address space."); - - bitstart = (dy * p->fix.line_length * 8) + (dx * bpp); - start_index = bitstart & (32 - 1); - pitch_index = (p->fix.line_length & (bpl - 1)) * 8; - - bitstart /= 8; - bitstart &= ~(bpl - 1); - dst1 = p->screen_base + bitstart; - - if (p->fbops->fb_sync) - p->fbops->fb_sync(p); - - if (image->depth == 1) { - if (p->fix.visual == FB_VISUAL_TRUECOLOR || - p->fix.visual == FB_VISUAL_DIRECTCOLOR) { - fgcolor = ((u32*)(p->pseudo_palette))[image->fg_color]; - bgcolor = ((u32*)(p->pseudo_palette))[image->bg_color]; - } else { - fgcolor = image->fg_color; - bgcolor = image->bg_color; - } - if (32 % bpp == 0 && !start_index && !pitch_index && - ((width & (32/bpp-1)) == 0) && - bpp >= 8 && bpp <= 32) - fast_imageblit(image, p, dst1, fgcolor, bgcolor); - else - slow_imageblit(image, p, dst1, fgcolor, bgcolor, - start_index, pitch_index); - } else - color_imageblit(image, p, dst1, start_index, pitch_index); -} +#define FB_WRITEL fb_writel +#define FB_READL fb_readl +#define FB_MEM __iomem +#define FB_IMAGEBLIT cfb_imageblit +#define FB_SPACE 0 +#define FB_SPACE_NAME "I/O" +#define FB_SCREEN_BASE(a) ((a)->screen_base) +#include "fb_imageblit.h" EXPORT_SYMBOL(cfb_imageblit); From patchwork Sun Feb 2 12:47:57 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Zsolt Kajtar X-Patchwork-Id: 862204 Received: from c64.rulez.org (c64.rulez.org [79.139.58.36]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1D97C1D6DB6 for ; Sun, 2 Feb 2025 12:47:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=79.139.58.36 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738500481; cv=none; b=LdTyhbn5kkXNXBW04R7Df+h6jFtNAXGlDTEY0x2GSJpydS9BaWQVjqT3xDpruqAkcNaCM1peSIAfZs5cssUb1tEWso+i7g/fpSHAMUXrra3T9TdTvnzJ5ImD8xgrqoSdtAkcxLD0HRLgunig4mvMUqM0drCNYXqG6LZdTF9pMPI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738500481; c=relaxed/simple; bh=UMNAbTf1e+EUuZPrM9+ArkBgL5HaIWMYQZf4V5/RMUA=; h=Message-ID:Date:MIME-Version:Subject:From:To:References: In-Reply-To:Content-Type; b=sZK2NWqDZikMRVWfmsOD8QUPcIJcW4Y7sNlYUmOFJsF2NVrEAu0Z+/qfWMH3PkjGjxTptmZkeoiR/x7fNzDn+AHl5qlvlG0eTHzK1/94f1uqnHn9EHR6GP+v3SzH3vdCZf4FJr5JCK6b0PMjK/1wcKtbDYlgBF0sXwUb/Bb1T9k= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=c64.rulez.org; spf=pass smtp.mailfrom=c64.rulez.org; arc=none smtp.client-ip=79.139.58.36 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=c64.rulez.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=c64.rulez.org Received: from [192.168.0.59] (unknown [89.134.12.53]) by c64.rulez.org (Postfix) with ESMTPSA id 54D40100F6 for ; Sun, 2 Feb 2025 13:47:57 +0100 (CET) Message-ID: <858519d3-c4ad-8514-20cd-36eb635459d2@c64.rulez.org> Date: Sun, 2 Feb 2025 13:47:57 +0100 Precedence: bulk X-Mailing-List: linux-fbdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Thunderbird/91.13.0 Subject: [RFC PATCH 12/12] fbdev: core: Use generic imageblit for as, sys_imageblit Content-Language: en-GB From: =?utf-8?q?Kajt=C3=A1r_Zsolt?= To: linux-fbdev@vger.kernel.org References: <0e2eba19-bc83-fd23-c9ff-59299a738bcf@c64.rulez.org> <50c335f3-d3c9-3f1d-dd3b-e78818425662@c64.rulez.org> <65535c64-6f8e-95b4-e171-528176969983@c64.rulez.org> <15ae6780-b3a9-abad-047b-a650d193aba3@c64.rulez.org> <7f2cf3dc-ae1e-7b6c-9c71-717b6f4453ea@c64.rulez.org> <6c0e4997-8215-a249-20ed-d353ca476cd4@c64.rulez.org> <8ed1d74c-0757-6c6c-d619-9d9b4fea00c0@c64.rulez.org> <4370d619-9567-d6e1-1d63-78f0a77ddbe6@c64.rulez.org> In-Reply-To: <4370d619-9567-d6e1-1d63-78f0a77ddbe6@c64.rulez.org> fbdev: core: Use generic imageblit for as sys_imageblit Signed-off-by: Zsolt Kajtar --- drivers/video/fbdev/core/sysimgblt.c | 324 +-------------------------- 1 file changed, 8 insertions(+), 316 deletions(-) diff --git a/drivers/video/fbdev/core/sysimgblt.c b/drivers/video/fbdev/core/sysimgblt.c index 6949bbd51..b62e66280 100644 --- a/drivers/video/fbdev/core/sysimgblt.c +++ b/drivers/video/fbdev/core/sysimgblt.c @@ -11,325 +11,17 @@ * more details. */ #include -#include #include #include -#define DEBUG - -#ifdef DEBUG -#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt,__func__,## args) -#else -#define DPRINTK(fmt, args...) -#endif - -static const u32 cfb_tab8_be[] = { - 0x00000000,0x000000ff,0x0000ff00,0x0000ffff, - 0x00ff0000,0x00ff00ff,0x00ffff00,0x00ffffff, - 0xff000000,0xff0000ff,0xff00ff00,0xff00ffff, - 0xffff0000,0xffff00ff,0xffffff00,0xffffffff -}; - -static const u32 cfb_tab8_le[] = { - 0x00000000,0xff000000,0x00ff0000,0xffff0000, - 0x0000ff00,0xff00ff00,0x00ffff00,0xffffff00, - 0x000000ff,0xff0000ff,0x00ff00ff,0xffff00ff, - 0x0000ffff,0xff00ffff,0x00ffffff,0xffffffff -}; - -static const u32 cfb_tab16_be[] = { - 0x00000000, 0x0000ffff, 0xffff0000, 0xffffffff -}; - -static const u32 cfb_tab16_le[] = { - 0x00000000, 0xffff0000, 0x0000ffff, 0xffffffff -}; - -static const u32 cfb_tab32[] = { - 0x00000000, 0xffffffff -}; - -static void color_imageblit(const struct fb_image *image, struct fb_info *p, - void *dst1, u32 start_index, u32 pitch_index) -{ - /* Draw the penguin */ - u32 *dst, *dst2; - u32 color = 0, val, shift; - int i, n, bpp = p->var.bits_per_pixel; - u32 null_bits = 32 - bpp; - u32 *palette = (u32 *) p->pseudo_palette; - const u8 *src = image->data; - - dst2 = dst1; - for (i = image->height; i--; ) { - n = image->width; - dst = dst1; - shift = 0; - val = 0; - - if (start_index) { - u32 start_mask = ~(FB_SHIFT_HIGH(p, ~(u32)0, - start_index)); - val = *dst & start_mask; - shift = start_index; - } - while (n--) { - if (p->fix.visual == FB_VISUAL_TRUECOLOR || - p->fix.visual == FB_VISUAL_DIRECTCOLOR ) - color = palette[*src]; - else - color = *src; - color <<= FB_LEFT_POS(p, bpp); - val |= FB_SHIFT_HIGH(p, color, shift); - if (shift >= null_bits) { - *dst++ = val; - - val = (shift == null_bits) ? 0 : - FB_SHIFT_LOW(p, color, 32 - shift); - } - shift += bpp; - shift &= (32 - 1); - src++; - } - if (shift) { - u32 end_mask = FB_SHIFT_HIGH(p, ~(u32)0, shift); - - *dst &= end_mask; - *dst |= val; - } - dst1 += p->fix.line_length; - if (pitch_index) { - dst2 += p->fix.line_length; - dst1 = (u8 *)((long)dst2 & ~(sizeof(u32) - 1)); - - start_index += pitch_index; - start_index &= 32 - 1; - } - } -} - -static void slow_imageblit(const struct fb_image *image, struct fb_info *p, - void *dst1, u32 fgcolor, u32 bgcolor, - u32 start_index, u32 pitch_index) -{ - u32 shift, color = 0, bpp = p->var.bits_per_pixel; - u32 *dst, *dst2; - u32 val, pitch = p->fix.line_length; - u32 null_bits = 32 - bpp; - u32 spitch = (image->width+7)/8; - const u8 *src = image->data, *s; - u32 i, j, l; - - dst2 = dst1; - fgcolor <<= FB_LEFT_POS(p, bpp); - bgcolor <<= FB_LEFT_POS(p, bpp); - - for (i = image->height; i--; ) { - shift = val = 0; - l = 8; - j = image->width; - dst = dst1; - s = src; - - /* write leading bits */ - if (start_index) { - u32 start_mask = ~(FB_SHIFT_HIGH(p, ~(u32)0, - start_index)); - val = *dst & start_mask; - shift = start_index; - } - - while (j--) { - l--; - color = (*s & (1 << l)) ? fgcolor : bgcolor; - val |= FB_SHIFT_HIGH(p, color, shift); - - /* Did the bitshift spill bits to the next long? */ - if (shift >= null_bits) { - *dst++ = val; - val = (shift == null_bits) ? 0 : - FB_SHIFT_LOW(p, color, 32 - shift); - } - shift += bpp; - shift &= (32 - 1); - if (!l) { l = 8; s++; } - } - - /* write trailing bits */ - if (shift) { - u32 end_mask = FB_SHIFT_HIGH(p, ~(u32)0, shift); - - *dst &= end_mask; - *dst |= val; - } - - dst1 += pitch; - src += spitch; - if (pitch_index) { - dst2 += pitch; - dst1 = (u8 *)((long)dst2 & ~(sizeof(u32) - 1)); - start_index += pitch_index; - start_index &= 32 - 1; - } - - } -} - -/* - * fast_imageblit - optimized monochrome color expansion - * - * Only if: bits_per_pixel == 8, 16, or 32 - * image->width is divisible by pixel/dword (ppw); - * fix->line_legth is divisible by 4; - * beginning and end of a scanline is dword aligned - */ -static void fast_imageblit(const struct fb_image *image, struct fb_info *p, - void *dst1, u32 fgcolor, u32 bgcolor) -{ - u32 fgx = fgcolor, bgx = bgcolor, bpp = p->var.bits_per_pixel; - u32 ppw = 32/bpp, spitch = (image->width + 7)/8; - u32 bit_mask, eorx, shift; - const u8 *s = image->data, *src; - u32 *dst; - const u32 *tab; - size_t tablen; - u32 colortab[16]; - int i, j, k; - - switch (bpp) { - case 8: - tab = fb_be_math(p) ? cfb_tab8_be : cfb_tab8_le; - tablen = 16; - break; - case 16: - tab = fb_be_math(p) ? cfb_tab16_be : cfb_tab16_le; - tablen = 4; - break; - case 32: - tab = cfb_tab32; - tablen = 2; - break; - default: - return; - } - - for (i = ppw-1; i--; ) { - fgx <<= bpp; - bgx <<= bpp; - fgx |= fgcolor; - bgx |= bgcolor; - } - - bit_mask = (1 << ppw) - 1; - eorx = fgx ^ bgx; - k = image->width/ppw; - - for (i = 0; i < tablen; ++i) - colortab[i] = (tab[i] & eorx) ^ bgx; - - for (i = image->height; i--; ) { - dst = dst1; - shift = 8; - src = s; - - /* - * Manually unroll the per-line copying loop for better - * performance. This works until we processed the last - * completely filled source byte (inclusive). - */ - switch (ppw) { - case 4: /* 8 bpp */ - for (j = k; j >= 2; j -= 2, ++src) { - *dst++ = colortab[(*src >> 4) & bit_mask]; - *dst++ = colortab[(*src >> 0) & bit_mask]; - } - break; - case 2: /* 16 bpp */ - for (j = k; j >= 4; j -= 4, ++src) { - *dst++ = colortab[(*src >> 6) & bit_mask]; - *dst++ = colortab[(*src >> 4) & bit_mask]; - *dst++ = colortab[(*src >> 2) & bit_mask]; - *dst++ = colortab[(*src >> 0) & bit_mask]; - } - break; - case 1: /* 32 bpp */ - for (j = k; j >= 8; j -= 8, ++src) { - *dst++ = colortab[(*src >> 7) & bit_mask]; - *dst++ = colortab[(*src >> 6) & bit_mask]; - *dst++ = colortab[(*src >> 5) & bit_mask]; - *dst++ = colortab[(*src >> 4) & bit_mask]; - *dst++ = colortab[(*src >> 3) & bit_mask]; - *dst++ = colortab[(*src >> 2) & bit_mask]; - *dst++ = colortab[(*src >> 1) & bit_mask]; - *dst++ = colortab[(*src >> 0) & bit_mask]; - } - break; - } - - /* - * For image widths that are not a multiple of 8, there - * are trailing pixels left on the current line. Print - * them as well. - */ - for (; j--; ) { - shift -= ppw; - *dst++ = colortab[(*src >> shift) & bit_mask]; - if (!shift) { - shift = 8; - ++src; - } - } - - dst1 += p->fix.line_length; - s += spitch; - } -} - -void sys_imageblit(struct fb_info *p, const struct fb_image *image) -{ - u32 fgcolor, bgcolor, start_index, bitstart, pitch_index = 0; - u32 bpl = sizeof(u32), bpp = p->var.bits_per_pixel; - u32 width = image->width; - u32 dx = image->dx, dy = image->dy; - void *dst1; - - if (p->state != FBINFO_STATE_RUNNING) - return; - - if (!(p->flags & FBINFO_VIRTFB)) - fb_warn_once(p, "Framebuffer is not in virtual address space."); - - bitstart = (dy * p->fix.line_length * 8) + (dx * bpp); - start_index = bitstart & (32 - 1); - pitch_index = (p->fix.line_length & (bpl - 1)) * 8; - - bitstart /= 8; - bitstart &= ~(bpl - 1); - dst1 = (void __force *)p->screen_base + bitstart; - - if (p->fbops->fb_sync) - p->fbops->fb_sync(p); - - if (image->depth == 1) { - if (p->fix.visual == FB_VISUAL_TRUECOLOR || - p->fix.visual == FB_VISUAL_DIRECTCOLOR) { - fgcolor = ((u32*)(p->pseudo_palette))[image->fg_color]; - bgcolor = ((u32*)(p->pseudo_palette))[image->bg_color]; - } else { - fgcolor = image->fg_color; - bgcolor = image->bg_color; - } - - if (32 % bpp == 0 && !start_index && !pitch_index && - ((width & (32/bpp-1)) == 0) && - bpp >= 8 && bpp <= 32) - fast_imageblit(image, p, dst1, fgcolor, bgcolor); - else - slow_imageblit(image, p, dst1, fgcolor, bgcolor, - start_index, pitch_index); - } else - color_imageblit(image, p, dst1, start_index, pitch_index); -} +#define FB_READL(a) (*a) +#define FB_WRITEL(a,b) do { *(b) = (a); } while (false) +#define FB_MEM /* nothing */ +#define FB_IMAGEBLIT sys_imageblit +#define FB_SPACE FBINFO_VIRTFB +#define FB_SPACE_NAME "virtual" +#define FB_SCREEN_BASE(a) ((a)->screen_buffer) +#include "fb_imageblit.h" EXPORT_SYMBOL(sys_imageblit);