shithub: riscv

Download patch

ref: 1fe3143e4c43ce2c74e0cfdd70b1bd556bbb9e1b
parent: 7b309d2e280675b6ce39f9b53cef6577e295c4f4
author: cinap_lenrek <[email protected]>
date: Fri Apr 10 13:12:51 EDT 2020

kernel: cleanup the software mouse cursor mess

The swcursor used a 32x32 image for saving/restoring
screen contents for no reason.

Add a doflush argument to swcursorhide(), so that
disabling software cursor with a double buffered
softscreen is properly hidden. The doflush parameter
should be set to 0 in all other cases as swcursordraw()
will flushes both (current and previours) locations.

Make sure swcursorinit() and swcursorhide() clear the
visibility flag, even when gscreen is nil.

Remove the cursor locking and just do everything within
the drawlock. All cursor functions such as curson(),
cursoff() and setcursor() will be called drawlock
locked. This also means &cursor can be read.

Fix devmouse cursor reads and writes. We now have the
global cursor variable that is only modified under
the drawlock. So copy under drawlock.

Move the pc software cursor implementation into vgasoft
driver, so screen.c does not need to handle it as
a special case.

Remove unused functions such as drawhasclients().

--- a/sys/src/9/bcm/screen.c
+++ b/sys/src/9/bcm/screen.c
@@ -55,28 +55,21 @@
 static void screenputc(char *buf);
 static void screenwin(void);
 
+/* called from devmouse */
+
 void
 cursoron(void)
 {
-	qlock(&drawlock);
-	lock(&cursor);
-	swcursorhide();
+	swcursorhide(0);
 	swcursordraw(mousexy());
-	unlock(&cursor);
-	qunlock(&drawlock);
 }
 
 void
 cursoroff(void)
 {
-	qlock(&drawlock);
-	lock(&cursor);
-	swcursorhide();
-	unlock(&cursor);
-	qunlock(&drawlock);
+	swcursorhide(0);
 }
 
-/* called from devmouse */
 void
 setcursor(Cursor* curs)
 {
--- a/sys/src/9/bcm/screen.h
+++ b/sys/src/9/bcm/screen.h
@@ -1,11 +1,6 @@
-typedef struct Cursor Cursor;
-typedef struct Cursorinfo Cursorinfo;
-struct Cursorinfo {
-	Cursor;
-	Lock;
-};
-
 /* devmouse.c */
+typedef struct Cursor Cursor;
+extern Cursor cursor;
 extern void mousetrack(int, int, int, ulong);
 extern void absmousetrack(int, int, int, ulong);
 extern Point mousexy(void);
@@ -15,9 +10,6 @@
 extern int m5mouseputc(Queue*, int);
 extern int mouseputc(Queue*, int);
 
-extern Cursorinfo cursor;
-extern Cursor arrow;
-
 /* mouse.c */
 extern void mousectl(Cmdbuf*);
 extern void mouseresize(void);
@@ -37,7 +29,7 @@
 #define ishwimage(i)	1		/* for ../port/devdraw.c */
 
 /* swcursor.c */
-void		swcursorhide(void);
+void		swcursorhide(int);
 void		swcursoravoid(Rectangle);
 void		swcursordraw(Point);
 void		swcursorload(Cursor *);
--- a/sys/src/9/omap/screen.c
+++ b/sys/src/9/omap/screen.c
@@ -189,24 +189,6 @@
 static	void	screenputc(char *buf);
 static	void	screenwin(void);
 
-/*
- * Software cursor. 
- */
-int	swvisible;	/* is the cursor visible? */
-int	swenabled;	/* is the cursor supposed to be on the screen? */
-Memimage*	swback;	/* screen under cursor */
-Memimage*	swimg;	/* cursor image */
-Memimage*	swmask;	/* cursor mask */
-Memimage*	swimg1;
-Memimage*	swmask1;
-
-Point	swoffset;
-Rectangle	swrect;	/* screen rectangle in swback */
-Point	swpt;	/* desired cursor location */
-Point	swvispt;	/* actual cursor location */
-int	swvers;	/* incremented each time cursor image changes */
-int	swvisvers;	/* the version on the screen */
-
 static void
 lcdoff(void)
 {
@@ -330,28 +312,21 @@
 	blankscreen(on == 0);
 }
 
+/* called from devmouse */
+
 void
 cursoron(void)
 {
-	qlock(&drawlock);
-	lock(&cursor);
-	swcursorhide();
+	swcursorhide(0);
 	swcursordraw(mousexy());
-	unlock(&cursor);
-	qunlock(&drawlock);
 }
 
 void
 cursoroff(void)
 {
-	qlock(&drawlock);
-	lock(&cursor);
-	swcursorhide();
-	unlock(&cursor);
-	qunlock(&drawlock);
+	swcursorhide(0);
 }
 
-/* called from devmouse */
 void
 setcursor(Cursor* curs)
 {
@@ -404,10 +379,7 @@
 		iprint("screen: frame buffer at %#p for %dx%d\n",
 			framebuf, oscreen.settings->wid, oscreen.settings->ht);
 
-		swenabled = 1;
 		swcursorinit();		/* needs gscreen set */
-		setcursor(&arrow);
-
 		first = 0;
 	}
 }
