Warning: Attempt to read property "date" on null in /usr/local/www/websvn.planix.org/blame.php on line 247

Warning: Attempt to read property "msg" on null in /usr/local/www/websvn.planix.org/blame.php on line 247
WebSVN – planix.SVN – Blame – /os/branches/feature-vt/sys/src/libdraw/init.c – Rev 2

Subversion Repositories planix.SVN

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include <u.h>
2
#include <libc.h>
3
#include <draw.h>
4
 
5
Display	*display;
6
Font	*font;
7
Image	*screen;
8
int	_drawdebug = 0;
9
 
10
static char deffontname[] = "*default*";
11
Screen	*_screen;
12
 
13
int		debuglockdisplay = 0;
14
 
15
static void _closedisplay(Display*, int);
16
 
17
/* note handler */
18
static void
19
drawshutdown(void)
20
{
21
	Display *d;
22
 
23
	d = display;
24
	if(d){
25
		display = nil;
26
		_closedisplay(d, 1);
27
	}
28
}
29
 
30
int
31
geninitdraw(char *devdir, void(*error)(Display*, char*), char *fontname, char *label, char *windir, int ref)
32
{
33
	int fd, n;
34
	Subfont *df;
35
	char buf[128];
36
 
37
	display = initdisplay(devdir, windir, error);
38
	if(display == nil)
39
		return -1;
40
 
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
		fd = open("/env/font", OREAD);
55
		if(fd >= 0){
56
			n = read(fd, buf, sizeof(buf));
57
			if(n>0 && n<sizeof buf-1){
58
				buf[n] = 0;
59
				fontname = buf;
60
			}
61
			close(fd);
62
		}
63
	}
64
	/*
65
	 * Build fonts with caches==depth of screen, for speed.
66
	 * If conversion were faster, we'd use 0 and save memory.
67
	 */
68
	if(fontname == nil){
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);
73
		if(font == nil){
74
			fprint(2, "imageinit: can't open default font: %r\n");
75
			goto Error;
76
		}
77
	}else{
78
		font = openfont(display, fontname);	/* BUG: grey fonts */
79
		if(font == nil){
80
			fprint(2, "imageinit: can't open font %s: %r\n", fontname);
81
			goto Error;
82
		}
83
	}
84
	display->defaultfont = font;
85
 
86
	/*
87
	 * Write label; ignore errors (we might not be running under rio)
88
	 */
89
	if(label){
90
		snprint(buf, sizeof buf, "%s/label", display->windir);
91
		fd = open(buf, OREAD);
92
		if(fd >= 0){
93
			read(fd, display->oldlabel, (sizeof display->oldlabel)-1);
94
			close(fd);
95
			fd = create(buf, OWRITE, 0666);
96
			if(fd >= 0){
97
				write(fd, label, strlen(label));
98
				close(fd);
99
			}
100
		}
101
	}
102
 
103
	snprint(buf, sizeof buf, "%s/winname", display->windir);
104
	if(gengetwindow(display, buf, &screen, &_screen, ref) < 0)
105
		goto Error;
106
 
107
	atexit(drawshutdown);
108
 
109
	return 1;
110
}
111
 
112
int
113
initdraw(void(*error)(Display*, char*), char *fontname , char *label)
114
{
115
	char *dev = "/dev";
116
 
117
	if(access("/dev/draw/new", AEXIST)<0 && bind("#i", "/dev", MAFTER)<0){
118
		fprint(2, "imageinit: can't bind /dev/draw: %r\n");
119
		return -1;
120
	}
121
	return geninitdraw(dev, error, fontname, label, dev, Refnone);
122
}
123
 
124
/*
125
 * Attach, or possibly reattach, to window.
126
 * If reattaching, maintain value of screen pointer.
127
 */
128
int
129
gengetwindow(Display *d, char *winname, Image **winp, Screen **scrp, int ref)
130
{
131
	int n, fd;
132
	char buf[64+1];
133
	Image *image;
134
	Rectangle r;
135
 
136
	fd = open(winname, OREAD);
137
	if(fd<0 || (n=read(fd, buf, sizeof buf-1))<=0){
138
		if((image=d->image) == nil){
139
			fprint(2, "gengetwindow: %r\n");
140
			*winp = nil;
141
			d->screenimage = nil;
142
			return -1;
143
		}
144
		strcpy(buf, "noborder");
145
	}else{
146
		close(fd);
147
		buf[n] = '\0';
148
		if(*winp != nil){
149
			_freeimage1(*winp);
150
			freeimage((*scrp)->image);
151
			freescreen(*scrp);
152
			*scrp = nil;
153
		}
154
		image = namedimage(d, buf);
155
		if(image == 0){
156
			fprint(2, "namedimage %s failed: %r\n", buf);
157
			*winp = nil;
158
			d->screenimage = nil;
159
			return -1;
160
		}
161
		assert(image->chan != 0);
162
	}
163
 
164
	d->screenimage = image;
165
	*scrp = allocscreen(image, d->white, 0);
166
	if(*scrp == nil){
167
		freeimage(d->screenimage);
168
		*winp = nil;
169
		d->screenimage = nil;
170
		return -1;
171
	}
172
 
173
	r = image->r;
174
	if(strncmp(buf, "noborder", 8) != 0)
175
		r = insetrect(image->r, Borderwidth);
176
	*winp = _allocwindow(*winp, *scrp, r, ref, DWhite);
177
	if(*winp == nil){
178
		freescreen(*scrp);
179
		*scrp = nil;
180
		freeimage(image);
181
		d->screenimage = nil;
182
		return -1;
183
	}
184
	d->screenimage = *winp;
185
	assert((*winp)->chan != 0);
186
	return 1;
187
}
188
 
