10 static char deffontname[] = "*default*";
13 int debuglockdisplay = 0;
15 static void _closedisplay(Display*, int);
31 geninitdraw(char *devdir, void(*error)(Display*, char*), char *fontname, char *label, char *windir, int ref)
37 display = initdisplay(devdir, windir, error);
44 df = getdefont(display);
45 display->defaultsubfont = df;
47 fprint(2, "imageinit: can't open default subfont: %r\n");
49 closedisplay(display);
54 fd = open("/env/font", OREAD);
56 n = read(fd, buf, sizeof(buf));
57 if(n>0 && n<sizeof buf-1){
65 * Build fonts with caches==depth of screen, for speed.
66 * If conversion were faster, we'd use 0 and save memory.
69 snprint(buf, sizeof buf, "%d %d\n0 %d\t%s\n", df->height, df->ascent,
70 df->n-1, deffontname);
71 //BUG: Need something better for this installsubfont("*default*", df);
72 font = buildfont(display, buf, deffontname);
74 fprint(2, "imageinit: can't open default font: %r\n");
78 font = openfont(display, fontname); /* BUG: grey fonts */
80 fprint(2, "imageinit: can't open font %s: %r\n", fontname);
84 display->defaultfont = font;
87 * Write label; ignore errors (we might not be running under rio)
90 snprint(buf, sizeof buf, "%s/label", display->windir);
91 fd = open(buf, OREAD);
93 read(fd, display->oldlabel, (sizeof display->oldlabel)-1);
95 fd = create(buf, OWRITE, 0666);
97 write(fd, label, strlen(label));
103 snprint(buf, sizeof buf, "%s/winname", display->windir);
104 if(gengetwindow(display, buf, &screen, &_screen, ref) < 0)
107 atexit(drawshutdown);
113 initdraw(void(*error)(Display*, char*), char *fontname , char *label)
117 if(access("/dev/draw/new", AEXIST)<0 && bind("#i", "/dev", MAFTER)<0){
118 fprint(2, "imageinit: can't bind /dev/draw: %r\n");
121 return geninitdraw(dev, error, fontname, label, dev, Refnone);
125 * Attach, or possibly reattach, to window.
126 * If reattaching, maintain value of screen pointer.
129 gengetwindow(Display *d, char *winname, Image **winp, Screen **scrp, int ref)
132 char buf[64+1], obuf[64+1];
138 fd = open(winname, OREAD);
139 if(fd<0 || (n=read(fd, buf, sizeof buf-1))<=0){
140 if((image=d->image) == nil){
141 fprint(2, "gengetwindow: %r\n");
143 d->screenimage = nil;
146 strcpy(buf, "noborder");
150 image = namedimage(d, buf);
153 * theres a race where the winname can change after
154 * we read it, so keep trying as long as the name
157 if(strcmp(buf, obuf) != 0){
161 fprint(2, "namedimage %s failed: %r\n", buf);
165 freeimage((*scrp)->image);
171 d->screenimage = nil;
174 assert(image->chan != 0);
177 d->screenimage = image;
178 *scrp = allocscreen(image, d->white, 0);
181 d->screenimage = nil;
187 if(strncmp(buf, "noborder", 8) != 0)
188 r = insetrect(image->r, Borderwidth);
189 *winp = _allocwindow(*winp, *scrp, r, ref, DWhite);
193 d->screenimage = nil;
197 assert((*winp)->chan != 0);
198 d->screenimage = *winp;
203 getwindow(Display *d, int ref)
207 snprint(winname, sizeof winname, "%s/winname", d->windir);
208 return gengetwindow(d, winname, &screen, &_screen, ref);
214 initdisplay(char *dev, char *win, void(*error)(Display*, char*))
216 char buf[128], info[NINFO+1], *t, isnew;
217 int n, datafd, ctlfd, reffd;
222 fmtinstall('P', Pfmt);
223 fmtinstall('R', Rfmt);
228 if(strlen(dev)>sizeof buf-25 || strlen(win)>sizeof buf-25){
229 werrstr("initdisplay: directory name too long");
236 sprint(buf, "%s/draw/new", dev);
237 ctlfd = open(buf, ORDWR|OCEXEC);
239 if(bind("#i", dev, MAFTER) < 0){
242 werrstr("initdisplay: %s: %r", buf);
245 ctlfd = open(buf, ORDWR|OCEXEC);
249 if((n=read(ctlfd, info, sizeof info)) < 12){
258 if(n < NINFO) /* this will do for now, we need something better here */
260 sprint(buf, "%s/draw/%d/data", dev, atoi(info+0*12));
261 datafd = open(buf, ORDWR|OCEXEC);
264 sprint(buf, "%s/draw/%d/refresh", dev, atoi(info+0*12));
265 reffd = open(buf, OREAD|OCEXEC);
271 disp = mallocz(sizeof(Display), 1);
285 image = mallocz(sizeof(Image), 1);
288 image->display = disp;
290 image->chan = strtochan(info+2*12);
291 image->depth = chantodepth(image->chan);
292 image->repl = atoi(info+3*12);
293 image->r.min.x = atoi(info+4*12);
294 image->r.min.y = atoi(info+5*12);
295 image->r.max.x = atoi(info+6*12);
296 image->r.max.y = atoi(info+7*12);
297 image->clipr.min.x = atoi(info+8*12);
298 image->clipr.min.y = atoi(info+9*12);
299 image->clipr.max.x = atoi(info+10*12);
300 image->clipr.max.y = atoi(info+11*12);
303 disp->_isnewdisplay = isnew;
304 disp->bufsize = iounit(datafd);
305 if(disp->bufsize <= 0)
306 disp->bufsize = 8000;
307 if(disp->bufsize < 512){
308 werrstr("iounit %d too small", disp->bufsize);
311 disp->buf = malloc(disp->bufsize+5); /* +5 for flush message */
316 disp->dirno = atoi(info+0*12);
320 disp->bufp = disp->buf;
323 disp->devdir = strdup(dev);
325 disp->white = allocimage(disp, Rect(0, 0, 1, 1), GREY1, 1, DWhite);
326 disp->black = allocimage(disp, Rect(0, 0, 1, 1), GREY1, 1, DBlack);
327 if(disp->white == nil || disp->black == nil){
333 disp->opaque = disp->white;
334 disp->transparent = disp->black;
335 dir = dirfstat(ctlfd);
336 if(dir!=nil && dir->type=='i'){
338 disp->dataqid = dir->qid.path;
340 if(dir!=nil && dir->qid.vers==1) /* other way to tell */
341 disp->_isnewdisplay = 1;
348 * Call with d unlocked.
349 * Note that disp->defaultfont and defaultsubfont are not freed here.
352 closedisplay(Display *disp)
354 _closedisplay(disp, 0);
358 _closedisplay(Display *disp, int isshutdown)
367 if(disp->oldlabel[0]){
368 snprint(buf, sizeof buf, "%s/label", disp->windir);
369 fd = open(buf, OWRITE);
371 write(fd, disp->oldlabel, strlen(disp->oldlabel));
377 * if we're shutting down, don't free all the resources.
378 * if other procs are getting shot down by notes too,
379 * one might get shot down while holding the malloc lock.
380 * just let the kernel clean things up when we exit.
387 freeimage(disp->white);
388 freeimage(disp->black);
391 /* should cause refresh slave to shut down */
393 qunlock(&disp->qlock);
398 lockdisplay(Display *disp)
400 if(debuglockdisplay){
401 /* avoid busy looping; it's rare we collide anyway */
402 while(!canqlock(&disp->qlock)){
403 fprint(1, "proc %d waiting for display lock...\n", getpid());
411 unlockdisplay(Display *disp)
413 qunlock(&disp->qlock);
417 drawerror(Display *d, char *s)
421 if(d != nil && d->error != nil)
424 errstr(err, sizeof err);
425 fprint(2, "draw: %s: %s\n", s, err);
440 if((nn=write(d->fd, d->buf, n)) != n){
442 fprint(2, "flushimage fail: d=%p: n=%d nn=%d %r\n", d, n, nn); /**/
443 d->bufp = d->buf; /* might as well; chance of continuing */
451 flushimage(Display *d, int visible)
456 *d->bufp++ = 'v'; /* five bytes always reserved for this */
457 if(d->_isnewdisplay){
458 BPLONG(d->bufp, d->screenimage->id);
466 bufimage(Display *d, int n)
470 if(n<0 || n>d->bufsize){
471 werrstr("bad count in bufimage");
474 if(d->bufp+n > d->buf+d->bufsize)