Blob


1 #include <u.h>
2 #include <libc.h>
3 #include <draw.h>
5 Display *display;
6 Font *font;
7 Image *screen;
8 int _drawdebug;
10 static char deffontname[] = "*default*";
11 Screen *_screen;
13 int debuglockdisplay = 1;
15 static void
16 drawshutdown(void)
17 {
18 Display *d;
20 d = display;
21 if(d){
22 display = nil;
23 closedisplay(d);
24 }
25 }
27 int
28 initdraw(void (*error)(Display*, char*), char *fontname, char *label)
29 {
30 Subfont *df;
31 char buf[128];
33 display = _initdisplay(error, label); /* sets screen too */
34 if(display == nil)
35 return -1;
37 lockdisplay(display);
38 display->screenimage = display->image;
40 /*
41 * Set up default font
42 */
43 df = getdefont(display);
44 display->defaultsubfont = df;
45 if(df == nil){
46 fprint(2, "imageinit: can't open default subfont: %r\n");
47 Error:
48 closedisplay(display);
49 display = nil;
50 return -1;
51 }
52 if(fontname == nil)
53 fontname = getenv("font"); /* leak */
55 /*
56 * Build fonts with caches==depth of screen, for speed.
57 * If conversion were faster, we'd use 0 and save memory.
58 */
59 if(fontname == nil){
60 snprint(buf, sizeof buf, "%d %d\n0 %d\t%s\n", df->height, df->ascent,
61 df->n-1, deffontname);
62 //BUG: Need something better for this installsubfont("*default*", df);
63 font = buildfont(display, buf, deffontname);
64 if(font == nil){
65 fprint(2, "initdraw: can't open default font: %r\n");
66 goto Error;
67 }
68 }else{
69 font = openfont(display, fontname); /* BUG: grey fonts */
70 if(font == nil){
71 fprint(2, "initdraw: can't open font %s: %r\n", fontname);
72 goto Error;
73 }
74 }
75 display->defaultfont = font;
77 display->white = allocimage(display, Rect(0,0,1,1), GREY1, 1, DWhite);
78 display->black = allocimage(display, Rect(0,0,1,1), GREY1, 1, DBlack);
79 if(display->white == nil || display->black == nil){
80 fprint(2, "initdraw: can't allocate white and black");
81 goto Error;
82 }
83 display->opaque = display->white;
84 display->transparent = display->black;
86 _screen = allocscreen(display->image, display->white, 0);
87 screen = _allocwindow(nil, _screen, display->image->r, Refnone, DWhite);
88 display->screenimage = screen;
89 draw(screen, screen->r, display->black, nil, ZP);
90 flushimage(display, 1);
92 atexit(drawshutdown);
93 return 1;
94 }
96 /*
97 * Call with d unlocked.
98 * Note that disp->defaultfont and defaultsubfont are not freed here.
99 */
100 void
101 closedisplay(Display *disp)
103 int fd;
104 char buf[128];
106 if(disp == nil)
107 return;
108 if(disp == display)
109 display = nil;
110 if(disp->oldlabel[0]){
111 snprint(buf, sizeof buf, "%s/label", disp->windir);
112 fd = open(buf, OWRITE);
113 if(fd >= 0){
114 write(fd, disp->oldlabel, strlen(disp->oldlabel));
115 close(fd);
119 free(disp->devdir);
120 free(disp->windir);
121 freeimage(disp->white);
122 freeimage(disp->black);
123 free(disp);
126 void
127 lockdisplay(Display *disp)
129 if(debuglockdisplay){
130 /* avoid busy looping; it's rare we collide anyway */
131 while(!canqlock(&disp->qlock)){
132 fprint(1, "proc %d waiting for display lock...\n", getpid());
133 sleep(1000);
135 }else
136 qlock(&disp->qlock);
139 void
140 unlockdisplay(Display *disp)
142 qunlock(&disp->qlock);
145 void
146 drawerror(Display *d, char *s)
148 char err[ERRMAX];
150 if(d->error)
151 d->error(d, s);
152 else{
153 errstr(err, sizeof err);
154 fprint(2, "draw: %s: %s\n", s, err);
155 exits(s);
159 static
160 int
161 doflush(Display *d)
163 int n;
165 n = d->bufp-d->buf;
166 if(n <= 0)
167 return 1;
169 if(_drawmsgwrite(d, d->buf, n) != n){
170 if(_drawdebug)
171 fprint(2, "flushimage fail: d=%p: %r\n", d); /**/
172 d->bufp = d->buf; /* might as well; chance of continuing */
173 return -1;
175 d->bufp = d->buf;
176 return 1;
179 int
180 flushimage(Display *d, int visible)
182 if(visible){
183 *d->bufp++ = 'v'; /* five bytes always reserved for this */
184 if(d->_isnewdisplay){
185 BPLONG(d->bufp, d->screenimage->id);
186 d->bufp += 4;
189 return doflush(d);
192 uchar*
193 bufimage(Display *d, int n)
195 uchar *p;
197 if(n<0 || n>d->bufsize){
198 abort();
199 werrstr("bad count in bufimage");
200 return 0;
202 if(d->bufp+n > d->buf+d->bufsize)
203 if(doflush(d) < 0)
204 return 0;
205 p = d->bufp;
206 d->bufp += n;
207 return p;