--- a/sys/src/9/omap/screen.h
+++ b/sys/src/9/omap/screen.h
@@ -1,22 +1,13 @@
 typedef struct Cursor Cursor;
-typedef struct Cursorinfo	Cursorinfo;
 typedef struct OScreen OScreen;
 typedef struct Omap3fb Omap3fb;
 typedef struct Settings Settings;
 
-struct Cursorinfo
-{
-	Cursor;
-	Lock;
-};
-
-extern Cursor	arrow;
-extern Cursorinfo cursor;
-
 /* devmouse.c */
-extern void mousetrack(int, int, int, ulong);
-extern void absmousetrack(int, int, int, ulong);
-extern Point mousexy(void);
+extern Cursor	cursor;
+extern void	mousetrack(int, int, int, ulong);
+extern void	absmousetrack(int, int, int, ulong);
+extern Point	mousexy(void);
 
 extern void	mouseaccelerate(int);
 extern void	mouseresize(void);
@@ -33,15 +24,9 @@
 extern Rectangle physgscreenr;	/* actual monitor size */
 extern void	blankscreen(int);
 
-extern void swcursorinit(void);
-extern void swcursorhide(void);
-extern void swcursoravoid(Rectangle);
-extern void swcursorunhide(void);
-
 /* devdraw.c */
 extern void	deletescreenimage(void);
 extern void	resetscreenimage(void);
-extern int		drawhasclients(void);
 extern void	setscreenimageclipr(Rectangle);
 extern void	drawflush(void);
 extern QLock	drawlock;
@@ -49,7 +34,7 @@
 #define ishwimage(i)	0		/* for ../port/devdraw.c */
 
 /* swcursor.c */
-void		swcursorhide(void);
+void		swcursorhide(int);
 void		swcursoravoid(Rectangle);
 void		swcursordraw(Point);
 void		swcursorload(Cursor *);
--- a/sys/src/9/pc/devvga.c
+++ b/sys/src/9/pc/devvga.c
@@ -233,36 +233,28 @@
 		if(scr->gscreen == nil)
 			error(Enoscreen);
 		if(strcmp(cb->f[1], "off") == 0){
-			lock(&cursor);
+			qlock(&drawlock);
+			cursoroff();
 			if(scr->cur){
 				if(scr->cur->disable)
 					scr->cur->disable(scr);
 				scr->cur = nil;
 			}
-			unlock(&cursor);
+			qunlock(&drawlock);
 			return;
 		}
-		if(strcmp(cb->f[1], "soft") == 0){
-			lock(&cursor);
-			swcursorinit();
-			if(scr->cur && scr->cur->disable)
-				scr->cur->disable(scr);
-			scr->cur = &swcursor;
-			if(scr->cur->enable)
-				scr->cur->enable(scr);
-			unlock(&cursor);
-			return;
-		}
 		for(i = 0; vgacur[i]; i++){
 			if(strcmp(cb->f[1], vgacur[i]->name))
 				continue;
-			lock(&cursor);
+			qlock(&drawlock);
+			cursoroff();
 			if(scr->cur && scr->cur->disable)
 				scr->cur->disable(scr);
 			scr->cur = vgacur[i];
 			if(scr->cur->enable)
 				scr->cur->enable(scr);
-			unlock(&cursor);
+			cursoron();
+			qunlock(&drawlock);
 			return;
 		}
 		break;
@@ -319,7 +311,6 @@
 			error("bad channel");
 		if(chantodepth(chan) != z)
 			error("depth, channel do not match");
-		cursoroff();
 		deletescreenimage();
 		if(screensize(x, y, z, chan))
 			error(Egreg);
@@ -338,7 +329,6 @@
 			error(Ebadarg);
 		if(!rectinrect(r, scr->gscreen->r))
 			error("physical screen bigger than virtual");
