9fans - fans of the OS Plan 9 from Bell Labs
 help / color / mirror / Atom feed
From: yy <yiyu.jgl@gmail.com>
To: Fans of the OS Plan 9 from Bell Labs <9fans@9fans.net>
Subject: Re: [9fans] Porter-Duff alpha blending
Date: Mon,  9 Mar 2009 16:32:00 +0100	[thread overview]
Message-ID: <a81fe9be0903090832s6d6904a9o4db609297442e0f0@mail.gmail.com> (raw)
In-Reply-To: <9d4e40b94d08829ff259ced7ab3eb0f8@quanstro.net>

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

2009/3/9 erik quanstrom <quanstro@quanstro.net>:
> i leave it as an exercize to the reader to port
> this to 9vx. ☺
>

There you are. Easy exercises are also good from time to time :)
The patch also allows to use Shift+Button3 as Button2 (as documented
in the man page).

Regards,


-- 
- yiyus || JGL .

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: libmemdraw.9vx.patch --]
[-- Type: text/x-diff; name="libmemdraw.9vx.patch", Size: 12055 bytes --]

diff -r a18e9872164b src/9vx/libmemdraw/draw.c
--- a/src/9vx/libmemdraw/draw.c	Wed Dec 10 03:29:15 2008 -0800
+++ b/src/9vx/libmemdraw/draw.c	Mon Mar 09 16:29:39 2009 +0100
@@ -10,22 +10,32 @@
 #define RGB2K(r,g,b)	((156763*(r)+307758*(g)+59769*(b))>>19)
 
 /*
- * for 0 ≤ x ≤ 255*255, (x*0x0101+0x100)>>16 is a perfect approximation.
- * for 0 ≤ x < (1<<16), x/255 = ((x+1)*0x0101)>>16 is a perfect approximation.
- * the last one is perfect for all up to 1<<16, avoids a multiply, but requires a rathole.
+ * For 16-bit values, x / 255 == (t = x+1, (t+(t>>8)) >> 8).
+ * We add another 127 to round to the nearest value rather
+ * than truncate.
+ *
+ * CALCxy does x bytewise calculations on y input images (x=1,4; y=1,2).
+ * CALC2x does two parallel 16-bit calculations on y input images (y=1,2).
  */
-/* #define DIV255(x) (((x)*257+256)>>16)  */
-#define DIV255(x) ((((x)+1)*257)>>16)
-/* #define DIV255(x) (tmp=(x)+1, (tmp+(tmp>>8))>>8) */
+#define CALC11(a, v, tmp) \
+ (tmp=(a)*(v)+128, (tmp+(tmp>>8))>>8)
+#define CALC12(a1, v1, a2, v2, tmp) \
+ (tmp=(a1)*(v1)+(a2)*(v2)+128, (tmp+(tmp>>8))>>8)
+#define MASK 0xFF00FF
 
-#define MUL(x, y, t)	(t = (x)*(y)+128, (t+(t>>8))>>8)
-#define MASK13	0xFF00FF00
-#define MASK02	0x00FF00FF
-#define MUL13(a, x, t)		(t = (a)*(((x)&MASK13)>>8)+128, ((t+((t>>8)&MASK02))>>8)&MASK02)
-#define MUL02(a, x, t)		(t = (a)*(((x)&MASK02)>>0)+128, ((t+((t>>8)&MASK02))>>8)&MASK02)
-#define MUL0123(a, x, s, t)	((MUL13(a, x, s)<<8)|MUL02(a, x, t))
+#define CALC21(a, vvuu, tmp) \
+ (tmp=(a)*(vvuu)+0x00800080, ((tmp+((tmp>>8)&MASK))>>8)&MASK)
 
