code: plan9front

Download patch

ref: 5f4e2670b4d8eb3cd1faed9808c3d0747284a288
parent: 26e4a18e7060b0300f57f6592e3440b5e0a4aea1
author: Jacob Moody <moody@posixcafe.org>
date: Mon Sep 18 19:36:13 EDT 2023

eui: draw in seperate proc

copied from doom.

--- a/sys/src/games/eui.c
+++ b/sys/src/games/eui.c
@@ -22,6 +22,9 @@
 static int vwdx, vwdy, vwbpp;
 static ulong vwchan;
 static Image *fb;
+static Channel *conv, *sync[2];
+static uchar *screenconv[2];
+static int screenconvi;
 
 struct Kfn{
 	Rune r;
@@ -188,6 +191,7 @@
 {
 	Point p;
 
+	send(sync[0], nil);
 	if(!fixscale){
 		scale = Dx(screen->r) / vwdx;
 		if(Dy(screen->r) / vwdy < scale)
@@ -205,7 +209,12 @@
 		vwchan, scale > 1, 0);
 	free(pic);
 	pic = emalloc(vwdx * vwdy * vwbpp * scale);
-	draw(screen, screen->r, bg, nil, ZP);	
+	free(screenconv[0]);
+	free(screenconv[1]);
+	screenconv[0] = emalloc(vwdx * vwdy * vwbpp * scale);
+	screenconv[1] = emalloc(vwdx * vwdy * vwbpp * scale);
+	draw(screen, screen->r, bg, nil, ZP);
+	recv(sync[1], nil);
 }
 
 void
@@ -214,8 +223,10 @@
 	Mouse m;
 
 	if(nbrecvul(mc->resizec) > 0){
+		send(sync[0], nil);
 		if(getwindow(display, Refnone) < 0)
 			sysfatal("resize failed: %r");
+		recv(sync[1], nil);
 		screeninit();
 	}
 	if(discard)
@@ -223,29 +234,60 @@
 			;
 }
 
-void
-flushscreen(void)
+static void
+screenproc(void*)
 {
-	if(scale == 1){
-		loadimage(fb, fb->r, pic, vwdx * vwdy * vwbpp);
-		draw(screen, picr, fb, nil, ZP);
-	} else {
-		Rectangle r;
-		uchar *s;
-		int w;
+	uchar *p;
+	enum { Draw, Sync1, Sync2 };
+	Alt alts[] = {
+		[Draw]	{.c = conv, .v = &p, .op = CHANRCV},
+		[Sync1]	{.c = sync[0], .op = CHANRCV},
+		[Sync2]	{.c = sync[1], .op = CHANNOP},
+		{.op = CHANEND},
+	};
 
-		s = pic;
-		r = picr;
-		w = vwdx * vwbpp * scale;
-		while(r.min.y < picr.max.y){
-			loadimage(fb, fb->r, s, w);
-			s += w;
-			r.max.y = r.min.y+scale;
-			draw(screen, r, fb, nil, ZP);
-			r.min.y = r.max.y;
+	for(;;) switch(alt(alts)){
+	case Draw:
+		if(scale == 1){
+			loadimage(fb, fb->r, p, vwdx * vwdy * vwbpp);
+			draw(screen, picr, fb, nil, ZP);
+		} else {
+			Rectangle r;
+			uchar *s;
+			int w;
+	
+			s = p;
+			r = picr;
+			w = vwdx * vwbpp * scale;
+			while(r.min.y < picr.max.y){
+				loadimage(fb, fb->r, s, w);
+				s += w;
+				r.max.y = r.min.y+scale;
+				draw(screen, r, fb, nil, ZP);
+				r.min.y = r.max.y;
+			}
 		}
+		flushimage(display, 1);
+		break;
+	case Sync1:
+		alts[Draw].op = CHANNOP;
+		alts[Sync1].op = CHANNOP;
+		alts[Sync2].op = CHANSND;
+		break;
+	case Sync2:
+		alts[Draw].op = CHANRCV;
+		alts[Sync1].op = CHANRCV;
+		alts[Sync2].op = CHANNOP;
+		break;
 	}
-	flushimage(display, 1);
+}
+
+void
+flushscreen(void)
+{
+	memmove(screenconv[screenconvi], pic, vwdx * vwdy * vwbpp * scale);
+	if(sendp(conv, screenconv[screenconvi]) > 0)
+		screenconvi = (screenconvi + 1) % 2;
 	if(profile)
 		timing();
 }
@@ -324,5 +366,9 @@
 		proccreate(joyproc, nil, mainstacksize);
 	bg = allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, 0xCCCCCCFF);
 	scale = fixscale;
+	conv = chancreate(sizeof(uchar*), 0);
+	sync[0] = chancreate(1, 0);
+	sync[1] = chancreate(1, 0);
+	proccreate(screenproc, nil, mainstacksize);
 	screeninit();
 }