linux-fbdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Antonino Daplas <adaplas@pol.net>
To: James Simmons <jsimmons@infradead.org>
Cc: Linux Fbdev development list <linux-fbdev-devel@lists.sourceforge.net>
Subject: Re: [PATCH] Tile Blitting
Date: 27 Feb 2003 22:15:10 +0800	[thread overview]
Message-ID: <1046355210.1206.42.camel@localhost.localdomain> (raw)
In-Reply-To: <Pine.LNX.4.44.0302270056200.16050-100000@phoenix.infradead.org>

[-- Attachment #1: Type: text/plain, Size: 3071 bytes --]

On Thu, 2003-02-27 at 09:18, James Simmons wrote:
> > As Geert and DaveM has
> > mentioned to me, the current implementation might not be thread-safe
> > (although I see more of a concurrency problem between CPU and GPU).
> 
> I agree I see more of a problem with CPU GPU syncing issue. I do have a 
> fix in BK with allocating and deallocating continuely but it is the wrong
> approach.
> 

We can avoid concurrency problems by assigning different sections of the
buffer per call to fb_imageblit(). There is really no need to map/unmap
or allocate/deallocate buffers unless you do not trust the drivers to
behave :-).  The buffer will not be exposed to userland, unlike DRM
which has to implement "map->user access->unmap->pass to hardware".
 
> > Thus, the restriction that the buffer must be completely copied by the
> > driver before returning.  And because of this restriction, an extra copy
> > which might be unnecessary cannot be avoided (this was noted by Petr).
> > 
> > Treating the buffer as a ringbuffer, we eliminate these restrictions.
> 
> I didn't realize that the below was a ringbuffer implementation. The name
> threw me off. 

Well, it's not strictly a ringbuffer implementation.  This would require
a head and tail pointer where fbcon will adjust the tail and the
driver/hardware will adjust the head.  This will be very difficult to
implement in a device independent manner.  So we just cheat by issuing
an fb_sync() per loop to flush all pending commands.

> 
> Do you still have the original patch?
> 

Here's a revised one. Driver's can choose to fill up the following
structure, or leave it empty:

#define FB_PIXMAP_DEFAULT 1     /* used internally by fbcon */
#define FB_PIXMAP_SYSTEM  2     /* memory is in system RAM  */
#define FB_PIXMAP_IO      4     /* memory is iomapped       */
#define FB_PIXMAP_SYNC    256   /* set if GPU can DMA       */

struct fb_pixmap {
        __u8  *addr; 
	__u32 size;  
	__u32 offset;
	__u32 buf_align; 
	__u32 scan_align; 
	__u32 flags; 
	void (*outbuf)(u8 dst, u8 *addr); 
	u8   (*inbuf) (u8 *addr);
	unsigned long lock_flags;
	spinlock_t lock; 
};

The buffer can be anywhere, system or io.  If it's in special memory
(ie, offscreen graphics), access methods must be specified (outbuf,
inbuf).  If the buffer is DMA'able by the GPU, then FB_PIXMAP_SYNC must
be set (it issues an fb_sync()), otherwise leave it cleared (ie soft
accels). The buf_align and scan_align are hardware specific.  This will
let fbcon format the bitmap into a form acceptable by the hardware.  The
modified rivafb sets the alignment according to its needs, which greatly
simplified the rivafb_imageblit() function.

The spinlock may be necessary because fbcon_cursor, which is called via
timer or interrupt, might also use fb_imageblit().  You can change it to
a more appropriate locking method if you want.

The patch should work without driver breakage.  

Diff is against linux-2.5.61 + your fbdev.diff.gz + my accel_putcs
optimization patch + Geert's logo updates.  I know you already applied
them all in your tree.

Tony
 


