git: 9front

Download patch

ref: 0e7087cac997cf55d88dc8c5a41c983984ee2be6
parent: cfb8010d1147e1acc8725bce1f687a1140a16409
author: rodri <rgl@antares-labs.eu>
date: Tue Jan 20 20:04:43 EST 2026

libmemdraw: avoid buffering in alphadraw() unless strictly necessary

--- a/sys/src/libmemdraw/draw.c
+++ b/sys/src/libmemdraw/draw.c
@@ -595,19 +595,21 @@
 	isgrey = dst->flags&Fgrey;
 
 	/*
-	 * Buffering when src and dst are the same bitmap is sufficient but not 
-	 * necessary.  There are stronger conditions we could use.  We could
-	 * check to see if the rectangles intersect, and if simply moving in the
-	 * correct y direction can avoid the need to buffer.
+	 * Buffering is only necessary when src and dst are the same
+	 * bitmap and both r and sr intersect each other and begin at
+	 * the same scanline.  We could even avoid this if it was
+	 * possible to walk the scanline pixels in the -x direction.
+	 *
+	 * The vector û = sr.min - r.min determines the safest
+	 * direction to follow on each axis.
 	 */
-	needbuf = (src->data == dst->data);
+	needbuf = (src->data == dst->data && r.min.y == sr.min.y && rectXrect(r, sr));
+	dir = (src->data == dst->data && r.min.y > sr.min.y && rectXrect(r, sr)) ? -1 : 1;
 
 	ndrawbuf = 0;
 	getparam(&z->spar, src, sr, isgrey, needbuf, &ndrawbuf);
 	getparam(&z->dpar, dst, r, isgrey, needbuf, &ndrawbuf);
 	getparam(&z->mpar, mask, mr, 0, needbuf, &ndrawbuf);
-
-	dir = (needbuf && byteaddr(dst, r.min) > byteaddr(src, sr.min)) ? -1 : 1;
 	z->spar.dir = z->mpar.dir = z->dpar.dir = dir;
 
 	/*
@@ -2027,13 +2029,13 @@
 		case CAlpha:
 			v |= (a>>(8-nb))<<d;
 			break;
+		case CGrey:
+			m = RGB2K(r,g,b);
+			v |= (m>>(8-nb))<<d;
+			break;
 		case CMap:
 			p = img->cmap->rgb2cmap;
 			m = p[(r>>4)*256+(g>>4)*16+(b>>4)];
-			v |= (m>>(8-nb))<<d;
-			break;
-		case CGrey:
-			m = RGB2K(r,g,b);
 			v |= (m>>(8-nb))<<d;
 			break;
 		}
--