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->image = display->screenimage;
39 screen = display->screenimage;
41 /*
42 * Set up default font
43 */
44 df = getdefont(display);
45 display->defaultsubfont = df;
46 if(df == nil){
47 fprint(2, "imageinit: can't open default subfont: %r\n");
48 Error:
49 closedisplay(display);
50 display = nil;
51 return -1;
52 }
53 if(fontname == nil)
54 fontname = getenv("font"); /* leak */
56 /*
57 * Build fonts with caches==depth of screen, for speed.
58 * If conversion were faster, we'd use 0 and save memory.
59 */
60 if(fontname == nil){
61 snprint(buf, sizeof buf, "%d %d\n0 %d\t%s\n", df->height, df->ascent,
62 df->n-1, deffontname);
63 //BUG: Need something better for this installsubfont("*default*", df);
64 font = buildfont(display, buf, deffontname);
65 if(font == nil){
66 fprint(2, "initdraw: can't open default font: %r\n");
67 goto Error;
68 }
69 }else{
70 font = openfont(display, fontname); /* BUG: grey fonts */
71 if(font == nil){
72 fprint(2, "initdraw: can't open font %s: %r\n", fontname);
73 goto Error;
74 }
75 }
76 display->defaultfont = font;
78 display->white = allocimage(display, Rect(0,0,1,1), GREY1, 1, DWhite);
79 display->black = allocimage(display, Rect(0,0,1,1), GREY1, 1, DBlack);
80 if(display->white == nil || display->black == nil){
81 fprint(2, "initdraw: can't allocate white and black");
82 goto Error;
83 }
84 display->opaque = display->white;
85 display->transparent = display->black;
86 atexit(drawshutdown);
87 return 1;
88 }
90 /*
91 * Call with d unlocked.
92 * Note that disp->defaultfont and defaultsubfont are not freed here.
93 */
94 void
95 closedisplay(Display *disp)
96 {
97 int fd;
98 char buf[128];
100 if(disp == nil)
101 return;
102 if(disp == display)
103 display = nil;
104 if(disp->oldlabel[0]){
105 snprint(buf, sizeof buf, "%s/label", disp->windir);
106 fd = open(buf, OWRITE);
107 if(fd >= 0){
108 write(fd, disp->oldlabel, strlen(disp->oldlabel));
109 close(fd);
113 free(disp->devdir);
114 free(disp->windir);
115 freeimage(disp->white);
116 freeimage(disp->black);
117 free(disp);
120 void
121 lockdisplay(Display *disp)
123 if(debuglockdisplay){
124 /* avoid busy looping; it's rare we collide anyway */
125 while(!canqlock(&disp->qlock)){
126 fprint(1, "proc %d waiting for display lock...\n", getpid());
127 sleep(1000);
129 }else
130 qlock(&disp->qlock);
133 void
134 unlockdisplay(Display *disp)
136 qunlock(&disp->qlock);
139 void
140 drawerror(Display *d, char *s)
142 char err[ERRMAX];
144 if(d->error)
145 d->error(d, s);
146 else{
147 errstr(err, sizeof err);
148 fprint(2, "draw: %s: %s\n", s, err);
149 exits(s);
153 static
154 int
155 doflush(Display *d)
157 int n;
159 n = d->bufp-d->buf;
160 if(n <= 0)
161 return 1;
163 if(_drawmsgwrite(d, d->buf, n) != n){
164 if(_drawdebug)
165 fprint(2, "flushimage fail: d=%p: %r\n", d); /**/
166 d->bufp = d->buf; /* might as well; chance of continuing */
167 return -1;
169 d->bufp = d->buf;
170 return 1;
173 int
174 flushimage(Display *d, int visible)
176 if(visible){
177 *d->bufp++ = 'v'; /* five bytes always reserved for this */
178 if(d->_isnewdisplay){
179 BPLONG(d->bufp, d->screenimage->id);
180 d->bufp += 4;
183 return doflush(d);
186 uchar*
187 bufimage(Display *d, int n)
189 uchar *p;
191 if(n<0 || n>d->bufsize){
192 abort();
193 werrstr("bad count in bufimage");
194 return 0;
196 if(d->bufp+n > d->buf+d->bufsize)
197 if(doflush(d) < 0)
198 return 0;
199 p = d->bufp;
200 d->bufp += n;
201 return p;