-#define MUL2(u, v, x, y)	(t = (u)*(v)+(x)*(y)+256, (t+(t>>8))>>8)
+#define CALC41(a, rgba, tmp1, tmp2) \
+ (CALC21(a, rgba & MASK, tmp1) | \
+ (CALC21(a, (rgba>>8)&MASK, tmp2)<<8))
+
+#define CALC22(a1, vvuu1, a2, vvuu2, tmp) \
+ (tmp=(a1)*(vvuu1)+(a2)*(vvuu2)+0x00800080, ((tmp+((tmp>>8)&MASK))>>8)&MASK)
+
+#define CALC42(a1, rgba1, a2, rgba2, tmp1, tmp2) \
+ (CALC22(a1, rgba1 & MASK, a2, rgba2 & MASK, tmp1) | \
+ (CALC22(a1, (rgba1>>8) & MASK, a2, (rgba2>>8) & MASK, tmp2)<<8))
 
 static void mktables(void);
 typedef int Subdraw(Memdrawparam*);
@@ -803,41 +813,85 @@
 	return bdst;
 }
 
+/*
+ * Do the channels in the buffers match enough
+ * that we can do word-at-a-time operations
+ * on the pixels?
+ */
+static int
+chanmatch(Buffer *bdst, Buffer *bsrc)
+{
+	uchar *drgb, *srgb;
+	
+	/*
+	 * first, r, g, b must be in the same place
+	 * in the rgba word.
+	 */
+	drgb = (uchar*)bdst->rgba;
+	srgb = (uchar*)bsrc->rgba;
+	if(bdst->red - drgb != bsrc->red - srgb
+	|| bdst->blu - drgb != bsrc->blu - srgb
+	|| bdst->grn - drgb != bsrc->grn - srgb)
+		return 0;
+	
+	/*
+	 * that implies alpha is in the same place,
+	 * if it is there at all (it might be == &ones).
+	 * if the destination is &ones, we can scribble
+	 * over the rgba slot just fine.
+	 */
+	if(bdst->alpha == &ones)
+		return 1;
+	
+	/*
+	 * if the destination is not ones but the src is,
+	 * then the simultaneous calculation will use
+	 * bogus bytes from the src's rgba.  no good.
+	 */
+	if(bsrc->alpha == &ones)
+		return 0;
+	
+	/*
+	 * otherwise, alphas are in the same place.
+	 */
+	return 1;
+}
+
 static Buffer
 alphacalc14(Buffer bdst, Buffer bsrc, Buffer bmask, int dx, int grey, int op)
 {
 	Buffer obdst;
 	int fd, sadelta;
 	int i, sa, ma, q;
-	uint32 s, t;
+	uint32 t, t1;
 
 	obdst = bdst;
 	sadelta = bsrc.alpha == &ones ? 0 : bsrc.delta;
-	q = bsrc.delta == 4 && bdst.delta == 4;
+	q = bsrc.delta == 4 && bdst.delta == 4 && chanmatch(&bdst, &bsrc);
 
 	for(i=0; i<dx; i++){
 		sa = *bsrc.alpha;
 		ma = *bmask.alpha;
-		fd = MUL(sa, ma, t);
+		fd = CALC11(sa, ma, t);
 		if(op == DoutS)
 			fd = 255-fd;
 
 		if(grey){
-			*bdst.grey = MUL(fd, *bdst.grey, t);
+			*bdst.grey = CALC11(fd, *bdst.grey, t);
 			bsrc.grey += bsrc.delta;
 			bdst.grey += bdst.delta;
 		}else{
 			if(q){
-				*bdst.rgba = MUL0123(fd, *bdst.rgba, s, t);
+				*bdst.rgba = CALC41(fd, *bdst.rgba, t, t1);
 				bsrc.rgba++;
 				bdst.rgba++;
 				bsrc.alpha += sadelta;
 				bmask.alpha += bmask.delta;
 				continue;
 			}
-			*bdst.red = MUL(fd, *bdst.red, t);
-			*bdst.grn = MUL(fd, *bdst.grn, t);
-			*bdst.blu = MUL(fd, *bdst.blu, t);
+			*bdst.red = CALC11(fd, *bdst.red, t);
+			*bdst.grn = CALC11(fd, *bdst.grn, t);
+			*bdst.blu = CALC11(fd, *bdst.blu, t);
 			bsrc.red += bsrc.delta;
 			bsrc.blu += bsrc.delta;
 			bsrc.grn += bsrc.delta;
@@ -846,7 +900,7 @@
 			bdst.grn += bdst.delta;
 		}
 		if(bdst.alpha != &ones){
-			*bdst.alpha = MUL(fd, *bdst.alpha, t);
+			*bdst.alpha = CALC11(fd, *bdst.alpha, t);
 			bdst.alpha += bdst.delta;
 		}
 		bmask.alpha += bmask.delta;
@@ -861,11 +915,11 @@
 	Buffer obdst;
 	int fs, sadelta;
 	int i, ma, da, q;
-	uint32 s, t;
+	uint32 t, t1;
 
 	obdst = bdst;
 	sadelta = bsrc.alpha == &ones ? 0 : bsrc.delta;
-	q = bsrc.delta == 4 && bdst.delta == 4;
+	q = bsrc.delta == 4 && bdst.delta == 4 && chanmatch(&bdst, &bsrc);
 
 	for(i=0; i<dx; i++){
 		ma = *bmask.alpha;
@@ -874,24 +928,24 @@
 			da = 255-da;
 		fs = ma;
 		if(op != S)
-			fs = MUL(fs, da, t);
+			fs = CALC11(fs, da, t);
 
 		if(grey){
-			*bdst.grey = MUL(fs, *bsrc.grey, t);
+			*bdst.grey = CALC11(fs, *bsrc.grey, t);
 			bsrc.grey += bsrc.delta;
 			bdst.grey += bdst.delta;
 		}else{
 			if(q){
-				*bdst.rgba = MUL0123(fs, *bsrc.rgba, s, t);
+				*bdst.rgba = CALC41(fs, *bsrc.rgba, t, t1);
 				bsrc.rgba++;
 				bdst.rgba++;
 				bmask.alpha += bmask.delta;
 				bdst.alpha += bdst.delta;
 				continue;
 			}
-			*bdst.red = MUL(fs, *bsrc.red, t);
-			*bdst.grn = MUL(fs, *bsrc.grn, t);
-			*bdst.blu = MUL(fs, *bsrc.blu, t);
+			*bdst.red = CALC11(fs, *bsrc.red, t);
+			*bdst.grn = CALC11(fs, *bsrc.grn, t);
+			*bdst.blu = CALC11(fs, *bsrc.blu, t);
 			bsrc.red += bsrc.delta;
 			bsrc.blu += bsrc.delta;
 			bsrc.grn += bsrc.delta;
@@ -900,7 +954,7 @@
 			bdst.grn += bdst.delta;
 		}
 		if(bdst.alpha != &ones){
-			*bdst.alpha = MUL(fs, *bsrc.alpha, t);
+			*bdst.alpha = CALC11(fs, *bsrc.alpha, t);
 			bdst.alpha += bdst.delta;
 		}
 		bmask.alpha += bmask.delta;
@@ -915,35 +969,35 @@
 	Buffer obdst;
 	int fs, fd, sadelta;
 	int i, sa, ma, da, q;
-	uint32 s, t, u, v;
+	uint32 t, t1;
 
 	obdst = bdst;
 	sadelta = bsrc.alpha == &ones ? 0 : bsrc.delta;
-	q = bsrc.delta == 4 && bdst.delta == 4;
+	q = bsrc.delta == 4 && bdst.delta == 4 && chanmatch(&bdst, &bsrc);
 
 	for(i=0; i<dx; i++){
 		sa = *bsrc.alpha;
 		ma = *bmask.alpha;
 		da = *bdst.alpha;
 		if(op == SatopD)
-			fs = MUL(ma, da, t);
+			fs = CALC11(ma, da, t);
 		else
-			fs = MUL(ma, 255-da, t);
+			fs = CALC11(ma, 255-da, t);
 		if(op == DoverS)
 			fd = 255;
 		else{
-			fd = MUL(sa, ma, t);
+			fd = CALC11(sa, ma, t);
 			if(op != DatopS)
 				fd = 255-fd;
 		}
 
 		if(grey){
-			*bdst.grey = MUL(fs, *bsrc.grey, s)+MUL(fd, *bdst.grey, t);
+			*bdst.grey = CALC12(fs, *bsrc.grey, fd, *bdst.grey, t);
 			bsrc.grey += bsrc.delta;
 			bdst.grey += bdst.delta;
 		}else{
 			if(q){
-				*bdst.rgba = MUL0123(fs, *bsrc.rgba, s, t)+MUL0123(fd, *bdst.rgba, u, v);
+				*bdst.rgba = CALC42(fs, *bsrc.rgba, fd, *bdst.rgba, t, t1);
 				bsrc.rgba++;
 				bdst.rgba++;
 				bsrc.alpha += sadelta;
@@ -951,9 +1005,9 @@
 				bdst.alpha += bdst.delta;
 				continue;
 			}
-			*bdst.red = MUL(fs, *bsrc.red, s)+MUL(fd, *bdst.red, t);
-			*bdst.grn = MUL(fs, *bsrc.grn, s)+MUL(fd, *bdst.grn, t);
-			*bdst.blu = MUL(fs, *bsrc.blu, s)+MUL(fd, *bdst.blu, t);
+			*bdst.red = CALC12(fs, *bsrc.red, fd, *bdst.red, t);
+			*bdst.grn = CALC12(fs, *bsrc.grn, fd, *bdst.grn, t);
+			*bdst.blu = CALC12(fs, *bsrc.blu, fd, *bdst.blu, t);
 			bsrc.red += bsrc.delta;
 			bsrc.blu += bsrc.delta;
 			bsrc.grn += bsrc.delta;
@@ -962,7 +1016,7 @@
 			bdst.grn += bdst.delta;
 		}
 		if(bdst.alpha != &ones){
-			*bdst.alpha = MUL(fs, sa, s)+MUL(fd, da, t);
+			*bdst.alpha = CALC12(fs, sa, fd, da, t);
 			bdst.alpha += bdst.delta;
 		}
 		bmask.alpha += bmask.delta;
@@ -988,34 +1042,34 @@
 	Buffer obdst;
 	int fd, sadelta;
 	int i, sa, ma, q;
-	uint32 s, t, u, v;
+	uint32 t, t1;
 
 	USED(op);
 	obdst = bdst;
 	sadelta = bsrc.alpha == &ones ? 0 : bsrc.delta;
-	q = bsrc.delta == 4 && bdst.delta == 4;
+	q = bsrc.delta == 4 && bdst.delta == 4 && chanmatch(&bdst, &bsrc);
 
 	for(i=0; i<dx; i++){
 		sa = *bsrc.alpha;
 		ma = *bmask.alpha;
-		fd = 255-MUL(sa, ma, t);
+		fd = 255-CALC11(sa, ma, t);
 
 		if(grey){
-			*bdst.grey = MUL(ma, *bsrc.grey, s)+MUL(fd, *bdst.grey, t);
+			*bdst.grey = CALC12(ma, *bsrc.grey, fd, *bdst.grey, t);
 			bsrc.grey += bsrc.delta;
 			bdst.grey += bdst.delta;
 		}else{
 			if(q){
-				*bdst.rgba = MUL0123(ma, *bsrc.rgba, s, t)+MUL0123(fd, *bdst.rgba, u, v);
+				*bdst.rgba = CALC42(ma, *bsrc.rgba, fd, *bdst.rgba, t, t1);
 				bsrc.rgba++;
 				bdst.rgba++;
 				bsrc.alpha += sadelta;
 				bmask.alpha += bmask.delta;
 				continue;
 			}
-			*bdst.red = MUL(ma, *bsrc.red, s)+MUL(fd, *bdst.red, t);
-			*bdst.grn = MUL(ma, *bsrc.grn, s)+MUL(fd, *bdst.grn, t);
-			*bdst.blu = MUL(ma, *bsrc.blu, s)+MUL(fd, *bdst.blu, t);
+			*bdst.red = CALC12(ma, *bsrc.red, fd, *bdst.red, t);
+			*bdst.grn = CALC12(ma, *bsrc.grn, fd, *bdst.grn, t);
+			*bdst.blu = CALC12(ma, *bsrc.blu, fd, *bdst.blu, t);
 			bsrc.red += bsrc.delta;
 			bsrc.blu += bsrc.delta;
 			bsrc.grn += bsrc.delta;
@@ -1024,7 +1078,7 @@
 			bdst.grn += bdst.delta;
 		}
 		if(bdst.alpha != &ones){
-			*bdst.alpha = MUL(ma, sa, s)+MUL(fd, *bdst.alpha, t);
+			*bdst.alpha = CALC12(ma, sa, fd, *bdst.alpha, t);
 			bdst.alpha += bdst.delta;
 		}
 		bmask.alpha += bmask.delta;
@@ -1080,7 +1134,7 @@
 	Buffer obdst;
 	int fd;
 	int i, ma;
-	uint32 s, t;
+	uint32 t;
 
 	USED(op);
 	obdst = bdst;
@@ -1090,13 +1144,13 @@
 		fd = 255-ma;
 
 		if(grey){
-			*bdst.grey = MUL(ma, *bsrc.grey, s)+MUL(fd, *bdst.grey, t);
+			*bdst.grey = CALC12(ma, *bsrc.grey, fd, *bdst.grey, t);
 			bsrc.grey += bsrc.delta;
 			bdst.grey += bdst.delta;
 		}else{
-			*bdst.red = MUL(ma, *bsrc.red, s)+MUL(fd, *bdst.red, t);
-			*bdst.grn = MUL(ma, *bsrc.grn, s)+MUL(fd, *bdst.grn, t);
-			*bdst.blu = MUL(ma, *bsrc.blu, s)+MUL(fd, *bdst.blu, t);
+			*bdst.red = CALC12(ma, *bsrc.red, fd, *bdst.red, t);
+			*bdst.grn = CALC12(ma, *bsrc.grn, fd, *bdst.grn, t);
+			*bdst.blu = CALC12(ma, *bsrc.blu, fd, *bdst.blu, t);
 			bsrc.red += bsrc.delta;
 			bsrc.blu += bsrc.delta;
 			bsrc.grn += bsrc.delta;
@@ -1105,7 +1159,7 @@
 			bdst.grn += bdst.delta;
 		}
 		if(bdst.alpha != &ones){
-			*bdst.alpha = ma+MUL(fd, *bdst.alpha, t);
+			*bdst.alpha = ma+CALC11(fd, *bdst.alpha, t);
 			bdst.alpha += bdst.delta;
 		}
 		bmask.alpha += bmask.delta;
@@ -1154,7 +1208,7 @@
 	Buffer obdst;
 	int fs, fd;
 	int i, ma, da, zero;
-	uint32 s, t;
+	uint32 t;
 
 	obdst = bdst;
 	zero = !(op&1);
@@ -1171,16 +1225,16 @@
 
 		if(grey){
 			if(ma)
-				*bdst.grey = MUL(fs, *bsrc.grey, s)+MUL(fd, *bdst.grey, t);
+				*bdst.grey = CALC12(fs, *bsrc.grey, fd, *bdst.grey, t);
 			else if(zero)
 				*bdst.grey = 0;
 			bsrc.grey += bsrc.delta;
 			bdst.grey += bdst.delta;
 		}else{
 			if(ma){
-				*bdst.red = MUL(fs, *bsrc.red, s)+MUL(fd, *bdst.red, t);
-				*bdst.grn = MUL(fs, *bsrc.grn, s)+MUL(fd, *bdst.grn, t);
-				*bdst.blu = MUL(fs, *bsrc.blu, s)+MUL(fd, *bdst.blu, t);
+				*bdst.red = CALC12(fs, *bsrc.red, fd, *bdst.red, t);
+				*bdst.grn = CALC12(fs, *bsrc.grn, fd, *bdst.grn, t);
+				*bdst.blu = CALC12(fs, *bsrc.blu, fd, *bdst.blu, t);
 			}
 			else if(zero)
 				*bdst.red = *bdst.grn = *bdst.blu = 0;
@@ -1194,7 +1248,7 @@
 		bmask.alpha += bmask.delta;
 		if(bdst.alpha != &ones){
 			if(ma)
-				*bdst.alpha = fs+MUL(fd, da, t);
+				*bdst.alpha = fs+CALC11(fd, da, t);
 			else if(zero)
 				*bdst.alpha = 0;
 			bdst.alpha += bdst.delta;
diff -r a18e9872164b src/9vx/x11/x11-itrans.c
--- a/src/9vx/x11/x11-itrans.c	Wed Dec 10 03:29:15 2008 -0800
+++ b/src/9vx/x11/x11-itrans.c	Mon Mar 09 16:29:39 2009 +0100
@@ -229,7 +229,7 @@
 	if(s & Button2Mask)
 		m->buttons |= 2;
 	if(s & Button3Mask)
-		m->buttons |= 4;
+		m->buttons |= s & ShiftMask ? 2 : 4;
 	if(s & Button4Mask)
 		m->buttons |= 8;
 	if(s & Button5Mask)

  reply	other threads:[~2009-03-09 15:32 UTC|newest]

Thread overview: 29+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-03-04 21:32 erik quanstrom
2009-03-04 21:37 ` andrey mirtchovski
2009-03-04 21:42   ` andrey mirtchovski
2009-03-04 21:44   ` erik quanstrom
2009-03-04 21:53     ` andrey mirtchovski
2009-03-04 22:03       ` erik quanstrom
2009-03-04 22:21         ` andrey mirtchovski
2009-03-04 22:22         ` Devon H. O'Dell
2009-03-04 22:45           ` andrey mirtchovski
2009-03-04 22:59             ` erik quanstrom
2009-03-04 23:05               ` andrey mirtchovski
2009-03-04 23:58             ` Charles Forsyth
2009-03-05  1:04               ` erik quanstrom
2009-03-05  1:29               ` andrey mirtchovski
2009-03-05  2:07                 ` andrey mirtchovski
2009-03-05  2:22                   ` erik quanstrom
2009-03-06  3:21                     ` andrey mirtchovski
2009-03-06 20:48                       ` Russ Cox
2009-03-06 21:42                         ` andrey mirtchovski
2009-03-08 22:33                           ` Jeff Sickel
2009-03-09 15:28                             ` Michaelian Ennis
2009-03-09 16:40                               ` Jeff Sickel
2009-03-09 14:00                         ` erik quanstrom
2009-03-09 15:32                           ` yy [this message]
2009-03-04 21:53 erik quanstrom
2009-03-04 22:01 ` andrey mirtchovski
2009-03-05 18:31 maht
2009-03-04 21:18 ` andrey mirtchovski
2009-03-04 23:24 ` Russ Cox

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=a81fe9be0903090832s6d6904a9o4db609297442e0f0@mail.gmail.com \
    --to=yiyu.jgl@gmail.com \
    --cc=9fans@9fans.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).