shithub: drawterm

Download patch

ref: df77799e3a82eb05bb5b8d11fedf34f8fd9e8167
parent: 17b41aefc5e3d3ab41cc202435061e4caf8011ac
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Sat Feb 27 22:09:06 EST 2016

import devdraw from 9front

--- a/gui-osx/screen.c
+++ b/gui-osx/screen.c
@@ -313,9 +313,9 @@
 		Rectangle rect =  { { 0, 0 },
  							{ bounds.size.width,
  							  bounds.size.height} };
-		drawqlock();
+		qlock(&drawlock);
  		flushmemscreen(rect);
- 		drawqunlock();
+ 		qunlock(&drawlock);
 	}
 }
 
@@ -331,9 +331,9 @@
 		Rectangle rect =  { { 0, 0 },
  							{ bounds.size.width,
  							  bounds.size.height} };
-		drawqlock();
+		qlock(&drawlock);
  		flushmemscreen(rect);
- 		drawqunlock();
+ 		qunlock(&drawlock);
 	}
 }
 
@@ -556,9 +556,9 @@
 				Rectangle rect =  { { 0, 0 },
  									{ bounds.size.width,
  									  bounds.size.height} };
-				drawqlock();
+				qlock(&drawlock);
  				flushmemscreen(rect);
- 				drawqunlock();
+ 				qunlock(&drawlock);
 				break;
 
 			default:
--- a/gui-x11/x11.c
+++ b/gui-x11/x11.c
@@ -163,7 +163,7 @@
 	int x, y;
 	uchar *p;
 
-	assert(!drawcanqlock());
+	assert(!canqlock(&drawlock));
 	if(r.min.x >= r.max.x || r.min.y >= r.max.y)
 		return;
 
@@ -193,9 +193,9 @@
 
 	memimageinit();
 	terminit();
-	drawqlock();
+	qlock(&drawlock);
 	flushmemscreen(gscreen->r);
-	drawqunlock();
+	qunlock(&drawlock);
 }
 
 uchar*
@@ -230,10 +230,10 @@
 void
 mouseset(Point xy)
 {
-	drawqlock();
+	qlock(&drawlock);
 	XWarpPointer(xdisplay, None, xdrawable, 0, 0, 0, 0, xy.x, xy.y);
 	XFlush(xdisplay);
-	drawqunlock();
+	qunlock(&drawlock);
 }
 
 static XCursor xcursor;
@@ -252,7 +252,7 @@
 		mask[i] = revbyte(cursor.set[i] | cursor.clr[i]);
 	}
 
-	drawqlock();
+	qlock(&drawlock);
 	fg = map[0];
 	bg = map[255];
 	xsrc = XCreateBitmapFromData(xdisplay, xdrawable, (char*)src, 16, 16);
@@ -267,13 +267,13 @@
 	XFreePixmap(xdisplay, xsrc);
 	XFreePixmap(xdisplay, xmask);
 	XFlush(xdisplay);
-	drawqunlock();
+	qunlock(&drawlock);
 }
 
 void
 cursorarrow(void)
 {
-	drawqlock();
+	qlock(&drawlock);
 	if(xcursor != 0){
 		XFreeCursor(xdisplay, xcursor);
 		xcursor = 0;
@@ -280,7 +280,7 @@
 	}
 	XUndefineCursor(xdisplay, xdrawable);
 	XFlush(xdisplay);
-	drawqunlock();
+	qunlock(&drawlock);
 }
 
 static void
@@ -716,7 +716,10 @@
 	r.min.y = xe->y;
 	r.max.x = xe->x + xe->width;
 	r.max.y = xe->y + xe->height;
-	drawflushr(r);
+
+	qlock(&drawlock);
+	flushmemscreen(r);
+	qunlock(&drawlock);
 }
 
 static void
