diff --git a/sys/src/9/bcm/fns.h b/sys/src/9/bcm/fns.h index 92615d9ed..1c480cc14 100644 --- a/sys/src/9/bcm/fns.h +++ b/sys/src/9/bcm/fns.h @@ -64,7 +64,6 @@ extern void setpower(int, int); extern void setr13(int, u32int*); extern int splfhi(void); extern int splflo(void); -extern void swcursorinit(void); extern int tas(void *); extern void touser(uintptr); extern void trapinit(void); diff --git a/sys/src/9/bcm/main.c b/sys/src/9/bcm/main.c index 4a00d1b13..1b78c80d1 100644 --- a/sys/src/9/bcm/main.c +++ b/sys/src/9/bcm/main.c @@ -249,8 +249,6 @@ main(void) clockinit(); printinit(); timersinit(); - if(conf.monitor) - swcursorinit(); cpuidprint(); archreset(); diff --git a/sys/src/9/bcm/picpuf b/sys/src/9/bcm/picpuf index 7ec5d9881..fcdc080dd 100644 --- a/sys/src/9/bcm/picpuf +++ b/sys/src/9/bcm/picpuf @@ -14,7 +14,7 @@ dev cap fs ip arp chandial ip ipv6 ipaux iproute netlog nullmedium pktmedium ptclbsum inferno - draw screen + draw screen swcursor mouse mouse uart diff --git a/sys/src/9/bcm/pif b/sys/src/9/bcm/pif index cf3c66485..f209a1211 100644 --- a/sys/src/9/bcm/pif +++ b/sys/src/9/bcm/pif @@ -14,7 +14,7 @@ dev cap fs ip arp chandial ip ipv6 ipaux iproute netlog nullmedium pktmedium ptclbsum inferno - draw screen + draw screen swcursor mouse mouse uart diff --git a/sys/src/9/bcm/screen.c b/sys/src/9/bcm/screen.c index e96fa4fdf..fe7ed6c93 100644 --- a/sys/src/9/bcm/screen.c +++ b/sys/src/9/bcm/screen.c @@ -69,203 +69,32 @@ static void myscreenputs(char *s, int n); static void screenputc(char *buf); static void screenwin(void); -/* - * Software cursor. - */ -static int swvisible; /* is the cursor visible? */ -static int swenabled; /* is the cursor supposed to be on the screen? */ -static Memimage *swback; /* screen under cursor */ -static Memimage *swimg; /* cursor image */ -static Memimage *swmask; /* cursor mask */ -static Memimage *swimg1; -static Memimage *swmask1; - -static Point swoffset; -static Rectangle swrect; /* screen rectangle in swback */ -static Point swpt; /* desired cursor location */ -static Point swvispt; /* actual cursor location */ -static int swvers; /* incremented each time cursor image changes */ -static int swvisvers; /* the version on the screen */ - -/* - * called with drawlock locked for us, most of the time. - * kernel prints at inopportune times might mean we don't - * hold the lock, but memimagedraw is now reentrant so - * that should be okay: worst case we get cursor droppings. - */ -static void -swcursorhide(void) +void +cursoron(void) { - if(swvisible == 0) - return; - if(swback == nil) - return; - swvisible = 0; - memimagedraw(gscreen, swrect, swback, ZP, memopaque, ZP, S); - flushmemscreen(swrect); -} - -static void -swcursoravoid(Rectangle r) -{ - if(swvisible && rectXrect(r, swrect)) - swcursorhide(); -} - -static void -swcursordraw(void) -{ - int dounlock; - - if(swvisible) - return; - if(swenabled == 0) - return; - if(swback == nil || swimg1 == nil || swmask1 == nil) - return; - dounlock = canqlock(&drawlock); - swvispt = swpt; - swvisvers = swvers; - swrect = rectaddpt(Rect(0,0,16,16), swvispt); - memimagedraw(swback, swback->r, gscreen, swpt, memopaque, ZP, S); - memimagedraw(gscreen, swrect, swimg1, ZP, swmask1, ZP, SoverD); - flushmemscreen(swrect); - swvisible = 1; - if(dounlock) - qunlock(&drawlock); -} - -int -cursoron(int dolock) -{ - int retry; - - if (dolock) - lock(&cursor); - if (canqlock(&drawlock)) { - retry = 0; - swcursorhide(); - swcursordraw(); - qunlock(&drawlock); - } else - retry = 1; - if (dolock) - unlock(&cursor); - return retry; + qlock(&drawlock); + lock(&cursor); + swcursorhide(); + swcursordraw(mousexy()); + unlock(&cursor); + qunlock(&drawlock); } void -cursoroff(int dolock) +cursoroff(void) { - if (dolock) - lock(&cursor); + qlock(&drawlock); + lock(&cursor); swcursorhide(); - if (dolock) - unlock(&cursor); -} - -static void -swload(Cursor *curs) -{ - uchar *ip, *mp; - int i, j, set, clr; - - if(!swimg || !swmask || !swimg1 || !swmask1) - return; - /* - * Build cursor image and mask. - * Image is just the usual cursor image - * but mask is a transparent alpha mask. - * - * The 16x16x8 memimages do not have - * padding at the end of their scan lines. - */ - ip = byteaddr(swimg, ZP); - mp = byteaddr(swmask, ZP); - for(i=0; i<32; i++){ - set = curs->set[i]; - clr = curs->clr[i]; - for(j=0x80; j; j>>=1){ - *ip++ = set&j ? 0x00 : 0xFF; - *mp++ = (clr|set)&j ? 0xFF : 0x00; - } - } - swoffset = curs->offset; - swvers++; - memimagedraw(swimg1, swimg1->r, swimg, ZP, memopaque, ZP, S); - memimagedraw(swmask1, swmask1->r, swmask, ZP, memopaque, ZP, S); + unlock(&cursor); + qunlock(&drawlock); } /* called from devmouse */ void setcursor(Cursor* curs) { - cursoroff(0); - swload(curs); - cursoron(0); -} - -static int -swmove(Point p) -{ - swpt = addpt(p, swoffset); - return 0; -} - -static void -swcursorclock(void) -{ - int x; - - if(!swenabled) - return; - swmove(mousexy()); - if(swvisible && eqpt(swpt, swvispt) && swvers==swvisvers) - return; - - x = splhi(); - if(swenabled) - if(!swvisible || !eqpt(swpt, swvispt) || swvers!=swvisvers) - if(canqlock(&drawlock)){ - swcursorhide(); - swcursordraw(); - qunlock(&drawlock); - } - splx(x); -} - -void -swcursorinit(void) -{ - static int init; - - if(!init){ - init = 1; - addclock0link(swcursorclock, 10); - swenabled = 1; - } - if(swback){ - freememimage(swback); - freememimage(swmask); - freememimage(swmask1); - freememimage(swimg); - freememimage(swimg1); - } - - swback = allocmemimage(Rect(0,0,32,32), 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); - swimg1 = allocmemimage(Rect(0,0,16,16), GREY1); - if(swback==nil || swmask==nil || swmask1==nil || swimg==nil || swimg1 == nil){ - print("software cursor: allocmemimage fails\n"); - return; - } - - memfillcolor(swmask, DOpaque); - memfillcolor(swmask1, DOpaque); - memfillcolor(swimg, DBlack); - memfillcolor(swimg1, DBlack); + swcursorload(curs); } int @@ -348,6 +177,7 @@ screeninit(void) memdefont = getmemdefont(); screenwin(); screenputs = myscreenputs; + swcursorinit(); } void diff --git a/sys/src/9/bcm/screen.h b/sys/src/9/bcm/screen.h index 8703796a9..9c45e3a2f 100644 --- a/sys/src/9/bcm/screen.h +++ b/sys/src/9/bcm/screen.h @@ -21,16 +21,24 @@ extern Cursor arrow; /* mouse.c */ extern void mousectl(Cmdbuf*); extern void mouseresize(void); +extern void mouseredraw(void); /* screen.c */ extern void blankscreen(int); extern void flushmemscreen(Rectangle); extern uchar* attachscreen(Rectangle*, ulong*, int*, int*, int*); -extern int cursoron(int); -extern void cursoroff(int); +extern void cursoron(void); +extern void cursoroff(void); extern void setcursor(Cursor*); /* devdraw.c */ 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); diff --git a/sys/src/9/omap/beagle b/sys/src/9/omap/beagle index 8852bd7d4..3dea87477 100644 --- a/sys/src/9/omap/beagle +++ b/sys/src/9/omap/beagle @@ -24,7 +24,7 @@ dev ether netif ip arp chandial ip ipv6 ipaux iproute netlog nullmedium pktmedium ptclbsum inferno - draw screen + draw screen swcursor dss mouse diff --git a/sys/src/9/omap/screen.c b/sys/src/9/omap/screen.c index e47fd2821..f2ec47054 100644 --- a/sys/src/9/omap/screen.c +++ b/sys/src/9/omap/screen.c @@ -346,174 +346,33 @@ screenpower(int on) blankscreen(on == 0); } -/* - * called with drawlock locked for us, most of the time. - * kernel prints at inopportune times might mean we don't - * hold the lock, but memimagedraw is now reentrant so - * that should be okay: worst case we get cursor droppings. - */ void -swcursorhide(void) +cursoron(void) { - if(swvisible == 0) - return; - if(swback == nil) - return; - swvisible = 0; - memimagedraw(gscreen, swrect, swback, ZP, memopaque, ZP, S); - flushmemscreen(swrect); -} - -void -swcursoravoid(Rectangle r) -{ - if(swvisible && rectXrect(r, swrect)) - swcursorhide(); -} - -void -swcursordraw(void) -{ - if(swvisible) - return; - if(swenabled == 0) - return; - if(swback == nil || swimg1 == nil || swmask1 == nil) - return; -// assert(!canqlock(&drawlock)); // assertion fails on omap - swvispt = swpt; - swvisvers = swvers; - swrect = rectaddpt(Rect(0,0,16,16), swvispt); - memimagedraw(swback, swback->r, gscreen, swpt, memopaque, ZP, S); - memimagedraw(gscreen, swrect, swimg1, ZP, swmask1, ZP, SoverD); - flushmemscreen(swrect); - swvisible = 1; -} - -int -cursoron(int dolock) -{ - if (dolock) - lock(&oscreen); - cursoroff(0); - swcursordraw(); - if (dolock) - unlock(&oscreen); - return 0; -} - -void -cursoroff(int dolock) -{ - if (dolock) - lock(&oscreen); + qlock(&drawlock); + lock(&cursor); swcursorhide(); - if (dolock) - unlock(&oscreen); + swcursordraw(mousexy()); + unlock(&cursor); + qunlock(&drawlock); } void -swload(Cursor *curs) +cursoroff(void) { - uchar *ip, *mp; - int i, j, set, clr; - - if(!swimg || !swmask || !swimg1 || !swmask1) - return; - /* - * Build cursor image and mask. - * Image is just the usual cursor image - * but mask is a transparent alpha mask. - * - * The 16x16x8 memimages do not have - * padding at the end of their scan lines. - */ - ip = byteaddr(swimg, ZP); - mp = byteaddr(swmask, ZP); - for(i=0; i<32; i++){ - set = curs->set[i]; - clr = curs->clr[i]; - for(j=0x80; j; j>>=1){ - *ip++ = set&j ? 0x00 : 0xFF; - *mp++ = (clr|set)&j ? 0xFF : 0x00; - } - } - swoffset = curs->offset; - swvers++; - memimagedraw(swimg1, swimg1->r, swimg, ZP, memopaque, ZP, S); - memimagedraw(swmask1, swmask1->r, swmask, ZP, memopaque, ZP, S); + qlock(&drawlock); + lock(&cursor); + swcursorhide(); + unlock(&cursor); + qunlock(&drawlock); } /* called from devmouse */ void setcursor(Cursor* curs) { - cursoroff(1); oscreen.Cursor = *curs; - swload(curs); - cursoron(1); -} - -int -swmove(Point p) -{ - swpt = addpt(p, swoffset); - return 0; -} - -void -swcursorclock(void) -{ - int x; - - if(!swenabled) - return; - swmove(mousexy()); - if(swvisible && eqpt(swpt, swvispt) && swvers==swvisvers) - return; - - x = splhi(); - if(swenabled) - if(!swvisible || !eqpt(swpt, swvispt) || swvers!=swvisvers) - if(canqlock(&drawlock)){ - swcursorhide(); - swcursordraw(); - qunlock(&drawlock); - } - splx(x); -} - -void -swcursorinit(void) -{ - static int init; - - if(!init){ - init = 1; - addclock0link(swcursorclock, 10); - } - if(swback){ - freememimage(swback); - freememimage(swmask); - freememimage(swmask1); - freememimage(swimg); - freememimage(swimg1); - } - - swback = allocmemimage(Rect(0,0,32,32), 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); - swimg1 = allocmemimage(Rect(0,0,16,16), GREY1); - if(swback==nil || swmask==nil || swmask1==nil || swimg==nil || swimg1 == nil){ - print("software cursor: allocmemimage fails\n"); - return; - } - - memfillcolor(swmask, DOpaque); - memfillcolor(swmask1, DOpaque); - memfillcolor(swimg, DBlack); - memfillcolor(swimg1, DBlack); + swcursorload(curs); } /* called from main and possibly later from devdss to change resolution */ diff --git a/sys/src/9/omap/screen.h b/sys/src/9/omap/screen.h index 6eff3649c..6083aea15 100644 --- a/sys/src/9/omap/screen.h +++ b/sys/src/9/omap/screen.h @@ -20,12 +20,13 @@ extern Point mousexy(void); extern void mouseaccelerate(int); extern void mouseresize(void); +extern void mouseredraw(void); /* screen.c */ extern uchar* attachscreen(Rectangle*, ulong*, int*, int*, int*); extern void flushmemscreen(Rectangle); -extern int cursoron(int); -extern void cursoroff(int); +extern void cursoron(void); +extern void cursoroff(void); extern void setcursor(Cursor*); extern int screensize(int, int, int, ulong); extern int screenaperture(int, int); @@ -49,6 +50,13 @@ 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); + /* for communication between devdss.c and screen.c */ enum { @@ -93,7 +101,6 @@ struct Settings { }; struct OScreen { - Lock; Cursor; Settings *settings; int open; diff --git a/sys/src/9/pc/devvga.c b/sys/src/9/pc/devvga.c index 14df25b89..3867d36dc 100644 --- a/sys/src/9/pc/devvga.c +++ b/sys/src/9/pc/devvga.c @@ -349,7 +349,7 @@ vgactl(Cmdbuf *cb) if(chantodepth(chan) != z) error("depth, channel do not match"); - cursoroff(1); + cursoroff(); deletescreenimage(); if(screensize(x, y, z, chan)) error(Egreg); @@ -397,7 +397,7 @@ vgactl(Cmdbuf *cb) y = scr->gscreen->r.max.y; z = scr->gscreen->depth; chan = scr->gscreen->chan; - cursoroff(1); + cursoroff(); deletescreenimage(); if(screensize(x, y, z, chan)) error(Egreg); @@ -411,7 +411,7 @@ vgactl(Cmdbuf *cb) hwaccel = !scr->softscreen && (scr->scroll || scr->fill); vgascreenwin(scr); resetscreenimage(); - cursoron(1); + cursoron(); return; case CMlinear: diff --git a/sys/src/9/pc/pccpuf b/sys/src/9/pc/pccpuf index b34e46c2d..9a808bf81 100644 --- a/sys/src/9/pc/pccpuf +++ b/sys/src/9/pc/pccpuf @@ -23,7 +23,7 @@ dev ether netif ip arp chandial ip ipv6 ipaux iproute netlog nullmedium pktmedium ptclbsum386 inferno - draw screen vga vgax + draw screen vga vgax swcursor mouse mouse kbd vga diff --git a/sys/src/9/pc/pcf b/sys/src/9/pc/pcf index 308faf7b9..6bb744d53 100644 --- a/sys/src/9/pc/pcf +++ b/sys/src/9/pc/pcf @@ -21,7 +21,7 @@ dev ether netif ip arp chandial ip ipv6 ipaux iproute netlog nullmedium pktmedium ptclbsum386 inferno - draw screen vga vgax + draw screen vga vgax swcursor mouse mouse kbd vga diff --git a/sys/src/9/pc/screen.c b/sys/src/9/pc/screen.c index f7426b783..42e31e65a 100644 --- a/sys/src/9/pc/screen.c +++ b/sys/src/9/pc/screen.c @@ -23,7 +23,7 @@ Memimage *gscreen; VGAscr vgascreen[1]; -Cursor arrow = { +Cursor arrow = { { -1, -1 }, { 0xFF, 0xFF, 0x80, 0x01, 0x80, 0x02, 0x80, 0x0C, 0x80, 0x10, 0x80, 0x10, 0x80, 0x08, 0x80, 0x04, @@ -37,8 +37,6 @@ Cursor arrow = { }, }; -int didswcursorinit; - int screensize(int x, int y, int, ulong chan) { @@ -101,8 +99,7 @@ screensize(int x, int y, int, ulong chan) poperror(); drawcmap(); - if(didswcursorinit) - swcursorinit(); + swcursorinit(); qunlock(&drawlock); poperror(); @@ -327,27 +324,63 @@ setcolor(ulong p, ulong r, ulong g, ulong b) return setpalette(p, r, g, b); } -int -cursoron(int dolock) +void +swenable(VGAscr*) { - VGAscr *scr; - int v; - - scr = &vgascreen[0]; - if(scr->cur == nil || scr->cur->move == nil) - return 0; - - if(dolock) - lock(&cursor); - v = scr->cur->move(scr, mousexy()); - if(dolock) - unlock(&cursor); - - return v; + swcursorload(&arrow); } void -cursoroff(int) +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; + VGAcur *cur; + + 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); +} + +void +cursoroff(void) { } @@ -532,196 +565,3 @@ vgalinearaddr(VGAscr *scr, ulong paddr, int size) poperror(); } } - - -/* - * 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 */ - -/* - * called with drawlock locked for us, most of the time. - * kernel prints at inopportune times might mean we don't - * hold the lock, but memimagedraw is now reentrant so - * that should be okay: worst case we get cursor droppings. - */ -void -swcursorhide(void) -{ - if(swvisible == 0) - return; - if(swback == nil) - return; - swvisible = 0; - memimagedraw(gscreen, swrect, swback, ZP, memopaque, ZP, S); - flushmemscreen(swrect); -} - -void -swcursoravoid(Rectangle r) -{ - if(swvisible && rectXrect(r, swrect)) - swcursorhide(); -} - -void -swcursordraw(void) -{ - if(swvisible) - return; - if(swenabled == 0) - return; - if(swback == nil || swimg1 == nil || swmask1 == nil) - return; - assert(!canqlock(&drawlock)); - swvispt = swpt; - swvisvers = swvers; - swrect = rectaddpt(Rect(0,0,16,16), swvispt); - memimagedraw(swback, swback->r, gscreen, swpt, memopaque, ZP, S); - memimagedraw(gscreen, swrect, swimg1, ZP, swmask1, ZP, SoverD); - flushmemscreen(swrect); - swvisible = 1; -} - -void -swload(VGAscr*, Cursor *curs) -{ - uchar *ip, *mp; - int i, j, set, clr; - - if(!swimg || !swmask || !swimg1 || !swmask1) - return; - /* - * Build cursor image and mask. - * Image is just the usual cursor image - * but mask is a transparent alpha mask. - * - * The 16x16x8 memimages do not have - * padding at the end of their scan lines. - */ - ip = byteaddr(swimg, ZP); - mp = byteaddr(swmask, ZP); - for(i=0; i<32; i++){ - set = curs->set[i]; - clr = curs->clr[i]; - for(j=0x80; j; j>>=1){ - *ip++ = set&j ? 0x00 : 0xFF; - *mp++ = (clr|set)&j ? 0xFF : 0x00; - } - } - swoffset = curs->offset; - swvers++; - memimagedraw(swimg1, swimg1->r, swimg, ZP, memopaque, ZP, S); - memimagedraw(swmask1, swmask1->r, swmask, ZP, memopaque, ZP, S); -} - -int -swmove(VGAscr*, Point p) -{ - swpt = addpt(p, swoffset); - return 0; -} - -void -swcursorclock(void) -{ - int x; - - if(!swenabled) - return; - if(swvisible && eqpt(swpt, swvispt) && swvers==swvisvers) - return; - - x = splhi(); - if(swenabled) - if(!swvisible || !eqpt(swpt, swvispt) || swvers!=swvisvers) - if(canqlock(&drawlock)){ - swcursorhide(); - swcursordraw(); - qunlock(&drawlock); - } - splx(x); -} - -void -swcursorinit(void) -{ - static int init; - VGAscr *scr; - - didswcursorinit = 1; - if(!init){ - init = 1; - addclock0link(swcursorclock, 10); - } - - scr = &vgascreen[0]; - if(scr->gscreen==nil) - return; - - if(swback){ - freememimage(swback); - freememimage(swmask); - freememimage(swmask1); - freememimage(swimg); - freememimage(swimg1); - } - swback = allocmemimage(Rect(0,0,32,32), 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); - swimg1 = allocmemimage(Rect(0,0,16,16), GREY1); - if(swback==nil || swmask==nil || swmask1==nil || swimg==nil || swimg1 == nil) - print("software cursor: allocmemimage fails"); - memfillcolor(swback, DTransparent); - memfillcolor(swmask, DOpaque); - memfillcolor(swmask1, DOpaque); - memfillcolor(swimg, DBlack); - memfillcolor(swimg1, DBlack); -} - -/* - * Need to lock drawlock for ourselves. - */ -void -swenable(VGAscr *scr) -{ - swenabled = 1; - if(canqlock(&drawlock)){ - swload(scr, &arrow); - swcursordraw(); - qunlock(&drawlock); - } -} - -void -swdisable(VGAscr*) -{ - swenabled = 0; - if(canqlock(&drawlock)){ - swcursorhide(); - qunlock(&drawlock); - } -} - -VGAcur swcursor = -{ - "soft", - swenable, - swdisable, - swload, - swmove, -}; diff --git a/sys/src/9/pc/screen.h b/sys/src/9/pc/screen.h index 9cf40bc05..bbe6b2512 100644 --- a/sys/src/9/pc/screen.h +++ b/sys/src/9/pc/screen.h @@ -132,6 +132,7 @@ enum { /* mouse.c */ extern void mousectl(Cmdbuf*); extern void mouseresize(void); +extern void mouseredraw(void); /* screen.c */ extern int hwaccel; /* use hw acceleration; default on */ @@ -140,8 +141,8 @@ extern int panning; /* use virtual screen panning; default off */ extern void addvgaseg(char*, ulong, ulong); extern uchar* attachscreen(Rectangle*, ulong*, int*, int*, int*); extern void flushmemscreen(Rectangle); -extern int cursoron(int); -extern void cursoroff(int); +extern void cursoron(void); +extern void cursoroff(void); extern void setcursor(Cursor*); extern int screensize(int, int, int, ulong); extern int screenaperture(int, int); @@ -176,3 +177,10 @@ 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 swcursoravoid(Rectangle); +void swcursordraw(Point); +void swcursorload(Cursor *); +void swcursorinit(void); diff --git a/sys/src/9/port/devmouse.c b/sys/src/9/port/devmouse.c index 676639f49..73d43d19a 100644 --- a/sys/src/9/port/devmouse.c +++ b/sys/src/9/port/devmouse.c @@ -33,16 +33,13 @@ struct Mouseinfo { Lock; Mousestate; - int dx; - int dy; - int track; /* dx & dy updated */ int redraw; /* update cursor on screen */ + Rendez redrawr; /* wait for cursor screen updates */ ulong lastcounter; /* value when /dev/mouse read */ ulong lastresize; ulong resize; Rendez r; Ref; - QLock; int open; int acceleration; int maxacc; @@ -77,8 +74,7 @@ Cursor curs; void Cursortocursor(Cursor*); int mousechanged(void*); - -static void mouseclock(void); +void mouseredraw(void); enum{ Qdir, @@ -114,8 +110,6 @@ mousereset(void) curs = arrow; Cursortocursor(&arrow); - /* redraw cursor about 30 times per second */ - addclock0link(mouseclock, 33); } static int @@ -129,6 +123,8 @@ mousedevgen(Chan *c, char *name, Dirtab *tab, int ntab, int i, Dir *dp) return rc; } +static void mouseproc(void*); + static void mouseinit(void) { @@ -137,8 +133,10 @@ mouseinit(void) curs = arrow; Cursortocursor(&arrow); - cursoron(1); + cursoron(); mousetime = seconds(); + + kproc("mouse", mouseproc, 0); } static Chan* @@ -222,13 +220,15 @@ mouseclose(Chan *c) unlock(&mouse); return; } - if(--mouse.ref == 0){ - cursoroff(1); - curs = arrow; - Cursortocursor(&arrow); - cursoron(1); + if(--mouse.ref != 0){ + unlock(&mouse); + return; } unlock(&mouse); + cursoroff(); + curs = arrow; + Cursortocursor(&arrow); + cursoron(); } } @@ -373,7 +373,7 @@ mousewrite(Chan *c, void *va, long n, vlong) error(Eisdir); case Qcursor: - cursoroff(1); + cursoroff(); if(n < 2*4+2*2*16){ curs = arrow; Cursortocursor(&arrow); @@ -385,11 +385,7 @@ mousewrite(Chan *c, void *va, long n, vlong) memmove(curs.set, p+40, 2*16); Cursortocursor(&curs); } - qlock(&mouse); - mouse.redraw = 1; - mouseclock(); - qunlock(&mouse); - cursoron(1); + cursoron(); return n; case Qmousectl: @@ -466,14 +462,10 @@ mousewrite(Chan *c, void *va, long n, vlong) if(p == 0) error(Eshort); pt.y = strtoul(p, 0, 0); - qlock(&mouse); - if(ptinrect(pt, gscreen->r)){ + if(gscreen != nil && ptinrect(pt, gscreen->r)){ mouse.xy = pt; - mouse.redraw = 1; - mouse.track = 1; - mouseclock(); + mousetrack(0, 0, mouse.buttons, TK2MS(MACHP(0)->ticks)); } - qunlock(&mouse); return n; } @@ -505,32 +497,40 @@ Dev mousedevtab = { void Cursortocursor(Cursor *c) { + qlock(&drawlock); lock(&cursor); memmove(&cursor.Cursor, c, sizeof(Cursor)); setcursor(c); unlock(&cursor); + qunlock(&drawlock); } +static int +shouldredraw(void*) +{ + return mouse.redraw != 0; +} + /* - * called by the clock routine to redraw the cursor + * process that redraws the cursor */ static void -mouseclock(void) +mouseproc(void*) { - if(mouse.track){ - mousetrack(mouse.dx, mouse.dy, mouse.buttons, TK2MS(MACHP(0)->ticks)); - mouse.track = 0; - mouse.dx = 0; - mouse.dy = 0; + while(waserror()) + ; + for(;;){ + if(mouse.redraw){ + mouse.redraw = 0; + cursoroff(); + cursoron(); + drawactive(1); + } else { + drawactive(0); + } + tsleep(&mouse.redrawr, shouldredraw, 0, 20*1000); } - if(mouse.redraw && canlock(&cursor)){ - mouse.redraw = 0; - cursoroff(0); - mouse.redraw = cursoron(0); - unlock(&cursor); - } - drawactive(0); } static int @@ -595,7 +595,6 @@ absmousetrack(int x, int y, int b, int msec) lastb = mouse.buttons; mouse.xy = Pt(x, y); mouse.buttons = b; - mouse.redraw = 1; mouse.counter++; mouse.msec = msec; @@ -611,7 +610,8 @@ absmousetrack(int x, int y, int b, int msec) mouse.qfull = 1; } wakeup(&mouse.r); - drawactive(1); + + mouseredraw(); } /* @@ -782,3 +782,9 @@ mouseresize(void) wakeup(&mouse.r); } +void +mouseredraw(void) +{ + mouse.redraw = 1; + wakeup(&mouse.redrawr); +} diff --git a/sys/src/9/port/portmkfile b/sys/src/9/port/portmkfile index 2f5ab1d54..c796452db 100644 --- a/sys/src/9/port/portmkfile +++ b/sys/src/9/port/portmkfile @@ -81,6 +81,7 @@ devuart.$O: ../port/netif.h devmouse.$O: screen.h /sys/include/memdraw.h devdraw.$O: screen.h /sys/include/memdraw.h screen.$O: screen.h /sys/include/memdraw.h +swcursor.$O: screen.h /sys/include/memdraw.h thwack.$O: ../port/thwack.h unthwack.$O: ../port/thwack.h devsdp.$O: ../port/thwack.h diff --git a/sys/src/9/port/swcursor.c b/sys/src/9/port/swcursor.c new file mode 100644 index 000000000..55ea014d0 --- /dev/null +++ b/sys/src/9/port/swcursor.c @@ -0,0 +1,133 @@ +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "../port/error.h" + +#define Image IMAGE +#include +#include +#include +#include "screen.h" + +extern Memimage* gscreen; + +/* + * Software cursor. + */ +static Memimage* swback; /* screen under cursor */ +static Memimage* swimg; /* cursor image */ +static Memimage* swmask; /* cursor mask */ +static Memimage* swimg1; +static Memimage* swmask1; + +static Point swoffset; +static Rectangle swrect; /* screen rectangle in swback */ +static Point swvispt; /* actual cursor location */ +static int swvisible; /* is the cursor visible? */ + +/* + * called with drawlock locked for us, most of the time. + * kernel prints at inopportune times might mean we don't + * hold the lock, but memimagedraw is now reentrant so + * that should be okay: worst case we get cursor droppings. + */ +void +swcursorhide(void) +{ + if(swvisible == 0) + return; + if(swback == nil || gscreen == nil) + return; + swvisible = 0; + memimagedraw(gscreen, swrect, swback, ZP, memopaque, ZP, S); + flushmemscreen(swrect); +} + +void +swcursoravoid(Rectangle r) +{ + if(swvisible && rectXrect(r, swrect)){ + swcursorhide(); + mouseredraw(); /* schedule cursor redraw after we release drawlock */ + } +} + +void +swcursordraw(Point p) +{ + if(swvisible) + return; + if(swback == nil || swimg1 == nil || swmask1 == nil || gscreen == nil) + return; + assert(!canqlock(&drawlock)); + swvispt = addpt(swoffset, p); + swrect = rectaddpt(Rect(0,0,16,16), swvispt); + memimagedraw(swback, swback->r, gscreen, swvispt, memopaque, ZP, S); + memimagedraw(gscreen, swrect, swimg1, ZP, swmask1, ZP, SoverD); + flushmemscreen(swrect); + swvisible = 1; +} + +void +swcursorload(Cursor *curs) +{ + uchar *ip, *mp; + int i, j, set, clr; + + if(swimg == nil || swmask == nil || swimg1 == nil || swmask1 == nil) + return; + /* + * Build cursor image and mask. + * Image is just the usual cursor image + * but mask is a transparent alpha mask. + * + * The 16x16x8 memimages do not have + * padding at the end of their scan lines. + */ + ip = byteaddr(swimg, ZP); + mp = byteaddr(swmask, ZP); + for(i=0; i<32; i++){ + set = curs->set[i]; + clr = curs->clr[i]; + for(j=0x80; j; j>>=1){ + *ip++ = set&j ? 0x00 : 0xFF; + *mp++ = (clr|set)&j ? 0xFF : 0x00; + } + } + 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) +{ + if(gscreen == nil) + return; + + if(swback){ + freememimage(swback); + freememimage(swmask); + freememimage(swmask1); + freememimage(swimg); + freememimage(swimg1); + } + swback = allocmemimage(Rect(0,0,32,32), 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); + swimg1 = allocmemimage(Rect(0,0,16,16), GREY1); + if(swback == nil || swmask == nil || swmask1 == nil || swimg == nil || swimg1 == nil){ + print("software cursor: allocmemimage fails\n"); + return; + } + memfillcolor(swback, DTransparent); + memfillcolor(swmask, DOpaque); + memfillcolor(swmask1, DOpaque); + memfillcolor(swimg, DBlack); + memfillcolor(swimg1, DBlack); +}