[-- Attachment #2: pixmap2.diff --]
[-- Type: text/x-patch, Size: 17922 bytes --]

diff -Naur linux-2.5.61/drivers/video/console/fbcon.c linux/drivers/video/console/fbcon.c
--- linux-2.5.61/drivers/video/console/fbcon.c	2003-02-27 09:28:55.000000000 +0000
+++ linux/drivers/video/console/fbcon.c	2003-02-27 11:40:39.000000000 +0000
@@ -134,6 +134,8 @@
 static int fbcon_set_origin(struct vc_data *);
 static int cursor_drawn;
 
+#define FBCON_PIXMAPSIZE 8192
+
 #define CURSOR_DRAW_DELAY		(1)
 
 /* # VBL ints between cursor state changes */
@@ -296,8 +298,191 @@
 }
 
 /*
+ * drawing helpers
+ */
+static inline void sysmove_buf_aligned(u8 *dst, u8 *src, u32 d_pitch, 
+				       u32 s_pitch, u32 height, 
+				       struct fb_info *info)
+{
+	int i, j;
+	
+	for (i = height; i--; ) {
+		for (j = 0; j < s_pitch; j++) 
+			dst[j] = *src++;
+		dst += d_pitch;
+	}
+}
+
+static inline void iomove_buf_aligned(u8 *dst, u8 *src, u32 d_pitch, 
+				      u32 s_pitch, u32 height,
+				      struct fb_info *info)
+{
+	int i, j;
+	
+	for (i = height; i--; ) {
+		for (j = 0; j < s_pitch; j++) 
+			info->pixmap.outbuf(*src++, dst+j);
+		dst += d_pitch;
+	}
+}
+
+static inline void sysmove_buf_unaligned(u8 *dst, u8 *src, u32 d_pitch, 
+					 u32 height, u32 mask, u32 shift_high,
+					 u32 shift_low, u32 mod, u32 idx,
+					 struct fb_info *info)
+{
+	int i, j;
+	
+	for (i = height; i--; ) {
+		for (j = 0; j < idx; j++) { 
+			dst[j] &= mask;
+			dst[j] |= *src >> shift_low;
+			dst[j+1] = *src << shift_high;
+			src++;
+		}
+		dst[idx] &= mask;
+		dst[idx] |= *src >> shift_low;
+		if (shift_high < mod)
+			dst[idx+1] = *src<<shift_high;
+		src++;
+		dst += d_pitch;
+	}
+}
+
+static inline void iomove_buf_unaligned(u8 *dst, u8 *src, u32 d_pitch, 
+					u32 height, u32 mask, u32 shift_high,
+					u32 shift_low,u32 mod, u32 idx, 
+					struct fb_info *info)
+{
+	int i, j;
+	u8 tmp;
+	
+	for (i = height; i--; ) {
+		for (j = 0; j < idx; j++) { 
+			tmp = info->pixmap.inbuf(dst+j);
+			tmp &= mask;
+			tmp |= *src >> shift_low;
+			info->pixmap.outbuf(tmp, dst+j);
+			info->pixmap.outbuf(*src << shift_high, dst+j+1);
+			src++;
+		}
+		tmp = info->pixmap.inbuf(dst+idx);
+		tmp &= mask;
+		tmp |= *src >> shift_low;
+		info->pixmap.outbuf(tmp, dst+idx);
+		if (shift_high < mod)
+			info->pixmap.outbuf(*src<<shift_high, dst+idx+1);
+		src++;
+		dst += d_pitch;
+	}
+}
+
+static void putcs_unaligned(struct vc_data *vc, struct display *p,
+			    struct fb_info *info, struct fb_image *image, 
+			    int count, const unsigned short *s)
+{
+	unsigned int width = (vc->vc_font.width + 7)/8;
+	unsigned int cellsize = vc->vc_font.height * width;
+	unsigned int maxcnt = info->pixmap.size/cellsize;
+	unsigned int pitch, cnt, k;
+	unsigned int shift_low = 0, mod = vc->vc_font.width % 8;
+	unsigned int shift_high = 8, size;
+	unsigned int buf_align = info->pixmap.buf_align - 1;
+	unsigned int scan_align = info->pixmap.scan_align - 1;
+	unsigned int idx = vc->vc_font.width/8;
+	unsigned short charmask = p->charmask;
+	u8 mask, *src, *dst, *dst0;
+	void (*move_data)(u8 *dst, u8 *src, u32 d_pitch, u32 height, u32 mask,
+			  u32 shift_high, u32 shift_low, u32 mod, u32 idx, 
+			  struct fb_info *info);
+	
+	if (info->pixmap.outbuf != NULL)
+		move_data = iomove_buf_unaligned;
+	else
+		move_data = sysmove_buf_unaligned;
+
+	while (count) {
+		if (count > maxcnt) 
+			cnt = k = maxcnt;
+		else
+			cnt = k = count;
+		
+		image->width = vc->vc_font.width * cnt;
+		pitch = (image->width + 7)/8 + scan_align;
+		pitch &= ~scan_align;
+		size = pitch * vc->vc_font.height + buf_align;
+		size &= ~buf_align;
+		dst0 = info->pixmap.addr + fb_get_buffer_offset(info, size);
+		image->data = dst0;
+		while (k--) {
+			src = p->fontdata + (scr_readw(s++) & charmask)*
+				cellsize;
+			dst = dst0;
+			mask = (u8) (0xfff << shift_high);
+			move_data(dst, src, pitch, image->height, mask,
+				  shift_high, shift_low, mod, idx, info);
+			shift_low += mod;
+			dst0 += (shift_low >= 8) ? width : width - 1;
+			shift_low &= 7;
+			shift_high = 8 - shift_low;
+		}
+		
+		info->fbops->fb_imageblit(info, image);
+		image->dx += cnt * vc->vc_font.width;
+		count -= cnt;
+	}
+}
+
+static void putcs_aligned(struct vc_data *vc, struct display *p,
+			  struct fb_info *info, struct fb_image *image, 
+			  int count, const unsigned short *s)
+{
+	unsigned int width = vc->vc_font.width/8;
+	unsigned int cellsize = vc->vc_font.height * width;
+	unsigned int maxcnt = info->pixmap.size/cellsize;
+	unsigned int scan_align = info->pixmap.scan_align - 1;
+	unsigned int buf_align = info->pixmap.buf_align - 1;
+	unsigned int pitch, cnt, size, k;
+	unsigned short charmask = p->charmask;
+	void (*move_data)(u8 *dst, u8 *src, u32 s_pitch, u32 d_pitch, 
+			  u32 height, struct fb_info *info);
+	u8 *src, *dst, *dst0;
+
+	if (info->pixmap.outbuf != NULL)
+		move_data = iomove_buf_aligned;
+	else
+		move_data = sysmove_buf_aligned;
+
+	while (count) {
+		if (count > maxcnt)
+			cnt = k = maxcnt;
+		else
+			cnt = k = count;
+		pitch = width * cnt + scan_align;
+		pitch &= ~scan_align;
+		size = pitch * vc->vc_font.height + buf_align;
+		size &= ~buf_align;
+		image->width = vc->vc_font.width * cnt;
+		dst0 = info->pixmap.addr + fb_get_buffer_offset(info, size);
+		image->data = dst0;
+		while (k--) {
+			src = p->fontdata + (scr_readw(s++) & charmask)*
+				cellsize;
+			dst = dst0;
+			move_data(dst, src, pitch, width, image->height, info);
+			dst0 += width;
+		}
+		
+		info->fbops->fb_imageblit(info, image);
+		image->dx += cnt * vc->vc_font.width;
+		count -= cnt;
+	}
+}
+
+/*
  * Accelerated handlers.
  */