-		cursoroff();
 		deletescreenimage();
 		physgscreenr = r;
 		goto Resized;
@@ -364,7 +354,6 @@
 		y = scr->gscreen->r.max.y;
 		z = scr->gscreen->depth;
 		chan = scr->gscreen->chan;
-		cursoroff();
 		deletescreenimage();
 		if(screensize(x, y, z, chan))
 			error(Egreg);
@@ -381,7 +370,6 @@
 		scr->gscreen->clipr = panning ? scr->gscreen->r : physgscreenr;
 		vgascreenwin(scr);
 		resetscreenimage();
-		cursoron();
 		return;
 
 	case CMlinear:
@@ -410,7 +398,6 @@
 			break;
 		if(scr->gscreen == nil)
 			return;
-		cursoroff();
 		deletescreenimage();
 		goto Resized;
 
--- a/sys/src/9/pc/pc
+++ b/sys/src/9/pc/pc
@@ -24,7 +24,7 @@
 	bridge		netif log
 	ip		arp chandial ip ipv6 ipaux iproute netlog nullmedium pktmedium inferno
 
-	draw		screen vga vgax swcursor
+	draw		screen vga vgax vgasoft
 	mouse		mouse
 	kbd
 	vga
@@ -114,6 +114,7 @@
 	uartisa
 	uartpci		pci
 
+	vgasoft		=cur swcursor
 	vga3dfx		+cur
 	vgaark2000pv	+cur
 	vgabt485	=cur
--- a/sys/src/9/pc/screen.c
+++ b/sys/src/9/pc/screen.c
@@ -13,6 +13,8 @@
 #include <cursor.h>
 #include "screen.h"
 
+extern VGAcur vgasoftcur;
+
 Rectangle physgscreenr;
 
 Memimage *gscreen;
@@ -82,7 +84,6 @@
 	poperror();
 
 	drawcmap();
-	swcursorinit();
 
 	qunlock(&drawlock);
 	poperror();
@@ -240,11 +241,9 @@
 	}
 	p &= x;
 
-	lock(&cursor);
 	*pr = scr->colormap[p][0];
 	*pg = scr->colormap[p][1];
 	*pb = scr->colormap[p][2];
-	unlock(&cursor);
 }
 
 int
@@ -256,7 +255,6 @@
 	scr = &vgascreen[0];
 	d = scr->palettedepth;
 
-	lock(&cursor);
 	scr->colormap[p][0] = r;
 	scr->colormap[p][1] = g;
 	scr->colormap[p][2] = b;
@@ -264,7 +262,6 @@
 	vgao(Pdata, r>>(32-d));
 	vgao(Pdata, g>>(32-d));
 	vgao(Pdata, b>>(32-d));
-	unlock(&cursor);
 
 	return ~0;
 }
@@ -302,41 +299,6 @@
 }
 
 void
-swenable(VGAscr*)
-{
-	swcursorload(&arrow);
-}
-
-void
-swdisable(VGAscr*)
-{
-}
-
-void
-swload(VGAscr*, Cursor *curs)
-{
-	swcursorload(curs);
-}
-
-int
-swmove(VGAscr*, Point p)
-{
-	swcursorhide();
-	swcursordraw(p);
-	return 0;
-}
-
-VGAcur swcursor =
-{
-	"soft",
-	swenable,
-	swdisable,
-	swload,
-	swmove,
-};
-
-
-void
 cursoron(void)
 {
 	VGAscr *scr;
@@ -344,16 +306,8 @@
 
 	scr = &vgascreen[0];
 	cur = scr->cur;
-	if(cur == nil || cur->move == nil)
-		return;
-
-	if(cur == &swcursor)
-		qlock(&drawlock);
-	lock(&cursor);
-	cur->move(scr, mousexy());
-	unlock(&cursor);
-	if(cur == &swcursor)
-		qunlock(&drawlock);
+	if(cur && cur->move)
+		cur->move(scr, mousexy());
 }
 
 void
@@ -365,12 +319,12 @@
 setcursor(Cursor* curs)
 {
 	VGAscr *scr;
+	VGAcur *cur;
 
 	scr = &vgascreen[0];
-	if(scr->cur == nil || scr->cur->load == nil)
-		return;
-
-	scr->cur->load(scr, curs);
+	cur = scr->cur;
+	if(cur && cur->load)
+		cur->load(scr, curs);
 }
 
 int hwaccel = 0;
@@ -395,7 +349,7 @@
 		src = nil;
 	if((mask = par->mask) && mask->data == nil)
 		mask = nil;
