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 */