Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
/*
2
 * bcm2385 framebuffer
3
 */
4
 
5
#include "u.h"
6
#include "../port/lib.h"
7
#include "mem.h"
8
#include "dat.h"
9
#include "fns.h"
10
 
11
#define	Image	IMAGE
12
#include <draw.h>
13
#include <memdraw.h>
14
#include <cursor.h>
15
#include "screen.h"
16
 
17
enum {
18
	Tabstop		= 4,
19
	Scroll		= 8,
20
	Wid		= 1024,
21
	Ht		= 768,
22
	Depth		= 16,
23
};
24
 
25
Cursor	arrow = {
26
	{ -1, -1 },
27
	{ 0xFF, 0xFF, 0x80, 0x01, 0x80, 0x02, 0x80, 0x0C,
28
	  0x80, 0x10, 0x80, 0x10, 0x80, 0x08, 0x80, 0x04,
29
	  0x80, 0x02, 0x80, 0x01, 0x80, 0x02, 0x8C, 0x04,
30
	  0x92, 0x08, 0x91, 0x10, 0xA0, 0xA0, 0xC0, 0x40,
31
	},
32
	{ 0x00, 0x00, 0x7F, 0xFE, 0x7F, 0xFC, 0x7F, 0xF0,
33
	  0x7F, 0xE0, 0x7F, 0xE0, 0x7F, 0xF0, 0x7F, 0xF8,
34
	  0x7F, 0xFC, 0x7F, 0xFE, 0x7F, 0xFC, 0x73, 0xF8,
35
	  0x61, 0xF0, 0x60, 0xE0, 0x40, 0x40, 0x00, 0x00,
36
	},
37
};
38
 
39
Memimage *gscreen;
40
 
41
static Memdata xgdata;
42
 
43
static Memimage xgscreen =
44
{
45
	{ 0, 0, Wid, Ht },	/* r */
46
	{ 0, 0, Wid, Ht },	/* clipr */
47
	Depth,			/* depth */
48
	3,			/* nchan */
49
	RGB16,			/* chan */
50
	nil,			/* cmap */
51
	&xgdata,		/* data */
52
	0,			/* zero */
53
	0, 			/* width in words of a single scan line */
54
	0,			/* layer */
55
	0,			/* flags */
56
};
57
 
58
static Memimage *conscol;
59
static Memimage *back;
60
static Memsubfont *memdefont;
61
 
62
static Lock screenlock;
63
 
64
static Point	curpos;
65
static int	h, w;
66
static Rectangle window;
67
 
68
static void myscreenputs(char *s, int n);
69
static void screenputc(char *buf);
70
static void screenwin(void);
71
 
72
/*
73
 * Software cursor. 
74
 */
75
static int	swvisible;	/* is the cursor visible? */
76
static int	swenabled;	/* is the cursor supposed to be on the screen? */
77
static Memimage *swback;	/* screen under cursor */
78
static Memimage *swimg;		/* cursor image */
79
static Memimage *swmask;	/* cursor mask */
80
static Memimage *swimg1;
81
static Memimage *swmask1;
82
 
83
static Point	swoffset;
84
static Rectangle swrect;	/* screen rectangle in swback */
85
static Point	swpt;		/* desired cursor location */
86
static Point	swvispt;	/* actual cursor location */
87
static int	swvers;		/* incremented each time cursor image changes */
88
static int	swvisvers;	/* the version on the screen */
89
 
90
/*
91
 * called with drawlock locked for us, most of the time.
92
 * kernel prints at inopportune times might mean we don't
93
 * hold the lock, but memimagedraw is now reentrant so
94
 * that should be okay: worst case we get cursor droppings.
95
 */
96
static void
97
swcursorhide(void)
98
{
99
	if(swvisible == 0)
100
		return;
101
	if(swback == nil)
102
		return;
103
	swvisible = 0;
104
	memimagedraw(gscreen, swrect, swback, ZP, memopaque, ZP, S);
105
	flushmemscreen(swrect);
106
}
107
 
108
static void
109
swcursoravoid(Rectangle r)
110
{
111
	if(swvisible && rectXrect(r, swrect))
112
		swcursorhide();
113
}
114
 
