devdraw: use global drawlk instead of per-client

Setting up for a real window system.
This commit is contained in:
Russ Cox 2020-01-25 14:33:20 -05:00
parent 94d381ec9d
commit 587933c161
3 changed files with 20 additions and 18 deletions

View file

@ -14,6 +14,8 @@
#include <drawfcall.h> #include <drawfcall.h>
#include "devdraw.h" #include "devdraw.h"
QLock drawlk;
static int drawuninstall(Client*, int); static int drawuninstall(Client*, int);
static Memimage* drawinstall(Client*, int, Memimage*, DScreen*); static Memimage* drawinstall(Client*, int, Memimage*, DScreen*);
static void drawfreedimage(Client*, DImage*); static void drawfreedimage(Client*, DImage*);
@ -47,14 +49,14 @@ gfx_replacescreenimage(Client *c, Memimage *m)
*/ */
Memimage *om; Memimage *om;
qlock(&c->drawlk); qlock(&drawlk);
om = c->screenimage; om = c->screenimage;
c->screenimage = m; c->screenimage = m;
m->screenref = 1; m->screenref = 1;
if(om && --om->screenref == 0){ if(om && --om->screenref == 0){
_freememimage(om); _freememimage(om);
} }
qunlock(&c->drawlk); qunlock(&drawlk);
gfx_mouseresized(c); gfx_mouseresized(c);
} }
@ -142,9 +144,9 @@ addflush(Client *c, Rectangle r)
// and gfx thread might be blocked on drawlk trying to install a new screen // and gfx thread might be blocked on drawlk trying to install a new screen
// during a resize. // during a resize.
rpc_gfxdrawunlock(); rpc_gfxdrawunlock();
qunlock(&c->drawlk); qunlock(&drawlk);
c->impl->rpc_flush(c, fr); c->impl->rpc_flush(c, fr);
qlock(&c->drawlk); qlock(&drawlk);
rpc_gfxdrawlock(); rpc_gfxdrawlock();
} }
} }
@ -187,9 +189,9 @@ drawflush(Client *c)
// and gfx thread might be blocked on drawlk trying to install a new screen // and gfx thread might be blocked on drawlk trying to install a new screen
// during a resize. // during a resize.
rpc_gfxdrawunlock(); rpc_gfxdrawunlock();
qunlock(&c->drawlk); qunlock(&drawlk);
c->impl->rpc_flush(c, r); c->impl->rpc_flush(c, r);
qlock(&c->drawlk); qlock(&drawlk);
rpc_gfxdrawlock(); rpc_gfxdrawlock();
} }
} }
@ -614,7 +616,7 @@ drawcoord(uchar *p, uchar *maxp, int oldx, int *newx)
int int
draw_dataread(Client *cl, void *a, int n) draw_dataread(Client *cl, void *a, int n)
{ {
qlock(&cl->drawlk); qlock(&drawlk);
if(cl->readdata == nil){ if(cl->readdata == nil){
werrstr("no draw data"); werrstr("no draw data");
goto err; goto err;
@ -627,11 +629,11 @@ draw_dataread(Client *cl, void *a, int n)
memmove(a, cl->readdata, cl->nreaddata); memmove(a, cl->readdata, cl->nreaddata);
free(cl->readdata); free(cl->readdata);
cl->readdata = nil; cl->readdata = nil;
qunlock(&cl->drawlk); qunlock(&drawlk);
return n; return n;
err: err:
qunlock(&cl->drawlk); qunlock(&drawlk);
return -1; return -1;
} }
@ -656,7 +658,7 @@ draw_datawrite(Client *client, void *v, int n)
Refreshfn reffn; Refreshfn reffn;
Refx *refx; Refx *refx;
qlock(&client->drawlk); qlock(&drawlk);
rpc_gfxdrawlock(); rpc_gfxdrawlock();
a = v; a = v;
m = 0; m = 0;
@ -1431,7 +1433,7 @@ draw_datawrite(Client *client, void *v, int n)
} }
} }
rpc_gfxdrawunlock(); rpc_gfxdrawunlock();
qunlock(&client->drawlk); qunlock(&drawlk);
return oldn - n; return oldn - n;
Enodrawimage: Enodrawimage:
@ -1502,6 +1504,6 @@ Ebadarg:
error: error:
werrstr("%s", err); werrstr("%s", err);
rpc_gfxdrawunlock(); rpc_gfxdrawunlock();
qunlock(&client->drawlk); qunlock(&drawlk);
return -1; return -1;
} }

View file

@ -56,6 +56,8 @@ struct ClientImpl
void (*rpc_flush)(Client*, Rectangle); void (*rpc_flush)(Client*, Rectangle);
}; };
extern QLock drawlk;
struct Client struct Client
{ {
int rfd; int rfd;
@ -69,10 +71,9 @@ struct Client
char* wsysid; char* wsysid;
// drawlk protects the draw data structures. // drawlk protects the draw data structures for all clients.
// It can be acquired by an RPC thread or a graphics thread // It can be acquired by an RPC thread or a graphics thread
// but must not be held on one thread while waiting for the other. // but must not be held on one thread while waiting for the other.
QLock drawlk;
/*Ref r;*/ /*Ref r;*/
DImage* dimage[NHASH]; DImage* dimage[NHASH];
CScreen* cscreen; CScreen* cscreen;

View file

@ -39,7 +39,6 @@ static uint msec(void);
static void rpc_resizeimg(Client*); static void rpc_resizeimg(Client*);
static void rpc_resizewindow(Client*, Rectangle); static void rpc_resizewindow(Client*, Rectangle);
static void rpc_serve(Client*);
static void rpc_setcursor(Client*, Cursor*, Cursor2*); static void rpc_setcursor(Client*, Cursor*, Cursor2*);
static void rpc_setlabel(Client*, char*); static void rpc_setlabel(Client*, char*);
static void rpc_setmouse(Client*, Point); static void rpc_setmouse(Client*, Point);
@ -496,17 +495,17 @@ rpc_flush(Client *client, Rectangle r)
if(!rectclip(&r, Rect(0, 0, self.dlayer.texture.width, self.dlayer.texture.height)) || !rectclip(&r, self.img->r)) if(!rectclip(&r, Rect(0, 0, self.dlayer.texture.width, self.dlayer.texture.height)) || !rectclip(&r, self.img->r))
return; return;
// self.client->drawlk protects the pixel data in self.img. // drawlk protects the pixel data in self.img.
// In addition to avoiding a technical data race, // In addition to avoiding a technical data race,
// the lock avoids drawing partial updates, which makes // the lock avoids drawing partial updates, which makes
// animations like sweeping windows much less flickery. // animations like sweeping windows much less flickery.
qlock(&self.client->drawlk); qlock(&drawlk);
[self.dlayer.texture [self.dlayer.texture
replaceRegion:MTLRegionMake2D(r.min.x, r.min.y, Dx(r), Dy(r)) replaceRegion:MTLRegionMake2D(r.min.x, r.min.y, Dx(r), Dy(r))
mipmapLevel:0 mipmapLevel:0
withBytes:byteaddr(self.img, Pt(r.min.x, r.min.y)) withBytes:byteaddr(self.img, Pt(r.min.x, r.min.y))
bytesPerRow:self.img->width*sizeof(u32int)]; bytesPerRow:self.img->width*sizeof(u32int)];
qunlock(&self.client->drawlk); qunlock(&drawlk);
NSRect nr = NSMakeRect(r.min.x, r.min.y, Dx(r), Dy(r)); NSRect nr = NSMakeRect(r.min.x, r.min.y, Dx(r), Dy(r));
dispatch_time_t time; dispatch_time_t time;