From patchwork Sun Jul 15 19:04:37 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Herrmann X-Patchwork-Id: 1199271 Return-Path: X-Original-To: patchwork-linux-fbdev@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork1.kernel.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by patchwork1.kernel.org (Postfix) with ESMTP id 6CB7A40B37 for ; Sun, 15 Jul 2012 19:06:19 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1750910Ab2GOTGR (ORCPT ); Sun, 15 Jul 2012 15:06:17 -0400 Received: from mail-wg0-f44.google.com ([74.125.82.44]:64757 "EHLO mail-wg0-f44.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751234Ab2GOTFW (ORCPT ); Sun, 15 Jul 2012 15:05:22 -0400 Received: by mail-wg0-f44.google.com with SMTP id dr13so324126wgb.1 for ; Sun, 15 Jul 2012 12:05:21 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=googlemail.com; s=20120113; h=from:to:cc:subject:date:message-id:x-mailer:in-reply-to:references; bh=n3TfHQwNZ3Z7TFwJPp5M6R4SSiQOsK2rW1MH+6E8Vjs=; b=KAHRk3TZDEM7oWYsw0AybBaCO3t3iQCOAPX/L+X/9ni/Yt0M5ui5zwcXVOgKwgUoh3 ZJI8rC1/Hq/LhWAIsYjlFMqYc6SDYOqx6pP8m7NWa6Co569O06llYS5mu2oar2SXL1B7 cBa++W++Bap/QnuIHQ5T87f0I4bBK2SSO5YVsVaXZLeqVVkiGggRWmT3xIUo47SyBs4c 6UusJdquP/qFi/aJsCAL2NrPlDaz90zfX63gcqIO91SAtp93lV7t5kKtCJAqpMsXnERv els2nhOJzw0RZG9NTSmAVqbFH6i1RY/vj9Nsh09xcSMznc4XC3swBBnr7xe3Y8wqn4hg 5dvA== Received: by 10.216.140.15 with SMTP id d15mr4165937wej.204.1342379121321; Sun, 15 Jul 2012 12:05:21 -0700 (PDT) Received: from localhost.localdomain (stgt-5f71ba59.pool.mediaWays.net. [95.113.186.89]) by mx.google.com with ESMTPS id j6sm25479086wiy.4.2012.07.15.12.05.19 (version=TLSv1/SSLv3 cipher=OTHER); Sun, 15 Jul 2012 12:05:20 -0700 (PDT) From: David Herrmann To: linux-kernel@vger.kernel.org Cc: Florian Tobias Schandinat , Andrew Morton , Greg Kroah-Hartman , linux-fbdev@vger.kernel.org, linux-serial@vger.kernel.org, Alan Cox , David Herrmann Subject: [PATCH v3 02/11] fbcon: move bit_putcs() into separate source file Date: Sun, 15 Jul 2012 21:04:37 +0200 Message-Id: <1342379086-7583-3-git-send-email-dh.herrmann@googlemail.com> X-Mailer: git-send-email 1.7.11.2 In-Reply-To: <1342379086-7583-1-git-send-email-dh.herrmann@googlemail.com> References: <1342379086-7583-1-git-send-email-dh.herrmann@googlemail.com> Sender: linux-fbdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fbdev@vger.kernel.org If we want to use font-draw-operations in other modules than fbcon, we need to split this function off of fbcon headers and sources. This also makes bit_putcs() totally independent of vc_* and fbcon_* structures. As scr_read() cannot be called inside of non-fbcon/vt functions, we need to assemble the buffer before passing it to fbdraw_font(). This slows down this operations a little bit but my rough benchmark showed that it didn't really matter. Anyway, if it does, we can still put it into VT_BUF_HAVE_RW conditions so platforms that don't use it won't be affected. And for other platforms we can add the buffer to the vc-struct so we can reuse it. Signed-off-by: David Herrmann --- drivers/video/console/bitblit.c | 127 ++++------------------------------------ drivers/video/console/fbdraw.c | 125 +++++++++++++++++++++++++++++++++++++++ drivers/video/console/fbdraw.h | 4 ++ 3 files changed, 139 insertions(+), 117 deletions(-) diff --git a/drivers/video/console/bitblit.c b/drivers/video/console/bitblit.c index 6ec2905..c5d897b 100644 --- a/drivers/video/console/bitblit.c +++ b/drivers/video/console/bitblit.c @@ -54,132 +54,25 @@ static void bit_clear(struct vc_data *vc, struct fb_info *info, int sy, info->fbops->fb_fillrect(info, ®ion); } -static inline void bit_putcs_aligned(struct vc_data *vc, struct fb_info *info, - const u16 *s, u32 attr, u32 cnt, - u32 d_pitch, u32 s_pitch, u32 cellsize, - struct fb_image *image, u8 *buf, u8 *dst) -{ - u16 charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff; - u32 idx = vc->vc_font.width >> 3; - u8 *src; - - while (cnt--) { - src = vc->vc_font.data + (scr_readw(s++)& - charmask)*cellsize; - - if (attr) { - fbdraw_update_attr(buf, src, attr, &vc->vc_font); - src = buf; - } - - if (likely(idx == 1)) - __fb_pad_aligned_buffer(dst, d_pitch, src, idx, - image->height); - else - fb_pad_aligned_buffer(dst, d_pitch, src, idx, - image->height); - - dst += s_pitch; - } - - info->fbops->fb_imageblit(info, image); -} - -static inline void bit_putcs_unaligned(struct vc_data *vc, - struct fb_info *info, const u16 *s, - u32 attr, u32 cnt, u32 d_pitch, - u32 s_pitch, u32 cellsize, - struct fb_image *image, u8 *buf, - u8 *dst) -{ - u16 charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff; - u32 shift_low = 0, mod = vc->vc_font.width % 8; - u32 shift_high = 8; - u32 idx = vc->vc_font.width >> 3; - u8 *src; - - while (cnt--) { - src = vc->vc_font.data + (scr_readw(s++)& - charmask)*cellsize; - - if (attr) { - fbdraw_update_attr(buf, src, attr, &vc->vc_font); - src = buf; - } - - fb_pad_unaligned_buffer(dst, d_pitch, src, idx, - image->height, shift_high, - shift_low, mod); - shift_low += mod; - dst += (shift_low >= 8) ? s_pitch : s_pitch - 1; - shift_low &= 7; - shift_high = 8 - shift_low; - } - - info->fbops->fb_imageblit(info, image); - -} - static void bit_putcs(struct vc_data *vc, struct fb_info *info, const unsigned short *s, int count, int yy, int xx, int fg, int bg) { - struct fb_image image; - u32 width = DIV_ROUND_UP(vc->vc_font.width, 8); - u32 cellsize = width * vc->vc_font.height; - u32 maxcnt = info->pixmap.size/cellsize; - u32 scan_align = info->pixmap.scan_align - 1; - u32 buf_align = info->pixmap.buf_align - 1; - u32 mod = vc->vc_font.width % 8, cnt, pitch, size; + u16 *buf; + int i; u32 attribute = get_attribute(info, scr_readw(s)); - u8 *dst, *buf = NULL; - image.fg_color = fg; - image.bg_color = bg; - image.dx = xx * vc->vc_font.width; - image.dy = yy * vc->vc_font.height; - image.height = vc->vc_font.height; - image.depth = 1; + buf = kmalloc(sizeof(*buf) * count, GFP_KERNEL); + if (!buf) + return; - if (attribute) { - buf = kmalloc(cellsize, GFP_KERNEL); - if (!buf) - return; - } - - while (count) { - if (count > maxcnt) - cnt = maxcnt; - else - cnt = count; - - image.width = vc->vc_font.width * cnt; - pitch = DIV_ROUND_UP(image.width, 8) + scan_align; - pitch &= ~scan_align; - size = pitch * image.height + buf_align; - size &= ~buf_align; - dst = fb_get_buffer_offset(info, &info->pixmap, size); - image.data = dst; - - if (!mod) - bit_putcs_aligned(vc, info, s, attribute, cnt, pitch, - width, cellsize, &image, buf, dst); - else - bit_putcs_unaligned(vc, info, s, attribute, cnt, - pitch, width, cellsize, &image, - buf, dst); - - image.dx += cnt * vc->vc_font.width; - count -= cnt; - s += cnt; - } + for (i = 0; i < count; ++i) + buf[i] = scr_readw(s++); - /* buf is always NULL except when in monochrome mode, so in this case - it's a gain to check buf against NULL even though kfree() handles - NULL pointers just fine */ - if (unlikely(buf)) - kfree(buf); + fbdraw_font(info, &vc->vc_font, vc->vc_hi_font_mask, xx, yy, fg, bg, + attribute, buf, count); + kfree(buf); } static void bit_clear_margins(struct vc_data *vc, struct fb_info *info, diff --git a/drivers/video/console/fbdraw.c b/drivers/video/console/fbdraw.c index aa18f7e..f7c3da7 100644 --- a/drivers/video/console/fbdraw.c +++ b/drivers/video/console/fbdraw.c @@ -41,6 +41,131 @@ void fbdraw_update_attr(u8 *dst, const u8 *src, int attribute, } EXPORT_SYMBOL_GPL(fbdraw_update_attr); +static inline void bit_putcs_aligned(struct fb_info *info, bool hi_font, + struct console_font *font, u32 attribute, + u32 d_pitch, u32 s_pitch, u32 cellsize, + struct fb_image *image, u8 *buf, u8 *dst, + const u16 *chars, size_t cnt) +{ + u16 charmask = hi_font ? 0x1ff : 0xff; + u32 idx = font->width >> 3; + u8 *src; + + while (cnt--) { + src = font->data + ((*chars++) & charmask) * cellsize; + + if (attribute) { + fbdraw_update_attr(buf, src, attribute, font); + src = buf; + } + + if (likely(idx == 1)) + __fb_pad_aligned_buffer(dst, d_pitch, src, idx, + image->height); + else + fb_pad_aligned_buffer(dst, d_pitch, src, idx, + image->height); + + dst += s_pitch; + } + + info->fbops->fb_imageblit(info, image); +} + +static inline void bit_putcs_unaligned(struct fb_info *info, bool hi_font, + struct console_font *font, u32 attribute, + u32 d_pitch, u32 s_pitch, u32 cellsize, + struct fb_image *image, u8 *buf, u8 *dst, + const u16 *chars, size_t cnt) +{ + u16 charmask = hi_font ? 0x1ff : 0xff; + u32 shift_low = 0, mod = font->width % 8; + u32 shift_high = 8; + u32 idx = font->width >> 3; + u8 *src; + + while (cnt--) { + src = font->data + ((*chars++) & charmask) * cellsize; + + if (attribute) { + fbdraw_update_attr(buf, src, attribute, font); + src = buf; + } + + fb_pad_unaligned_buffer(dst, d_pitch, src, idx, + image->height, shift_high, + shift_low, mod); + shift_low += mod; + dst += (shift_low >= 8) ? s_pitch : s_pitch - 1; + shift_low &= 7; + shift_high = 8 - shift_low; + } + + info->fbops->fb_imageblit(info, image); +} + +void fbdraw_font(struct fb_info *info, struct console_font *font, bool hi_font, + unsigned int xpos, unsigned int ypos, int fg, int bg, + u32 attribute, const u16 *chars, size_t count) +{ + struct fb_image image; + u32 width = DIV_ROUND_UP(font->width, 8); + u32 cellsize = width * font->height; + u32 maxcnt = info->pixmap.size / cellsize; + u32 scan_align = info->pixmap.scan_align - 1; + u32 buf_align = info->pixmap.buf_align - 1; + u32 mod = font->width % 8, cnt, pitch, size; + u8 *dst, *buf = NULL; + + image.fg_color = fg; + image.bg_color = bg; + image.dx = xpos * font->width; + image.dy = ypos * font->height; + image.height = font->height; + image.depth = 1; + + if (attribute) { + buf = kmalloc(cellsize, GFP_KERNEL); + if (!buf) + return; + } + + while (count) { + if (count > maxcnt) + cnt = maxcnt; + else + cnt = count; + + image.width = font->width * cnt; + pitch = DIV_ROUND_UP(image.width, 8) + scan_align; + pitch &= ~scan_align; + size = pitch * image.height + buf_align; + size &= ~buf_align; + dst = fb_get_buffer_offset(info, &info->pixmap, size); + image.data = dst; + + if (!mod) + bit_putcs_aligned(info, hi_font, font, attribute, + pitch, width, cellsize, &image, buf, + dst, chars, cnt); + else + bit_putcs_unaligned(info, hi_font, font, attribute, + pitch, width, cellsize, &image, buf, + dst, chars, cnt); + + image.dx += cnt * font->width; + count -= cnt; + chars += cnt; + } + + /* buf is always NULL except when in monochrome mode, so in this case + it's a gain to check buf against NULL even though kfree() handles + NULL pointers just fine */ + if (unlikely(buf)) + kfree(buf); +} +EXPORT_SYMBOL_GPL(fbdraw_font); + MODULE_LICENSE("GPL"); MODULE_AUTHOR("David Herrmann "); MODULE_DESCRIPTION("Framebuffer helpers for image draw-operations"); diff --git a/drivers/video/console/fbdraw.h b/drivers/video/console/fbdraw.h index 77edd7f..b9f1ffa 100644 --- a/drivers/video/console/fbdraw.h +++ b/drivers/video/console/fbdraw.h @@ -23,4 +23,8 @@ void fbdraw_update_attr(u8 *dst, const u8 *src, int attribute, struct console_font *font); +void fbdraw_font(struct fb_info *info, struct console_font *font, bool hi_font, + unsigned int xpos, unsigned int ypos, int fg, int bg, + u32 attribute, const u16 *chars, size_t count); + #endif /* _VIDEO_FBDRAW_H */