+
 void accel_bmove(struct display *p, int sy, int sx, int dy, int dx,
 			int height, int width)
 {
@@ -331,22 +516,52 @@
 	info->fbops->fb_fillrect(info, &region);
 }	
 
-#define FB_PIXMAPSIZE 8192
-/*
- * FIXME: Break up this function, it's becoming too long...
- */        
-void accel_putcs(struct vc_data *vc, struct display *p,
-			const unsigned short *s, int count, int yy, int xx)
+static void accel_putc(struct vc_data *vc, struct display *p,
+		       int c, int ypos, int xpos)
 {
-	static u8 pixmap[FB_PIXMAPSIZE];
 	struct fb_image image;
 	struct fb_info *info = p->fb_info;
 	unsigned short charmask = p->charmask;
-	unsigned int width = ((vc->vc_font.width + 7)/8);
-	unsigned int cellsize = vc->vc_font.height * width;
-	unsigned int pitch, cnt, i, j, k;
-	unsigned int maxcnt = FB_PIXMAPSIZE/cellsize;
-	u8 *src, *dst, *dst0;
+	unsigned int width = (vc->vc_font.width + 7)/8;
+	unsigned int size, pitch;
+	unsigned int scan_align = info->pixmap.scan_align - 1;
+	unsigned int buf_align = info->pixmap.buf_align - 1;
+	void (*move_data)(u8 *dst, u8 *src, u32 s_pitch, u32 d_pitch, 
+			  u32 height, struct fb_info *info);
+	u8 *src, *dst;
+
+	if (info->pixmap.outbuf != NULL)
+		move_data = iomove_buf_aligned;
+	else
+		move_data = sysmove_buf_aligned;
+
+	image.dx = xpos * vc->vc_font.width;
+	image.dy = ypos * vc->vc_font.height;
+	image.width = vc->vc_font.width;
+	image.height = vc->vc_font.height;
+	image.fg_color = attr_fgcol(p, c);
+	image.bg_color = attr_bgcol(p, c);
+	image.depth = 0;
+
+	pitch = width + scan_align;
+	pitch &= ~scan_align;
+	size = pitch * vc->vc_font.height;
+	size += buf_align;
+	size &= ~buf_align;
+	dst = info->pixmap.addr + fb_get_buffer_offset(info, size);
+	image.data = dst;
+	src = p->fontdata + (c & charmask) * vc->vc_font.height * width;
+
+	move_data(dst, src, pitch, width, image.height, info);
+
+	info->fbops->fb_imageblit(info, &image);
+}
+
+void accel_putcs(struct vc_data *vc, struct display *p,
+			const unsigned short *s, int count, int yy, int xx)
+{
+	struct fb_info *info = p->fb_info;
+	struct fb_image image;
 	u16 c = scr_readw(s);
 	
 	image.fg_color = attr_fgcol(p, c);
@@ -355,80 +570,11 @@
 	image.dy = yy * vc->vc_font.height;
 	image.height = vc->vc_font.height;
 	image.depth = 0;
-	image.data = pixmap;
 
-	if (!(vc->vc_font.width & 7)) {
-		while (count) {
-			if (count > maxcnt) 
-				cnt = k = maxcnt;
-			else
-				cnt = k = count;
-			
-			dst0 = pixmap;
-			pitch = width * cnt;
-			image.width = vc->vc_font.width * cnt;
-			while (k--) {
-				src = p->fontdata + (scr_readw(s++)&charmask)*
-					cellsize;
-				dst = dst0;
-				for (i = image.height; i--; ) {
-					for (j = 0; j < width; j++) 
-						dst[j] = *src++;
-					dst += pitch;
-				}
-				dst0 += width;
-			}
-
-			info->fbops->fb_imageblit(info, &image);
-			image.dx += cnt * vc->vc_font.width;
-			count -= cnt;
-		}
-		
-	} else {
-		unsigned int shift_low = 0, mod = vc->vc_font.width % 8;
-		unsigned int shift_high = 8;
-		unsigned idx = vc->vc_font.width/8;
-		u8 mask;
-
-		while (count) {
-			if (count > maxcnt) 
-				cnt = k = maxcnt;
-			else
-				cnt = k = count;
-			
-			dst0 = pixmap;
-			image.width = vc->vc_font.width * cnt;
-			pitch = (image.width + 7)/8;
-			while (k--) {
-				src = p->fontdata + (scr_readw(s++)&charmask)* 
-					cellsize;
-				dst = dst0;
-				mask = (u8) (0xfff << shift_high);
-				for (i = image.height; i--; ) {
-					for (j = 0; j < idx; j++) {
-						dst[j] &= mask;
-						dst[j] |= *src >> shift_low;
-						dst[j+1] = *src << shift_high;
-						src++;
-					}
-					dst[idx] &= mask;
-					dst[idx] |= *src >> shift_low;
-					if (shift_high < mod)
-						dst[idx+1] = *src << shift_high;
-					src++;
-					dst += pitch;
-				}
-				shift_low += mod;
-				dst0 += (shift_low >= 8) ? width : width - 1;
-				shift_low &= 7;
-				shift_high = 8 - shift_low;
-			}
-			
-			info->fbops->fb_imageblit(info, &image);
-			image.dx += cnt * vc->vc_font.width;
-			count -= cnt;
-		}
-	}
+	if (!(vc->vc_font.width & 7)) 
+		putcs_aligned(vc, p, info, &image, count, s);
+	else 
+		putcs_unaligned(vc, p, info, &image, count, s);
 }
 
 void accel_clear_margins(struct vc_data *vc, struct display *p,
@@ -633,6 +779,18 @@
 	vc->vc_cols = info->var.xres/vc->vc_font.width;
 	vc->vc_rows = info->var.yres/vc->vc_font.height;
 	
+	if (info->pixmap.addr == NULL) {
+		info->pixmap.addr = kmalloc(FBCON_PIXMAPSIZE, GFP_KERNEL);
+		if (!info->pixmap.addr)
+			return NULL;
+		info->pixmap.size = FBCON_PIXMAPSIZE;
+		info->pixmap.buf_align = 1;
+		info->pixmap.scan_align = 1;
+		info->pixmap.flags = FB_PIXMAP_DEFAULT;
+	}
+	info->pixmap.offset = 0;
+	spin_lock_init(&info->pixmap.lock);
+
 	/* We trust the mode the driver supplies. */
 	if (info->fbops->fb_set_par)
 		info->fbops->fb_set_par(info);
@@ -1030,10 +1188,6 @@
 static void fbcon_putc(struct vc_data *vc, int c, int ypos, int xpos)
 {
 	struct display *p = &fb_display[vc->vc_num];
-	struct fb_info *info = p->fb_info;
-	unsigned short charmask = p->charmask;
-	unsigned int width = ((vc->vc_font.width + 7) >> 3);
-	struct fb_image image;
 	int redraw_cursor = 0;
 
 	if (!p->can_soft_blank && console_blanked)
@@ -1047,16 +1201,7 @@
 		redraw_cursor = 1;
 	}
 
-	image.fg_color = attr_fgcol(p, c);
-	image.bg_color = attr_bgcol(p, c);
-	image.dx = xpos * vc->vc_font.width;
-	image.dy = real_y(p, ypos) * vc->vc_font.height;
-	image.width = vc->vc_font.width;
-	image.height = vc->vc_font.height;
-	image.depth = 1;
-	image.data = p->fontdata + (c & charmask) * vc->vc_font.height * width;
-
-	info->fbops->fb_imageblit(info, &image);
+	accel_putc(vc, p, c, real_y(p, ypos), xpos);
 
 	if (redraw_cursor)
 		vbl_cursor_cnt = CURSOR_DRAW_DELAY;
diff -Naur linux-2.5.61/drivers/video/fbmem.c linux/drivers/video/fbmem.c
--- linux-2.5.61/drivers/video/fbmem.c	2003-02-27 09:28:25.000000000 +0000
+++ linux/drivers/video/fbmem.c	2003-02-27 14:11:03.000000000 +0000
@@ -368,6 +368,31 @@
 	return n < 0 ? d >> -n : d << n;
 }
 