-	if(scr->cur == &swcursor){
+	if(scr->cur == &vgasoftcur){
 		if(dst->data->bdata == scrd->bdata)
 			swcursoravoid(par->r);
 		if(src && src->data->bdata == scrd->bdata)
@@ -687,11 +641,8 @@
 	vgaimageinit(chan);
 	vgascreenwin(scr);
 
-	/* turn mouse cursor on */
-	swcursorinit();
-	scr->cur = &swcursor;
+	scr->cur = &vgasoftcur;
 	scr->cur->enable(scr);
-	cursoron();
 
 	conf.monitor = 1;
 }
--- a/sys/src/9/pc/screen.h
+++ b/sys/src/9/pc/screen.h
@@ -1,11 +1,6 @@
-typedef struct Cursor Cursor;
-typedef struct Cursorinfo Cursorinfo;
-struct Cursorinfo {
-	Cursor;
-	Lock;
-};
-
 /* devmouse.c */
+typedef struct Cursor Cursor;
+extern Cursor cursor;
 extern void mousetrack(int, int, int, ulong);
 extern void absmousetrack(int, int, int, ulong);
 extern Point mousexy(void);
@@ -15,9 +10,6 @@
 extern int m5mouseputc(Queue*, int);
 extern int mouseputc(Queue*, int);
 
-extern Cursorinfo cursor;
-extern Cursor arrow;
-
 /*
  * Generic VGA registers.
  */
@@ -134,11 +126,11 @@
 extern void	mouseredraw(void);
 
 /* screen.c */
-extern int		hwaccel;	/* use hw acceleration */
-extern int		hwblank;	/* use hw blanking */
-extern int		panning;	/* use virtual screen panning */
-extern void addvgaseg(char*, ulong, ulong);
-extern Memdata* attachscreen(Rectangle*, ulong*, int*, int*, int*);
+extern int	hwaccel;	/* use hw acceleration */
+extern int	hwblank;	/* use hw blanking */
+extern int	panning;	/* use virtual screen panning */
+extern void	addvgaseg(char*, ulong, ulong);
+extern Memdata*	attachscreen(Rectangle*, ulong*, int*, int*, int*);
 extern void	flushmemscreen(Rectangle);
 extern void	cursoron(void);
 extern void	cursoroff(void);
@@ -148,20 +140,12 @@
 extern Rectangle physgscreenr;	/* actual monitor size */
 extern void	blankscreen(int);
 extern char*	rgbmask2chan(char *buf, int depth, u32int rm, u32int gm, u32int bm);
-
 extern void	bootscreeninit(void);
 extern void	bootscreenconf(VGAscr*);
 
-extern VGAcur swcursor;
-extern void swcursorinit(void);
-extern void swcursorhide(void);
-extern void swcursoravoid(Rectangle);
-extern void swcursorunhide(void);
-
 /* devdraw.c */
 extern void	deletescreenimage(void);
 extern void	resetscreenimage(void);
-extern int		drawhasclients(void);
 extern void	setscreenimageclipr(Rectangle);
 extern void	drawflush(void);
 extern QLock	drawlock;
@@ -171,15 +155,13 @@
 extern void	vgaimageinit(ulong);
 extern void	vgalinearpci(VGAscr*);
 extern void	vgalinearaddr(VGAscr*, ulong, int);
-
 extern void	vgablank(VGAscr*, int);
-
 extern Lock	vgascreenlock;
 
 #define ishwimage(i)	(vgascreen[0].gscreendata && (i)->data->bdata == vgascreen[0].gscreendata->bdata)
 
 /* swcursor.c */
-void		swcursorhide(void);
+void		swcursorhide(int);
 void		swcursoravoid(Rectangle);
 void		swcursordraw(Point);
 void		swcursorload(Cursor *);
--- a/sys/src/9/pc/vga3dfx.c
+++ b/sys/src/9/pc/vga3dfx.c
@@ -168,7 +168,7 @@
 	/*
 	 * Load, locate and enable the 64x64 cursor in X11 mode.
 	 */
-	tdfxcurload(scr, &arrow);
+	tdfxcurload(scr, &cursor);
 	tdfxcurmove(scr, ZP);
 	cursor3dfx->vidProcCfg |= 0x08000002;
 }
--- a/sys/src/9/pc/vgaclgd546x.c
+++ b/sys/src/9/pc/vgaclgd546x.c
@@ -186,7 +186,7 @@
 	/*
 	 * Load, locate and enable the 64x64 cursor.
 	 */