115
static void
116
swcursordraw(void)
117
{
118
	int dounlock;
119
 
120
	if(swvisible)
121
		return;
122
	if(swenabled == 0)
123
		return;
124
	if(swback == nil || swimg1 == nil || swmask1 == nil)
125
		return;
126
	dounlock = canqlock(&drawlock);
127
	swvispt = swpt;
128
	swvisvers = swvers;
129
	swrect = rectaddpt(Rect(0,0,16,16), swvispt);
130
	memimagedraw(swback, swback->r, gscreen, swpt, memopaque, ZP, S);
131
	memimagedraw(gscreen, swrect, swimg1, ZP, swmask1, ZP, SoverD);
132
	flushmemscreen(swrect);
133
	swvisible = 1;
134
	if(dounlock)
135
		qunlock(&drawlock);
136
}
137
 
138
int
139
cursoron(int dolock)
140
{
141
	int retry;
142
 
143
	if (dolock)
144
		lock(&cursor);
145
	if (canqlock(&drawlock)) {
146
		retry = 0;
147
		swcursorhide();
148
		swcursordraw();
149
		qunlock(&drawlock);
150
	} else
151
		retry = 1;
152
	if (dolock)
153
		unlock(&cursor);
154
	return retry;
155
}
156
 
157
void
158
cursoroff(int dolock)
159
{
160
	if (dolock)
161
		lock(&cursor);
162
	swcursorhide();
163
	if (dolock)
164
		unlock(&cursor);
165
}
166
 
167
static void
168
swload(Cursor *curs)
169
{
170
	uchar *ip, *mp;
171
	int i, j, set, clr;
172
 
173
	if(!swimg || !swmask || !swimg1 || !swmask1)
174
		return;
175
	/*
176
	 * Build cursor image and mask.
177
	 * Image is just the usual cursor image
178
	 * but mask is a transparent alpha mask.
179
	 * 
180
	 * The 16x16x8 memimages do not have
181
	 * padding at the end of their scan lines.
182
	 */
183
	ip = byteaddr(swimg, ZP);
184
	mp = byteaddr(swmask, ZP);
185
	for(i=0; i<32; i++){
186
		set = curs->set[i];
187
		clr = curs->clr[i];
188
		for(j=0x80; j; j>>=1){
189
			*ip++ = set&j ? 0x00 : 0xFF;
190
			*mp++ = (clr|set)&j ? 0xFF : 0x00;
191
		}
192
	}
193
	swoffset = curs->offset;
194
	swvers++;
195
	memimagedraw(swimg1,  swimg1->r,  swimg,  ZP, memopaque, ZP, S);
196
	memimagedraw(swmask1, swmask1->r, swmask, ZP, memopaque, ZP, S);
197
}
198
 
199
/* called from devmouse */
200
void
201
setcursor(Cursor* curs)
202
{
203
	cursoroff(0);
204
	swload(curs);
205
	cursoron(0);
206
}
207
 
208
static int
209
swmove(Point p)
210
{
211
	swpt = addpt(p, swoffset);
212
	return 0;
213
}
214
 
215
static void
216
swcursorclock(void)
217
{
218
	int x;
219
 
220
	if(!swenabled)
221
		return;
222
	swmove(mousexy());
223
	if(swvisible && eqpt(swpt, swvispt) && swvers==swvisvers)
224
		return;
225
 
226
	x = splhi();
227
	if(swenabled)
228
	if(!swvisible || !eqpt(swpt, swvispt) || swvers!=swvisvers)
229
	if(canqlock(&drawlock)){
230
		swcursorhide();
231
		swcursordraw();
232
		qunlock(&drawlock);
233
	}
234
	splx(x);
235
}
236
 
237
void
238
swcursorinit(void)
239
{
240
	static int init;
241
 
242
	if(!init){
243
		init = 1;
244
		addclock0link(swcursorclock, 10);
245
		swenabled = 1;
246
	}
247
	if(swback){
248
		freememimage(swback);
249
		freememimage(swmask);
250
		freememimage(swmask1);
251
		freememimage(swimg);
252
		freememimage(swimg1);
253
	}
254
 
255
	swback  = allocmemimage(Rect(0,0,32,32), gscreen->chan);
256
	swmask  = allocmemimage(Rect(0,0,16,16), GREY8);
257
	swmask1 = allocmemimage(Rect(0,0,16,16), GREY1);
258
	swimg   = allocmemimage(Rect(0,0,16,16), GREY8);
259
	swimg1  = allocmemimage(Rect(0,0,16,16), GREY1);
260
	if(swback==nil || swmask==nil || swmask1==nil || swimg==nil || swimg1 == nil){
261
		print("software cursor: allocmemimage fails\n");
262
		return;
263
	}
264
 
265
	memfillcolor(swmask, DOpaque);
266
	memfillcolor(swmask1, DOpaque);
267
	memfillcolor(swimg, DBlack);
268
	memfillcolor(swimg1, DBlack);
269
}
270
 