+/*
+ * we need to lock this section since fbcon_cursor
+ * may use fb_imageblit()
+ */
+u32 fb_get_buffer_offset(struct fb_info *info, u32 size)
+{
+	u32 align = info->pixmap.buf_align - 1;
+	u32 offset;
+
+	spin_lock_irqsave(&info->pixmap.lock,
+			  info->pixmap.lock_flags);
+	offset = info->pixmap.offset + align;
+	offset &= ~align;
+	if (offset + size > info->pixmap.size) {
+		if (info->fbops->fb_sync && 
+		    info->pixmap.flags & FB_PIXMAP_SYNC)
+			info->fbops->fb_sync(info);
+		offset = 0;
+	}
+	info->pixmap.offset = offset + size;
+	spin_unlock_irqrestore(&info->pixmap.lock,
+			       info->pixmap.lock_flags);
+	return offset;
+}
+
 #ifdef CONFIG_LOGO
 #include <linux/linux_logo.h>
 
@@ -1240,5 +1265,6 @@
 EXPORT_SYMBOL(fb_set_var);
 EXPORT_SYMBOL(fb_blank);
 EXPORT_SYMBOL(fb_pan_display);
+EXPORT_SYMBOL(fb_get_buffer_offset);
 
 MODULE_LICENSE("GPL");