-	clgd546xcurload(scr, &arrow);
+	clgd546xcurload(scr, &cursor);
 	clgd546xcurmove(scr, ZP);
 	cursor546x->enable = 1;
 }
--- a/sys/src/9/pc/vgacyber938x.c
+++ b/sys/src/9/pc/vgacyber938x.c
@@ -181,7 +181,7 @@
 	 * enable is bit 7). Bit 3 needs to be set on 9382
 	 * chips otherwise even the white bits are black.
 	 */
-	cyber938xcurload(scr, &arrow);
+	cyber938xcurload(scr, &cursor);
 	cyber938xcurmove(scr, ZP);
 	vgaxo(Crtx, 0x50, CursorON);
 }
--- a/sys/src/9/pc/vgageode.c
+++ b/sys/src/9/pc/vgageode.c
@@ -91,7 +91,7 @@
 {
 	geodeenable(scr);
 	if(!scr->mmio) return;
-	geodecurload(scr, &arrow);
+	geodecurload(scr, &cursor);
 	geodecurmove(scr, ZP);
 	((ulong*)scr->mmio)[DC_UNLOCK] = DC_UNLOCKVALUE;
 	((ulong*)scr->mmio)[DC_CURS_ST_OFFSET] = scr->storage;
--- a/sys/src/9/pc/vgahiqvideo.c
+++ b/sys/src/9/pc/vgahiqvideo.c
@@ -200,7 +200,7 @@
 	 * Load, locate and enable the 32x32 cursor.
 	 * Cursor enable in Xr80 better be set already.
 	 */
-	hiqvideocurload(scr, &arrow);
+	hiqvideocurload(scr, &cursor);
 	hiqvideocurmove(scr, ZP);
 	hiqvideoxo(Xrx, 0xA0, 0x11);
 }
--- a/sys/src/9/pc/vgai81x.c
+++ b/sys/src/9/pc/vgai81x.c
@@ -210,7 +210,7 @@
 	/*
 	 * Load, locate and enable the 32x32 cursor in 2bpp mode.
 	 */
-	i81xcurload(scr, &arrow);
+	i81xcurload(scr, &cursor);
 	i81xcurmove(scr, ZP);
 }
 
--- a/sys/src/9/pc/vgaigfx.c
+++ b/sys/src/9/pc/vgaigfx.c
@@ -198,7 +198,7 @@
 	int i;
 
 	igfxenable(scr);
-	igfxcurload(scr, &arrow);
+	igfxcurload(scr, &cursor);
 	igfxcurmove(scr, ZP);
 
 	for(i=0; i<NPIPE; i++){
--- a/sys/src/9/pc/vgamach64xx.c
+++ b/sys/src/9/pc/vgamach64xx.c
@@ -603,7 +603,7 @@
 	/*
 	 * Load, locate and enable the 64x64 cursor.
 	 */
-	mach64xxcurload(scr, &arrow);
+	mach64xxcurload(scr, &cursor);
 	mach64xxcurmove(scr, ZP);
 	iow32(scr, GenTestCntl, 0x80|r);
 }
--- a/sys/src/9/pc/vgamga2164w.c
+++ b/sys/src/9/pc/vgamga2164w.c
@@ -202,7 +202,7 @@
 	 * Load, locate and enable the
 	 * 64x64 cursor in 3-colour mode.
 	 */
-	tvp3026load(scr, &arrow);
+	tvp3026load(scr, &cursor);
 	tvp3026move(scr, ZP);
 	*(tvp3026+Cctl) = 0x01;
 }
--- a/sys/src/9/pc/vgamga4xx.c
+++ b/sys/src/9/pc/vgamga4xx.c
@@ -302,7 +302,7 @@
 	 * Load, locate and enable the
 	 * 64x64 cursor in X11 mode.
 	 */
-	dac4xxload(scr, &arrow);
+	dac4xxload(scr, &cursor);
 	dac4xxmove(scr, ZP);
 }
 
--- a/sys/src/9/pc/vganeomagic.c
+++ b/sys/src/9/pc/vganeomagic.c
@@ -230,7 +230,7 @@
 	/*
 	 * Load, locate and enable the 64x64 cursor.
 	 */
-	neomagiccurload(scr, &arrow);
+	neomagiccurload(scr, &cursor);
 	neomagiccurmove(scr, ZP);
 	cursornm->enable = 1;
 }
--- a/sys/src/9/pc/vganvidia.c
+++ b/sys/src/9/pc/vganvidia.c
@@ -232,7 +232,7 @@
 
 	vgaxo(Crtx, 0x1F, 0x57);
 