189
int
190
getwindow(Display *d, int ref)
191
{
192
	char winname[128];
193
 
194
	snprint(winname, sizeof winname, "%s/winname", d->windir);
195
	return gengetwindow(d, winname, &screen, &_screen, ref);
196
}
197
 
198
#define	NINFO	12*12
199
 
200
Display*
201
initdisplay(char *dev, char *win, void(*error)(Display*, char*))
202
{
203
	char buf[128], info[NINFO+1], *t, isnew;
204
	int n, datafd, ctlfd, reffd;
205
	Display *disp;
206
	Dir *dir;
207
	Image *image;
208
 
209
	fmtinstall('P', Pfmt);
210
	fmtinstall('R', Rfmt);
211
	if(dev == 0)
212
		dev = "/dev";
213
	if(win == 0)
214
		win = "/dev";
215
	if(strlen(dev)>sizeof buf-25 || strlen(win)>sizeof buf-25){
216
		werrstr("initdisplay: directory name too long");
217
		return nil;
218
	}
219
	t = strdup(win);
220
	if(t == nil)
221
		return nil;
222
 
223
	sprint(buf, "%s/draw/new", dev);
224
	ctlfd = open(buf, ORDWR|OCEXEC);
225
	if(ctlfd < 0){
226
		if(bind("#i", dev, MAFTER) < 0){
227
    Error1:
228
			free(t);
229
			werrstr("initdisplay: %s: %r", buf);
230
			return 0;
231
		}
232
		ctlfd = open(buf, ORDWR|OCEXEC);
233
	}
234
	if(ctlfd < 0)
235
		goto Error1;
236
	if((n=read(ctlfd, info, sizeof info)) < 12){
237
    Error2:
238
		close(ctlfd);
239
		goto Error1;
240
	}
241
	if(n==NINFO+1)
242
		n = NINFO;
243
	info[n] = '\0';
244
	isnew = 0;
245
	if(n < NINFO)	/* this will do for now, we need something better here */
246
		isnew = 1;
247
	sprint(buf, "%s/draw/%d/data", dev, atoi(info+0*12));
248
	datafd = open(buf, ORDWR|OCEXEC);
249
	if(datafd < 0)
250
		goto Error2;
251
	sprint(buf, "%s/draw/%d/refresh", dev, atoi(info+0*12));
252
	reffd = open(buf, OREAD|OCEXEC);
253
	if(reffd < 0){
254
    Error3:
255
		close(datafd);
256
		goto Error2;
257
	}
258
	disp = mallocz(sizeof(Display), 1);
259
	if(disp == 0){
260
    Error4:
261
		close(reffd);
262
		goto Error3;
263
	}
264
	image = nil;
265
	if(0){
266
    Error5:
267
		free(image);
268
		free(disp);
269
		goto Error4;
270
	}
271
	if(n >= NINFO){
272
		image = mallocz(sizeof(Image), 1);
273
		if(image == nil)
274
			goto Error5;
275
		image->display = disp;
276
		image->id = 0;
277
		image->chan = strtochan(info+2*12);
278
		image->depth = chantodepth(image->chan);
279
		image->repl = atoi(info+3*12);
280
		image->r.min.x = atoi(info+4*12);
281
		image->r.min.y = atoi(info+5*12);
282
		image->r.max.x = atoi(info+6*12);
283
		image->r.max.y = atoi(info+7*12);
284
		image->clipr.min.x = atoi(info+8*12);
285
		image->clipr.min.y = atoi(info+9*12);
286
		image->clipr.max.x = atoi(info+10*12);
287
		image->clipr.max.y = atoi(info+11*12);
288
	}
289
 
290
	disp->_isnewdisplay = isnew;
291
	disp->bufsize = iounit(datafd);
292
	if(disp->bufsize <= 0)
293
		disp->bufsize = 8000;
294
	if(disp->bufsize < 512){
295
		werrstr("iounit %d too small", disp->bufsize);
296
		goto Error5;
297
	}
298
	disp->buf = malloc(disp->bufsize+5);	/* +5 for flush message */
299
	if(disp->buf == nil)
300
		goto Error5;
301
 
302
	disp->image = image;
303
	disp->dirno = atoi(info+0*12);
304
	disp->fd = datafd;
305
	disp->ctlfd = ctlfd;
306
	disp->reffd = reffd;
307
	disp->bufp = disp->buf;
308
	disp->error = error;
309
	disp->windir = t;
310
	disp->devdir = strdup(dev);
311
	qlock(&disp->qlock);
312
	disp->white = allocimage(disp, Rect(0, 0, 1, 1), GREY1, 1, DWhite);
313
	disp->black = allocimage(disp, Rect(0, 0, 1, 1), GREY1, 1, DBlack);
314
	if(disp->white == nil || disp->black == nil){
315
		free(disp->devdir);
316
		free(disp->white);
317
		free(disp->black);
318
		goto Error5;
319
	}
320
	disp->opaque = disp->white;
321
	disp->transparent = disp->black;
322
	dir = dirfstat(ctlfd);
323
	if(dir!=nil && dir->type=='i'){
324
		disp->local = 1;
325
		disp->dataqid = dir->qid.path;
326
	}
327
	if(dir!=nil && dir->qid.vers==1)	/* other way to tell */
328
		disp->_isnewdisplay = 1;
329
	free(dir);
330
 
331
	return disp;
332
}
333
 