--- a/kern/devdraw.c
+++ b/kern/devdraw.c
@@ -15,6 +15,7 @@
 {
 	Qtopdir		= 0,
 	Qnew,
+	Qwinname,
 	Q3rd,
 	Q2nd,
 	Qcolormap,
@@ -36,7 +37,7 @@
 
 #define	NHASH		(1<<5)
 #define	HASHMASK	(NHASH-1)
-#define	IOUNIT	(64*1024)
+#define	IOUNIT		(64*1024)
 
 typedef struct Client Client;
 typedef struct Draw Draw;
@@ -52,17 +53,15 @@
 
 struct Draw
 {
-	QLock	lk;
 	int		clientid;
 	int		nclient;
 	Client**	client;
 	int		nname;
-	DName*	name;
+	DName*		name;
 	int		vers;
 	int		softscreen;
 	int		blanked;	/* screen turned off */
 	ulong		blanktime;	/* time of last operation */
-	ulong		savemap[3*256];
 };
 
 struct Client
@@ -72,6 +71,7 @@
 	CScreen*	cscreen;
 	Refresh*	refresh;
 	Rendez		refrend;
+	QLock		refq;
 	uchar*		readdata;
 	int		nreaddata;
 	int		busy;
@@ -97,10 +97,10 @@
 
 struct DName
 {
-	char			*name;
-	Client	*client;
+	char		*name;
+	Client		*client;
 	DImage*		dimage;
-	int			vers;
+	int		vers;
 };
 
 struct FChar
@@ -130,7 +130,7 @@
 	int		nfchar;
 	FChar*		fchar;
 	DScreen*	dscreen;	/* 0 if not a window */
-	DImage*	fromname;	/* image this one is derived from, by name */
+	DImage*		fromname;	/* image this one is derived from, by name */
 	DImage*		next;
 };
 
@@ -145,8 +145,8 @@
 	int		id;
 	int		public;
 	int		ref;
-	DImage	*dimage;
-	DImage	*dfill;
+	DImage		*dimage;
+	DImage		*dfill;
 	Memscreen*	screen;
 	Client*		owner;
 	DScreen*	next;
@@ -153,8 +153,13 @@
 };
 
 static	Draw		sdraw;
+	QLock	drawlock;
+
 static	Memimage	*screenimage;
-static	Memdata	screendata;
+static	DImage*	screendimage;
+static	char	screenname[40];
+static	int	screennameid;
+
 static	Rectangle	flushrect;
 static	int		waste;
 static	DScreen*	dscreen;
@@ -163,6 +168,7 @@
 	void		drawuninstall(Client*, int);
 	void		drawfreedimage(DImage*);
 	Client*		drawclientofpath(ulong);
+	DImage*	allocdimage(Memimage*);
 
 static	char Enodrawimage[] =	"unknown id for draw image";
 static	char Enodrawscreen[] =	"unknown id for draw screen";
@@ -176,7 +182,6 @@
 static	char Enotfont[] =	"image not a font";
 static	char Eindex[] =		"character index out of range";
 static	char Enoclient[] =	"no such draw client";
-/* static	char Edepth[] =	"image has bad depth"; */
 static	char Enameused[] =	"image name in use";
 static	char Enoname[] =	"no image with that name";
 static	char Eoldname[] =	"named image no longer valid";
@@ -183,26 +188,20 @@
 static	char Enamed[] = 	"image already has name";
 static	char Ewrongname[] = 	"wrong name for image";
 
-int
-drawcanqlock(void)
+static void
+dlock(void)
 {
-	return canqlock(&sdraw.lk);
+	qlock(&drawlock);
 }
 
-void
-drawqlock(void)
+static void
+dunlock(void)
 {
-	qlock(&sdraw.lk);
+	qunlock(&drawlock);
 }
 
-void
-drawqunlock(void)
-{
-	qunlock(&sdraw.lk);
-}
-
 static int