-	nvidiacurload(scr, &arrow);
+	nvidiacurload(scr, &cursor);
 	nvidiacurmove(scr, ZP);
 
 	vgaxo(Crtx, 0x31, vgaxi(Crtx, 0x31) | 0x01);
--- a/sys/src/9/pc/vgaradeon.c
+++ b/sys/src/9/pc/vgaradeon.c
@@ -201,7 +201,7 @@
 	radeoncurdisable(scr);
 	storage = scr->apsize - 1*Meg;
 	scr->storage = (uintptr)KADDR(scr->paddr + storage);
-	radeoncurload(scr, &arrow);
+	radeoncurload(scr, &cursor);
 	radeoncurmove(scr, ZP);
 
 	OUTREGP(scr->mmio, CRTC_GEN_CNTL, CRTC_CUR_EN | 2<<20,
--- a/sys/src/9/pc/vgas3.c
+++ b/sys/src/9/pc/vgas3.c
@@ -317,7 +317,7 @@
 	 * Load, locate and enable the cursor
 	 * in Microsoft Windows format.
 	 */
-	s3load(scr, &arrow);
+	s3load(scr, &cursor);
 	s3move(scr, ZP);
 	vgaxo(Crtx, 0x55, vgaxi(Crtx, 0x55) & ~0x10);
 	s3vsyncactive();
--- /dev/null
+++ b/sys/src/9/pc/vgasoft.c
@@ -1,0 +1,50 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "ureg.h"
+#include "../port/error.h"
+
+#define	Image	IMAGE
+#include <draw.h>
+#include <memdraw.h>
+#include <cursor.h>
+#include "screen.h"
+
+static void
+swenable(VGAscr*)
+{
+	swcursorinit();
+	swcursorload(&cursor);
+}
+
+static void
+swdisable(VGAscr*)
+{
+	swcursorhide(1);
+}
+
+static void
+swload(VGAscr*, Cursor *curs)
+{
+	swcursorload(curs);
+}
+
+static int
+swmove(VGAscr*, Point p)
+{
+	swcursorhide(0);
+	swcursordraw(p);
+	return 0;
+}
+
+VGAcur vgasoftcur =
+{
+	"soft",
+	swenable,
+	swdisable,
+	swload,
+	swmove,
+};
--- a/sys/src/9/pc/vgat2r4.c
+++ b/sys/src/9/pc/vgat2r4.c
@@ -261,7 +261,7 @@
 	/*
 	 * Load, locate and enable the cursor, 64x64, mode 2.
 	 */
-	t2r4curload(scr, &arrow);
+	t2r4curload(scr, &cursor);
 	t2r4curmove(scr, ZP);
 	t2r4xo(scr, CursorCtl, CursorMode);
 }
--- a/sys/src/9/pc64/pc64
+++ b/sys/src/9/pc64/pc64
@@ -23,7 +23,7 @@
 	bridge		netif log
 	ip		arp chandial ip ipv6 ipaux iproute netlog ethermedium nullmedium pktmedium inferno
 
-	draw		screen vga vgax swcursor
+	draw		screen vga vgax vgasoft
 	mouse		mouse
 	kbd
 	vga
@@ -112,6 +112,7 @@
 	uartisa
 	uartpci		pci
 
+	vgasoft		=cur swcursor
 #	vga3dfx		+cur
 #	vgaark2000pv	+cur
 #	vgabt485	=cur
--- a/sys/src/9/port/devdraw.c
+++ b/sys/src/9/port/devdraw.c
@@ -799,17 +799,6 @@
 	return op;
 }
 
-int
-drawhasclients(void)
-{
-	/*
-	 * if draw has ever been used, we can't resize the frame buffer,
-	 * even if all clients have exited (nclients is cumulative); it's too
-	 * hard to make work.
-	 */
-	return sdraw.nclient != 0;
-}
-
 Client*
 drawclientofpath(ulong path)
 {
--- a/sys/src/9/port/devmouse.c
+++ b/sys/src/9/port/devmouse.c
@@ -71,10 +71,7 @@
 };
 
 Mouseinfo	mouse;
-Cursorinfo	cursor;
-Cursor		curs;
 
-void	Cursortocursor(Cursor*);
 void	mouseblankscreen(int);
 int	mousechanged(void*);
 void	mouseredraw(void);
@@ -105,7 +102,7 @@
 
 extern Memimage* gscreen;
 
-Cursor	arrow = {
+Cursor arrow = {
 	{ -1, -1 },
 	{ 0xFF, 0xFF, 0x80, 0x01, 0x80, 0x02, 0x80, 0x0C,
 	  0x80, 0x10, 0x80, 0x10, 0x80, 0x08, 0x80, 0x04,
@@ -118,17 +115,10 @@
 	  0x61, 0xF0, 0x60, 0xE0, 0x40, 0x40, 0x00, 0x00,
 	},
 };
+Cursor cursor;
 
-static void
-mousereset(void)
-{
-	if(!conf.monitor)
-		return;
+static void Cursortocursor(Cursor*);
 
-	curs = arrow;
-	Cursortocursor(&arrow);
-}
-
 static int
 mousedevgen(Chan *c, char *name, Dirtab *tab, int ntab, int i, Dir *dp)
 {
@@ -147,12 +137,8 @@
 {
 	if(!conf.monitor)
 		return;
-
-	curs = arrow;
-	Cursortocursor(&arrow);
-	cursoron();
 	mousetime = seconds();
-
+	Cursortocursor(&arrow);
 	kproc("mouse", mouseproc, 0);
 }
 
@@ -232,10 +218,7 @@
 	case Qcursor:
 		if(decref(&mouse) != 0)
 			return;
-		cursoroff();
-		curs = arrow;
 		Cursortocursor(&arrow);
-		cursoron();
 	}
 }
 
@@ -246,6 +229,7 @@
 	char buf[1+4*12+1];
 	uchar *p;
 	ulong offset = off;
+	Cursor curs;
 	Mousestate m;
 	int b;
 
@@ -259,6 +243,11 @@
 			return 0;
 		if(n < 2*4+2*2*16)
 			error(Eshort);
+
+		qlock(&drawlock);
+		memmove(&curs, &cursor, sizeof(Cursor));
+		qunlock(&drawlock);
+
 		n = 2*4+2*2*16;
 		BPLONG(p+0, curs.offset.x);
 		BPLONG(p+4, curs.offset.y);
@@ -360,6 +349,7 @@
 	Point pt;
 	Cmdbuf *cb;
 	Cmdtab *ct;
+	Cursor curs;
 	char buf[64];
 	int b, z, msec;
 	Mousestate *m;
@@ -370,19 +360,16 @@
 		error(Eisdir);
 
 	case Qcursor:
-		cursoroff();
 		if(n < 2*4+2*2*16){
-			curs = arrow;
 			Cursortocursor(&arrow);
-		}else{
-			n = 2*4+2*2*16;
-			curs.offset.x = BGLONG(p+0);
-			curs.offset.y = BGLONG(p+4);
-			memmove(curs.clr, p+8, 2*16);
-			memmove(curs.set, p+40, 2*16);
-			Cursortocursor(&curs);
+			return n;
 		}
-		cursoron();
+		n = 2*4+2*2*16;
+		curs.offset.x = BGLONG(p+0);
+		curs.offset.y = BGLONG(p+4);
+		memmove(curs.clr, p+8, 2*16);
+		memmove(curs.set, p+40, 2*16);
+		Cursortocursor(&curs);
 		return n;
 
 	case Qmousectl:
@@ -498,7 +485,7 @@
 	'm',
 	"mouse",
 
-	mousereset,
+	devreset,
 	mouseinit,
 	devshutdown,
 	mouseattach,
@@ -515,14 +502,14 @@
 	devwstat,
 };
 
-void
+static void
 Cursortocursor(Cursor *c)
 {
 	qlock(&drawlock);
-	lock(&cursor);
-	memmove(&cursor.Cursor, c, sizeof(Cursor));
+	cursoroff();
+	memmove(&cursor, c, sizeof(Cursor));
 	setcursor(c);
-	unlock(&cursor);
+	cursoron();
 	qunlock(&drawlock);
 }
 
@@ -558,8 +545,11 @@
 	for(;;){
 		sleep(&mouse.redrawr, shouldredraw, nil);
 		mouse.redraw = 0;
+
+		qlock(&drawlock);
 		cursoroff();
 		cursoron();
+		qunlock(&drawlock);
 	}
 }
 
--- a/sys/src/9/port/swcursor.c
+++ b/sys/src/9/port/swcursor.c
@@ -34,14 +34,18 @@
  * that should be okay: worst case we get cursor droppings.
  */
 void
-swcursorhide(void)
+swcursorhide(int doflush)
 {
 	if(swvisible == 0)
 		return;
+	swvisible = 0;
 	if(swback == nil || gscreen == nil)
 		return;
-	swvisible = 0;
 	memimagedraw(gscreen, swrect, swback, ZP, memopaque, ZP, S);
+	if(doflush){
+		flushmemscreen(swrect);
+		swrect = ZR;
+	}
 }
 
 void