334
/*
335
 * Call with d unlocked.
336
 * Note that disp->defaultfont and defaultsubfont are not freed here.
337
 */
338
void
339
closedisplay(Display *disp)
340
{
341
	_closedisplay(disp, 0);
342
}
343
 
344
static void
345
_closedisplay(Display *disp, int isshutdown)
346
{
347
	int fd;
348
	char buf[128];
349
 
350
	if(disp == nil)
351
		return;
352
	if(disp == display)
353
		display = nil;
354
	if(disp->oldlabel[0]){
355
		snprint(buf, sizeof buf, "%s/label", disp->windir);
356
		fd = open(buf, OWRITE);
357
		if(fd >= 0){
358
			write(fd, disp->oldlabel, strlen(disp->oldlabel));
359
			close(fd);
360
		}
361
	}
362
 
363
	/*
364
	 * if we're shutting down, don't free all the resources.
365
	 * if other procs are getting shot down by notes too,
366
	 * one might get shot down while holding the malloc lock.
367
	 * just let the kernel clean things up when we exit.
368
	 */
369
	if(isshutdown)
370
		return;
371
 
372
	free(disp->devdir);
373
	free(disp->windir);
374
	freeimage(disp->white);
375
	freeimage(disp->black);
376
	close(disp->fd);
377
	close(disp->ctlfd);
378
	/* should cause refresh slave to shut down */
379
	close(disp->reffd);
380
	qunlock(&disp->qlock);
381
	free(disp);
382
}
383
 
384
void
385
lockdisplay(Display *disp)
386
{
387
	if(debuglockdisplay){
388
		/* avoid busy looping; it's rare we collide anyway */
389
		while(!canqlock(&disp->qlock)){
390
			fprint(1, "proc %d waiting for display lock...\n", getpid());
391
			sleep(1000);
392
		}
393
	}else
394
		qlock(&disp->qlock);
395
}
396
 
397
void
398
unlockdisplay(Display *disp)
399
{
400
	qunlock(&disp->qlock);
401
}
402
 
403
void
404
drawerror(Display *d, char *s)
405
{
406
	char err[ERRMAX];
407
 
408
	if(d && d->error)
409
		d->error(d, s);
410
	else{
411
		errstr(err, sizeof err);
412
		fprint(2, "draw: %s: %s\n", s, err);
413
		exits(s);
414
	}
415
}
416
 
417
static
418
int
419
doflush(Display *d)
420
{
421
	int n, nn;
422
 
423
	n = d->bufp-d->buf;
424
	if(n <= 0)
425
		return 1;
426
 
427
	if((nn=write(d->fd, d->buf, n)) != n){
428
		if(_drawdebug)
429
			fprint(2, "flushimage fail: d=%p: n=%d nn=%d %r\n", d, n, nn); /**/
430
		d->bufp = d->buf;	/* might as well; chance of continuing */
431
		return -1;
432
	}
433
	d->bufp = d->buf;
434
	return 1;
435
}
436
 
437
int
438
flushimage(Display *d, int visible)
439
{
440
	if(d == nil)
441
		return 0;
442
	if(visible){
443
		*d->bufp++ = 'v';	/* five bytes always reserved for this */
444
		if(d->_isnewdisplay){
445
			BPLONG(d->bufp, d->screenimage->id);
446
			d->bufp += 4;
447
		}
448
	}
449
	return doflush(d);
450
}
451
 
452
uchar*
453
bufimage(Display *d, int n)
454
{
455
	uchar *p;
456
 
457
	if(n<0 || n>d->bufsize){
458
		werrstr("bad count in bufimage");
459
		return 0;
460
	}
461
	if(d->bufp+n > d->buf+d->bufsize)
462
		if(doflush(d) < 0)
463
			return 0;
464
	p = d->bufp;
465
	d->bufp += n;
466
	return p;
467
}
468