Commit cfe1d063 authored by James Simmons's avatar James Simmons

[GENERIC IMAGEBLIT ACCEL]

a) Fix for cfb_imagblit so it can handle monochrome bitmaps with widths not multiples of 8.

b) Further optiminzation of fast_imageblit by removing unnecessary steps from its main loop.

c) fast_imageblit show now work for bitmaps widths which are least divisible by 4. 4x6 and 12x22 shoudl use fast_imageblit now.

d) Use hadrware syncing method of hardware if present.

e) trivial: wrap text at 80 columns. 

[RIVA and 3DFX] imageblit functions busted for large images. Use generic functions for now.

Several syncing issues fixed between the accel engine and access to the framebuffer is several files.
parent 9b0f2f7d
...@@ -38,7 +38,7 @@ obj-$(CONFIG_FB_CLPS711X) += clps711xfb.o cfbfillrect.o cfbcopyarea.o cf ...@@ -38,7 +38,7 @@ obj-$(CONFIG_FB_CLPS711X) += clps711xfb.o cfbfillrect.o cfbcopyarea.o cf
obj-$(CONFIG_FB_CYBER) += cyberfb.o obj-$(CONFIG_FB_CYBER) += cyberfb.o
obj-$(CONFIG_FB_CYBER2000) += cyber2000fb.o obj-$(CONFIG_FB_CYBER2000) += cyber2000fb.o
obj-$(CONFIG_FB_SGIVW) += sgivwfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o obj-$(CONFIG_FB_SGIVW) += sgivwfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
obj-$(CONFIG_FB_3DFX) += tdfxfb.o obj-$(CONFIG_FB_3DFX) += tdfxfb.o cfbimgblt.o
obj-$(CONFIG_FB_MAC) += macfb.o macmodes.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o obj-$(CONFIG_FB_MAC) += macfb.o macmodes.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
obj-$(CONFIG_FB_HP300) += hpfb.o cfbfillrect.o cfbimgblt.o obj-$(CONFIG_FB_HP300) += hpfb.o cfbfillrect.o cfbimgblt.o
obj-$(CONFIG_FB_OF) += offb.o cfbfillrect.o cfbimgblt.o cfbcopyarea.o obj-$(CONFIG_FB_OF) += offb.o cfbfillrect.o cfbimgblt.o cfbcopyarea.o
......
...@@ -65,13 +65,15 @@ static void bitcpy(unsigned long *dst, int dst_idx, const unsigned long *src, ...@@ -65,13 +65,15 @@ static void bitcpy(unsigned long *dst, int dst_idx, const unsigned long *src,
// Single word // Single word
if (last) if (last)
first &= last; first &= last;
FB_WRITEL((*src & first) | (FB_READL(dst) & ~first), dst); FB_WRITEL((*src & first) | (FB_READL(dst) & ~first),
dst);
} else { } else {
// Multiple destination words // Multiple destination words
// Leading bits // Leading bits
if (first) { if (first) {
FB_WRITEL((*src & first) | (FB_READL(dst) & ~first), dst); FB_WRITEL((*src & first) | (FB_READL(dst) &
~first), dst);
dst++; dst++;
src++; src++;
n -= BITS_PER_LONG-dst_idx; n -= BITS_PER_LONG-dst_idx;
...@@ -94,7 +96,8 @@ static void bitcpy(unsigned long *dst, int dst_idx, const unsigned long *src, ...@@ -94,7 +96,8 @@ static void bitcpy(unsigned long *dst, int dst_idx, const unsigned long *src,
FB_WRITEL(*src++, dst++); FB_WRITEL(*src++, dst++);
// Trailing bits // Trailing bits
if (last) if (last)
FB_WRITEL((*src & last) | (FB_READL(dst) & ~last), dst); FB_WRITEL((*src & last) | (FB_READL(dst) &
~last), dst);
} }
} else { } else {
// Different alignment for source and dest // Different alignment for source and dest
...@@ -108,15 +111,18 @@ static void bitcpy(unsigned long *dst, int dst_idx, const unsigned long *src, ...@@ -108,15 +111,18 @@ static void bitcpy(unsigned long *dst, int dst_idx, const unsigned long *src,
first &= last; first &= last;
if (shift > 0) { if (shift > 0) {
// Single source word // Single source word
FB_WRITEL(((*src >> right) & first) | (FB_READL(dst) & ~first), dst); FB_WRITEL(((*src >> right) & first) |
(FB_READL(dst) & ~first), dst);
} else if (src_idx+n <= BITS_PER_LONG) { } else if (src_idx+n <= BITS_PER_LONG) {
// Single source word // Single source word
FB_WRITEL(((*src << left) & first) | (FB_READL(dst) & ~first), dst); FB_WRITEL(((*src << left) & first) |
(FB_READL(dst) & ~first), dst);
} else { } else {
// 2 source words // 2 source words
d0 = *src++; d0 = *src++;
d1 = *src; d1 = *src;
FB_WRITEL(((d0 << left | d1 >> right) & first) | (FB_READL(dst) & ~first), dst); FB_WRITEL(((d0<<left | d1>>right) & first) |
(FB_READL(dst) & ~first), dst);
} }
} else { } else {
// Multiple destination words // Multiple destination words
...@@ -124,13 +130,15 @@ static void bitcpy(unsigned long *dst, int dst_idx, const unsigned long *src, ...@@ -124,13 +130,15 @@ static void bitcpy(unsigned long *dst, int dst_idx, const unsigned long *src,
// Leading bits // Leading bits
if (shift > 0) { if (shift > 0) {
// Single source word // Single source word
FB_WRITEL(((d0 >> right) & first) | (FB_READL(dst) & ~first), dst); FB_WRITEL(((d0 >> right) & first) |
(FB_READL(dst) & ~first), dst);
dst++; dst++;
n -= BITS_PER_LONG-dst_idx; n -= BITS_PER_LONG-dst_idx;
} else { } else {
// 2 source words // 2 source words
d1 = *src++; d1 = *src++;
FB_WRITEL(((d0 << left | d1 >> right) & first) | (FB_READL(dst) & ~first), dst); FB_WRITEL(((d0<<left | d1>>right) & first) |
(FB_READL(dst) & ~first), dst);
d0 = d1; d0 = d1;
dst++; dst++;
n -= BITS_PER_LONG-dst_idx; n -= BITS_PER_LONG-dst_idx;
...@@ -164,11 +172,15 @@ static void bitcpy(unsigned long *dst, int dst_idx, const unsigned long *src, ...@@ -164,11 +172,15 @@ static void bitcpy(unsigned long *dst, int dst_idx, const unsigned long *src,
if (last) { if (last) {
if (m <= right) { if (m <= right) {
// Single source word // Single source word
FB_WRITEL(((d0 << left) & last) | (FB_READL(dst) & ~last), dst); FB_WRITEL(((d0 << left) & last) |
(FB_READL(dst) & ~last),
dst);
} else { } else {
// 2 source words // 2 source words
d1 = *src; d1 = *src;
FB_WRITEL(((d0 << left | d1 >> right) & last) | (FB_READL(dst) & ~last), dst); FB_WRITEL(((d0<<left | d1>>right) &
last) | (FB_READL(dst) &
~last), dst);
} }
} }
} }
...@@ -208,12 +220,14 @@ static void bitcpy_rev(unsigned long *dst, int dst_idx, ...@@ -208,12 +220,14 @@ static void bitcpy_rev(unsigned long *dst, int dst_idx,
// Single word // Single word
if (last) if (last)
first &= last; first &= last;
FB_WRITEL((*src & first) | (FB_READL(dst) & ~first), dst); FB_WRITEL((*src & first) | (FB_READL(dst) & ~first),
dst);
} else { } else {
// Multiple destination words // Multiple destination words
// Leading bits // Leading bits
if (first) { if (first) {
FB_WRITEL((*src & first) | (FB_READL(dst) & ~first), dst); FB_WRITEL((*src & first) | (FB_READL(dst) &
~first), dst);
dst--; dst--;
src--; src--;
n -= dst_idx+1; n -= dst_idx+1;
...@@ -237,7 +251,8 @@ static void bitcpy_rev(unsigned long *dst, int dst_idx, ...@@ -237,7 +251,8 @@ static void bitcpy_rev(unsigned long *dst, int dst_idx,
// Trailing bits // Trailing bits
if (last) if (last)
FB_WRITEL((*src & last) | (FB_READL(dst) & ~last), dst); FB_WRITEL((*src & last) | (FB_READL(dst) &
~last), dst);
} }
} else { } else {
// Different alignment for source and dest // Different alignment for source and dest
...@@ -251,15 +266,18 @@ static void bitcpy_rev(unsigned long *dst, int dst_idx, ...@@ -251,15 +266,18 @@ static void bitcpy_rev(unsigned long *dst, int dst_idx,
first &= last; first &= last;
if (shift < 0) { if (shift < 0) {
// Single source word // Single source word
FB_WRITEL((*src << left & first) | (FB_READL(dst) & ~first), dst); FB_WRITEL((*src << left & first) |
(FB_READL(dst) & ~first), dst);
} else if (1+(unsigned long)src_idx >= n) { } else if (1+(unsigned long)src_idx >= n) {
// Single source word // Single source word
FB_WRITEL(((*src >> right) & first) | (FB_READL(dst) & ~first), dst); FB_WRITEL(((*src >> right) & first) |
(FB_READL(dst) & ~first), dst);
} else { } else {
// 2 source words // 2 source words
d0 = *src--; d0 = *src--;
d1 = *src; d1 = *src;
FB_WRITEL(((d0 >> right | d1 << left) & first) | (FB_READL(dst) & ~first), dst); FB_WRITEL(((d0>>right | d1<<left) & first) |
(FB_READL(dst) & ~first), dst);
} }
} else { } else {
// Multiple destination words // Multiple destination words
...@@ -267,13 +285,15 @@ static void bitcpy_rev(unsigned long *dst, int dst_idx, ...@@ -267,13 +285,15 @@ static void bitcpy_rev(unsigned long *dst, int dst_idx,
// Leading bits // Leading bits
if (shift < 0) { if (shift < 0) {
// Single source word // Single source word
FB_WRITEL(((d0 << left) & first) | (FB_READL(dst) & ~first), dst); FB_WRITEL(((d0 << left) & first) |
(FB_READL(dst) & ~first), dst);
dst--; dst--;
n -= dst_idx+1; n -= dst_idx+1;
} else { } else {
// 2 source words // 2 source words
d1 = *src--; d1 = *src--;
FB_WRITEL(((d0 >> right | d1 << left) & first) | (FB_READL(dst) & ~first), dst); FB_WRITEL(((d0>>right | d1<<left) & first) |
(FB_READL(dst) & ~first), dst);
d0 = d1; d0 = d1;
dst--; dst--;
n -= dst_idx+1; n -= dst_idx+1;
...@@ -307,12 +327,15 @@ static void bitcpy_rev(unsigned long *dst, int dst_idx, ...@@ -307,12 +327,15 @@ static void bitcpy_rev(unsigned long *dst, int dst_idx,
if (last) { if (last) {
if (m <= left) { if (m <= left) {
// Single source word // Single source word
FB_WRITEL(((d0 >> right) & last) | (FB_READL(dst) & ~last), dst); FB_WRITEL(((d0 >> right) & last) |
(FB_READL(dst) & ~last),
dst);
} else { } else {
// 2 source words // 2 source words
d1 = *src; d1 = *src;
FB_WRITEL(((d0 >> right | d1 << left) & last) | FB_WRITEL(((d0>>right | d1<<left) &
(FB_READL(dst) & ~last), dst); last) | (FB_READL(dst) &
~last), dst);
} }
} }
} }
...@@ -363,18 +386,22 @@ void cfb_copyarea(struct fb_info *p, struct fb_copyarea *area) ...@@ -363,18 +386,22 @@ void cfb_copyarea(struct fb_info *p, struct fb_copyarea *area)
(area->sx + area->width) > vxres || (area->sx + area->width) > vxres ||
(area->sy + area->height) > vyres) (area->sy + area->height) > vyres)
return; return;
if (area->dy > area->sy || (area->dy == area->sy && area->dx > area->sx)) { if ((area->dy == area->sy && area->dx > area->sx) ||
(area->dy > area->sy)) {
area->dy += area->height; area->dy += area->height;
area->sy += area->height; area->sy += area->height;
rev_copy = 1; rev_copy = 1;
} }
dst = src = (unsigned long *)((unsigned long)p->screen_base & ~(BYTES_PER_LONG-1)); dst = src = (unsigned long *)((unsigned long)p->screen_base &
~(BYTES_PER_LONG-1));
dst_idx = src_idx = (unsigned long)p->screen_base & (BYTES_PER_LONG-1); dst_idx = src_idx = (unsigned long)p->screen_base & (BYTES_PER_LONG-1);
dst_idx += area->dy*next_line*8 + area->dx*p->var.bits_per_pixel; dst_idx += area->dy*next_line*8 + area->dx*p->var.bits_per_pixel;
src_idx += area->sy*next_line*8 + area->sx*p->var.bits_per_pixel; src_idx += area->sy*next_line*8 + area->sx*p->var.bits_per_pixel;
if (p->fbops->fb_sync)
p->fbops->fb_sync(p);
if (rev_copy) { if (rev_copy) {
while (area->height--) { while (area->height--) {
dst_idx -= next_line*8; dst_idx -= next_line*8;
...@@ -383,8 +410,9 @@ void cfb_copyarea(struct fb_info *p, struct fb_copyarea *area) ...@@ -383,8 +410,9 @@ void cfb_copyarea(struct fb_info *p, struct fb_copyarea *area)
dst_idx &= (BYTES_PER_LONG-1); dst_idx &= (BYTES_PER_LONG-1);
src += src_idx >> SHIFT_PER_LONG; src += src_idx >> SHIFT_PER_LONG;
src_idx &= (BYTES_PER_LONG-1); src_idx &= (BYTES_PER_LONG-1);
bitcpy_rev((unsigned long*)dst, dst_idx, (unsigned long *)src, bitcpy_rev((unsigned long*)dst, dst_idx,
src_idx, area->width*p->var.bits_per_pixel); (unsigned long *)src, src_idx,
area->width*p->var.bits_per_pixel);
} }
} else { } else {
while (area->height--) { while (area->height--) {
...@@ -392,8 +420,9 @@ void cfb_copyarea(struct fb_info *p, struct fb_copyarea *area) ...@@ -392,8 +420,9 @@ void cfb_copyarea(struct fb_info *p, struct fb_copyarea *area)
dst_idx &= (BYTES_PER_LONG-1); dst_idx &= (BYTES_PER_LONG-1);
src += src_idx >> SHIFT_PER_LONG; src += src_idx >> SHIFT_PER_LONG;
src_idx &= (BYTES_PER_LONG-1); src_idx &= (BYTES_PER_LONG-1);
bitcpy((unsigned long*)dst, dst_idx, (unsigned long *)src, bitcpy((unsigned long*)dst, dst_idx,
src_idx, area->width*p->var.bits_per_pixel); (unsigned long *)src, src_idx,
area->width*p->var.bits_per_pixel);
dst_idx += next_line*8; dst_idx += next_line*8;
src_idx += next_line*8; src_idx += next_line*8;
} }
......
...@@ -99,7 +99,8 @@ static inline u32 pixel_to_pat32(const struct fb_info *p, pixel_t pixel) ...@@ -99,7 +99,8 @@ static inline u32 pixel_to_pat32(const struct fb_info *p, pixel_t pixel)
* the correct start position * the correct start position
*/ */
static inline unsigned long pixel_to_pat(const struct fb_info *p, pixel_t pixel, int left) static inline unsigned long pixel_to_pat(const struct fb_info *p,
pixel_t pixel, int left)
{ {
unsigned long pat = pixel; unsigned long pat = pixel;
u32 bpp = p->var.bits_per_pixel; u32 bpp = p->var.bits_per_pixel;
...@@ -373,7 +374,8 @@ void cfb_fillrect(struct fb_info *p, struct fb_fillrect *rect) ...@@ -373,7 +374,8 @@ void cfb_fillrect(struct fb_info *p, struct fb_fillrect *rect)
vxres = p->var.xres_virtual; vxres = p->var.xres_virtual;
vyres = p->var.yres_virtual; vyres = p->var.yres_virtual;
if (!rect->width || !rect->height || rect->dx > vxres || rect->dy > vyres) if (!rect->width || !rect->height ||
rect->dx > vxres || rect->dy > vyres)
return; return;
/* We could use hardware clipping but on many cards you get around /* We could use hardware clipping but on many cards you get around
...@@ -392,14 +394,18 @@ void cfb_fillrect(struct fb_info *p, struct fb_fillrect *rect) ...@@ -392,14 +394,18 @@ void cfb_fillrect(struct fb_info *p, struct fb_fillrect *rect)
else else
fg = rect->color; fg = rect->color;
dst = (unsigned long *)((unsigned long)p->screen_base & ~(BYTES_PER_LONG-1)); dst = (unsigned long *)((unsigned long)p->screen_base &
~(BYTES_PER_LONG-1));
dst_idx = ((unsigned long)p->screen_base & (BYTES_PER_LONG-1))*8; dst_idx = ((unsigned long)p->screen_base & (BYTES_PER_LONG-1))*8;
dst_idx += rect->dy*p->fix.line_length*8+rect->dx*bpp; dst_idx += rect->dy*p->fix.line_length*8+rect->dx*bpp;
/* FIXME For now we support 1-32 bpp only */ /* FIXME For now we support 1-32 bpp only */
left = BITS_PER_LONG % bpp; left = BITS_PER_LONG % bpp;
if (p->fbops->fb_sync)
p->fbops->fb_sync(p);
if (!left) { if (!left) {
u32 pat = pixel_to_pat32(p, fg); u32 pat = pixel_to_pat32(p, fg);
void (*fill_op32)(unsigned long *dst, int dst_idx, u32 pat, u32 n) = NULL; void (*fill_op32)(unsigned long *dst, int dst_idx, u32 pat,
u32 n) = NULL;
switch (rect->rop) { switch (rect->rop) {
case ROP_XOR: case ROP_XOR:
...@@ -420,8 +426,9 @@ void cfb_fillrect(struct fb_info *p, struct fb_fillrect *rect) ...@@ -420,8 +426,9 @@ void cfb_fillrect(struct fb_info *p, struct fb_fillrect *rect)
unsigned long pat = pixel_to_pat(p, fg, (left-dst_idx) % bpp); unsigned long pat = pixel_to_pat(p, fg, (left-dst_idx) % bpp);
int right = bpp-left; int right = bpp-left;
int r; int r;
void (*fill_op)(unsigned long *dst, int dst_idx, unsigned long pat, void (*fill_op)(unsigned long *dst, int dst_idx,
int left, int right, u32 n) = NULL; unsigned long pat, int left, int right,
u32 n) = NULL;
switch (rect->rop) { switch (rect->rop) {
case ROP_XOR: case ROP_XOR:
...@@ -435,7 +442,8 @@ void cfb_fillrect(struct fb_info *p, struct fb_fillrect *rect) ...@@ -435,7 +442,8 @@ void cfb_fillrect(struct fb_info *p, struct fb_fillrect *rect)
while (height--) { while (height--) {
dst += dst_idx >> SHIFT_PER_LONG; dst += dst_idx >> SHIFT_PER_LONG;
dst_idx &= (BITS_PER_LONG-1); dst_idx &= (BITS_PER_LONG-1);
fill_op(dst, dst_idx, pat, left, right, rect->width*bpp); fill_op(dst, dst_idx, pat, left, right,
rect->width*bpp);
r = (p->fix.line_length*8) % bpp; r = (p->fix.line_length*8) % bpp;
pat = pat << (bpp-r) | pat >> r; pat = pat << (bpp-r) | pat >> r;
dst_idx += p->fix.line_length*8; dst_idx += p->fix.line_length*8;
......
...@@ -19,10 +19,6 @@ ...@@ -19,10 +19,6 @@
* up to the nearest byte. For example a bitmap 12 bits wide must be two * up to the nearest byte. For example a bitmap 12 bits wide must be two
* bytes width. * bytes width.
* *
* FIXME
* The code for 24 bit is horrible. It copies byte by byte size instead of
* longs like the other sizes. Needs to be optimized.
*
* Tony: * Tony:
* Incorporate mask tables similar to fbcon-cfb*.c in 2.4 API. This speeds * Incorporate mask tables similar to fbcon-cfb*.c in 2.4 API. This speeds
* up the code significantly. * up the code significantly.
...@@ -32,7 +28,6 @@ ...@@ -32,7 +28,6 @@
* *
* Also need to add code to deal with cards endians that are different than * 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 native cpu endians. I also need to deal with MSB position in the word.
*
*/ */
#include <linux/config.h> #include <linux/config.h>
#include <linux/module.h> #include <linux/module.h>
...@@ -98,8 +93,9 @@ static u32 cfb_tab32[] = { ...@@ -98,8 +93,9 @@ static u32 cfb_tab32[] = {
#define SHIFT_LOW(val, bits) ((val) >> (bits)) #define SHIFT_LOW(val, bits) ((val) >> (bits))
#endif #endif
static inline void color_imageblit(struct fb_image *image, struct fb_info *p, u8 *dst1, static inline void color_imageblit(struct fb_image *image, struct fb_info *p,
unsigned long start_index, unsigned long pitch_index) u8 *dst1, unsigned long start_index,
unsigned long pitch_index)
{ {
/* Draw the penguin */ /* Draw the penguin */
unsigned long *dst, *dst2, color = 0, val, shift; unsigned long *dst, *dst2, color = 0, val, shift;
...@@ -116,8 +112,8 @@ static inline void color_imageblit(struct fb_image *image, struct fb_info *p, u8 ...@@ -116,8 +112,8 @@ static inline void color_imageblit(struct fb_image *image, struct fb_info *p, u8
val = 0; val = 0;
if (start_index) { if (start_index) {
unsigned long start_mask = ~(SHIFT_HIGH(~0UL, start_index)); unsigned long start_mask = ~(SHIFT_HIGH(~0UL,
start_index));
val = FB_READL(dst) & start_mask; val = FB_READL(dst) & start_mask;
shift = start_index; shift = start_index;
} }
...@@ -131,10 +127,9 @@ static inline void color_imageblit(struct fb_image *image, struct fb_info *p, u8 ...@@ -131,10 +127,9 @@ static inline void color_imageblit(struct fb_image *image, struct fb_info *p, u8
val |= SHIFT_HIGH(color, shift); val |= SHIFT_HIGH(color, shift);
if (shift >= null_bits) { if (shift >= null_bits) {
FB_WRITEL(val, dst++); FB_WRITEL(val, dst++);
if (shift == null_bits)
val = 0; val = (shift == null_bits) ? 0 :
else SHIFT_LOW(color,BITS_PER_LONG - shift);
val = SHIFT_LOW(color, BITS_PER_LONG - shift);
} }
shift += bpp; shift += bpp;
shift &= (BITS_PER_LONG - 1); shift &= (BITS_PER_LONG - 1);
...@@ -157,60 +152,62 @@ static inline void color_imageblit(struct fb_image *image, struct fb_info *p, u8 ...@@ -157,60 +152,62 @@ static inline void color_imageblit(struct fb_image *image, struct fb_info *p, u8
} }
} }
static inline void slow_imageblit(struct fb_image *image, struct fb_info *p, u8 *dst1, static inline void slow_imageblit(struct fb_image *image, struct fb_info *p,
unsigned long fgcolor, unsigned long bgcolor, u8 *dst1, unsigned long fgcolor,
unsigned long start_index, unsigned long pitch_index) unsigned long bgcolor,
unsigned long start_index,
unsigned long pitch_index)
{ {
unsigned long i, j, l = 8; unsigned long shift, color = 0, bpp = p->var.bits_per_pixel;
unsigned long shift, color, bpp = p->var.bits_per_pixel;
unsigned long *dst, *dst2, val, pitch = p->fix.line_length; unsigned long *dst, *dst2, val, pitch = p->fix.line_length;
unsigned long null_bits = BITS_PER_LONG - bpp; unsigned long null_bits = BITS_PER_LONG - bpp;
u8 *src = image->data; unsigned long spitch = (image->width+7)/8;
u8 *src = image->data, *s;
unsigned long i, j, l;
dst2 = (unsigned long *) dst1; dst2 = (unsigned long *) dst1;
for (i = image->height; i--; ) { for (i = image->height; i--; ) {
shift = 0; shift = val = 0;
val = 0; l = 8;
j = image->width; j = image->width;
dst = (unsigned long *) dst1; dst = (unsigned long *) dst1;
s = src;
/* write leading bits */ /* write leading bits */
if (start_index) { if (start_index) {
unsigned long start_mask = ~(SHIFT_HIGH(~0UL, start_index)); unsigned long start_mask = ~(SHIFT_HIGH(~0UL,
start_index));
val = FB_READL(dst) & start_mask; val = FB_READL(dst) & start_mask;
shift = start_index; shift = start_index;
} }
while (j--) { while (j--) {
l--; l--;
if (*src & (1 << l)) color = (*s & (1 << l)) ? fgcolor : bgcolor;
color = fgcolor;
else
color = bgcolor;
color <<= LEFT_POS(bpp); color <<= LEFT_POS(bpp);
val |= SHIFT_HIGH(color, shift); val |= SHIFT_HIGH(color, shift);
/* Did the bitshift spill bits to the next long? */ /* Did the bitshift spill bits to the next long? */
if (shift >= null_bits) { if (shift >= null_bits) {
FB_WRITEL(val, dst++); FB_WRITEL(val, dst++);
if (shift == null_bits) val = (shift == null_bits) ? 0 :
val = 0; SHIFT_LOW(color,BITS_PER_LONG - shift);
else
val = SHIFT_LOW(color, BITS_PER_LONG - shift);
} }
shift += bpp; shift += bpp;
shift &= (BITS_PER_LONG - 1); shift &= (BITS_PER_LONG - 1);
if (!l) { l = 8; src++; }; if (!l) { l = 8; s++; };
} }
/* write trailing bits */ /* write trailing bits */
if (shift) { if (shift) {
unsigned long end_mask = SHIFT_HIGH(~0UL, shift); unsigned long end_mask = SHIFT_HIGH(~0UL, shift);
FB_WRITEL((FB_READL(dst) & end_mask) | val, dst); FB_WRITEL((FB_READL(dst) & end_mask) | val, dst);
} }
dst1 += pitch;
dst1 += pitch;
src += spitch;
if (pitch_index) { if (pitch_index) {
dst2 += pitch; dst2 += pitch;
dst1 = (char *) dst2; dst1 = (char *) dst2;
...@@ -223,26 +220,34 @@ static inline void slow_imageblit(struct fb_image *image, struct fb_info *p, u8 ...@@ -223,26 +220,34 @@ static inline void slow_imageblit(struct fb_image *image, struct fb_info *p, u8
} }
} }
static inline void fast_imageblit(struct fb_image *image, struct fb_info *p, u8 *dst1, /*
unsigned long fgcolor, unsigned long bgcolor) * 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(struct fb_image *image, struct fb_info *p,
u8 *dst1, unsigned long fgcolor,
unsigned long bgcolor)
{ {
int i, j, k, l = 8, n; unsigned long fgx = fgcolor, bgx = bgcolor, bpp = p->var.bits_per_pixel;
unsigned long bit_mask, end_mask, eorx; unsigned long ppw = BITS_PER_LONG/bpp, spitch = (image->width + 7)/8;
unsigned long fgx = fgcolor, bgx = bgcolor, pad, bpp = p->var.bits_per_pixel; unsigned long bit_mask, end_mask, eorx, shift;
unsigned long tmp = (1 << bpp) - 1; char *s = image->data, *src;
unsigned long ppw = BITS_PER_LONG/bpp, ppos;
unsigned long *dst; unsigned long *dst;
u32 *tab = NULL; u32 *tab = NULL;
char *src = image->data; int i, j, k;
switch (ppw) { switch (bpp) {
case 4: case 8:
tab = cfb_tab8; tab = cfb_tab8;
break; break;
case 2: case 16:
tab = cfb_tab16; tab = cfb_tab16;
break; break;
case 1: case 32:
tab = cfb_tab32; tab = cfb_tab32;
break; break;
} }
...@@ -254,56 +259,39 @@ static inline void fast_imageblit(struct fb_image *image, struct fb_info *p, u8 ...@@ -254,56 +259,39 @@ static inline void fast_imageblit(struct fb_image *image, struct fb_info *p, u8
bgx |= bgcolor; bgx |= bgcolor;
} }
n = ((image->width + 7) / 8);
pad = (n * 8) - image->width;
n = image->width % ppw;
bit_mask = (1 << ppw) - 1; bit_mask = (1 << ppw) - 1;
eorx = fgx ^ bgx; eorx = fgx ^ bgx;
k = image->width/ppw; k = image->width/ppw;
for (i = image->height; i--; ) { for (i = image->height; i--; ) {
dst = (unsigned long *) dst1; dst = (unsigned long *) dst1, shift = 8; src = s;
for (j = k; j--; ) { for (j = k; j--; ) {
l -= ppw; shift -= ppw;
end_mask = tab[(*src >> l) & bit_mask]; end_mask = tab[(*src >> shift) & bit_mask];
FB_WRITEL((end_mask & eorx)^bgx, dst++);
if (!l) { l = 8; src++; }
}
if (n) {
end_mask = 0;
ppos = LEFT_POS(bpp);
for (j = n; j > 0; j--) {
l--;
if (*src & (1 << l))
end_mask |= tmp << ppos;
NEXT_POS(ppos, bpp);
if (!l) { l = 8; src++; }
}
FB_WRITEL((end_mask & eorx)^bgx, dst++); FB_WRITEL((end_mask & eorx)^bgx, dst++);
if (!shift) { shift = 8; src++; }
} }
l -= pad; dst1 += p->fix.line_length;
dst1 += p->fix.line_length; s += spitch;
} }
} }
void cfb_imageblit(struct fb_info *p, struct fb_image *image) void cfb_imageblit(struct fb_info *p, struct fb_image *image)
{ {
int x2, y2, vxres, vyres;
unsigned long fgcolor, bgcolor, start_index, bitstart, pitch_index = 0; unsigned long fgcolor, bgcolor, start_index, bitstart, pitch_index = 0;
unsigned long bpl = sizeof(unsigned long), bpp = p->var.bits_per_pixel; unsigned long bpl = sizeof(unsigned long), bpp = p->var.bits_per_pixel;
int x2, y2, vxres, vyres;
u8 *dst1; u8 *dst1;
vxres = p->var.xres_virtual; vxres = p->var.xres_virtual;
vyres = p->var.yres_virtual; vyres = p->var.yres_virtual;
/* /*
* We could use hardware clipping but on many cards you get around hardware * We could use hardware clipping but on many cards you get around
* clipping by writing to framebuffer directly like we are doing here. * hardware clipping by writing to framebuffer directly like we are
* doing here.
*/ */
if (image->dx > vxres || if (image->dx > vxres || image->dy > vyres)
image->dy > vyres)
return; return;
x2 = image->dx + image->width; x2 = image->dx + image->width;
...@@ -323,18 +311,22 @@ void cfb_imageblit(struct fb_info *p, struct fb_image *image) ...@@ -323,18 +311,22 @@ void cfb_imageblit(struct fb_info *p, struct fb_image *image)
bitstart &= ~(bpl - 1); bitstart &= ~(bpl - 1);
dst1 = p->screen_base + bitstart; dst1 = p->screen_base + bitstart;
if (p->fbops->fb_sync)
p->fbops->fb_sync(p);
if (image->depth == 1) { if (image->depth == 1) {
if (p->fix.visual == FB_VISUAL_TRUECOLOR || if (p->fix.visual == FB_VISUAL_TRUECOLOR ||
p->fix.visual == FB_VISUAL_DIRECTCOLOR) { p->fix.visual == FB_VISUAL_DIRECTCOLOR) {
fgcolor = ((u32 *)(p->pseudo_palette))[image->fg_color]; fgcolor = ((u32*)(p->pseudo_palette))[image->fg_color];
bgcolor = ((u32 *)(p->pseudo_palette))[image->bg_color]; bgcolor = ((u32*)(p->pseudo_palette))[image->bg_color];
} else { } else {
fgcolor = image->fg_color; fgcolor = image->fg_color;
bgcolor = image->bg_color; bgcolor = image->bg_color;
} }
if (BITS_PER_LONG % bpp == 0 && !start_index && !pitch_index && if (BITS_PER_LONG % bpp == 0 && !start_index && !pitch_index &&
bpp >= 8 && bpp <= 32 && (image->width & 7) == 0) ((image->width & (BITS_PER_LONG/bpp-1)) == 0) &&
bpp >= 8 && bpp <= 32)
fast_imageblit(image, p, dst1, fgcolor, bgcolor); fast_imageblit(image, p, dst1, fgcolor, bgcolor);
else else
slow_imageblit(image, p, dst1, fgcolor, bgcolor, start_index, pitch_index); slow_imageblit(image, p, dst1, fgcolor, bgcolor, start_index, pitch_index);
......
...@@ -432,12 +432,13 @@ void accel_putcs(struct vc_data *vc, struct display *p, ...@@ -432,12 +432,13 @@ void accel_putcs(struct vc_data *vc, struct display *p,
image.width = vc->vc_font.width; image.width = vc->vc_font.width;
while (count--) { while (count--) {
image.data = p->fontdata + image.data = p->fontdata +
(scr_readw(s++) & charmask) * (scr_readw(s++) & charmask) * cellsize;
vc->vc_font.height * width;
info->fbops->fb_imageblit(info, &image); info->fbops->fb_imageblit(info, &image);
image.dx += vc->vc_font.width; image.dx += vc->vc_font.width;
} }
} }
if (info->fbops->fb_sync)
info->fbops->fb_sync(info);
} }
void accel_clear_margins(struct vc_data *vc, struct display *p, void accel_clear_margins(struct vc_data *vc, struct display *p,
......
...@@ -656,6 +656,8 @@ fb_read(struct file *file, char *buf, size_t count, loff_t *ppos) ...@@ -656,6 +656,8 @@ fb_read(struct file *file, char *buf, size_t count, loff_t *ppos)
count = info->fix.smem_len; count = info->fix.smem_len;
if (count + p > info->fix.smem_len) if (count + p > info->fix.smem_len)
count = info->fix.smem_len - p; count = info->fix.smem_len - p;
if (info->fbops->fb_sync)
info->fbops->fb_sync(info);
if (count) { if (count) {
char *base_addr; char *base_addr;
...@@ -692,6 +694,8 @@ fb_write(struct file *file, const char *buf, size_t count, loff_t *ppos) ...@@ -692,6 +694,8 @@ fb_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
count = info->fix.smem_len - p; count = info->fix.smem_len - p;
err = -ENOSPC; err = -ENOSPC;
} }
if (info->fbops->fb_sync)
info->fbops->fb_sync(info);
if (count) { if (count) {
char *base_addr; char *base_addr;
......
...@@ -1538,7 +1538,7 @@ static struct fb_ops riva_fb_ops = { ...@@ -1538,7 +1538,7 @@ static struct fb_ops riva_fb_ops = {
.fb_blank = rivafb_blank, .fb_blank = rivafb_blank,
.fb_fillrect = rivafb_fillrect, .fb_fillrect = rivafb_fillrect,
.fb_copyarea = rivafb_copyarea, .fb_copyarea = rivafb_copyarea,
.fb_imageblit = rivafb_imageblit, .fb_imageblit = cfb_imageblit,
.fb_cursor = soft_cursor, .fb_cursor = soft_cursor,
.fb_sync = rivafb_sync, .fb_sync = rivafb_sync,
}; };
......
...@@ -177,7 +177,7 @@ static struct fb_ops tdfxfb_ops = { ...@@ -177,7 +177,7 @@ static struct fb_ops tdfxfb_ops = {
.fb_pan_display = tdfxfb_pan_display, .fb_pan_display = tdfxfb_pan_display,
.fb_fillrect = tdfxfb_fillrect, .fb_fillrect = tdfxfb_fillrect,
.fb_copyarea = tdfxfb_copyarea, .fb_copyarea = tdfxfb_copyarea,
.fb_imageblit = tdfxfb_imageblit, .fb_imageblit = cfb_imageblit,
.fb_sync = banshee_wait_idle, .fb_sync = banshee_wait_idle,
.fb_cursor = soft_cursor, .fb_cursor = soft_cursor,
}; };
...@@ -939,14 +939,16 @@ static void tdfxfb_imageblit(struct fb_info *info, struct fb_image *pixmap) ...@@ -939,14 +939,16 @@ static void tdfxfb_imageblit(struct fb_info *info, struct fb_image *pixmap)
u8 *chardata = (u8 *) pixmap->data; u8 *chardata = (u8 *) pixmap->data;
u32 srcfmt; u32 srcfmt;
if (pixmap->depth == 1) { if (pixmap->depth != 1) {
//banshee_make_room(par, 6 + ((size + 3) >> 2));
//srcfmt = stride | ((bpp+((bpp==8) ? 0 : 8)) << 13) | 0x400000;
cfb_imageblit(info, pixmap);
return;
} else {
banshee_make_room(par, 8 + ((size + 3) >> 2)); banshee_make_room(par, 8 + ((size + 3) >> 2));
tdfx_outl(par, COLORFORE, pixmap->fg_color); tdfx_outl(par, COLORFORE, pixmap->fg_color);
tdfx_outl(par, COLORBACK, pixmap->bg_color); tdfx_outl(par, COLORBACK, pixmap->bg_color);
srcfmt = 0x400000; srcfmt = 0x400000;
} else {
//banshee_make_room(par, 6 + ((size + 3) >> 2));
//srcfmt = stride | ((bpp+((bpp==8) ? 0 : 8)) << 13) | 0x400000;
} }
tdfx_outl(par, SRCXY, 0); tdfx_outl(par, SRCXY, 0);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment