Thread (6 messages) 6 messages, 4 authors, 2004-04-14

Re: [PATCH] radeonfb: copyarea() "memmove()" problem

From: James Simmons <hidden>
Date: 2004-04-02 23:49:14

quoted
Now that my local kernel actually calls copyarea(), I see that my code was
buggy... That is, the hardware needs to be told which way to do its memory
copies if areas overlap.  Think of memmove() versus memcpy().  
Attached is the fix.

Unfortunately, I think the fbcon layer is also buggy... 
(try opening a file with vim, and typing "5ddP"  the copyarea()'s that 
get sent to the fb driver seem totally bogus...)
Excellent. James, any clue about the copyarea issue ?
I have seen this before. The issue comes you when we have over lapping 
areas. The direction you draw in is important. I have a patch that I 
tested. Give this a shot.


diff -urN -X /home/jsimmons/dontdiff fbdev-2.6/drivers/video/aty/radeon_accel.c fbdev-2.5/drivers/video/aty/radeon_accel.c
--- fbdev-2.6/drivers/video/aty/radeon_accel.c	2004-04-02 15:32:04.566209515 -0800
+++ fbdev-2.5/drivers/video/aty/radeon_accel.c	2004-04-02 15:29:06.337306396 -0800
@@ -53,6 +53,9 @@
 static void radeonfb_prim_copyarea(struct radeonfb_info *rinfo, 
 				   const struct fb_copyarea *area)
 {
+	u32 sx = area->sx, sy = area->sy, dx = area->dx, dy = area->dy;
+	u32 flag;
+
 	radeon_fifo_wait(3);
 	OUTREG(DP_GUI_MASTER_CNTL,
 		rinfo->dp_gui_master_cntl /* i.e. GMC_DST_32BPP */
@@ -60,7 +63,24 @@
 		| ROP3_S 
 		| DP_SRC_RECT );
 	OUTREG(DP_WRITE_MSK, 0xffffffff);
-	OUTREG(DP_CNTL, (DST_X_LEFT_TO_RIGHT | DST_Y_TOP_TO_BOTTOM));
+
+	if (sy < dy) {
+		sy += (area->height - 1);
+		dy += (area->height - 1);
+
+		flag |= DST_Y_BOTTOM_TO_TOP;
+	} else
+		flag |= DST_Y_TOP_TO_BOTTOM;
+
+	if (area->sx < area->dx) {
+		sx += (area->width - 1);
+		dx += (area->width - 1);
+
+		flag |= DST_X_LEFT_TO_RIGHT;
+	} else
+		flag |= DST_X_RIGHT_TO_LEFT;
+
+	OUTREG(DP_CNTL, flag);
 
 	radeon_fifo_wait(3);
 	OUTREG(SRC_Y_X, (area->sy << 16) | area->sx);
diff -urN -X /home/jsimmons/dontdiff fbdev-2.6/drivers/video/aty/radeonfb.h fbdev-2.5/drivers/video/aty/radeonfb.h
--- fbdev-2.6/drivers/video/aty/radeonfb.h	2004-04-02 15:38:57.115407055 -0800
+++ fbdev-2.5/drivers/video/aty/radeonfb.h	2004-04-02 15:35:53.237300302 -0800
@@ -295,8 +295,6 @@
 	struct panel_info	panel_info;
 	int			mon1_type;
 	u8			*mon1_EDID;
-	struct fb_videomode	*mon1_modedb;
-	int			mon1_dbsize;
 	int			mon2_type;
 	u8		        *mon2_EDID;
 
diff -urN -X /home/jsimmons/dontdiff fbdev-2.6/drivers/video/aty/radeon_monitor.c fbdev-2.5/drivers/video/aty/radeon_monitor.c
--- fbdev-2.6/drivers/video/aty/radeon_monitor.c	2004-04-02 15:31:42.854142518 -0800
+++ fbdev-2.5/drivers/video/aty/radeon_monitor.c	2004-04-02 12:09:07.000000000 -0800
@@ -804,12 +804,8 @@
 	/*
 	 * Now build modedb from EDID
 	 */
-	if (rinfo->mon1_EDID) {
-		rinfo->mon1_modedb = fb_create_modedb(rinfo->mon1_EDID,
-						      &rinfo->mon1_dbsize);
+	if (rinfo->mon1_EDID)
 		fb_get_monitor_limits(rinfo->mon1_EDID, &rinfo->info->monspecs);
-	}
-
 	
 	/*
 	 * Finally, if we don't have panel infos we need to figure some (or
@@ -835,8 +831,8 @@
 		}
 		printk(KERN_WARNING "radeonfb: Assuming panel size %dx%d\n",
 		       rinfo->panel_info.xres, rinfo->panel_info.yres);
-		modedb = rinfo->mon1_modedb;
-		dbsize = rinfo->mon1_dbsize;
+		modedb = rinfo->info->monspecs.modedb;
+		dbsize = rinfo->info->monspecs.modedb_len;
 		snprintf(modename, 31, "%dx%d", rinfo->panel_info.xres, rinfo->panel_info.yres);
 		if (fb_find_mode(&rinfo->info->var, rinfo->info, modename,
 				 modedb, dbsize, NULL, 8) == 0) {
@@ -859,7 +855,7 @@
 		else
 			radeon_var_to_videomode(&default_mode, &radeonfb_default_var);
 		if (fb_find_mode(&rinfo->info->var, rinfo->info, mode_option,
-				 rinfo->mon1_modedb, rinfo->mon1_dbsize, &default_mode, 8) == 0)
+				 rinfo->info->monspecs.modedb, rinfo->info->monspecs.modedb_len, &default_mode, 8) == 0)
 			rinfo->info->var = radeonfb_default_var;
 	}
 
@@ -915,9 +911,9 @@
 	memcpy(dest, src, sizeof(struct fb_var_screeninfo));
 
 	/* Check if we have a modedb built from EDID */
-	if (rinfo->mon1_modedb) {
-		db = rinfo->mon1_modedb;
-		dbsize = rinfo->mon1_dbsize;
+	if (rinfo->info->monspecs.modedb) {
+		db = rinfo->info->monspecs.modedb;
+		dbsize = rinfo->info->monspecs.modedb_len;
 		native_db = 1;
 	}
 
@@ -935,7 +931,7 @@
 		 * 640x480-60, but I assume userland knows what it's doing here
 		 * (though I may be proven wrong...)
 		 */
-		if (has_rmx == 0 && rinfo->mon1_modedb)
+		if (has_rmx == 0 && rinfo->info->monspecs.modedb)
 			if (fb_validate_mode((struct fb_var_screeninfo *)src, rinfo->info))
 				return -EINVAL;
 		return 0;




-------------------------------------------------------
This SF.Net email is sponsored by: IBM Linux Tutorials
Free Linux tutorial presented by Daniel Robbins, President and CEO of
GenToo technologies. Learn everything from fundamentals to system
administration.http://ads.osdn.com/?ad_id=1470&alloc_id=3638&op=click
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help