diff -Naur linux-2.5.61/drivers/video/softcursor.c linux/drivers/video/softcursor.c
--- linux-2.5.61/drivers/video/softcursor.c	2002-12-16 02:07:59.000000000 +0000
+++ linux/drivers/video/softcursor.c	2003-02-27 11:40:28.000000000 +0000
@@ -17,30 +17,79 @@
 #include <asm/uaccess.h>
 #include <asm/io.h>
 
+static inline void sysmove_buf(u8 *dst, u8 *src, u32 d_pitch, u32 s_pitch, 
+			       u32 height, struct fb_info *info)
+{
+	int i, j;
+	
+	for (i = height; i--; ) {
+		for (j = 0; j < s_pitch; j++) 
+			dst[j] = *src++;
+		dst += d_pitch;
+	}
+}
+
+static inline void iomove_buf(u8 *dst, u8 *src, u32 d_pitch, u32 s_pitch, 
+			      u32 height, struct fb_info *info)
+{
+	int i, j;
+	
+	for (i = height; i--; ) {
+		for (j = 0; j < s_pitch; j++) 
+			info->pixmap.outbuf(*src++, dst+j);
+		dst += d_pitch;
+	}
+}
+
 int soft_cursor(struct fb_info *info, struct fb_cursor *cursor)
 {
-	int i, size = ((cursor->image.width + 7) / 8) * cursor->image.height;
+	static u8 src[64];
 	struct fb_image image;
-	static char data[64];
+	unsigned int i, size, s_pitch, d_pitch;
+	unsigned dsize = ((cursor->image.width + 7)/8) * cursor->image.height;
+	unsigned int scan_align = info->pixmap.scan_align - 1;
+	unsigned int buf_align = info->pixmap.buf_align - 1;
+	void (*move_data)(u8 *dst, u8 *src, u32 s_pitch, 
+			  u32 d_pitch, u32 height,
+			  struct fb_info *info);
+	u8 *dst;
+			  
+	if (info->pixmap.outbuf != NULL)
+		move_data = iomove_buf;
+	else
+		move_data = sysmove_buf;
+
+	s_pitch = (cursor->image.width + 7)/8;
+	d_pitch = (s_pitch + scan_align) & ~scan_align;
+	size = d_pitch * cursor->image.height + buf_align;
+	size &= ~buf_align;
+	dst = info->pixmap.addr + fb_get_buffer_offset(info, size);
+	image.data = dst;
 
 	if (cursor->enable) {
 		switch (cursor->rop) {
 		case ROP_XOR:
-			for (i = 0; i < size; i++)
-				data[i] = (cursor->image.data[i] &
+			for (i = 0; i < dsize; i++) {
+				src[i] =  (cursor->image.data[i] &
 					   cursor->mask[i]) ^
-				    	   cursor->dest[i];
+					   cursor->dest[i];
+			}
 			break;
 		case ROP_COPY:
 		default:
-			for (i = 0; i < size; i++)
-				data[i] =
-				    cursor->image.data[i] & cursor->mask[i];
+			for (i = 0; i < dsize; i++) {
+				src[i] = cursor->image.data[i] &
+					 cursor->mask[i];
+			}
 			break;
 		}
-	} else
-		memcpy(data, cursor->dest, size);
-
+		move_data(dst, src, d_pitch, s_pitch, cursor->image.height, 
+			  info);
+	} else {
+		move_data(dst, cursor->dest, s_pitch, d_pitch, 
+			  cursor->image.height, info);
+	}
+	  
 	image.bg_color = cursor->image.bg_color;
 	image.fg_color = cursor->image.fg_color;
 	image.dx = cursor->image.dx;
@@ -48,7 +97,6 @@
 	image.width = cursor->image.width;
 	image.height = cursor->image.height;
 	image.depth = cursor->image.depth;
-	image.data = data;
 
 	if (info->fbops->fb_imageblit)
 		info->fbops->fb_imageblit(info, &image);
diff -Naur linux-2.5.61/include/linux/fb.h linux/include/linux/fb.h
--- linux-2.5.61/include/linux/fb.h	2003-02-27 09:22:20.000000000 +0000
+++ linux/include/linux/fb.h	2003-02-27 11:40:08.000000000 +0000
@@ -325,6 +325,23 @@
 	struct fb_image	image;	/* Cursor image */
 };
 
