summaryrefslogtreecommitdiff
path: root/sys/src/9/bcm
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@gmx.de>2013-04-14 16:28:54 +0200
committercinap_lenrek <cinap_lenrek@gmx.de>2013-04-14 16:28:54 +0200
commit3045d639691c893dfa3393f88289ad72cbcdd86e (patch)
treea9e85a6669b8c4ffbc9324cfc35394ceb1b129f9 /sys/src/9/bcm
parent58e500f4a717a9faf912e503fa7ba9cbe71a84cc (diff)
reduce software cursor flickering
the software cursor starts flickering and reacts bumby if a process spends most of its time with drawlock acquired because the timer interrupt thats supposed to redraw the cursor fails to acquire the lock at the time the timer fires. instead of trying to draw the cursor on the screen from a timer interrupt 30 times per second, devmouse now creates a process calling cursoron() and cursoroff() when the cursor needs to be redrawn. this allows the swcursor to schedule a redraw while holding the drawlock in swcursoravoid() and cursoron()/cursoroff() are now able to wait for a qlock (drawlock) because they get called from process context. the overall responsiveness is also improved with this change as the cursor redraw rate isnt limited to 30 times a second anymore.
Diffstat (limited to 'sys/src/9/bcm')
-rw-r--r--sys/src/9/bcm/fns.h1
-rw-r--r--sys/src/9/bcm/main.c2
-rw-r--r--sys/src/9/bcm/picpuf2
-rw-r--r--sys/src/9/bcm/pif2
-rw-r--r--sys/src/9/bcm/screen.c200
-rw-r--r--sys/src/9/bcm/screen.h12
6 files changed, 27 insertions, 192 deletions
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)
-{
- 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;
-}
-
void
-cursoroff(int dolock)
+cursoron(void)
{
- if (dolock)
- lock(&cursor);
+ qlock(&drawlock);
+ lock(&cursor);
swcursorhide();
- if (dolock)
- unlock(&cursor);
+ swcursordraw(mousexy());
+ unlock(&cursor);
+ qunlock(&drawlock);
}
-static void
-swload(Cursor *curs)
+void
+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(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);