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 /*
16 static void
17 drawshutdown(void)
18 {
19 Display *d;
21 d = display;
22 if(d){
23 display = nil;
24 closedisplay(d);
25 }
26 }
27 */
29 int
30 initdraw(void (*error)(Display*, char*), char *fontname, char *label)
31 {
32 Subfont *df;
33 char buf[128];
35 rfork(RFNOTEG); /* x11-event.c will postnote hangup */
36 display = _initdisplay(error, label); /* sets screen too */
37 if(display == nil)
38 return -1;
40 lockdisplay(display);
41 display->screenimage = display->image;
43 /*
44 * Set up default font
45 */
46 df = getdefont(display);
47 display->defaultsubfont = df;
48 if(df == nil){
49 fprint(2, "imageinit: can't open default subfont: %r\n");
50 Error:
51 closedisplay(display);
52 display = nil;
53 return -1;
54 }
55 if(fontname == nil)
56 fontname = getenv("font"); /* leak */
58 /*
59 * Build fonts with caches==depth of screen, for speed.
60 * If conversion were faster, we'd use 0 and save memory.
61 */
62 if(fontname == nil){
63 snprint(buf, sizeof buf, "%d %d\n0 %d\t%s\n", df->height, df->ascent,
64 df->n-1, deffontname);
65 /*BUG: Need something better for this installsubfont("*default*", df); */
66 font = buildfont(display, buf, deffontname);
67 if(font == nil){
68 fprint(2, "initdraw: can't open default font: %r\n");
69 goto Error;
70 }
71 }else{
72 font = openfont(display, fontname); /* BUG: grey fonts */
73 if(font == nil){
74 fprint(2, "initdraw: can't open font %s: %r\n", fontname);
75 goto Error;
76 }
77 }
78 display->defaultfont = font;
80 display->white = allocimage(display, Rect(0,0,1,1), GREY1, 1, DWhite);
81 display->black = allocimage(display, Rect(0,0,1,1), GREY1, 1, DBlack);
82 if(display->white == nil || display->black == nil){
83 fprint(2, "initdraw: can't allocate white and black");
84 goto Error;
85 }
86 display->opaque = display->white;
87 display->transparent = display->black;
89 _screen = allocscreen(display->image, display->white, 0);
90 screen = _allocwindow(nil, _screen, display->image->r, Refnone, DWhite);
91 display->screenimage = screen;
92 draw(screen, screen->r, display->white, nil, ZP);
93 flushimage(display, 1);
95 /*
96 * I don't see any reason to go away gracefully,
97 * and if some other proc exits holding the display
98 * lock, this atexit call never finishes.
99 *
100 * atexit(drawshutdown);
101 */
102 return 1;
105 /*
106 * Call with d unlocked.
107 * Note that disp->defaultfont and defaultsubfont are not freed here.
108 */
109 void
110 closedisplay(Display *disp)
112 int fd;
113 char buf[128];
115 if(disp == nil)
116 return;
117 if(disp == display)
118 display = nil;
119 if(disp->oldlabel[0]){
120 snprint(buf, sizeof buf, "%s/label", disp->windir);
121 fd = open(buf, OWRITE);
122 if(fd >= 0){
123 write(fd, disp->oldlabel, strlen(disp->oldlabel));
124 close(fd);
128 free(disp->devdir);
129 free(disp->windir);
130 if(disp->white)
131 freeimage(disp->white);
132 if(disp->black)
133 freeimage(disp->black);
134 free(disp);
137 void
138 lockdisplay(Display *disp)
140 if(debuglockdisplay){
141 /* avoid busy looping; it's rare we collide anyway */
142 while(!canqlock(&disp->qlock)){
143 fprint(1, "proc %d waiting for display lock...\n", getpid());
144 sleep(1000);
146 }else
147 qlock(&disp->qlock);
150 void
151 unlockdisplay(Display *disp)
153 qunlock(&disp->qlock);
156 void
157 drawerror(Display *d, char *s)
159 char err[ERRMAX];
161 if(d->error)
162 d->error(d, s);
163 else{
164 errstr(err, sizeof err);
165 fprint(2, "draw: %s: %s\n", s, err);
166 exits(s);
170 static
171 int
172 doflush(Display *d)
174 int n;
176 n = d->bufp-d->buf;
177 if(n <= 0)
178 return 1;
180 if(_drawmsgwrite(d, d->buf, n) != n){
181 if(_drawdebug)
182 fprint(2, "flushimage fail: d=%p: %r\n", d); /**/
183 d->bufp = d->buf; /* might as well; chance of continuing */
184 return -1;
186 d->bufp = d->buf;
187 return 1;
190 int
191 flushimage(Display *d, int visible)
193 if(visible){
194 *d->bufp++ = 'v'; /* five bytes always reserved for this */
195 if(d->_isnewdisplay){
196 BPLONG(d->bufp, d->screenimage->id);
197 d->bufp += 4;
200 return doflush(d);
203 uchar*
204 bufimage(Display *d, int n)
206 uchar *p;
208 if(n<0 || d == nil || n>d->bufsize){
209 abort();
210 werrstr("bad count in bufimage");
211 return 0;
213 if(d->bufp+n > d->buf+d->bufsize)
214 if(doflush(d) < 0)
215 return 0;
216 p = d->bufp;
217 d->bufp += n;
218 return p;