+#define FB_PIXMAP_DEFAULT 1     /* used internally by fbcon */
+#define FB_PIXMAP_SYSTEM  2     /* memory is in system RAM  */
+#define FB_PIXMAP_IO      4     /* memory is iomapped       */
+#define FB_PIXMAP_SYNC    256   /* set if GPU can DMA       */
+
+struct fb_pixmap {
+        __u8  *addr;                      /* pointer to memory             */  
+	__u32 size;                       /* size of buffer in bytes       */
+	__u32 offset;                     /* current offset to buffer      */
+	__u32 buf_align;                  /* byte alignment of each bitmap */
+	__u32 scan_align;                 /* alignment per scanline        */
+	__u32 flags;                      /* see FB_PIXMAP_*               */
+	void (*outbuf)(u8 dst, u8 *addr); /* access methods                */
+	u8   (*inbuf) (u8 *addr);
+	unsigned long lock_flags;         /* flags for locking             */
+	spinlock_t lock;                  /* spinlock                      */
+};
 #ifdef __KERNEL__
 
 #include <linux/fs.h>
@@ -390,6 +407,7 @@
    struct fb_monspecs monspecs;         /* Current Monitor specs */
    struct fb_cursor cursor;		/* Current cursor */	
    struct fb_cmap cmap;                 /* Current cmap */
