From: James Simmons <jsimmons@infradead.org>

I broke up the cursor patch.  This patch creates a seperate cursor image
drawing region and regular drawing region.  It does not break any drivers
to my knowledge.  I posted it anyways for people to test it.



---

 drivers/video/console/fbcon.c |   19 +++---
 drivers/video/fbmem.c         |   76 ++++++++++++++++--------
 drivers/video/softcursor.c    |    8 +-
 include/linux/fb.h            |  132 +++++++++++++++++++-----------------------
 4 files changed, 129 insertions(+), 106 deletions(-)

diff -puN drivers/video/console/fbcon.c~fbdev-cursor-1 drivers/video/console/fbcon.c
--- 25/drivers/video/console/fbcon.c~fbdev-cursor-1	2004-02-16 23:43:22.000000000 -0800
+++ 25-akpm/drivers/video/console/fbcon.c	2004-02-16 23:43:22.000000000 -0800
@@ -324,7 +324,7 @@ static void putcs_unaligned(struct vc_da
 	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 >> 3;
-	u8 mask, *src, *dst, *dst0;
+	u8 *src, *dst, *dst0;
 
 	while (count) {
 		if (count > maxcnt)
@@ -337,15 +337,15 @@ static void putcs_unaligned(struct vc_da
 		pitch &= ~scan_align;
 		size = pitch * vc->vc_font.height + buf_align;
 		size &= ~buf_align;
-		dst0 = info->pixmap.addr + fb_get_buffer_offset(info, size);
+		dst0 = fb_get_buffer_offset(info, &info->pixmap, size);
 		image->data = dst0;
 		while (k--) {
 			src = vc->vc_font.data + (scr_readw(s++) & charmask)*
 			cellsize;
 			dst = dst0;
-			mask = (u8) (0xfff << shift_high);
-			move_buf_unaligned(info, dst, src, pitch, image->height,
-					mask, shift_high, shift_low, mod, idx);
+			fb_move_buf_unaligned(info, &info->pixmap, dst, pitch, src,
+						idx, image->height, shift_high,
+						shift_low, mod);
 			shift_low += mod;
 			dst0 += (shift_low >= 8) ? width : width - 1;
 			shift_low &= 7;
@@ -381,12 +381,13 @@ static void putcs_aligned(struct vc_data
 		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);
+		dst0 = fb_get_buffer_offset(info, &info->pixmap, size);
 		image->data = dst0;
 		while (k--) {
 			src = vc->vc_font.data + (scr_readw(s++)&charmask)*cellsize;
 			dst = dst0;
-			move_buf_aligned(info, dst, src, pitch, width, image->height);
+			fb_move_buf_aligned(info, &info->pixmap, dst, pitch, src,
+						width, image->height);
 			dst0 += width;
 		}
 		info->fbops->fb_imageblit(info, image);
@@ -455,11 +456,11 @@ static void accel_putc(struct vc_data *v
 	size = pitch * vc->vc_font.height;
 	size += buf_align;
 	size &= ~buf_align;
-	dst = info->pixmap.addr + fb_get_buffer_offset(info, size);
+	dst = fb_get_buffer_offset(info, &info->pixmap, size);
 	image.data = dst;
 	src = vc->vc_font.data + (c & charmask) * vc->vc_font.height * width;
 
-	move_buf_aligned(info, dst, src, pitch, width, image.height);
+	fb_move_buf_aligned(info, &info->pixmap, dst, pitch, src, width, image.height);
 
 	info->fbops->fb_imageblit(info, &image);
 }
diff -puN drivers/video/fbmem.c~fbdev-cursor-1 drivers/video/fbmem.c
--- 25/drivers/video/fbmem.c~fbdev-cursor-1	2004-02-16 23:43:22.000000000 -0800
+++ 25-akpm/drivers/video/fbmem.c	2004-02-16 23:43:22.000000000 -0800
@@ -395,7 +395,7 @@ static struct {
 };
 
 #define NUM_FB_DRIVERS	(sizeof(fb_drivers)/sizeof(*fb_drivers))
-#define FBPIXMAPSIZE	8192
+#define FBPIXMAPSIZE	16384
 
 extern const char *global_mode_option;
 
@@ -412,52 +412,54 @@ static int ofonly __initdata = 0;
 /*
  * Drawing helpers.
  */
-u8 sys_inbuf(u8 *src)
+u8 sys_inbuf(struct fb_info *info, u8 *src)
 {	
 	return *src;
 }
 
-void sys_outbuf(u8 *src, u8 *dst, unsigned int size)
+void sys_outbuf(struct fb_info *info, u8 *dst, u8 *src, unsigned int size)
 {
 	memcpy(dst, src, size);
 }	
 
-void move_buf_aligned(struct fb_info *info, u8 *dst, u8 *src, u32 d_pitch, 
-			u32 s_pitch, u32 height)
+void fb_move_buf_aligned(struct fb_info *info, struct fb_pixmap *buf,
+			u8 *dst, u32 d_pitch, u8 *src, u32 s_pitch,
+			u32 height)
 {
 	int i;
 
 	for (i = height; i--; ) {
-		info->pixmap.outbuf(src, dst, s_pitch);
+		buf->outbuf(info, dst, src, s_pitch);
 		src += s_pitch;
 		dst += d_pitch;
 	}
 }
 
-void move_buf_unaligned(struct fb_info *info, u8 *dst, u8 *src, u32 d_pitch, 
-			u32 height, u32 mask, u32 shift_high, u32 shift_low,
-			u32 mod, u32 idx)
+void fb_move_buf_unaligned(struct fb_info *info, struct fb_pixmap *buf,
+			u8 *dst, u32 d_pitch, u8 *src, u32 idx,
+			u32 height, u32 shift_high, u32 shift_low,
+			u32 mod)
 {
+	u8 mask = (u8) (0xfff << shift_high), tmp;
 	int i, j;
-	u8 tmp;
 
 	for (i = height; i--; ) {
 		for (j = 0; j < idx; j++) {
-			tmp = info->pixmap.inbuf(dst+j);
+			tmp = buf->inbuf(info, dst+j);
 			tmp &= mask;
 			tmp |= *src >> shift_low;
-			info->pixmap.outbuf(&tmp, dst+j, 1);
+			buf->outbuf(info, dst+j, &tmp, 1);
 			tmp = *src << shift_high;
-			info->pixmap.outbuf(&tmp, dst+j+1, 1);
+			buf->outbuf(info, dst+j+1, &tmp, 1);
 			src++;
 		}
-		tmp = info->pixmap.inbuf(dst+idx);
+		tmp = buf->inbuf(info, dst+idx);
 		tmp &= mask;
 		tmp |= *src >> shift_low;
-		info->pixmap.outbuf(&tmp, dst+idx, 1);
+		buf->outbuf(info, dst+idx, &tmp, 1);
 		if (shift_high < mod) {
 			tmp = *src << shift_high;
-			info->pixmap.outbuf(&tmp, dst+idx+1, 1);
+			buf->outbuf(info, dst+idx+1, &tmp, 1);
 		}	
 		src++;
 		dst += d_pitch;
@@ -468,10 +470,10 @@ void move_buf_unaligned(struct fb_info *
  * we need to lock this section since fb_cursor
  * may use fb_imageblit()
  */
-u32 fb_get_buffer_offset(struct fb_info *info, u32 size)
+char* fb_get_buffer_offset(struct fb_info *info, struct fb_pixmap *buf, u32 size)
 {
-	struct fb_pixmap *buf = &info->pixmap;
 	u32 align = buf->buf_align - 1, offset;
+	char *addr = buf->addr;
 
 	/* If IO mapped, we need to sync before access, no sharing of
 	 * the pixmap is done
@@ -479,7 +481,7 @@ u32 fb_get_buffer_offset(struct fb_info 
 	if (buf->flags & FB_PIXMAP_IO) {
 		if (info->fbops->fb_sync && (buf->flags & FB_PIXMAP_SYNC))
 			info->fbops->fb_sync(info);
-		return 0;
+		return addr;
 	}
 
 	/* See if we fit in the remaining pixmap space */
@@ -495,8 +497,9 @@ u32 fb_get_buffer_offset(struct fb_info 
 		offset = 0;
 	}
 	buf->offset = offset + size;
+	addr += offset;
 
-	return offset;
+	return addr;
 }
 
 #ifdef CONFIG_LOGO
@@ -869,6 +872,15 @@ static void try_to_load(int fb)
 }
 #endif /* CONFIG_KMOD */
 
+void
+fb_load_cursor_image(struct fb_info *info)
+{
+	unsigned int width = (info->cursor.image.width + 7) >> 3;
+	u8 *data = (u8 *) info->cursor.image.data;
+
+	info->sprite.outbuf(info, info->sprite.addr, data, width);
+}
+
 int
 fb_cursor(struct fb_info *info, struct fb_cursor *sprite)
 {
@@ -1276,6 +1288,21 @@ register_framebuffer(struct fb_info *fb_
 	if (fb_info->pixmap.inbuf == NULL)
 		fb_info->pixmap.inbuf = sys_inbuf;
 
+	if (fb_info->sprite.addr == NULL) {
+		fb_info->sprite.addr = kmalloc(FBPIXMAPSIZE, GFP_KERNEL);
+		if (fb_info->sprite.addr) {
+			fb_info->sprite.size = FBPIXMAPSIZE;
+			fb_info->sprite.buf_align = 1;
+			fb_info->sprite.scan_align = 1;
+			fb_info->sprite.flags = FB_PIXMAP_DEFAULT;
+		}
+	}
+	fb_info->sprite.offset = 0;
+	if (fb_info->sprite.outbuf == NULL)
+		fb_info->sprite.outbuf = sys_outbuf;
+	if (fb_info->sprite.inbuf == NULL)
+		fb_info->sprite.inbuf = sys_inbuf;
+
 	registered_fb[i] = fb_info;
 
 	devfs_mk_cdev(MKDEV(FB_MAJOR, i),
@@ -1304,8 +1331,10 @@ unregister_framebuffer(struct fb_info *f
 		return -EINVAL;
 	devfs_remove("fb/%d", i);
 
-	if (fb_info->pixmap.addr)
+	if (fb_info->pixmap.addr && (fb_info->pixmap.flags & FB_PIXMAP_DEFAULT))
 		kfree(fb_info->pixmap.addr);
+	if (fb_info->sprite.addr && (fb_info->pixmap.flags & FB_PIXMAP_DEFAULT))
+		kfree(fb_info->sprite.addr);
 	registered_fb[i]=NULL;
 	num_registered_fb--;
 	return 0;
@@ -1460,8 +1489,9 @@ EXPORT_SYMBOL(fb_set_var);
 EXPORT_SYMBOL(fb_blank);
 EXPORT_SYMBOL(fb_pan_display);
 EXPORT_SYMBOL(fb_get_buffer_offset);
-EXPORT_SYMBOL(move_buf_unaligned);
-EXPORT_SYMBOL(move_buf_aligned);
+EXPORT_SYMBOL(fb_move_buf_unaligned);
+EXPORT_SYMBOL(fb_move_buf_aligned);
+EXPORT_SYMBOL(fb_load_cursor_image);
 EXPORT_SYMBOL(fb_set_suspend);
 EXPORT_SYMBOL(fb_register_client);
 EXPORT_SYMBOL(fb_unregister_client);
diff -puN drivers/video/softcursor.c~fbdev-cursor-1 drivers/video/softcursor.c
--- 25/drivers/video/softcursor.c~fbdev-cursor-1	2004-02-16 23:43:22.000000000 -0800
+++ 25-akpm/drivers/video/softcursor.c	2004-02-16 23:43:22.000000000 -0800
@@ -19,8 +19,8 @@
 
 int soft_cursor(struct fb_info *info, struct fb_cursor *cursor)
 {
-	unsigned int scan_align = info->pixmap.scan_align - 1;
-	unsigned int buf_align = info->pixmap.buf_align - 1;
+	unsigned int scan_align = info->sprite.scan_align - 1;
+	unsigned int buf_align = info->sprite.buf_align - 1;
 	unsigned int i, size, dsize, s_pitch, d_pitch;
 	u8 *dst, src[64];
 
@@ -56,7 +56,7 @@ int soft_cursor(struct fb_info *info, st
 	d_pitch = (s_pitch + scan_align) & ~scan_align;
 	size = d_pitch * info->cursor.image.height + buf_align;
 	size &= ~buf_align;
-	dst = info->pixmap.addr + fb_get_buffer_offset(info, size);
+	dst = fb_get_buffer_offset(info, &info->sprite, size);
 
 	if (info->cursor.enable) {
 		switch (info->cursor.rop) {
@@ -73,7 +73,7 @@ int soft_cursor(struct fb_info *info, st
 	} else 
 		memcpy(src, cursor->image.data, dsize);
 	
-	move_buf_aligned(info, dst, src, d_pitch, s_pitch, info->cursor.image.height);
+	fb_move_buf_aligned(info, &info->sprite, dst, d_pitch, src, s_pitch, info->cursor.image.height);
 	info->cursor.image.data = dst;
 	
 	info->fbops->fb_imageblit(info, &info->cursor.image);
diff -puN include/linux/fb.h~fbdev-cursor-1 include/linux/fb.h
--- 25/include/linux/fb.h~fbdev-cursor-1	2004-02-16 23:43:22.000000000 -0800
+++ 25-akpm/include/linux/fb.h	2004-02-16 23:43:22.000000000 -0800
@@ -371,16 +371,16 @@ extern int fb_unregister_client(struct n
 #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 access_align;	/* alignment per read/write             */
-	u32 flags;		/* see FB_PIXMAP_*                      */
-					  /* access methods                */
-	void (*outbuf)(u8 *dst, u8 *addr, unsigned int size); 
-	u8   (*inbuf) (u8 *addr);
+	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 access_align;	/* alignment per read/write		*/
+	u32 flags;		/* see FB_PIXMAP_*			*/
+				/* access methods			*/
+	void (*outbuf)(struct fb_info *info, u8 *addr, u8 *src, unsigned int size);
+	u8   (*inbuf) (struct fb_info *info, u8 *addr);
 };
 
     /*
@@ -388,64 +388,53 @@ struct fb_pixmap {
      */
 
 struct fb_ops {
-    /* open/release and usage marking */
-    struct module *owner;
-    int (*fb_open)(struct fb_info *info, int user);
-    int (*fb_release)(struct fb_info *info, int user);
-
-    /* For framebuffers with strange non linear layouts */	
-	ssize_t(*fb_read) (struct file * file, char *buf, size_t count,
-			   loff_t * ppos);
-	ssize_t(*fb_write) (struct file * file, const char *buf,
-			    size_t count, loff_t * ppos);
+	/* open/release and usage marking */
+	struct module *owner;
+	int (*fb_open)(struct fb_info *info, int user);
+	int (*fb_release)(struct fb_info *info, int user);
+
+	/* For framebuffers with strange non linear layouts */
+	ssize_t (*fb_read)(struct file *file, char *buf, size_t count, loff_t *ppos);
+	ssize_t (*fb_write)(struct file *file, const char *buf, size_t count, loff_t *ppos);
 
 	/* checks var and eventually tweaks it to something supported,
 	 * DO NOT MODIFY PAR */
-	int (*fb_check_var) (struct fb_var_screeninfo * var,
-			     struct fb_info * info);
+	int (*fb_check_var)(struct fb_var_screeninfo *var, struct fb_info *info);
 	/* set the video mode according to info->var */
-    int (*fb_set_par)(struct fb_info *info);
+	int (*fb_set_par)(struct fb_info *info);
 
-    /* set color register */
-    int (*fb_setcolreg)(unsigned regno, unsigned red, unsigned green,
-			     unsigned blue, unsigned transp,
-			     struct fb_info * info);
-
-    /* blank display */
-    int (*fb_blank)(int blank, struct fb_info *info);
-
-    /* pan display */
-	int (*fb_pan_display) (struct fb_var_screeninfo * var,
-			       struct fb_info * info);
-
-    /* draws a rectangle */
-	void (*fb_fillrect) (struct fb_info * info,
-			     const struct fb_fillrect * rect);
-    /* Copy data from area to another */
-	void (*fb_copyarea) (struct fb_info * info,
-			     const struct fb_copyarea * region);
-    /* Draws a image to the display */
-	void (*fb_imageblit) (struct fb_info * info,
-			      const struct fb_image * image);
-
-    /* Draws cursor */
-	int (*fb_cursor) (struct fb_info * info,
-			  struct fb_cursor * cursor);
-
-    /* Rotates the display */
-    void (*fb_rotate)(struct fb_info *info, int angle);
-
-    /* wait for blit idle, optional */
-    int (*fb_sync)(struct fb_info *info);		
-
-    /* perform fb specific ioctl (optional) */
-	int (*fb_ioctl) (struct inode * inode, struct file * file,
-			 unsigned int cmd, unsigned long arg,
-			 struct fb_info * info);
-
-    /* perform fb specific mmap */
-	int (*fb_mmap) (struct fb_info * info, struct file * file,
-			struct vm_area_struct * vma);
+	/* set color register */
+	int (*fb_setcolreg)(unsigned regno, unsigned red, unsigned green,
+			    unsigned blue, unsigned transp, struct fb_info *info);
+
+	/* blank display */
+	int (*fb_blank)(int blank, struct fb_info *info);
+
+	/* pan display */
+	int (*fb_pan_display)(struct fb_var_screeninfo *var, struct fb_info *info);
+
+	/* Draws a rectangle */
+	void (*fb_fillrect) (struct fb_info *info, const struct fb_fillrect *rect);
+	/* Copy data from area to another */
+	void (*fb_copyarea) (struct fb_info *info, const struct fb_copyarea *region);
+	/* Draws a image to the display */
+	void (*fb_imageblit) (struct fb_info *info, const struct fb_image *image);
+
+	/* Draws cursor */
+	int (*fb_cursor) (struct fb_info *info, struct fb_cursor *cursor);
+
+	/* Rotates the display */
+	void (*fb_rotate)(struct fb_info *info, int angle);
+
+	/* wait for blit idle, optional */
+	int (*fb_sync)(struct fb_info *info);
+
+	/* perform fb specific ioctl (optional) */
+	int (*fb_ioctl)(struct inode *inode, struct file *file, unsigned int cmd,
+			unsigned long arg, struct fb_info *info);
+
+	/* perform fb specific mmap */
+	int (*fb_mmap)(struct fb_info *info, struct file *file, struct vm_area_struct *vma);
 };
 
 struct fb_info {
@@ -459,6 +448,7 @@ struct fb_info {
 	struct fb_cursor cursor;	/* Current cursor */	
 	struct work_struct queue;	/* Framebuffer event queue */
 	struct fb_pixmap pixmap;	/* Image Hardware Mapper */
+	struct fb_pixmap sprite;	/* Cursor hardware Mapper */
 	struct fb_cmap cmap;		/* Current cmap */
 	struct fb_ops *fbops;
 	char *screen_base;		/* Virtual address */
@@ -537,14 +527,16 @@ extern int register_framebuffer(struct f
 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 void move_buf_unaligned(struct fb_info *info, u8 * dst, u8 * src,
-				u32 d_pitch, u32 height, u32 mask,
-				u32 shift_high, u32 shift_low, u32 mod,
-				u32 idx);
-extern void move_buf_aligned(struct fb_info *info, u8 * dst, u8 * src,
-				u32 d_pitch, u32 s_pitch, u32 height);
+extern char* fb_get_buffer_offset(struct fb_info *info, struct fb_pixmap *buf, u32 size);
+extern void fb_move_buf_unaligned(struct fb_info *info, struct fb_pixmap *buf,
+				u8 *dst, u32 d_pitch, u8 *src, u32 idx,
+				u32 height, u32 shift_high, u32 shift_low, u32 mod);
+extern void fb_move_buf_aligned(struct fb_info *info, struct fb_pixmap *buf,
+				u8 *dst, u32 d_pitch, u8 *src, u32 s_pitch,
+				u32 height);
+extern void fb_load_cursor_image(struct fb_info *);
 extern void fb_set_suspend(struct fb_info *info, int state);
+
 extern struct fb_info *registered_fb[FB_MAX];
 extern int num_registered_fb;
 

_