271
int
272
hwdraw(Memdrawparam *par)
273
{
274
	Memimage *dst, *src, *mask;
275
 
276
	if((dst=par->dst) == nil || dst->data == nil)
277
		return 0;
278
	if((src=par->src) == nil || src->data == nil)
279
		return 0;
280
	if((mask=par->mask) == nil || mask->data == nil)
281
		return 0;
282
 
283
	if(dst->data->bdata == xgdata.bdata)
284
		swcursoravoid(par->r);
285
	if(src->data->bdata == xgdata.bdata)
286
		swcursoravoid(par->sr);
287
	if(mask->data->bdata == xgdata.bdata)
288
		swcursoravoid(par->mr);
289
 
290
	return 0;
291
}
292
 
293
static int
294
screensize(void)
295
{
296
	char *p;
297
	char *f[3];
298
	int width, height, depth;
299
 
300
	p = getconf("vgasize");
301
	if(p == nil || getfields(p, f, nelem(f), 0, "x") != nelem(f) ||
302
	    (width = atoi(f[0])) < 16 ||
303
	    (height = atoi(f[1])) <= 0 ||
304
	    (depth = atoi(f[2])) <= 0)
305
		return -1;
306
	xgscreen.r.max = Pt(width, height);
307
	xgscreen.depth = depth;
308
	return 0;
309
}
310
 
311
void
312
screeninit(void)
313
{
314
	uchar *fb;
315
	int set;
316
	ulong chan;
317
 
318
	set = screensize() == 0;
319
	fb = fbinit(set, &xgscreen.r.max.x, &xgscreen.r.max.y, &xgscreen.depth);
320
	if(fb == nil){
321
		print("can't initialise %dx%dx%d framebuffer \n",
322
			xgscreen.r.max.x, xgscreen.r.max.y, xgscreen.depth);
323
		return;
324
	}
325
	xgscreen.clipr = xgscreen.r;
326
	switch(xgscreen.depth){
327
	default:
328
		print("unsupported screen depth %d\n", xgscreen.depth);
329
		xgscreen.depth = 16;
330
		/* fall through */
331
	case 16:
332
		chan = RGB16;
333
		break;
334
	case 24:
335
		chan = BGR24;
336
		break;
337
	case 32:
338
		chan = ARGB32;
339
		break;
340
	}
341
	memsetchan(&xgscreen, chan);
342
	conf.monitor = 1;
343
	xgdata.bdata = fb;
344
	xgdata.ref = 1;
345
	gscreen = &xgscreen;
346
	gscreen->width = wordsperline(gscreen->r, gscreen->depth);
347
 
348
	memimageinit();
349
	memdefont = getmemdefont();
350
	screenwin();
351
	screenputs = myscreenputs;
352
}
353
 
354
void
355
flushmemscreen(Rectangle)
356
{
357
}
358
 
359
uchar*
360
attachscreen(Rectangle *r, ulong *chan, int* d, int *width, int *softscreen)
361
{
362
	*r = gscreen->r;
363
	*d = gscreen->depth;
364
	*chan = gscreen->chan;
365
	*width = gscreen->width;
366
	*softscreen = 0;
367
 
368
	return gscreen->data->bdata;
369
}
370
 
371
void
372
getcolor(ulong p, ulong *pr, ulong *pg, ulong *pb)
373
{
374
	USED(p, pr, pg, pb);
375
}
376
 
377
int
378
setcolor(ulong p, ulong r, ulong g, ulong b)
379
{
380
	USED(p, r, g, b);
381
	return 0;
382
}
383
 
384
void
385
blankscreen(int blank)
386
{
387
	fbblank(blank);
388
}
389
 
390
static void
391
myscreenputs(char *s, int n)
392
{
393
	int i;
394
	Rune r;
395
	char buf[4];
396
 
397
	if(!islo()) {
398
		/* don't deadlock trying to print in interrupt */
399
		if(!canlock(&screenlock))
400
			return;	
401
	}
402
	else
403
		lock(&screenlock);
404
 
405
	while(n > 0){
406
		i = chartorune(&r, s);
407
		if(i == 0){
408
			s++;
409
			--n;
410
			continue;
411
		}
412
		memmove(buf, s, i);
413
		buf[i] = 0;
414
		n -= i;
415
		s += i;
416
		screenputc(buf);
417
	}
418
	unlock(&screenlock);
419
}
420
 