+   struct fb_pixmap pixmap;	        /* Current pixmap */
    struct fb_ops *fbops;
    char *screen_base;                   /* Virtual address */
    struct vc_data *display_fg;		/* Console visible on this display */
@@ -464,6 +482,7 @@
 extern int unregister_framebuffer(struct fb_info *fb_info);
 extern int fb_prepare_logo(struct fb_info *fb_info);
 extern int fb_show_logo(struct fb_info *fb_info);
+extern u32 fb_get_buffer_offset(struct fb_info *info, u32 size);
 extern struct fb_info *registered_fb[FB_MAX];
 extern int num_registered_fb;
 

[-- Attachment #3: rivafb_pixmap.diff --]
[-- Type: text/x-patch, Size: 3719 bytes --]

diff -Naur linux-2.5.61/drivers/video/riva/fbdev.c linux/drivers/video/riva/fbdev.c
--- linux-2.5.61/drivers/video/riva/fbdev.c	2003-02-27 09:22:20.000000000 +0000
+++ linux/drivers/video/riva/fbdev.c	2003-02-27 09:49:39.000000000 +0000
@@ -1383,18 +1383,16 @@
 			     const struct fb_image *image)
 {
 	struct riva_par *par = (struct riva_par *) info->par;
-	u32 fgx = 0, bgx = 0, width, mod, tmp;
+	u32 fgx = 0, bgx = 0, width, tmp;
 	u8 *cdat = (u8 *) image->data;
 	volatile u32 *d;
-	int i, j, k, size;
+	int i, size;
 
 	if (image->depth != 0) {
-		wait_for_idle(par);
 		cfb_imageblit(info, image);
 		return;
 	}
 
-	width = (image->width + 7)/8;
 	switch (info->var.bits_per_pixel) {
 	case 8:
 		fgx = image->fg_color;
@@ -1429,49 +1427,23 @@
 
 	d = &par->riva.Bitmap->MonochromeData01E;
 
-	mod = width % 4;
-
-	if (width >= 4) {
-		k = image->height;
-		while (k--) {
-			size = width / 4;
-			while (size >= 16) {
-				RIVA_FIFO_FREE(par->riva, Bitmap, 16);
-				for (i = 0; i < 16; i++) {
-					tmp = *((u32 *)cdat)++;
-					reverse_order(&tmp);
-					d[i] = tmp;
-				}
-				size -= 16;
-			}
-
-			if (size) {
-				RIVA_FIFO_FREE(par->riva, Bitmap, size);
-				for (i = 0; i < size; i++) {
-					tmp = *((u32 *) cdat)++;
-					reverse_order(&tmp);
-					d[i] = tmp;
-				}
-			}
-
-			if (mod) {
-				RIVA_FIFO_FREE(par->riva, Bitmap, 1);
-				for (i = 0; i < mod; i++)
-					((u8 *)&tmp)[i] = *cdat++;
-				reverse_order(&tmp);
-				d[i] = tmp;
-			}
+	width = (image->width + 31)/32;
+	size = width * image->height;
+	while (size >= 16) {
+		RIVA_FIFO_FREE(par->riva, Bitmap, 16);
+		for (i = 0; i < 16; i++) {
+			tmp = *((u32 *)cdat)++;
+			reverse_order(&tmp);
+			d[i] = tmp;
 		}
-	} else {
-		for (i = image->height; i > 0; i-=16) {
-			size = (i >= 16) ? 16 : i;
-			RIVA_FIFO_FREE(par->riva, Bitmap, size);
-			for (j = 0; j < size; j++) {
-				for (k = 0; k < width; k++) 
-					((u8 *) &tmp)[k] = *cdat++;
-				reverse_order(&tmp);
-				d[j] = tmp;
-			}
+		size -= 16;
+	}
+	if (size) {
+		RIVA_FIFO_FREE(par->riva, Bitmap, size);
+		for (i = 0; i < size; i++) {
+			tmp = *((u32 *) cdat)++;
+			reverse_order(&tmp);
+			d[i] = tmp;
 		}
 	}
 }
@@ -1632,6 +1604,12 @@
 
 	cmap_len = riva_get_cmap_len(&info->var);
 	fb_alloc_cmap(&info->cmap, cmap_len, 0);	
+
+	info->pixmap.size = 64 * 1024;
+	info->pixmap.buf_align = 4;
+	info->pixmap.scan_align = 4;
+	info->pixmap.flags = FB_PIXMAP_SYSTEM;
+
 	return 0;
 }
 
@@ -1776,6 +1754,11 @@
 	memset(info, 0, sizeof(struct fb_info));
 	memset(default_par, 0, sizeof(struct riva_par));
 
+	info->pixmap.addr = kmalloc(64 * 1024, GFP_KERNEL);
+	if (info->pixmap.addr == NULL)
+		goto err_out_kfree1;
+	memset(info->pixmap.addr, 0, 64 * 1024);
+
 	strcat(rivafb_fix.id, rci->name);
 	default_par->riva.Architecture = rci->arch_rev;
 
@@ -1805,7 +1788,7 @@
 	if (!request_mem_region(rivafb_fix.mmio_start,
 				rivafb_fix.mmio_len, "rivafb")) {
 		printk(KERN_ERR PFX "cannot reserve MMIO region\n");
-		goto err_out_kfree;
+		goto err_out_kfree2;
 	}
 
 	default_par->ctrl_base = ioremap(rivafb_fix.mmio_start,
@@ -1921,6 +1904,10 @@
 	iounmap(default_par->ctrl_base);
 err_out_free_base0:
 	release_mem_region(rivafb_fix.mmio_start, rivafb_fix.mmio_len);
+err_out_kfree2:
+	kfree(info->pixmap.addr);
+err_out_kfree1:
+	kfree(default_par);
 err_out_kfree:
 	kfree(info);
 err_out:
@@ -1954,6 +1941,7 @@
 		iounmap((caddr_t)par->riva.PRAMIN);
 		release_mem_region(info->fix.smem_start + 0x00C00000, 0x00008000);
 	}
+	kfree(info->pixmap.addr);
 	kfree(par);
 	kfree(info);
 	pci_set_drvdata(pd, NULL);

  reply	other threads:[~2003-02-27 14:14 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2003-02-23  4:42 [PATCH] Tile Blitting Antonino Daplas
2003-02-23  7:43 ` Antonino Daplas
2003-02-23 11:07   ` Antonino Daplas
2003-02-26 20:11     ` James Simmons
2003-02-27  0:35       ` Antonino Daplas
2003-02-27  1:18         ` James Simmons
2003-02-27 14:15           ` Antonino Daplas [this message]
2003-02-27 18:25             ` Michel Dänzer
2003-02-27 19:48               ` James Simmons
2003-03-02 12:14                 ` Geert Uytterhoeven
2003-03-03 21:32                   ` Antonino Daplas
2003-02-27 21:47               ` Antonino Daplas

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=1046355210.1206.42.camel@localhost.localdomain \
    --to=adaplas@pol.net \
    --cc=jsimmons@infradead.org \
    --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).