17dd7cddfSDavid du Colombier #include <u.h>
27dd7cddfSDavid du Colombier #include <libc.h>
37dd7cddfSDavid du Colombier #include <draw.h>
47dd7cddfSDavid du Colombier
57dd7cddfSDavid du Colombier Display *display;
67dd7cddfSDavid du Colombier Font *font;
77dd7cddfSDavid du Colombier Image *screen;
8711d1557SDavid du Colombier int _drawdebug = 0;
97dd7cddfSDavid du Colombier
107dd7cddfSDavid du Colombier static char deffontname[] = "*default*";
117dd7cddfSDavid du Colombier Screen *_screen;
127dd7cddfSDavid du Colombier
137dd7cddfSDavid du Colombier int debuglockdisplay = 0;
147dd7cddfSDavid du Colombier
15f366f900SDavid du Colombier static void _closedisplay(Display*, int);
16f366f900SDavid du Colombier
17f366f900SDavid du Colombier /* note handler */
187dd7cddfSDavid du Colombier static void
drawshutdown(void)197dd7cddfSDavid du Colombier drawshutdown(void)
207dd7cddfSDavid du Colombier {
217dd7cddfSDavid du Colombier Display *d;
227dd7cddfSDavid du Colombier
237dd7cddfSDavid du Colombier d = display;
247dd7cddfSDavid du Colombier if(d){
257dd7cddfSDavid du Colombier display = nil;
26f366f900SDavid du Colombier _closedisplay(d, 1);
277dd7cddfSDavid du Colombier }
287dd7cddfSDavid du Colombier }
297dd7cddfSDavid du Colombier
307dd7cddfSDavid du Colombier int
geninitdraw(char * devdir,void (* error)(Display *,char *),char * fontname,char * label,char * windir,int ref)317dd7cddfSDavid du Colombier geninitdraw(char *devdir, void(*error)(Display*, char*), char *fontname, char *label, char *windir, int ref)
327dd7cddfSDavid du Colombier {
337dd7cddfSDavid du Colombier int fd, n;
347dd7cddfSDavid du Colombier Subfont *df;
357dd7cddfSDavid du Colombier char buf[128];
367dd7cddfSDavid du Colombier
377dd7cddfSDavid du Colombier display = initdisplay(devdir, windir, error);
387dd7cddfSDavid du Colombier if(display == nil)
397dd7cddfSDavid du Colombier return -1;
407dd7cddfSDavid du Colombier
417dd7cddfSDavid du Colombier /*
427dd7cddfSDavid du Colombier * Set up default font
437dd7cddfSDavid du Colombier */
447dd7cddfSDavid du Colombier df = getdefont(display);
457dd7cddfSDavid du Colombier display->defaultsubfont = df;
467dd7cddfSDavid du Colombier if(df == nil){
479a747e4fSDavid du Colombier fprint(2, "imageinit: can't open default subfont: %r\n");
487dd7cddfSDavid du Colombier Error:
497dd7cddfSDavid du Colombier closedisplay(display);
507dd7cddfSDavid du Colombier display = nil;
517dd7cddfSDavid du Colombier return -1;
527dd7cddfSDavid du Colombier }
537dd7cddfSDavid du Colombier if(fontname == nil){
547dd7cddfSDavid du Colombier fd = open("/env/font", OREAD);
557dd7cddfSDavid du Colombier if(fd >= 0){
567dd7cddfSDavid du Colombier n = read(fd, buf, sizeof(buf));
577dd7cddfSDavid du Colombier if(n>0 && n<sizeof buf-1){
587dd7cddfSDavid du Colombier buf[n] = 0;
597dd7cddfSDavid du Colombier fontname = buf;
607dd7cddfSDavid du Colombier }
617dd7cddfSDavid du Colombier close(fd);
627dd7cddfSDavid du Colombier }
637dd7cddfSDavid du Colombier }
647dd7cddfSDavid du Colombier /*
657dd7cddfSDavid du Colombier * Build fonts with caches==depth of screen, for speed.
667dd7cddfSDavid du Colombier * If conversion were faster, we'd use 0 and save memory.
677dd7cddfSDavid du Colombier */
687dd7cddfSDavid du Colombier if(fontname == nil){
697dd7cddfSDavid du Colombier snprint(buf, sizeof buf, "%d %d\n0 %d\t%s\n", df->height, df->ascent,
707dd7cddfSDavid du Colombier df->n-1, deffontname);
717dd7cddfSDavid du Colombier //BUG: Need something better for this installsubfont("*default*", df);
727dd7cddfSDavid du Colombier font = buildfont(display, buf, deffontname);
737dd7cddfSDavid du Colombier if(font == nil){
749a747e4fSDavid du Colombier fprint(2, "imageinit: can't open default font: %r\n");
757dd7cddfSDavid du Colombier goto Error;
767dd7cddfSDavid du Colombier }
777dd7cddfSDavid du Colombier }else{
787dd7cddfSDavid du Colombier font = openfont(display, fontname); /* BUG: grey fonts */
797dd7cddfSDavid du Colombier if(font == nil){
809a747e4fSDavid du Colombier fprint(2, "imageinit: can't open font %s: %r\n", fontname);
817dd7cddfSDavid du Colombier goto Error;
827dd7cddfSDavid du Colombier }
837dd7cddfSDavid du Colombier }
847dd7cddfSDavid du Colombier display->defaultfont = font;
857dd7cddfSDavid du Colombier
867dd7cddfSDavid du Colombier /*
877dd7cddfSDavid du Colombier * Write label; ignore errors (we might not be running under rio)
887dd7cddfSDavid du Colombier */
897dd7cddfSDavid du Colombier if(label){
907dd7cddfSDavid du Colombier snprint(buf, sizeof buf, "%s/label", display->windir);
917dd7cddfSDavid du Colombier fd = open(buf, OREAD);
927dd7cddfSDavid du Colombier if(fd >= 0){
937dd7cddfSDavid du Colombier read(fd, display->oldlabel, (sizeof display->oldlabel)-1);
947dd7cddfSDavid du Colombier close(fd);
957dd7cddfSDavid du Colombier fd = create(buf, OWRITE, 0666);
967dd7cddfSDavid du Colombier if(fd >= 0){
977dd7cddfSDavid du Colombier write(fd, label, strlen(label));
987dd7cddfSDavid du Colombier close(fd);
997dd7cddfSDavid du Colombier }
1007dd7cddfSDavid du Colombier }
1017dd7cddfSDavid du Colombier }
1027dd7cddfSDavid du Colombier
1039a747e4fSDavid du Colombier snprint(buf, sizeof buf, "%s/winname", display->windir);
1049a747e4fSDavid du Colombier if(gengetwindow(display, buf, &screen, &_screen, ref) < 0)
1057dd7cddfSDavid du Colombier goto Error;
1067dd7cddfSDavid du Colombier
1077dd7cddfSDavid du Colombier atexit(drawshutdown);
1087dd7cddfSDavid du Colombier
1097dd7cddfSDavid du Colombier return 1;
1107dd7cddfSDavid du Colombier }
1117dd7cddfSDavid du Colombier
1127dd7cddfSDavid du Colombier int
initdraw(void (* error)(Display *,char *),char * fontname,char * label)1137dd7cddfSDavid du Colombier initdraw(void(*error)(Display*, char*), char *fontname , char *label)
1147dd7cddfSDavid du Colombier {
1157dd7cddfSDavid du Colombier char *dev = "/dev";
1167dd7cddfSDavid du Colombier
1179a747e4fSDavid du Colombier if(access("/dev/draw/new", AEXIST)<0 && bind("#i", "/dev", MAFTER)<0){
11872061b92SDavid du Colombier fprint(2, "imageinit: can't bind /dev/draw: %r\n");
1197dd7cddfSDavid du Colombier return -1;
1207dd7cddfSDavid du Colombier }
1217dd7cddfSDavid du Colombier return geninitdraw(dev, error, fontname, label, dev, Refnone);
1227dd7cddfSDavid du Colombier }
1237dd7cddfSDavid du Colombier
1247dd7cddfSDavid du Colombier /*
1257dd7cddfSDavid du Colombier * Attach, or possibly reattach, to window.
1267dd7cddfSDavid du Colombier * If reattaching, maintain value of screen pointer.
1277dd7cddfSDavid du Colombier */
1287dd7cddfSDavid du Colombier int
gengetwindow(Display * d,char * winname,Image ** winp,Screen ** scrp,int ref)12980ee5cbfSDavid du Colombier gengetwindow(Display *d, char *winname, Image **winp, Screen **scrp, int ref)
1307dd7cddfSDavid du Colombier {
1317dd7cddfSDavid du Colombier int n, fd;
13280ee5cbfSDavid du Colombier char buf[64+1];
1337dd7cddfSDavid du Colombier Image *image;
1349a747e4fSDavid du Colombier Rectangle r;
1357dd7cddfSDavid du Colombier
13680ee5cbfSDavid du Colombier fd = open(winname, OREAD);
13780ee5cbfSDavid du Colombier if(fd<0 || (n=read(fd, buf, sizeof buf-1))<=0){
1389a747e4fSDavid du Colombier if((image=d->image) == nil){
1399a747e4fSDavid du Colombier fprint(2, "gengetwindow: %r\n");
1409a747e4fSDavid du Colombier *winp = nil;
1419a747e4fSDavid du Colombier d->screenimage = nil;
1429a747e4fSDavid du Colombier return -1;
1437dd7cddfSDavid du Colombier }
1449a747e4fSDavid du Colombier strcpy(buf, "noborder");
1459a747e4fSDavid du Colombier }else{
1467dd7cddfSDavid du Colombier close(fd);
14780ee5cbfSDavid du Colombier buf[n] = '\0';
14880ee5cbfSDavid du Colombier if(*winp != nil){
14980ee5cbfSDavid du Colombier _freeimage1(*winp);
15080ee5cbfSDavid du Colombier freeimage((*scrp)->image);
15180ee5cbfSDavid du Colombier freescreen(*scrp);
15280ee5cbfSDavid du Colombier *scrp = nil;
1537dd7cddfSDavid du Colombier }
15480ee5cbfSDavid du Colombier image = namedimage(d, buf);
1557dd7cddfSDavid du Colombier if(image == 0){
1569a747e4fSDavid du Colombier fprint(2, "namedimage %s failed: %r\n", buf);
15780ee5cbfSDavid du Colombier *winp = nil;
1589a747e4fSDavid du Colombier d->screenimage = nil;
1597dd7cddfSDavid du Colombier return -1;
1607dd7cddfSDavid du Colombier }
1617dd7cddfSDavid du Colombier assert(image->chan != 0);
1629a747e4fSDavid du Colombier }
1637dd7cddfSDavid du Colombier
1649a747e4fSDavid du Colombier d->screenimage = image;
16580ee5cbfSDavid du Colombier *scrp = allocscreen(image, d->white, 0);
16680ee5cbfSDavid du Colombier if(*scrp == nil){
1679a747e4fSDavid du Colombier freeimage(d->screenimage);
16880ee5cbfSDavid du Colombier *winp = nil;
1699a747e4fSDavid du Colombier d->screenimage = nil;
1707dd7cddfSDavid du Colombier return -1;
1717dd7cddfSDavid du Colombier }
1727dd7cddfSDavid du Colombier
1739a747e4fSDavid du Colombier r = image->r;
1749a747e4fSDavid du Colombier if(strncmp(buf, "noborder", 8) != 0)
1759a747e4fSDavid du Colombier r = insetrect(image->r, Borderwidth);
1769a747e4fSDavid du Colombier *winp = _allocwindow(*winp, *scrp, r, ref, DWhite);
1779a747e4fSDavid du Colombier if(*winp == nil){
1789a747e4fSDavid du Colombier freescreen(*scrp);
1799a747e4fSDavid du Colombier *scrp = nil;
1809a747e4fSDavid du Colombier freeimage(image);
1819a747e4fSDavid du Colombier d->screenimage = nil;
1827dd7cddfSDavid du Colombier return -1;
1839a747e4fSDavid du Colombier }
1849a747e4fSDavid du Colombier d->screenimage = *winp;
18580ee5cbfSDavid du Colombier assert((*winp)->chan != 0);
1867dd7cddfSDavid du Colombier return 1;
1877dd7cddfSDavid du Colombier }
1887dd7cddfSDavid du Colombier
18980ee5cbfSDavid du Colombier int
getwindow(Display * d,int ref)19080ee5cbfSDavid du Colombier getwindow(Display *d, int ref)
19180ee5cbfSDavid du Colombier {
19280ee5cbfSDavid du Colombier char winname[128];
19380ee5cbfSDavid du Colombier
19480ee5cbfSDavid du Colombier snprint(winname, sizeof winname, "%s/winname", d->windir);
19580ee5cbfSDavid du Colombier return gengetwindow(d, winname, &screen, &_screen, ref);
19680ee5cbfSDavid du Colombier }
19780ee5cbfSDavid du Colombier
1987dd7cddfSDavid du Colombier #define NINFO 12*12
1997dd7cddfSDavid du Colombier
2007dd7cddfSDavid du Colombier Display*
initdisplay(char * dev,char * win,void (* error)(Display *,char *))2017dd7cddfSDavid du Colombier initdisplay(char *dev, char *win, void(*error)(Display*, char*))
2027dd7cddfSDavid du Colombier {
203*5d9de2d3SDavid du Colombier char buf[128], info[NINFO+1], *t, isnew;
2049a747e4fSDavid du Colombier int n, datafd, ctlfd, reffd;
2057dd7cddfSDavid du Colombier Display *disp;
2069a747e4fSDavid du Colombier Dir *dir;
2077dd7cddfSDavid du Colombier Image *image;
2087dd7cddfSDavid du Colombier
2099a747e4fSDavid du Colombier fmtinstall('P', Pfmt);
2109a747e4fSDavid du Colombier fmtinstall('R', Rfmt);
2117dd7cddfSDavid du Colombier if(dev == 0)
2127dd7cddfSDavid du Colombier dev = "/dev";
2137dd7cddfSDavid du Colombier if(win == 0)
2147dd7cddfSDavid du Colombier win = "/dev";
2157dd7cddfSDavid du Colombier if(strlen(dev)>sizeof buf-25 || strlen(win)>sizeof buf-25){
2167dd7cddfSDavid du Colombier werrstr("initdisplay: directory name too long");
2177dd7cddfSDavid du Colombier return nil;
2187dd7cddfSDavid du Colombier }
2197dd7cddfSDavid du Colombier t = strdup(win);
2207dd7cddfSDavid du Colombier if(t == nil)
2217dd7cddfSDavid du Colombier return nil;
2227dd7cddfSDavid du Colombier
2237dd7cddfSDavid du Colombier sprint(buf, "%s/draw/new", dev);
2247dd7cddfSDavid du Colombier ctlfd = open(buf, ORDWR|OCEXEC);
2257dd7cddfSDavid du Colombier if(ctlfd < 0){
2267dd7cddfSDavid du Colombier if(bind("#i", dev, MAFTER) < 0){
2277dd7cddfSDavid du Colombier Error1:
2287dd7cddfSDavid du Colombier free(t);
2297dd7cddfSDavid du Colombier werrstr("initdisplay: %s: %r", buf);
2307dd7cddfSDavid du Colombier return 0;
2317dd7cddfSDavid du Colombier }
2327dd7cddfSDavid du Colombier ctlfd = open(buf, ORDWR|OCEXEC);
2337dd7cddfSDavid du Colombier }
2347dd7cddfSDavid du Colombier if(ctlfd < 0)
2357dd7cddfSDavid du Colombier goto Error1;
2369a747e4fSDavid du Colombier if((n=read(ctlfd, info, sizeof info)) < 12){
2377dd7cddfSDavid du Colombier Error2:
2387dd7cddfSDavid du Colombier close(ctlfd);
2397dd7cddfSDavid du Colombier goto Error1;
2407dd7cddfSDavid du Colombier }
2419a747e4fSDavid du Colombier if(n==NINFO+1)
2429a747e4fSDavid du Colombier n = NINFO;
243*5d9de2d3SDavid du Colombier info[n] = '\0';
2449a747e4fSDavid du Colombier isnew = 0;
2459a747e4fSDavid du Colombier if(n < NINFO) /* this will do for now, we need something better here */
2469a747e4fSDavid du Colombier isnew = 1;
2477dd7cddfSDavid du Colombier sprint(buf, "%s/draw/%d/data", dev, atoi(info+0*12));
2487dd7cddfSDavid du Colombier datafd = open(buf, ORDWR|OCEXEC);
2497dd7cddfSDavid du Colombier if(datafd < 0)
2507dd7cddfSDavid du Colombier goto Error2;
2517dd7cddfSDavid du Colombier sprint(buf, "%s/draw/%d/refresh", dev, atoi(info+0*12));
2527dd7cddfSDavid du Colombier reffd = open(buf, OREAD|OCEXEC);
2537dd7cddfSDavid du Colombier if(reffd < 0){
2547dd7cddfSDavid du Colombier Error3:
2557dd7cddfSDavid du Colombier close(datafd);
2567dd7cddfSDavid du Colombier goto Error2;
2577dd7cddfSDavid du Colombier }
2589a747e4fSDavid du Colombier disp = mallocz(sizeof(Display), 1);
2597dd7cddfSDavid du Colombier if(disp == 0){
2607dd7cddfSDavid du Colombier Error4:
2617dd7cddfSDavid du Colombier close(reffd);
2627dd7cddfSDavid du Colombier goto Error3;
2637dd7cddfSDavid du Colombier }
2649a747e4fSDavid du Colombier image = nil;
2659a747e4fSDavid du Colombier if(0){
2667dd7cddfSDavid du Colombier Error5:
2679a747e4fSDavid du Colombier free(image);
2687dd7cddfSDavid du Colombier free(disp);
2697dd7cddfSDavid du Colombier goto Error4;
2707dd7cddfSDavid du Colombier }
2719a747e4fSDavid du Colombier if(n >= NINFO){
2729a747e4fSDavid du Colombier image = mallocz(sizeof(Image), 1);
2739a747e4fSDavid du Colombier if(image == nil)
2749a747e4fSDavid du Colombier goto Error5;
2757dd7cddfSDavid du Colombier image->display = disp;
2767dd7cddfSDavid du Colombier image->id = 0;
2779a747e4fSDavid du Colombier image->chan = strtochan(info+2*12);
2789a747e4fSDavid du Colombier image->depth = chantodepth(image->chan);
2797dd7cddfSDavid du Colombier image->repl = atoi(info+3*12);
2807dd7cddfSDavid du Colombier image->r.min.x = atoi(info+4*12);
2817dd7cddfSDavid du Colombier image->r.min.y = atoi(info+5*12);
2827dd7cddfSDavid du Colombier image->r.max.x = atoi(info+6*12);
2837dd7cddfSDavid du Colombier image->r.max.y = atoi(info+7*12);
2847dd7cddfSDavid du Colombier image->clipr.min.x = atoi(info+8*12);
2857dd7cddfSDavid du Colombier image->clipr.min.y = atoi(info+9*12);
2867dd7cddfSDavid du Colombier image->clipr.max.x = atoi(info+10*12);
2877dd7cddfSDavid du Colombier image->clipr.max.y = atoi(info+11*12);
2889a747e4fSDavid du Colombier }
2899a747e4fSDavid du Colombier
2909a747e4fSDavid du Colombier disp->_isnewdisplay = isnew;
2919a747e4fSDavid du Colombier disp->bufsize = iounit(datafd);
2929a747e4fSDavid du Colombier if(disp->bufsize <= 0)
2939a747e4fSDavid du Colombier disp->bufsize = 8000;
2949a747e4fSDavid du Colombier if(disp->bufsize < 512){
2959a747e4fSDavid du Colombier werrstr("iounit %d too small", disp->bufsize);
2969a747e4fSDavid du Colombier goto Error5;
2979a747e4fSDavid du Colombier }
2989a747e4fSDavid du Colombier disp->buf = malloc(disp->bufsize+5); /* +5 for flush message */
2999a747e4fSDavid du Colombier if(disp->buf == nil)
3009a747e4fSDavid du Colombier goto Error5;
3019a747e4fSDavid du Colombier
3029a747e4fSDavid du Colombier disp->image = image;
3037dd7cddfSDavid du Colombier disp->dirno = atoi(info+0*12);
3047dd7cddfSDavid du Colombier disp->fd = datafd;
3057dd7cddfSDavid du Colombier disp->ctlfd = ctlfd;
3067dd7cddfSDavid du Colombier disp->reffd = reffd;
3077dd7cddfSDavid du Colombier disp->bufp = disp->buf;
3087dd7cddfSDavid du Colombier disp->error = error;
3097dd7cddfSDavid du Colombier disp->windir = t;
3107dd7cddfSDavid du Colombier disp->devdir = strdup(dev);
3117dd7cddfSDavid du Colombier qlock(&disp->qlock);
3127dd7cddfSDavid du Colombier disp->white = allocimage(disp, Rect(0, 0, 1, 1), GREY1, 1, DWhite);
3137dd7cddfSDavid du Colombier disp->black = allocimage(disp, Rect(0, 0, 1, 1), GREY1, 1, DBlack);
3147dd7cddfSDavid du Colombier if(disp->white == nil || disp->black == nil){
3157dd7cddfSDavid du Colombier free(disp->devdir);
3167dd7cddfSDavid du Colombier free(disp->white);
3177dd7cddfSDavid du Colombier free(disp->black);
3187dd7cddfSDavid du Colombier goto Error5;
3197dd7cddfSDavid du Colombier }
3207dd7cddfSDavid du Colombier disp->opaque = disp->white;
3217dd7cddfSDavid du Colombier disp->transparent = disp->black;
3229a747e4fSDavid du Colombier dir = dirfstat(ctlfd);
3239a747e4fSDavid du Colombier if(dir!=nil && dir->type=='i'){
3247dd7cddfSDavid du Colombier disp->local = 1;
3259a747e4fSDavid du Colombier disp->dataqid = dir->qid.path;
3267dd7cddfSDavid du Colombier }
3279a747e4fSDavid du Colombier if(dir!=nil && dir->qid.vers==1) /* other way to tell */
3289a747e4fSDavid du Colombier disp->_isnewdisplay = 1;
3299a747e4fSDavid du Colombier free(dir);
3307dd7cddfSDavid du Colombier
3317dd7cddfSDavid du Colombier return disp;
3327dd7cddfSDavid du Colombier }
3337dd7cddfSDavid du Colombier
3347dd7cddfSDavid du Colombier /*
3357dd7cddfSDavid du Colombier * Call with d unlocked.
3367dd7cddfSDavid du Colombier * Note that disp->defaultfont and defaultsubfont are not freed here.
3377dd7cddfSDavid du Colombier */
3387dd7cddfSDavid du Colombier void
closedisplay(Display * disp)3397dd7cddfSDavid du Colombier closedisplay(Display *disp)
3407dd7cddfSDavid du Colombier {
341f366f900SDavid du Colombier _closedisplay(disp, 0);
342f366f900SDavid du Colombier }
343f366f900SDavid du Colombier
344f366f900SDavid du Colombier static void
_closedisplay(Display * disp,int isshutdown)345f366f900SDavid du Colombier _closedisplay(Display *disp, int isshutdown)
346f366f900SDavid du Colombier {
3477dd7cddfSDavid du Colombier int fd;
3487dd7cddfSDavid du Colombier char buf[128];
3497dd7cddfSDavid du Colombier
3507dd7cddfSDavid du Colombier if(disp == nil)
3517dd7cddfSDavid du Colombier return;
3527dd7cddfSDavid du Colombier if(disp == display)
3537dd7cddfSDavid du Colombier display = nil;
3547dd7cddfSDavid du Colombier if(disp->oldlabel[0]){
3557dd7cddfSDavid du Colombier snprint(buf, sizeof buf, "%s/label", disp->windir);
3567dd7cddfSDavid du Colombier fd = open(buf, OWRITE);
3577dd7cddfSDavid du Colombier if(fd >= 0){
3587dd7cddfSDavid du Colombier write(fd, disp->oldlabel, strlen(disp->oldlabel));
3597dd7cddfSDavid du Colombier close(fd);
3607dd7cddfSDavid du Colombier }
3617dd7cddfSDavid du Colombier }
3627dd7cddfSDavid du Colombier
363f366f900SDavid du Colombier /*
364f366f900SDavid du Colombier * if we're shutting down, don't free all the resources.
365f366f900SDavid du Colombier * if other procs are getting shot down by notes too,
366f366f900SDavid du Colombier * one might get shot down while holding the malloc lock.
367f366f900SDavid du Colombier * just let the kernel clean things up when we exit.
368f366f900SDavid du Colombier */
369f366f900SDavid du Colombier if(isshutdown)
370f366f900SDavid du Colombier return;
371f366f900SDavid du Colombier
3727dd7cddfSDavid du Colombier free(disp->devdir);
3737dd7cddfSDavid du Colombier free(disp->windir);
3747dd7cddfSDavid du Colombier freeimage(disp->white);
3757dd7cddfSDavid du Colombier freeimage(disp->black);
3767dd7cddfSDavid du Colombier close(disp->fd);
3777dd7cddfSDavid du Colombier close(disp->ctlfd);
3787dd7cddfSDavid du Colombier /* should cause refresh slave to shut down */
3797dd7cddfSDavid du Colombier close(disp->reffd);
3807dd7cddfSDavid du Colombier qunlock(&disp->qlock);
3817dd7cddfSDavid du Colombier free(disp);
3827dd7cddfSDavid du Colombier }
3837dd7cddfSDavid du Colombier
3847dd7cddfSDavid du Colombier void
lockdisplay(Display * disp)3857dd7cddfSDavid du Colombier lockdisplay(Display *disp)
3867dd7cddfSDavid du Colombier {
3877dd7cddfSDavid du Colombier if(debuglockdisplay){
3887dd7cddfSDavid du Colombier /* avoid busy looping; it's rare we collide anyway */
3897dd7cddfSDavid du Colombier while(!canqlock(&disp->qlock)){
3909a747e4fSDavid du Colombier fprint(1, "proc %d waiting for display lock...\n", getpid());
3917dd7cddfSDavid du Colombier sleep(1000);
3927dd7cddfSDavid du Colombier }
3937dd7cddfSDavid du Colombier }else
3947dd7cddfSDavid du Colombier qlock(&disp->qlock);
3957dd7cddfSDavid du Colombier }
3967dd7cddfSDavid du Colombier
3977dd7cddfSDavid du Colombier void
unlockdisplay(Display * disp)3987dd7cddfSDavid du Colombier unlockdisplay(Display *disp)
3997dd7cddfSDavid du Colombier {
4007dd7cddfSDavid du Colombier qunlock(&disp->qlock);
4017dd7cddfSDavid du Colombier }
4027dd7cddfSDavid du Colombier
4037dd7cddfSDavid du Colombier void
drawerror(Display * d,char * s)4047dd7cddfSDavid du Colombier drawerror(Display *d, char *s)
4057dd7cddfSDavid du Colombier {
4069a747e4fSDavid du Colombier char err[ERRMAX];
4077dd7cddfSDavid du Colombier
4088d37e088SDavid du Colombier if(d && d->error)
4097dd7cddfSDavid du Colombier d->error(d, s);
4107dd7cddfSDavid du Colombier else{
4119a747e4fSDavid du Colombier errstr(err, sizeof err);
4129a747e4fSDavid du Colombier fprint(2, "draw: %s: %s\n", s, err);
4137dd7cddfSDavid du Colombier exits(s);
4147dd7cddfSDavid du Colombier }
4157dd7cddfSDavid du Colombier }
4167dd7cddfSDavid du Colombier
4177dd7cddfSDavid du Colombier static
4187dd7cddfSDavid du Colombier int
doflush(Display * d)4197dd7cddfSDavid du Colombier doflush(Display *d)
4207dd7cddfSDavid du Colombier {
421711d1557SDavid du Colombier int n, nn;
4227dd7cddfSDavid du Colombier
4237dd7cddfSDavid du Colombier n = d->bufp-d->buf;
4247dd7cddfSDavid du Colombier if(n <= 0)
4257dd7cddfSDavid du Colombier return 1;
4267dd7cddfSDavid du Colombier
427711d1557SDavid du Colombier if((nn=write(d->fd, d->buf, n)) != n){
42859cc4ca5SDavid du Colombier if(_drawdebug)
429711d1557SDavid du Colombier fprint(2, "flushimage fail: d=%p: n=%d nn=%d %r\n", d, n, nn); /**/
4307dd7cddfSDavid du Colombier d->bufp = d->buf; /* might as well; chance of continuing */
4317dd7cddfSDavid du Colombier return -1;
4327dd7cddfSDavid du Colombier }
4337dd7cddfSDavid du Colombier d->bufp = d->buf;
4347dd7cddfSDavid du Colombier return 1;
4357dd7cddfSDavid du Colombier }
4367dd7cddfSDavid du Colombier
4377dd7cddfSDavid du Colombier int
flushimage(Display * d,int visible)4387dd7cddfSDavid du Colombier flushimage(Display *d, int visible)
4397dd7cddfSDavid du Colombier {
440108f07eeSDavid du Colombier if(d == nil)
441108f07eeSDavid du Colombier return 0;
4429a747e4fSDavid du Colombier if(visible){
4439a747e4fSDavid du Colombier *d->bufp++ = 'v'; /* five bytes always reserved for this */
4449a747e4fSDavid du Colombier if(d->_isnewdisplay){
4459a747e4fSDavid du Colombier BPLONG(d->bufp, d->screenimage->id);
4469a747e4fSDavid du Colombier d->bufp += 4;
4479a747e4fSDavid du Colombier }
4489a747e4fSDavid du Colombier }
4497dd7cddfSDavid du Colombier return doflush(d);
4507dd7cddfSDavid du Colombier }
4517dd7cddfSDavid du Colombier
4527dd7cddfSDavid du Colombier uchar*
bufimage(Display * d,int n)4537dd7cddfSDavid du Colombier bufimage(Display *d, int n)
4547dd7cddfSDavid du Colombier {
4557dd7cddfSDavid du Colombier uchar *p;
4567dd7cddfSDavid du Colombier
4579a747e4fSDavid du Colombier if(n<0 || n>d->bufsize){
4587dd7cddfSDavid du Colombier werrstr("bad count in bufimage");
4597dd7cddfSDavid du Colombier return 0;
4607dd7cddfSDavid du Colombier }
4619a747e4fSDavid du Colombier if(d->bufp+n > d->buf+d->bufsize)
4627dd7cddfSDavid du Colombier if(doflush(d) < 0)
4637dd7cddfSDavid du Colombier return 0;
4647dd7cddfSDavid du Colombier p = d->bufp;
4657dd7cddfSDavid du Colombier d->bufp += n;
4667dd7cddfSDavid du Colombier return p;
4677dd7cddfSDavid du Colombier }
4687dd7cddfSDavid du Colombier
469