421
static void
422
screenwin(void)
423
{
424
	char *greet;
425
	Memimage *orange;
426
	Point p, q;
427
	Rectangle r;
428
 
429
	back = memwhite;
430
	conscol = memblack;
431
 
432
	orange = allocmemimage(Rect(0, 0, 1, 1), RGB16);
433
	orange->flags |= Frepl;
434
	orange->clipr = gscreen->r;
435
	orange->data->bdata[0] = 0x40;		/* magic: colour? */
436
	orange->data->bdata[1] = 0xfd;		/* magic: colour? */
437
 
438
	w = memdefont->info[' '].width;
439
	h = memdefont->height;
440
 
441
	r = insetrect(gscreen->r, 4);
442
 
443
	memimagedraw(gscreen, r, memblack, ZP, memopaque, ZP, S);
444
	window = insetrect(r, 4);
445
	memimagedraw(gscreen, window, memwhite, ZP, memopaque, ZP, S);
446
 
447
	memimagedraw(gscreen, Rect(window.min.x, window.min.y,
448
		window.max.x, window.min.y + h + 5 + 6), orange, ZP, nil, ZP, S);
449
	freememimage(orange);
450
	window = insetrect(window, 5);
451
 
452
	greet = " Plan 9 Console ";
453
	p = addpt(window.min, Pt(10, 0));
454
	q = memsubfontwidth(memdefont, greet);
455
	memimagestring(gscreen, p, conscol, ZP, memdefont, greet);
456
	flushmemscreen(r);
457
	window.min.y += h + 6;
458
	curpos = window.min;
459
	window.max.y = window.min.y + ((window.max.y - window.min.y) / h) * h;
460
}
461
 
462
static void
463
scroll(void)
464
{
465
	int o;
466
	Point p;
467
	Rectangle r;
468
 
469
	o = Scroll*h;
470
	r = Rpt(window.min, Pt(window.max.x, window.max.y-o));
471
	p = Pt(window.min.x, window.min.y+o);
472
	memimagedraw(gscreen, r, gscreen, p, nil, p, S);
473
	flushmemscreen(r);
474
	r = Rpt(Pt(window.min.x, window.max.y-o), window.max);
475
	memimagedraw(gscreen, r, back, ZP, nil, ZP, S);
476
	flushmemscreen(r);
477
 
478
	curpos.y -= o;
479
}
480
 
481
static void
482
screenputc(char *buf)
483
{
484
	int w;
485
	uint pos;
486
	Point p;
487
	Rectangle r;
488
	static int *xp;
489
	static int xbuf[256];
490
 
491
	if (xp < xbuf || xp >= &xbuf[sizeof(xbuf)])
492
		xp = xbuf;
493
 
494
	switch (buf[0]) {
495
	case '\n':
496
		if (curpos.y + h >= window.max.y)
497
			scroll();
498
		curpos.y += h;
499
		screenputc("\r");
500
		break;
501
	case '\r':
502
		xp = xbuf;
503
		curpos.x = window.min.x;
504
		break;
505
	case '\t':
506
		p = memsubfontwidth(memdefont, " ");
507
		w = p.x;
508
		if (curpos.x >= window.max.x - Tabstop * w)
509
			screenputc("\n");
510
 
511
		pos = (curpos.x - window.min.x) / w;
512
		pos = Tabstop - pos % Tabstop;
513
		*xp++ = curpos.x;
514
		r = Rect(curpos.x, curpos.y, curpos.x + pos * w, curpos.y + h);
515
		memimagedraw(gscreen, r, back, back->r.min, nil, back->r.min, S);
516
		flushmemscreen(r);
517
		curpos.x += pos * w;
518
		break;
519
	case '\b':
520
		if (xp <= xbuf)
521
			break;
522
		xp--;
523
		r = Rect(*xp, curpos.y, curpos.x, curpos.y + h);
524
		memimagedraw(gscreen, r, back, back->r.min, nil, back->r.min, S);
525
		flushmemscreen(r);
526
		curpos.x = *xp;
527
		break;
528
	case '\0':
529
		break;
530
	default:
531
		p = memsubfontwidth(memdefont, buf);
532
		w = p.x;
533
 
534
		if (curpos.x >= window.max.x - w)
535
			screenputc("\n");
536
 
537
		*xp++ = curpos.x;
538
		r = Rect(curpos.x, curpos.y, curpos.x + w, curpos.y + h);
539
		memimagedraw(gscreen, r, back, back->r.min, nil, back->r.min, S);
540
		memimagestring(gscreen, curpos, conscol, ZP, memdefont, buf);
541
		flushmemscreen(r);
542
		curpos.x += w;
543
		break;
544
	}
545
}