From: Antonino Daplas <adaplas@pol.net>
To: fbdev <linux-fbdev-devel@lists.sourceforge.net>
Subject: RFC: Optimizing putcs()
Date: 06 Aug 2002 06:04:19 +0800 [thread overview]
Message-ID: <1028584418.556.29.camel@daplas> (raw)
[-- Attachment #1: Type: text/plain, Size: 2201 bytes --]
With fbcon-accel and the new drawing functions in linux-2.5, console
performance degraded compared to the linux-2.4 implementation. This is
because putcs() has to to do 1 fb_imageblit() per character to be
drawn.
This can be optimized by letting putcs() initially construct the row of
text to be drawn into an offscreen buffer, then do a single
fb_imageblit() in the end. Performance wil increase for several
reasons:
1. Drawing can be done in "bursts" instead of "trickles"
2. For drivers that support accelerated drawing functions, the
offscreen buffer can be optionally placed in graphics (or AGP) memory,
which is better suited for most hardware that can only do blit's from
video memory to video memory.
3. Some level of asynchronicity can be achieved, ie, the hardware can
be blitting while fbcon-accel is constructing bitmaps. This would
require "walking" the offscreen buffer, and support for hardware
graphics sync'ing on demand.
I have included a patch for 2.5.27 that implements it in fbcon-accel.
It's preliminary, but I have tested it with cfb_imageblit and with
hardware imageblit, with buffers in System or Video memory.
The code is also present for hardware syncing on demand, though
unimplemented.
For drivers that uses cfb_imageblit or similar, a code such as the one
below can be inserted during initialization:
info->pixmap.addr = (unsigned long) kmalloc(BUFFER_SIZE, GFP_KERNEL);
info->pixmap.size = BUFFER_SIZE;
info->pixmap.offset = 0;
info->pixmap.buf_align = 1;
info->pixmap.scan_align = 1;
Some benchmarks:
time cat /usr/src/linux/MAINTAINERS (40K text file)
mode: 1024x768@8bpp, y-panning disabled.
cfb_imageblit - no offscreen buffer (default)
real 0m13.586s
user 0m0.001s
sys 0m13.585s
cfb_imageblit - with offscreen buffer in system memory
real 0m10.708s
user 0m0.001s
sys 0m10.707s
hardware imageblit - no offscreen buffer
real 0m6.036s
user 0m0.001s
sys 0m6.035s
hardware imageblit - with offscreen buffer in graphics memory
real 0m3.160s
user 0m0.001s
sys 0m3.160s
hardware imageblit - graphics offscreen buffer + hardware sync on demand
real 0m1.843s
user 0m0.000s
sys 0m1.843s
Tony
[-- Attachment #2: fb-pixmap.diff --]
[-- Type: text/x-patch, Size: 5107 bytes --]
diff -Naur linux-2.5.27/drivers/video/fbcon-accel.c linux/drivers/video/fbcon-accel.c
--- linux-2.5.27/drivers/video/fbcon-accel.c Mon Aug 5 21:15:56 2002
+++ linux/drivers/video/fbcon-accel.c Mon Aug 5 21:17:22 2002
@@ -70,9 +70,47 @@
image.width = fontwidth(p);
image.height = fontheight(p);
image.depth = 1;
- image.data = p->fontdata + (c & charmask)*fontheight(p)*width;
+ if (!info->pixmap.addr) {
+ image.data = p->fontdata + (c & charmask)*fontheight(p)*width;
+ info->fbops->fb_imageblit(info, &image);
+ }
+ else {
+ unsigned int d_size, d_pitch, i, j;
+ unsigned int scan_align = (info->pixmap.scan_align) ? info->pixmap.scan_align - 1 : 0;
+ unsigned int buf_align = (info->pixmap.buf_align) ? info->pixmap.buf_align - 1 : 0;
+ char *d_addr, *s_addr;
+
+ d_pitch = (width + scan_align) & ~scan_align;
+ d_size = d_pitch * image.height;
+
+ if (d_size > info->pixmap.size) {
+ BUG();
+ return;
+ }
+
+ info->pixmap.offset = (info->pixmap.offset + buf_align) & ~buf_align;
- info->fbops->fb_imageblit(info, &image);
+ if (info->pixmap.offset + d_size > info->pixmap.size) {
+#if 0
+ /* Some form of hardware sync'ing may be necessary here */
+ if (info->fbops->fb_sync)
+ info->fbops->fb_sync(info);
+#endif
+ info->pixmap.offset = 0;
+ }
+ s_addr = p->fontdata + (c & charmask)*fontheight(p)*width;
+ image.data = (char *) (info->pixmap.addr + info->pixmap.offset);
+ d_addr = image.data;
+
+ for (i = image.height; i--; ) {
+ for (j = 0; j < width; j++)
+ d_addr[j] = *s_addr++;
+ d_addr += d_pitch;
+ }
+
+ info->fbops->fb_imageblit(info, &image);
+ info->pixmap.offset += d_size;
+ }
}
void fbcon_accel_putcs(struct vc_data *vc, struct display *p,
@@ -87,15 +125,61 @@
image.bg_color = attr_bgcol(p, *s);
image.dx = xx * fontwidth(p);
image.dy = yy * fontheight(p);
- image.width = fontwidth(p);
image.height = fontheight(p);
image.depth = 1;
+ if (!info->pixmap.addr) {
+ image.width = fontwidth(p);
+ while (count--) {
+ image.data = p->fontdata +
+ (scr_readw(s++) & charmask) * fontheight(p) * width;
+ info->fbops->fb_imageblit(info, &image);
+ image.dx += fontwidth(p);
+ }
+ }
+ else {
+ unsigned int d_pitch, d_size, i, j;
+ unsigned int scan_align = (info->pixmap.scan_align) ? info->pixmap.scan_align - 1 : 0;
+ unsigned int buf_align = (info->pixmap.buf_align) ? info->pixmap.buf_align - 1 : 0;
+ char *s_addr, *d_addr, *d_addr0;
+
+ d_pitch = (width * count) + scan_align;
+ d_pitch &= ~scan_align;
+ d_size = d_pitch * image.height;
+
+ if (d_size > info->pixmap.size) {
+ BUG();
+ return;
+ }
+
+ info->pixmap.offset = (info->pixmap.offset + buf_align) & ~buf_align;
+
+ if (info->pixmap.offset + d_size > info->pixmap.size) {
+#if 0
+ /* Some form of hardware sync'ing may be necessary here */
+ if (info->fbops->fb_sync)
+ info->fbops->fb_sync(info);
+#endif
+ info->pixmap.offset = 0;
+ }
+
+ image.width = fontwidth(p) * count;
+ image.data = (char *) (info->pixmap.addr + info->pixmap.offset);
+ d_addr = image.data;
+
+ while (count--) {
+ s_addr = p->fontdata +
+ (scr_readw(s++) & charmask) * fontheight(p) * width;
+ d_addr0 = d_addr;
+ for (i = image.height; i--; ) {
+ for (j = 0; j < width; j++)
+ d_addr0[j] = *s_addr++;
+ d_addr0 += d_pitch;
+ }
+ d_addr += width;
+ }
- while (count--) {
- image.data = p->fontdata +
- (scr_readw(s++) & charmask) * fontheight(p) * width;
info->fbops->fb_imageblit(info, &image);
- image.dx += fontwidth(p);
+ info->pixmap.offset += d_size;
}
}
diff -Naur linux-2.5.27/include/linux/fb.h linux/include/linux/fb.h
--- linux-2.5.27/include/linux/fb.h Mon Aug 5 21:16:16 2002
+++ linux/include/linux/fb.h Mon Aug 5 21:17:48 2002
@@ -291,6 +291,14 @@
char *data; /* Pointer to image data */
};
+struct fb_pixmap {
+ __u32 addr; /* buffer pointer (system or video), NULL if none */
+ __u32 offset; /* offset to buffer */
+ __u32 size; /* size of buffer */
+ __u32 buf_align; /* buffer start alignment */
+ __u32 scan_align; /* scanline alignment, should be <= buf_align */
+};
+
#ifdef __KERNEL__
#if 1 /* to go away in 2.5.0 */
@@ -359,6 +367,10 @@
int (*fb_mmap)(struct fb_info *info, struct file *file, struct vm_area_struct *vma);
/* switch to/from raster image mode */
int (*fb_rasterimg)(struct fb_info *info, int start);
+#if 0
+ /* wait for blit idle, optional */
+ void (*fb_sync)(struct fb_info *info);
+#endif
};
struct fb_info {
@@ -371,6 +383,7 @@
struct fb_fix_screeninfo fix; /* Current fix */
struct fb_monspecs monspecs; /* Current Monitor specs */
struct fb_cmap cmap; /* Current cmap */
+ struct fb_pixmap pixmap; /* Offscreen pixmap */
struct fb_ops *fbops;
char *screen_base; /* Virtual address */
struct display *disp; /* initial display variable */
next reply other threads:[~2002-08-05 22:00 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2002-08-05 22:04 Antonino Daplas [this message]
2002-08-06 20:08 ` RFC: Optimizing putcs() Geert Uytterhoeven
2002-08-07 0:17 ` Antonino Daplas
2002-08-07 5:25 ` Antonino Daplas
[not found] <20020806054957.44715.qmail@web13004.mail.yahoo.com>
2002-08-06 18:11 ` Antonino Daplas
2002-08-08 18:31 ` James Simmons
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1028584418.556.29.camel@daplas \
--to=adaplas@pol.net \
--cc=linux-fbdev-devel@lists.sourceforge.net \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).