@@ -48,7 +52,7 @@
 swcursoravoid(Rectangle r)
 {
 	if(swvisible && rectXrect(r, swrect)){
-		swcursorhide();
+		swcursorhide(0);
 		mouseredraw();	/* schedule cursor redraw after we release drawlock */
 	}
 }
@@ -62,10 +66,9 @@
 		return;
 	if(swback == nil || swimg1 == nil || swmask1 == nil || gscreen == nil)
 		return;
-	assert(!canqlock(&drawlock));
 	swvispt = addpt(swoffset, p);
 	flushr = swrect; 
-	swrect = rectaddpt(Rect(0,0,16,16), swvispt);
+	swrect = rectaddpt(swimg1->r, swvispt);
 	combinerect(&flushr, swrect);
 	memimagedraw(swback, swback->r, gscreen, swvispt, memopaque, ZP, S);
 	memimagedraw(gscreen, swrect, swimg1, ZP, swmask1, ZP, SoverD);
@@ -102,13 +105,12 @@
 	swoffset = curs->offset;
 	memimagedraw(swimg1, swimg1->r, swimg, ZP, memopaque, ZP, S);
 	memimagedraw(swmask1, swmask1->r, swmask, ZP, memopaque, ZP, S);
-
-	mouseredraw();
 }
 
 void
 swcursorinit(void)
 {
+	swvisible = 0;
 	if(gscreen == nil)
 		return;
 
@@ -119,7 +121,7 @@
 		freememimage(swimg);
 		freememimage(swimg1); 
 	}
-	swback = allocmemimage(Rect(0,0,32,32), gscreen->chan);
+	swback = allocmemimage(Rect(0,0,16,16), gscreen->chan);
 	swmask = allocmemimage(Rect(0,0,16,16), GREY8);
 	swmask1 = allocmemimage(Rect(0,0,16,16), GREY1);
 	swimg = allocmemimage(Rect(0,0,16,16), GREY8);
--- a/sys/src/9/sgi/screen.h
+++ b/sys/src/9/sgi/screen.h
@@ -1,11 +1,6 @@
-typedef struct Cursor Cursor;
-typedef struct Cursorinfo Cursorinfo;
-struct Cursorinfo {
-	Cursor;
-	Lock;
-};
-
 /* devmouse.c */
+typedef struct Cursor Cursor;
+extern Cursor cursor;
 extern void mousetrack(int, int, int, ulong);
 extern void absmousetrack(int, int, int, ulong);
 extern Point mousexy(void);
@@ -15,9 +10,6 @@
 extern int m5mouseputc(Queue*, int);
 extern int mouseputc(Queue*, int);
 
-extern Cursorinfo cursor;
-extern Cursor arrow;
-
 /* mouse.c */
 extern void mousectl(Cmdbuf*);
 extern void mouseresize(void);
@@ -35,10 +27,3 @@
 extern QLock	drawlock;
 
 #define ishwimage(i)	0		/* for ../port/devdraw.c */
-
-/* swcursor.c */
-void		swcursorhide(void);
-void		swcursoravoid(Rectangle);
-void		swcursordraw(Point);
-void		swcursorload(Cursor *);
-void		swcursorinit(void);
--- a/sys/src/9/zynq/screen.h
+++ b/sys/src/9/zynq/screen.h
@@ -1,11 +1,6 @@
-typedef struct Cursor Cursor;
-typedef struct Cursorinfo Cursorinfo;
-struct Cursorinfo {
-	Cursor;
-	Lock;
-};
-
 /* devmouse.c */
+typedef struct Cursor Cursor;
+extern Cursor cursor;
 extern void mousetrack(int, int, int, ulong);
 extern void absmousetrack(int, int, int, ulong);
 extern Point mousexy(void);
@@ -15,9 +10,6 @@
 extern int m5mouseputc(Queue*, int);
 extern int mouseputc(Queue*, int);
 
-extern Cursorinfo cursor;
-extern Cursor arrow;
-
 /* mouse.c */
 extern void mousectl(Cmdbuf*);
 extern void mouseresize(void);
@@ -37,10 +29,3 @@
 extern QLock	drawlock;
 
 #define ishwimage(i)	1		/* for ../port/devdraw.c */
-
-/* swcursor.c */
-void		swcursorhide(void);
-void		swcursoravoid(Rectangle);
-void		swcursordraw(Point);
-void		swcursorload(Cursor *);
-void		swcursorinit(void);