-drawgen(Chan *c, char *name, Dirtab *dt, int ndt, int s, Dir *dp)
+drawgen(Chan *c, char *n, Dirtab *d, int nd, int s, Dir *dp)
 {
 	int t;
 	Qid q;
@@ -209,9 +208,9 @@
 	ulong path;
 	Client *cl;
 
-	USED(name);
-	USED(dt);
-	USED(ndt);
+	USED(n);
+	USED(d);
+	USED(nd);
 
 	q.vers = 0;
 
@@ -241,15 +240,17 @@
 	 * Top level directory contains the name of the device.
 	 */
 	t = QID(c->qid);
-	if(t == Qtopdir){
-		switch(s){
-		case 0:
+	if(t == Qtopdir || t == Qwinname){
+		if(s == 1 || t == Qwinname){
+			mkqid(&q, Qwinname, 0, QTFILE);
+			devdir(c, q, "winname", 0, eve, 0444, dp);
+		}
+		else if(s == 0){
 			mkqid(&q, Q2nd, 0, QTDIR);
 			devdir(c, q, "draw", 0, eve, 0555, dp);
-			break;
-		default:
-			return -1;
 		}
+		else
+			return -1;
 		return 1;
 	}
 
@@ -326,7 +327,7 @@
 
 static
 void
-drawrefresh(Memimage *m, Rectangle r, void *v)
+drawrefresh(Memimage *i, Rectangle r, void *v)
 {
 	Refx *x;
 	DImage *d;
@@ -333,7 +334,7 @@
 	Client *c;
 	Refresh *ref;
 
-	USED(m);
+	USED(i);
 
 	if(v == 0)
 		return;
@@ -360,9 +361,8 @@
 	int abb, ar, anbb;
 	Rectangle nbb;
 
-	if(sdraw.softscreen==0 || !rectclip(&r, screenimage->r))
+	if(sdraw.softscreen==0 || screenimage == nil || !rectclip(&r, screenimage->r))
 		return;
-
 	if(flushrect.min.x >= flushrect.max.x){
 		flushrect = r;
 		waste = 0;
@@ -408,14 +408,8 @@
 		combinerect(&flushrect, r);
 		return;
 	}
-	/* how can this happen? -rsc, dec 12 2002 */
-	if(dst == 0){
-		print("nil dstflush\n");
+	if(screenimage == nil || dst == nil || (l = dst->layer) == nil)
 		return;
-	}
-	l = dst->layer;
-	if(l == nil)
-		return;
 	do{
 		if(l->screen->image->data != screenimage->data)
 			return;
@@ -428,20 +422,11 @@
 void
 drawflush(void)
 {
-	if(flushrect.min.x < flushrect.max.x)
+	if(screenimage && flushrect.min.x < flushrect.max.x)
 		flushmemscreen(flushrect);
 	flushrect = Rect(10000, 10000, -10000, -10000);
 }
 
-void
-drawflushr(Rectangle r)
-{
-	qlock(&sdraw.lk);
-	flushmemscreen(r);
-	qunlock(&sdraw.lk);
-}
-
-static
 int
 drawcmp(char *a, char *b, int n)
 {
@@ -529,8 +514,8 @@
 	return 0;
 }
 
-Memimage*
-drawinstall(Client *client, int id, Memimage *i, DScreen *dscreen)
+DImage*
+allocdimage(Memimage *i)
 {
 	DImage *d;
 
@@ -537,7 +522,6 @@
 	d = malloc(sizeof(DImage));
 	if(d == 0)
 		return 0;
-	d->id = id;
 	d->ref = 1;
 	d->name = 0;
 	d->vers = 0;
@@ -545,6 +529,18 @@
 	d->nfchar = 0;
 	d->fchar = 0;
 	d->fromname = 0;
+	return d;
+}
+
+Memimage*
+drawinstall(Client *client, int id, Memimage *i, DScreen *dscreen)
+{
+	DImage *d;
+
+	d = allocdimage(i);
+	if(d == 0)
+		return 0;
+	d->id = id;
 	d->dscreen = dscreen;
 	d->next = client->dimage[id&HASHMASK];
 	client->dimage[id&HASHMASK] = d;
@@ -607,6 +603,7 @@
 {
 	int i;
 
+	free(name->name);
 	i = name-sdraw.name;
 	memmove(name, name+1, (sdraw.nname-(i+1))*sizeof(DName));
 	sdraw.nname--;
@@ -627,7 +624,7 @@
 		dscreen = this->next;
 		goto Found;
 	}
-	while((next = ds->next)){	/* assign = */
+	while(next = ds->next){	/* assign = */
 		if(next == this){
 			ds->next = this->next;
 			goto Found;
@@ -668,12 +665,10 @@
 		drawfreedimage(dimage->fromname);
 		goto Return;
 	}
-	if(dimage->image == screenimage)	/* don't free the display */
-		goto Return;
 	ds = dimage->dscreen;
 	if(ds){
 		l = dimage->image;
-		if(l->data == screenimage->data)
+		if(screenimage && l->data == screenimage->data)
 			addflush(l->layer->screenr);
 		if(l->layer->refreshfn == drawrefresh)	/* else true owner will clean up */
 			free(l->layer->refreshptr);
@@ -702,7 +697,7 @@
 		free(this);
 		return;
 	}
-	while((next = cs->next)){	/* assign = */
+	while(next = cs->next){	/* assign = */
 		if(next == this){
 			cs->next = this->next;
 			drawfreedscreen(this->dscreen);
@@ -726,7 +721,7 @@
 		drawfreedimage(d);
 		return;
 	}
-	while((next = d->next)){	/* assign = */
+	while(next = d->next){	/* assign = */
 		if(next->id == id){
 			d->next = next->next;
 			drawfreedimage(next);
@@ -867,12 +862,8 @@
 	p->y = BGLONG(a+1*4);
 }
 
-#define isvgascreen(dst) 1
-
-
 Point
-drawchar(Memimage *dst, Memimage *rdst, Point p, 
-	Memimage *src, Point *sp, DImage *font, int index, int op)
+drawchar(Memimage *dst, Memimage *rdst, Point p, Memimage *src, Point *sp, DImage *font, int index, int op)
 {
 	FChar *fc;
 	Rectangle r;
@@ -886,7 +877,7 @@
 	r.max.y = r.min.y+(fc->maxy-fc->miny);
 	sp1.x = sp->x+fc->left;
 	sp1.y = sp->y+fc->miny;
-	
+
 	/*
 	 * If we're drawing greyscale fonts onto a VGA screen,
 	 * it's very costly to read the screen memory to do the
@@ -895,7 +886,7 @@
 	 * refer to for the underlying dst pixels instead of reading dst
 	 * directly.
 	 */
-	if(1 || (isvgascreen(dst) && !isvgascreen(rdst) /*&& font->image->depth > 1*/)){
+	if(ishwimage(dst) && !ishwimage(rdst) && font->image->depth > 1){
 		if(tmp == nil || tmp->chan != dst->chan || Dx(tmp->r) < Dx(r) || Dy(tmp->r) < Dy(r)){
 			if(tmp)
 				freememimage(tmp);
@@ -916,30 +907,69 @@
 	return p;
 }
 
-static int
-initscreenimage(void)
+static DImage*
+makescreenimage(void)
 {
 	int width, depth;
 	ulong chan;
+	DImage *di;
+	Memdata *md;
+	Memimage *i;
 	Rectangle r;
+	uchar *data;
 
-	if(screenimage != nil)
-		return 1;
+	if((data = attachscreen(&r, &chan, &depth, &width, &sdraw.softscreen)) == nil)
+		return nil;
+	if(sdraw.softscreen == 0xa110c){
+		/* hack: softscreen is memimage. */
+		md = *((Memdata**)(data - sizeof(ulong) - sizeof(Memdata*)));
 
-	screendata.base = nil;
-	screendata.bdata = attachscreen(&r, &chan, &depth, &width, &sdraw.softscreen);
-	if(screendata.bdata == nil)
-		return 0;
-	screendata.ref = 1;
+		assert(md->bdata == data);
+		assert(md->ref > 1);
+		assert(md->allocd);
 
-	screenimage = allocmemimaged(r, chan, &screendata);
-	if(screenimage == nil){
-		/* RSC: BUG: detach screen */
-		return 0;
+		if((i = allocmemimaged(r, chan, md)) == nil){
+			md->ref--;
+			return nil;
+		}
+	}else{
+		if((md = malloc(sizeof *md)) == nil)
+			return nil;
+		md->allocd = 1;
+		md->base = nil;
+		md->bdata = data;
+		md->ref = 1;
+		if((i = allocmemimaged(r, chan, md)) == nil){
+			free(md);
+			return nil;
+		}
 	}
+	i->width = width;
+	i->clipr = r;
+	di = allocdimage(i);
+	if(di == nil){
+		freememimage(i);	/* frees md */
+		return nil;
+	}
+	if(!waserror()){
+		snprint(screenname, sizeof screenname, "noborder.screen.%d", ++screennameid);
+		drawaddname(nil, di, strlen(screenname), screenname);
+		poperror();
+	}
+	return di;
+}
 
-	screenimage->width = width;
-	screenimage->clipr = r;
+static int
+initscreenimage(void)
+{
+	if(screenimage != nil)
+		return 1;
+
+	screendimage = makescreenimage();
+	if(screendimage == nil)
+		return 0;
+	screenimage = screendimage->image;
+// iprint("initscreenimage %p %p\n", screendimage, screenimage);
 	return 1;
 }
 
@@ -946,23 +976,36 @@
 void
 deletescreenimage(void)
 {
-	qlock(&sdraw.lk);
-	/* RSC: BUG: detach screen */
-	if(screenimage)
-		freememimage(screenimage);
-	screenimage = nil;
-	qunlock(&sdraw.lk);
+	dlock();
+	if(screenimage){
+		/* will be freed via screendimage; disable */
+		screenimage->clipr = ZR;
+		screenimage = nil;
+	}
+	if(screendimage){
+		drawfreedimage(screendimage);
+		screendimage = nil;
+	}
+	dunlock();
 }
 
+void
+resetscreenimage(void)
+{
+	dlock();
+	initscreenimage();
+	dunlock();
+}
+
 static Chan*
 drawattach(char *spec)
 {
-	qlock(&sdraw.lk);
+	dlock();
 	if(!initscreenimage()){
-		qunlock(&sdraw.lk);
+		dunlock();
 		error("no frame buffer");
 	}
-	qunlock(&sdraw.lk);
+	dunlock();
 	return devattach('i', spec);
 }
 
@@ -969,7 +1012,7 @@
 static Walkqid*
 drawwalk(Chan *c, Chan *nc, char **name, int nname)
 {
-	if(screendata.bdata == nil)
+	if(screenimage == nil)
 		error("no frame buffer");
 	return devwalk(c, nc, name, nname, 0, 0, drawgen);
 }
@@ -984,6 +1027,8 @@
 drawopen(Chan *c, int omode)
 {
 	Client *cl;
+	DName *dn;
+	DImage *di;
 
 	if(c->qid.type & QTDIR){
 		c = devopen(c, omode, 0, 0, drawgen);
@@ -990,9 +1035,9 @@
 		c->iounit = IOUNIT;
 	}
 
-	qlock(&sdraw.lk);
+	dlock();
 	if(waserror()){
-		qunlock(&sdraw.lk);
+		dunlock();
 		nexterror();
 	}
 
@@ -1004,6 +1049,9 @@
 	}
 
 	switch(QID(c->qid)){
+	case Qwinname:
+		break;
+
 	case Qnew:
 		break;
 
@@ -1013,9 +1061,22 @@
 			error(Einuse);
 		cl->busy = 1;
 		flushrect = Rect(10000, 10000, -10000, -10000);
-		drawinstall(cl, 0, screenimage, 0);
+		dn = drawlookupname(strlen(screenname), screenname);
+		if(dn == 0)
+			error("draw: cannot happen 2");
+		if(drawinstall(cl, 0, dn->dimage->image, 0) == 0)
+			error(Edrawmem);
+		di = drawlookup(cl, 0, 0);
+		if(di == 0)
+			error("draw: cannot happen 1");
+		di->vers = dn->vers;
+		di->name = smalloc(strlen(screenname)+1);
+		strcpy(di->name, screenname);
+		di->fromname = dn->dimage;
+		di->fromname->ref++;
 		incref(&cl->r);
 		break;
+
 	case Qcolormap:
 	case Qdata:
 	case Qrefresh:
@@ -1023,7 +1084,7 @@
 		incref(&cl->r);
 		break;
 	}
-	qunlock(&sdraw.lk);
+	dunlock();
 	poperror();
 	c->mode = openmode(omode);
 	c->flag |= COPEN;
@@ -1042,9 +1103,9 @@
 
 	if(QID(c->qid) < Qcolormap)	/* Qtopdir, Qnew, Q3rd, Q2nd have no client */
 		return;
-	qlock(&sdraw.lk);
+	dlock();
 	if(waserror()){
-		qunlock(&sdraw.lk);
+		dunlock();
 		nexterror();
 	}
 
@@ -1052,7 +1113,7 @@
 	if(QID(c->qid) == Qctl)
 		cl->busy = 0;
 	if((c->flag&COPEN) && (decref(&cl->r)==0)){
-		while((r = cl->refresh)){	/* assign = */
+		while(r = cl->refresh){	/* assign = */
 			cl->refresh = r->next;
 			free(r);
 		}
@@ -1077,7 +1138,7 @@
 		drawflush();	/* to erase visible, now dead windows */
 		free(cl);
 	}
-	qunlock(&sdraw.lk);
+	dunlock();
 	poperror();
 }
 
@@ -1096,10 +1157,13 @@
 
 	if(c->qid.type & QTDIR)
 		return devdirread(c, a, n, 0, 0, drawgen);
+	if(QID(c->qid) == Qwinname)
+		return readstr(off, a, n, screenname);
+
 	cl = drawclient(c);
-	qlock(&sdraw.lk);
+	dlock();
 	if(waserror()){
-		qunlock(&sdraw.lk);
+		dunlock();
 		nexterror();
 	}
 	switch(QID(c->qid)){
@@ -1118,15 +1182,15 @@
 				error(Enodrawimage);
 			i = di->image;
 		}
-		n = sprint(a, "%11d %11d %11s %11d %11d %11d %11d %11d %11d %11d %11d %11d ",
+		n = sprint(a, "%11d %11d %11s %11d %11d %11d %11d %11d %11d %11d %11d %11d",
 			cl->clientid, cl->infoid, chantostr(buf, i->chan), (i->flags&Frepl)==Frepl,
 			i->r.min.x, i->r.min.y, i->r.max.x, i->r.max.y,
 			i->clipr.min.x, i->clipr.min.y, i->clipr.max.x, i->clipr.max.y);
+		((char*)a)[n++] = ' ';
 		cl->infoid = -1;
 		break;
 
 	case Qcolormap:
-		drawactive(1);	/* to restore map from backup */
 		p = malloc(4*12*256+1);
 		if(p == 0)
 			error(Enomem);
@@ -1156,14 +1220,21 @@
 		for(;;){
 			if(cl->refreshme || cl->refresh)
 				break;
-			qunlock(&sdraw.lk);
+			dunlock();
 			if(waserror()){
-				qlock(&sdraw.lk);	/* restore lock for waserror() above */
+				dlock();
 				nexterror();
 			}
+			qlock(&cl->refq);
+			if(waserror()){
+				qunlock(&cl->refq);
+				nexterror();
+			}
 			sleep(&cl->refrend, drawrefactive, cl);
 			poperror();
-			qlock(&sdraw.lk);
+			qunlock(&cl->refq);
+			poperror();
+			dlock();
 		}
 		p = a;
 		while(cl->refresh && n>=5*4){
@@ -1180,8 +1251,9 @@
 		}
 		cl->refreshme = 0;
 		n = p-(uchar*)a;
+		break;
 	}
-	qunlock(&sdraw.lk);
+	dunlock();
 	poperror();
 	return n;
 }
@@ -1200,21 +1272,21 @@
 }
 
 static long
-drawwrite(Chan *c, void *a, long n, vlong offset)
+drawwrite(Chan *c, void *a, long n, vlong off)
 {
 	char buf[128], *fields[4], *q;
 	Client *cl;
 	int i, m, red, green, blue, x;
 
-	USED(offset);
+	USED(off);
 
 	if(c->qid.type & QTDIR)
 		error(Eisdir);
 	cl = drawclient(c);
-	qlock(&sdraw.lk);
+	dlock();
 	if(waserror()){
 		drawwakeall();
-		qunlock(&sdraw.lk);
+		dunlock();
 		nexterror();
 	}
 	switch(QID(c->qid)){
@@ -1225,7 +1297,6 @@
 		break;
 
 	case Qcolormap:
-		drawactive(1);	/* to restore map from backup */
 		m = n;
 		n = 0;
 		while(m > 0){
@@ -1268,7 +1339,7 @@
 	default:
 		error(Ebadusefd);
 	}
-	qunlock(&sdraw.lk);
+	dunlock();
 	poperror();
 	return n;
 }
@@ -1306,14 +1377,6 @@
 	int s;
 
 	if(1|| plsprnt==0){
-		SET(s);
-		SET(q);
-		SET(p);
-		USED(fmt);
-		USED(a);
-		p = buf;
-		USED(p);
-		USED(q);
 		USED(s);
 		return;
 	}
@@ -1364,7 +1427,7 @@
 	ulong value, chan;
 	Rectangle r, clipr;
 	Point p, q, *pp, sp;
-	Memimage *i, *dst, *src, *mask;
+	Memimage *i, *bg, *dst, *src, *mask;
 	Memimage *l, **lp;
 	Memscreen *scrn;
 	DImage *font, *ll, *di, *ddst, *dsrc;
@@ -1396,7 +1459,7 @@
 			if(n < m)
 				error(Eshortdraw);
 			dstid = BGLONG(a+1);
-			scrnid = BGSHORT(a+5);
+			scrnid = BGLONG(a+5);
 			refresh = a[9];
 			chan = BGLONG(a+10);
 			repl = a[14];
@@ -1410,7 +1473,7 @@
 				scrn = dscrn->screen;
 				if(repl || chan!=scrn->image->chan)
 					error("image parameters incompatible with screen");
-				reffn = 0;
+				reffn = nil;
 				switch(refresh){
 				case Refbackup:
 					break;
@@ -1493,7 +1556,7 @@
 			if(ddst == nil)
 				error(Enodrawimage);
 			if(ddst->name)
-				error("can't change repl/clipr of shared image");
+				error("cannot change repl/clipr of shared image");
 			dst = ddst->image;
 			if(a[5])
 				dst->flags |= Frepl;
@@ -1553,9 +1616,9 @@
 			oy = BGLONG(a+41);
 			op = drawclientop(client);
 			/* high bit indicates arc angles are present */
-			if(ox & (1U<<31)){
+			if(ox & (1<<31)){
 				if((ox & (1<<30)) == 0)
-					ox &= ~(1U<<31);
+					ox &= ~(1<<31);
 				memarc(dst, p, e0, e1, c, src, sp, ox, oy, op);
 			}else
 				memellipse(dst, p, e0, e1, c, src, sp, op);
@@ -1592,12 +1655,12 @@
 				error(Eshortdraw);
 			dstid = BGLONG(a+1);
 			if(dstid == 0)
-				error("can't use display as font");
+				error("cannot use display as font");
 			font = drawlookup(client, dstid, 1);
 			if(font == 0)
 				error(Enodrawimage);
 			if(font->image->layer)
-				error("can't use window as font");
+				error("cannot use window as font");
 			ni = BGLONG(a+5);
 			if(ni<=0 || ni>4096)
 				error("bad font size (4096 chars max)");
@@ -1698,7 +1761,7 @@
 				error(Edrawmem);
 			di = drawlookup(client, dstid, 0);
 			if(di == 0)
-				error("draw: can't happen");
+				error("draw: cannot happen");
 			di->vers = dn->vers;
 			di->name = smalloc(j+1);
 			di->fromname = dn->dimage;
@@ -1799,7 +1862,7 @@
 			if(pp == nil)
 				error(Enomem);
 			doflush = 0;
-			if(dstid==0 || (dst->layer && dst->layer->screen->image->data == screenimage->data))
+			if(dstid==0 || (screenimage && dst->layer && dst->layer->screen->image->data == screenimage->data))
 				doflush = 1;	/* simplify test in loop */
 			ox = oy = 0;
 			esize = 0;
@@ -1901,10 +1964,10 @@
 			clipr = dst->clipr;
 			dst->clipr = r;
 			op = drawclientop(client);
-			l = dst;
+			bg = dst;
 			if(*a == 'x'){
 				/* paint background */
-				l = drawimage(client, a+47);
+				bg = drawimage(client, a+47);
 				drawpoint(&q, a+51);
 				r.min.x = p.x;
 				r.min.y = p.y-font->ascent;
@@ -1920,7 +1983,7 @@
 					r.max.x += font->fchar[ci].width;
 					u += 2;
 				}
-				memdraw(dst, r, l, q, memopaque, ZP, op);
+				memdraw(dst, r, bg, q, memopaque, ZP, op);
 				u -= 2*ni;
 			}
 			q = p;
@@ -1930,7 +1993,7 @@
 					dst->clipr = clipr;
 					error(Eindex);
 				}
-				q = drawchar(dst, l, q, src, &sp, font, ci, op);
+				q = drawchar(dst, bg, q, src, &sp, font, ci, op);
 				u += 2;
 			}
 			dst->clipr = clipr;
@@ -1988,7 +2051,7 @@
 				memltofrontn(lp, nw);
 			else
 				memltorearn(lp, nw);
-			if(lp[0]->layer->screen->image->data == screenimage->data)
+			if(screenimage && lp[0]->layer->screen->image->data == screenimage->data)
 				for(j=0; j<nw; j++)
 					addflush(lp[j]->layer->screenr);
 			ll = drawlookup(client, BGLONG(a+1+1+2), 1);
@@ -2060,7 +2123,6 @@
 	int num, den;
 	int i, j;
 
-	drawactive(1);	/* to restore map from backup */
 	for(r=0,i=0; r!=4; r++)
 	    for(v=0; v!=4; v++,i+=16){
 		for(g=0,j=v-r; g!=4; g++)
@@ -2083,65 +2145,3 @@
 		    }
 	}
 }
-
-void
-drawblankscreen(int blank)
-{
-	int i, nc;
-	ulong *p;
-
-	if(blank == sdraw.blanked)
-		return;
-	if(!canqlock(&sdraw.lk))
-		return;
-	if(!initscreenimage()){
-		qunlock(&sdraw.lk);
-		return;
-	}
-	p = sdraw.savemap;
-	nc = screenimage->depth > 8 ? 256 : 1<<screenimage->depth;
-
-	/*
-	 * blankscreen uses the hardware to blank the screen
-	 * when possible.  to help in cases when it is not possible,
-	 * we set the color map to be all black.
-	 */
-	if(blank == 0){	/* turn screen on */
-		for(i=0; i<nc; i++, p+=3)
-			setcolor(i, p[0], p[1], p[2]);
-	//	blankscreen(0);
-	}else{	/* turn screen off */
-	//	blankscreen(1);
-		for(i=0; i<nc; i++, p+=3){
-			getcolor(i, &p[0], &p[1], &p[2]);
-			setcolor(i, 0, 0, 0);
-		}
-	}
-	sdraw.blanked = blank;
-	qunlock(&sdraw.lk);
-}
-
-/*
- * record activity on screen, changing blanking as appropriate
- */
-void
-drawactive(int active)
-{
-/*
-	if(active){
-		drawblankscreen(0);
-		sdraw.blanktime = MACHP(0)->ticks;
-	}else{
-		if(blanktime && sdraw.blanktime && TK2SEC(MACHP(0)->ticks - sdraw.blanktime)/60 >= blanktime)
-			drawblankscreen(1);
-	}
-*/
-}
-
-int
-drawidletime(void)
-{
-	return 0;
-/*	return TK2SEC(MACHP(0)->ticks - sdraw.blanktime)/60; */
-}
-
--- a/kern/fns.h
+++ b/kern/fns.h
@@ -77,11 +77,7 @@
 int		devstat(Chan*, uchar*, int, Dirtab*, int, Devgen*);
 Walkqid*	devwalk(Chan*, Chan*, char**, int, Dirtab*, int, Devgen*);
 int		devwstat(Chan*, uchar*, int);
-void		drawactive(int);
 void		drawcmap(void);
-int		drawcanqlock(void);
-void		drawqlock(void);
-void		drawqunlock(void);
 void		dumpaproc(Proc*);
 void		dumpqueues(void);
 void		dumpregs(Ureg*);
--- a/kern/screen.h
+++ b/kern/screen.h
@@ -48,16 +48,13 @@
 void	getcolor(ulong, ulong*, ulong*, ulong*);
 void	setcolor(ulong, ulong, ulong, ulong);
 
-void	refreshrect(Rectangle);
-
 void	cursorarrow(void);
 void	setcursor(void);
 void	mouseset(Point);
-void	drawflushr(Rectangle);
 void	flushmemscreen(Rectangle);
-uchar *attachscreen(Rectangle*, ulong*, int*, int*, int*);
+uchar*	attachscreen(Rectangle*, ulong*, int*, int*, int*);
 
-void	drawqlock(void);
-void	drawqunlock(void);
-int	drawcanqlock(void);
+extern	QLock drawlock;
+#define	ishwimage(i)	1
+
 void	terminit(void);
--- a/kern/term.c
+++ b/kern/term.c
@@ -34,8 +34,10 @@
 static void
 screenflush(void)
 {
-	drawflushr(flushr);
+	qlock(&drawlock);
+	flushmemscreen(flushr);
 	flushr = Rect(10000, 10000, -10000, -10000);
+	qunlock(&drawlock);
 }
 
 static void
@@ -54,7 +56,7 @@
 	char *greet;
 	Memimage *grey;
 
-	drawqlock();
+	qlock(&drawlock);
 	back = memwhite;
 	conscol = memblack;
 	memfillcolor(gscreen, 0x444488FF);
@@ -86,7 +88,7 @@
 	curpos = window.min;
 	window.max.y = window.min.y+((window.max.y-window.min.y)/h)*h;
 	flushmemscreen(gscreen->r);
-	drawqunlock();
+	qunlock(&drawlock);
 }
 
 void
@@ -184,7 +186,7 @@
 	char buf[4];
 
 	lock(&screenlock);
-	locked = drawcanqlock();
+	locked = canqlock(&drawlock);
 	while(n > 0){
 		i = chartorune(&r, s);
 		if(i == 0){
@@ -199,7 +201,7 @@
 		screenputc(buf);
 	}
 	if(locked)
-		drawqunlock();
+		qunlock(&drawlock);
 	screenflush();
 	unlock(&screenlock);
 }