xref: /plan9-contrib/sys/src/9/bcm/screen.c (revision 5c47fe09a0cc86dfb02c0ea4a2b6aec7eda2361f)
15d9de2d3SDavid du Colombier /*
25d9de2d3SDavid du Colombier  * bcm2385 framebuffer
35d9de2d3SDavid du Colombier  */
45d9de2d3SDavid du Colombier 
55d9de2d3SDavid du Colombier #include "u.h"
65d9de2d3SDavid du Colombier #include "../port/lib.h"
75d9de2d3SDavid du Colombier #include "mem.h"
85d9de2d3SDavid du Colombier #include "dat.h"
95d9de2d3SDavid du Colombier #include "fns.h"
105d9de2d3SDavid du Colombier 
115d9de2d3SDavid du Colombier #define	Image	IMAGE
125d9de2d3SDavid du Colombier #include <draw.h>
135d9de2d3SDavid du Colombier #include <memdraw.h>
145d9de2d3SDavid du Colombier #include <cursor.h>
155d9de2d3SDavid du Colombier #include "screen.h"
165d9de2d3SDavid du Colombier 
175d9de2d3SDavid du Colombier enum {
185d9de2d3SDavid du Colombier 	Tabstop		= 4,
195d9de2d3SDavid du Colombier 	Scroll		= 8,
205d9de2d3SDavid du Colombier 	Wid		= 1024,
215d9de2d3SDavid du Colombier 	Ht		= 768,
225d9de2d3SDavid du Colombier 	Depth		= 16,
235d9de2d3SDavid du Colombier };
245d9de2d3SDavid du Colombier 
255d9de2d3SDavid du Colombier Cursor	arrow = {
265d9de2d3SDavid du Colombier 	{ -1, -1 },
275d9de2d3SDavid du Colombier 	{ 0xFF, 0xFF, 0x80, 0x01, 0x80, 0x02, 0x80, 0x0C,
285d9de2d3SDavid du Colombier 	  0x80, 0x10, 0x80, 0x10, 0x80, 0x08, 0x80, 0x04,
295d9de2d3SDavid du Colombier 	  0x80, 0x02, 0x80, 0x01, 0x80, 0x02, 0x8C, 0x04,
305d9de2d3SDavid du Colombier 	  0x92, 0x08, 0x91, 0x10, 0xA0, 0xA0, 0xC0, 0x40,
315d9de2d3SDavid du Colombier 	},
325d9de2d3SDavid du Colombier 	{ 0x00, 0x00, 0x7F, 0xFE, 0x7F, 0xFC, 0x7F, 0xF0,
335d9de2d3SDavid du Colombier 	  0x7F, 0xE0, 0x7F, 0xE0, 0x7F, 0xF0, 0x7F, 0xF8,
345d9de2d3SDavid du Colombier 	  0x7F, 0xFC, 0x7F, 0xFE, 0x7F, 0xFC, 0x73, 0xF8,
355d9de2d3SDavid du Colombier 	  0x61, 0xF0, 0x60, 0xE0, 0x40, 0x40, 0x00, 0x00,
365d9de2d3SDavid du Colombier 	},
375d9de2d3SDavid du Colombier };
385d9de2d3SDavid du Colombier 
395d9de2d3SDavid du Colombier Memimage *gscreen;
40*5c47fe09SDavid du Colombier Lcd	*lcd;
415d9de2d3SDavid du Colombier 
425d9de2d3SDavid du Colombier static Memdata xgdata;
435d9de2d3SDavid du Colombier 
44*5c47fe09SDavid du Colombier /*static*/ Memimage xgscreen =
455d9de2d3SDavid du Colombier {
465d9de2d3SDavid du Colombier 	{ 0, 0, Wid, Ht },	/* r */
475d9de2d3SDavid du Colombier 	{ 0, 0, Wid, Ht },	/* clipr */
485d9de2d3SDavid du Colombier 	Depth,			/* depth */
495d9de2d3SDavid du Colombier 	3,			/* nchan */
505d9de2d3SDavid du Colombier 	RGB16,			/* chan */
515d9de2d3SDavid du Colombier 	nil,			/* cmap */
525d9de2d3SDavid du Colombier 	&xgdata,		/* data */
535d9de2d3SDavid du Colombier 	0,			/* zero */
545d9de2d3SDavid du Colombier 	0, 			/* width in words of a single scan line */
555d9de2d3SDavid du Colombier 	0,			/* layer */
565d9de2d3SDavid du Colombier 	0,			/* flags */
575d9de2d3SDavid du Colombier };
585d9de2d3SDavid du Colombier 
595d9de2d3SDavid du Colombier static Memimage *conscol;
605d9de2d3SDavid du Colombier static Memimage *back;
615d9de2d3SDavid du Colombier static Memsubfont *memdefont;
625d9de2d3SDavid du Colombier 
635d9de2d3SDavid du Colombier static Lock screenlock;
645d9de2d3SDavid du Colombier 
655d9de2d3SDavid du Colombier static Point	curpos;
665d9de2d3SDavid du Colombier static int	h, w;
675d9de2d3SDavid du Colombier static Rectangle window;
685d9de2d3SDavid du Colombier 
695d9de2d3SDavid du Colombier static void myscreenputs(char *s, int n);
705d9de2d3SDavid du Colombier static void screenputc(char *buf);
715d9de2d3SDavid du Colombier static void screenwin(void);
725d9de2d3SDavid du Colombier 
735d9de2d3SDavid du Colombier /*
745d9de2d3SDavid du Colombier  * Software cursor.
755d9de2d3SDavid du Colombier  */
765d9de2d3SDavid du Colombier static int	swvisible;	/* is the cursor visible? */
775d9de2d3SDavid du Colombier static int	swenabled;	/* is the cursor supposed to be on the screen? */
785d9de2d3SDavid du Colombier static Memimage *swback;	/* screen under cursor */
795d9de2d3SDavid du Colombier static Memimage *swimg;		/* cursor image */
805d9de2d3SDavid du Colombier static Memimage *swmask;	/* cursor mask */
815d9de2d3SDavid du Colombier static Memimage *swimg1;
825d9de2d3SDavid du Colombier static Memimage *swmask1;
835d9de2d3SDavid du Colombier 
845d9de2d3SDavid du Colombier static Point	swoffset;
855d9de2d3SDavid du Colombier static Rectangle swrect;	/* screen rectangle in swback */
865d9de2d3SDavid du Colombier static Point	swpt;		/* desired cursor location */
875d9de2d3SDavid du Colombier static Point	swvispt;	/* actual cursor location */
885d9de2d3SDavid du Colombier static int	swvers;		/* incremented each time cursor image changes */
895d9de2d3SDavid du Colombier static int	swvisvers;	/* the version on the screen */
905d9de2d3SDavid du Colombier 
915d9de2d3SDavid du Colombier /*
925d9de2d3SDavid du Colombier  * called with drawlock locked for us, most of the time.
935d9de2d3SDavid du Colombier  * kernel prints at inopportune times might mean we don't
945d9de2d3SDavid du Colombier  * hold the lock, but memimagedraw is now reentrant so
955d9de2d3SDavid du Colombier  * that should be okay: worst case we get cursor droppings.
965d9de2d3SDavid du Colombier  */
975d9de2d3SDavid du Colombier static void
swcursorhide(void)985d9de2d3SDavid du Colombier swcursorhide(void)
995d9de2d3SDavid du Colombier {
1005d9de2d3SDavid du Colombier 	if(swvisible == 0)
1015d9de2d3SDavid du Colombier 		return;
1025d9de2d3SDavid du Colombier 	if(swback == nil)
1035d9de2d3SDavid du Colombier 		return;
1045d9de2d3SDavid du Colombier 	swvisible = 0;
1055d9de2d3SDavid du Colombier 	memimagedraw(gscreen, swrect, swback, ZP, memopaque, ZP, S);
1065d9de2d3SDavid du Colombier 	flushmemscreen(swrect);
1075d9de2d3SDavid du Colombier }
1085d9de2d3SDavid du Colombier 
1095d9de2d3SDavid du Colombier static void
swcursoravoid(Rectangle r)1105d9de2d3SDavid du Colombier swcursoravoid(Rectangle r)
1115d9de2d3SDavid du Colombier {
1125d9de2d3SDavid du Colombier 	if(swvisible && rectXrect(r, swrect))
1135d9de2d3SDavid du Colombier 		swcursorhide();
1145d9de2d3SDavid du Colombier }
1155d9de2d3SDavid du Colombier 
1165d9de2d3SDavid du Colombier static void
swcursordraw(void)1175d9de2d3SDavid du Colombier swcursordraw(void)
1185d9de2d3SDavid du Colombier {
1195d9de2d3SDavid du Colombier 	int dounlock;
1205d9de2d3SDavid du Colombier 
1215d9de2d3SDavid du Colombier 	if(swvisible)
1225d9de2d3SDavid du Colombier 		return;
1235d9de2d3SDavid du Colombier 	if(swenabled == 0)
1245d9de2d3SDavid du Colombier 		return;
1255d9de2d3SDavid du Colombier 	if(swback == nil || swimg1 == nil || swmask1 == nil)
1265d9de2d3SDavid du Colombier 		return;
1275d9de2d3SDavid du Colombier 	dounlock = canqlock(&drawlock);
1285d9de2d3SDavid du Colombier 	swvispt = swpt;
1295d9de2d3SDavid du Colombier 	swvisvers = swvers;
1305d9de2d3SDavid du Colombier 	swrect = rectaddpt(Rect(0,0,16,16), swvispt);
1315d9de2d3SDavid du Colombier 	memimagedraw(swback, swback->r, gscreen, swpt, memopaque, ZP, S);
1325d9de2d3SDavid du Colombier 	memimagedraw(gscreen, swrect, swimg1, ZP, swmask1, ZP, SoverD);
1335d9de2d3SDavid du Colombier 	flushmemscreen(swrect);
1345d9de2d3SDavid du Colombier 	swvisible = 1;
1355d9de2d3SDavid du Colombier 	if(dounlock)
1365d9de2d3SDavid du Colombier 		qunlock(&drawlock);
1375d9de2d3SDavid du Colombier }
1385d9de2d3SDavid du Colombier 
1395d9de2d3SDavid du Colombier int
cursoron(int dolock)1405d9de2d3SDavid du Colombier cursoron(int dolock)
1415d9de2d3SDavid du Colombier {
1425d9de2d3SDavid du Colombier 	int retry;
1435d9de2d3SDavid du Colombier 
1445d9de2d3SDavid du Colombier 	if (dolock)
1455d9de2d3SDavid du Colombier 		lock(&cursor);
1465d9de2d3SDavid du Colombier 	if (canqlock(&drawlock)) {
1475d9de2d3SDavid du Colombier 		retry = 0;
1485d9de2d3SDavid du Colombier 		swcursorhide();
1495d9de2d3SDavid du Colombier 		swcursordraw();
1505d9de2d3SDavid du Colombier 		qunlock(&drawlock);
1515d9de2d3SDavid du Colombier 	} else
1525d9de2d3SDavid du Colombier 		retry = 1;
1535d9de2d3SDavid du Colombier 	if (dolock)
1545d9de2d3SDavid du Colombier 		unlock(&cursor);
1555d9de2d3SDavid du Colombier 	return retry;
1565d9de2d3SDavid du Colombier }
1575d9de2d3SDavid du Colombier 
1585d9de2d3SDavid du Colombier void
cursoroff(int dolock)1595d9de2d3SDavid du Colombier cursoroff(int dolock)
1605d9de2d3SDavid du Colombier {
1615d9de2d3SDavid du Colombier 	if (dolock)
1625d9de2d3SDavid du Colombier 		lock(&cursor);
1635d9de2d3SDavid du Colombier 	swcursorhide();
1645d9de2d3SDavid du Colombier 	if (dolock)
1655d9de2d3SDavid du Colombier 		unlock(&cursor);
1665d9de2d3SDavid du Colombier }
1675d9de2d3SDavid du Colombier 
1685d9de2d3SDavid du Colombier static void
swload(Cursor * curs)1695d9de2d3SDavid du Colombier swload(Cursor *curs)
1705d9de2d3SDavid du Colombier {
1715d9de2d3SDavid du Colombier 	uchar *ip, *mp;
1725d9de2d3SDavid du Colombier 	int i, j, set, clr;
1735d9de2d3SDavid du Colombier 
1745d9de2d3SDavid du Colombier 	if(!swimg || !swmask || !swimg1 || !swmask1)
1755d9de2d3SDavid du Colombier 		return;
1765d9de2d3SDavid du Colombier 	/*
1775d9de2d3SDavid du Colombier 	 * Build cursor image and mask.
1785d9de2d3SDavid du Colombier 	 * Image is just the usual cursor image
1795d9de2d3SDavid du Colombier 	 * but mask is a transparent alpha mask.
1805d9de2d3SDavid du Colombier 	 *
1815d9de2d3SDavid du Colombier 	 * The 16x16x8 memimages do not have
1825d9de2d3SDavid du Colombier 	 * padding at the end of their scan lines.
1835d9de2d3SDavid du Colombier 	 */
1845d9de2d3SDavid du Colombier 	ip = byteaddr(swimg, ZP);
1855d9de2d3SDavid du Colombier 	mp = byteaddr(swmask, ZP);
1865d9de2d3SDavid du Colombier 	for(i=0; i<32; i++){
1875d9de2d3SDavid du Colombier 		set = curs->set[i];
1885d9de2d3SDavid du Colombier 		clr = curs->clr[i];
1895d9de2d3SDavid du Colombier 		for(j=0x80; j; j>>=1){
1905d9de2d3SDavid du Colombier 			*ip++ = set&j ? 0x00 : 0xFF;
1915d9de2d3SDavid du Colombier 			*mp++ = (clr|set)&j ? 0xFF : 0x00;
1925d9de2d3SDavid du Colombier 		}
1935d9de2d3SDavid du Colombier 	}
1945d9de2d3SDavid du Colombier 	swoffset = curs->offset;
1955d9de2d3SDavid du Colombier 	swvers++;
1965d9de2d3SDavid du Colombier 	memimagedraw(swimg1,  swimg1->r,  swimg,  ZP, memopaque, ZP, S);
1975d9de2d3SDavid du Colombier 	memimagedraw(swmask1, swmask1->r, swmask, ZP, memopaque, ZP, S);
1985d9de2d3SDavid du Colombier }
1995d9de2d3SDavid du Colombier 
2005d9de2d3SDavid du Colombier /* called from devmouse */
2015d9de2d3SDavid du Colombier void
setcursor(Cursor * curs)2025d9de2d3SDavid du Colombier setcursor(Cursor* curs)
2035d9de2d3SDavid du Colombier {
2045d9de2d3SDavid du Colombier 	cursoroff(0);
2055d9de2d3SDavid du Colombier 	swload(curs);
2065d9de2d3SDavid du Colombier 	cursoron(0);
2075d9de2d3SDavid du Colombier }
2085d9de2d3SDavid du Colombier 
2095d9de2d3SDavid du Colombier static int
swmove(Point p)2105d9de2d3SDavid du Colombier swmove(Point p)
2115d9de2d3SDavid du Colombier {
2125d9de2d3SDavid du Colombier 	swpt = addpt(p, swoffset);
2135d9de2d3SDavid du Colombier 	return 0;
2145d9de2d3SDavid du Colombier }
2155d9de2d3SDavid du Colombier 
2165d9de2d3SDavid du Colombier static void
swcursorclock(void)2175d9de2d3SDavid du Colombier swcursorclock(void)
2185d9de2d3SDavid du Colombier {
2195d9de2d3SDavid du Colombier 	int x;
2205d9de2d3SDavid du Colombier 
2215d9de2d3SDavid du Colombier 	if(!swenabled)
2225d9de2d3SDavid du Colombier 		return;
2235d9de2d3SDavid du Colombier 	swmove(mousexy());
2245d9de2d3SDavid du Colombier 	if(swvisible && eqpt(swpt, swvispt) && swvers==swvisvers)
2255d9de2d3SDavid du Colombier 		return;
2265d9de2d3SDavid du Colombier 
2275d9de2d3SDavid du Colombier 	x = splhi();
2285d9de2d3SDavid du Colombier 	if(swenabled)
2295d9de2d3SDavid du Colombier 	if(!swvisible || !eqpt(swpt, swvispt) || swvers!=swvisvers)
2305d9de2d3SDavid du Colombier 	if(canqlock(&drawlock)){
2315d9de2d3SDavid du Colombier 		swcursorhide();
2325d9de2d3SDavid du Colombier 		swcursordraw();
2335d9de2d3SDavid du Colombier 		qunlock(&drawlock);
2345d9de2d3SDavid du Colombier 	}
2355d9de2d3SDavid du Colombier 	splx(x);
2365d9de2d3SDavid du Colombier }
2375d9de2d3SDavid du Colombier 
2385d9de2d3SDavid du Colombier void
swcursorinit(void)2395d9de2d3SDavid du Colombier swcursorinit(void)
2405d9de2d3SDavid du Colombier {
2415d9de2d3SDavid du Colombier 	static int init;
2425d9de2d3SDavid du Colombier 
2435d9de2d3SDavid du Colombier 	if(!init){
2445d9de2d3SDavid du Colombier 		init = 1;
2455d9de2d3SDavid du Colombier 		addclock0link(swcursorclock, 10);
2465d9de2d3SDavid du Colombier 		swenabled = 1;
2475d9de2d3SDavid du Colombier 	}
2485d9de2d3SDavid du Colombier 	if(swback){
2495d9de2d3SDavid du Colombier 		freememimage(swback);
2505d9de2d3SDavid du Colombier 		freememimage(swmask);
2515d9de2d3SDavid du Colombier 		freememimage(swmask1);
2525d9de2d3SDavid du Colombier 		freememimage(swimg);
2535d9de2d3SDavid du Colombier 		freememimage(swimg1);
2545d9de2d3SDavid du Colombier 	}
2555d9de2d3SDavid du Colombier 
2565d9de2d3SDavid du Colombier 	swback  = allocmemimage(Rect(0,0,32,32), gscreen->chan);
2575d9de2d3SDavid du Colombier 	swmask  = allocmemimage(Rect(0,0,16,16), GREY8);
2585d9de2d3SDavid du Colombier 	swmask1 = allocmemimage(Rect(0,0,16,16), GREY1);
2595d9de2d3SDavid du Colombier 	swimg   = allocmemimage(Rect(0,0,16,16), GREY8);
2605d9de2d3SDavid du Colombier 	swimg1  = allocmemimage(Rect(0,0,16,16), GREY1);
2615d9de2d3SDavid du Colombier 	if(swback==nil || swmask==nil || swmask1==nil || swimg==nil || swimg1 == nil){
2625d9de2d3SDavid du Colombier 		print("software cursor: allocmemimage fails\n");
2635d9de2d3SDavid du Colombier 		return;
2645d9de2d3SDavid du Colombier 	}
2655d9de2d3SDavid du Colombier 
2665d9de2d3SDavid du Colombier 	memfillcolor(swmask, DOpaque);
2675d9de2d3SDavid du Colombier 	memfillcolor(swmask1, DOpaque);
2685d9de2d3SDavid du Colombier 	memfillcolor(swimg, DBlack);
2695d9de2d3SDavid du Colombier 	memfillcolor(swimg1, DBlack);
2705d9de2d3SDavid du Colombier }
2715d9de2d3SDavid du Colombier 
2725d9de2d3SDavid du Colombier int
hwdraw(Memdrawparam * par)2735d9de2d3SDavid du Colombier hwdraw(Memdrawparam *par)
2745d9de2d3SDavid du Colombier {
2755d9de2d3SDavid du Colombier 	Memimage *dst, *src, *mask;
2765d9de2d3SDavid du Colombier 
2775d9de2d3SDavid du Colombier 	if((dst=par->dst) == nil || dst->data == nil)
2785d9de2d3SDavid du Colombier 		return 0;
2795d9de2d3SDavid du Colombier 	if((src=par->src) == nil || src->data == nil)
2805d9de2d3SDavid du Colombier 		return 0;
2815d9de2d3SDavid du Colombier 	if((mask=par->mask) == nil || mask->data == nil)
2825d9de2d3SDavid du Colombier 		return 0;
2835d9de2d3SDavid du Colombier 
2845d9de2d3SDavid du Colombier 	if(dst->data->bdata == xgdata.bdata)
2855d9de2d3SDavid du Colombier 		swcursoravoid(par->r);
2865d9de2d3SDavid du Colombier 	if(src->data->bdata == xgdata.bdata)
2875d9de2d3SDavid du Colombier 		swcursoravoid(par->sr);
2885d9de2d3SDavid du Colombier 	if(mask->data->bdata == xgdata.bdata)
2895d9de2d3SDavid du Colombier 		swcursoravoid(par->mr);
2905d9de2d3SDavid du Colombier 
291*5c47fe09SDavid du Colombier 	if(lcd)
292*5c47fe09SDavid du Colombier 		lcd->draw(par->r);
293*5c47fe09SDavid du Colombier 
2945d9de2d3SDavid du Colombier 	return 0;
2955d9de2d3SDavid du Colombier }
2965d9de2d3SDavid du Colombier 
2975d9de2d3SDavid du Colombier static int
screensize(void)2985d9de2d3SDavid du Colombier screensize(void)
2995d9de2d3SDavid du Colombier {
300*5c47fe09SDavid du Colombier 	char *p, buf[32];
3015d9de2d3SDavid du Colombier 	char *f[3];
3025d9de2d3SDavid du Colombier 	int width, height, depth;
3035d9de2d3SDavid du Colombier 
3045d9de2d3SDavid du Colombier 	p = getconf("vgasize");
305*5c47fe09SDavid du Colombier 	if(p == nil || memccpy(buf, p, '\0', sizeof buf) == nil)
306*5c47fe09SDavid du Colombier 		return -1;
307*5c47fe09SDavid du Colombier 
308*5c47fe09SDavid du Colombier 	if(getfields(buf, f, nelem(f), 0, "x") != nelem(f) ||
309b4d1cf41SDavid du Colombier 	    (width = atoi(f[0])) < 16 ||
310b4d1cf41SDavid du Colombier 	    (height = atoi(f[1])) <= 0 ||
3115d9de2d3SDavid du Colombier 	    (depth = atoi(f[2])) <= 0)
3125d9de2d3SDavid du Colombier 		return -1;
3135d9de2d3SDavid du Colombier 	xgscreen.r.max = Pt(width, height);
3145d9de2d3SDavid du Colombier 	xgscreen.depth = depth;
3155d9de2d3SDavid du Colombier 	return 0;
3165d9de2d3SDavid du Colombier }
3175d9de2d3SDavid du Colombier 
3185d9de2d3SDavid du Colombier void
screeninit(void)3195d9de2d3SDavid du Colombier screeninit(void)
3205d9de2d3SDavid du Colombier {
3215d9de2d3SDavid du Colombier 	uchar *fb;
322*5c47fe09SDavid du Colombier 	char *p;
323*5c47fe09SDavid du Colombier 	int set, rgbswap;
3245d9de2d3SDavid du Colombier 	ulong chan;
3255d9de2d3SDavid du Colombier 
3265d9de2d3SDavid du Colombier 	set = screensize() == 0;
3275d9de2d3SDavid du Colombier 	fb = fbinit(set, &xgscreen.r.max.x, &xgscreen.r.max.y, &xgscreen.depth);
3285d9de2d3SDavid du Colombier 	if(fb == nil){
329*5c47fe09SDavid du Colombier 		xgscreen.r.max = Pt(640, 480);
330*5c47fe09SDavid du Colombier 		xgscreen.depth = 16;
331*5c47fe09SDavid du Colombier 		fb = fbinit(set, &xgscreen.r.max.x, &xgscreen.r.max.y, &xgscreen.depth);
332*5c47fe09SDavid du Colombier 	}
333*5c47fe09SDavid du Colombier 	if(fb == nil){
3345d9de2d3SDavid du Colombier 		print("can't initialise %dx%dx%d framebuffer \n",
3355d9de2d3SDavid du Colombier 			xgscreen.r.max.x, xgscreen.r.max.y, xgscreen.depth);
3365d9de2d3SDavid du Colombier 		return;
3375d9de2d3SDavid du Colombier 	}
338*5c47fe09SDavid du Colombier 	rgbswap = ((p = getconf("bcm2708_fb.fbswap")) != nil && *p == '1');
3395d9de2d3SDavid du Colombier 	xgscreen.clipr = xgscreen.r;
3405d9de2d3SDavid du Colombier 	switch(xgscreen.depth){
3415d9de2d3SDavid du Colombier 	default:
3425d9de2d3SDavid du Colombier 		print("unsupported screen depth %d\n", xgscreen.depth);
3435d9de2d3SDavid du Colombier 		xgscreen.depth = 16;
3445d9de2d3SDavid du Colombier 		/* fall through */
3455d9de2d3SDavid du Colombier 	case 16:
3465d9de2d3SDavid du Colombier 		chan = RGB16;
3475d9de2d3SDavid du Colombier 		break;
3485d9de2d3SDavid du Colombier 	case 24:
349*5c47fe09SDavid du Colombier 		chan = rgbswap? RGB24 : BGR24;
3505d9de2d3SDavid du Colombier 		break;
3515d9de2d3SDavid du Colombier 	case 32:
352*5c47fe09SDavid du Colombier 		chan = rgbswap? XRGB32 : XBGR32;
3535d9de2d3SDavid du Colombier 		break;
3545d9de2d3SDavid du Colombier 	}
3555d9de2d3SDavid du Colombier 	memsetchan(&xgscreen, chan);
3565d9de2d3SDavid du Colombier 	conf.monitor = 1;
3575d9de2d3SDavid du Colombier 	xgdata.bdata = fb;
3585d9de2d3SDavid du Colombier 	xgdata.ref = 1;
3595d9de2d3SDavid du Colombier 	gscreen = &xgscreen;
3605d9de2d3SDavid du Colombier 	gscreen->width = wordsperline(gscreen->r, gscreen->depth);
3615d9de2d3SDavid du Colombier 
3625d9de2d3SDavid du Colombier 	memimageinit();
3635d9de2d3SDavid du Colombier 	memdefont = getmemdefont();
3645d9de2d3SDavid du Colombier 	screenwin();
3655d9de2d3SDavid du Colombier 	screenputs = myscreenputs;
3665d9de2d3SDavid du Colombier }
3675d9de2d3SDavid du Colombier 
3685d9de2d3SDavid du Colombier void
flushmemscreen(Rectangle)3695d9de2d3SDavid du Colombier flushmemscreen(Rectangle)
3705d9de2d3SDavid du Colombier {
3715d9de2d3SDavid du Colombier }
3725d9de2d3SDavid du Colombier 
3735d9de2d3SDavid du Colombier uchar*
attachscreen(Rectangle * r,ulong * chan,int * d,int * width,int * softscreen)3745d9de2d3SDavid du Colombier attachscreen(Rectangle *r, ulong *chan, int* d, int *width, int *softscreen)
3755d9de2d3SDavid du Colombier {
3765d9de2d3SDavid du Colombier 	*r = gscreen->r;
3775d9de2d3SDavid du Colombier 	*d = gscreen->depth;
3785d9de2d3SDavid du Colombier 	*chan = gscreen->chan;
3795d9de2d3SDavid du Colombier 	*width = gscreen->width;
3805d9de2d3SDavid du Colombier 	*softscreen = 0;
3815d9de2d3SDavid du Colombier 
3825d9de2d3SDavid du Colombier 	return gscreen->data->bdata;
3835d9de2d3SDavid du Colombier }
3845d9de2d3SDavid du Colombier 
3855d9de2d3SDavid du Colombier void
getcolor(ulong p,ulong * pr,ulong * pg,ulong * pb)3865d9de2d3SDavid du Colombier getcolor(ulong p, ulong *pr, ulong *pg, ulong *pb)
3875d9de2d3SDavid du Colombier {
3885d9de2d3SDavid du Colombier 	USED(p, pr, pg, pb);
3895d9de2d3SDavid du Colombier }
3905d9de2d3SDavid du Colombier 
3915d9de2d3SDavid du Colombier int
setcolor(ulong p,ulong r,ulong g,ulong b)3925d9de2d3SDavid du Colombier setcolor(ulong p, ulong r, ulong g, ulong b)
3935d9de2d3SDavid du Colombier {
3945d9de2d3SDavid du Colombier 	USED(p, r, g, b);
3955d9de2d3SDavid du Colombier 	return 0;
3965d9de2d3SDavid du Colombier }
3975d9de2d3SDavid du Colombier 
3985d9de2d3SDavid du Colombier void
blankscreen(int blank)3995d9de2d3SDavid du Colombier blankscreen(int blank)
4005d9de2d3SDavid du Colombier {
4015d9de2d3SDavid du Colombier 	fbblank(blank);
402*5c47fe09SDavid du Colombier 	if(lcd)
403*5c47fe09SDavid du Colombier 		lcd->blank(blank);
4045d9de2d3SDavid du Colombier }
4055d9de2d3SDavid du Colombier 
4065d9de2d3SDavid du Colombier static void
myscreenputs(char * s,int n)4075d9de2d3SDavid du Colombier myscreenputs(char *s, int n)
4085d9de2d3SDavid du Colombier {
4095d9de2d3SDavid du Colombier 	int i;
4105d9de2d3SDavid du Colombier 	Rune r;
4115d9de2d3SDavid du Colombier 	char buf[4];
4125d9de2d3SDavid du Colombier 
4135d9de2d3SDavid du Colombier 	if(!islo()) {
4145d9de2d3SDavid du Colombier 		/* don't deadlock trying to print in interrupt */
4155d9de2d3SDavid du Colombier 		if(!canlock(&screenlock))
4165d9de2d3SDavid du Colombier 			return;
4175d9de2d3SDavid du Colombier 	}
4185d9de2d3SDavid du Colombier 	else
4195d9de2d3SDavid du Colombier 		lock(&screenlock);
4205d9de2d3SDavid du Colombier 
4215d9de2d3SDavid du Colombier 	while(n > 0){
4225d9de2d3SDavid du Colombier 		i = chartorune(&r, s);
4235d9de2d3SDavid du Colombier 		if(i == 0){
4245d9de2d3SDavid du Colombier 			s++;
4255d9de2d3SDavid du Colombier 			--n;
4265d9de2d3SDavid du Colombier 			continue;
4275d9de2d3SDavid du Colombier 		}
4285d9de2d3SDavid du Colombier 		memmove(buf, s, i);
4295d9de2d3SDavid du Colombier 		buf[i] = 0;
4305d9de2d3SDavid du Colombier 		n -= i;
4315d9de2d3SDavid du Colombier 		s += i;
4325d9de2d3SDavid du Colombier 		screenputc(buf);
4335d9de2d3SDavid du Colombier 	}
4345d9de2d3SDavid du Colombier 	unlock(&screenlock);
4355d9de2d3SDavid du Colombier }
4365d9de2d3SDavid du Colombier 
4375d9de2d3SDavid du Colombier static void
screenwin(void)4385d9de2d3SDavid du Colombier screenwin(void)
4395d9de2d3SDavid du Colombier {
4405d9de2d3SDavid du Colombier 	char *greet;
4415d9de2d3SDavid du Colombier 	Memimage *orange;
4425d9de2d3SDavid du Colombier 	Point p, q;
4435d9de2d3SDavid du Colombier 	Rectangle r;
4445d9de2d3SDavid du Colombier 
4455d9de2d3SDavid du Colombier 	back = memwhite;
4465d9de2d3SDavid du Colombier 	conscol = memblack;
4475d9de2d3SDavid du Colombier 
4485d9de2d3SDavid du Colombier 	orange = allocmemimage(Rect(0, 0, 1, 1), RGB16);
4495d9de2d3SDavid du Colombier 	orange->flags |= Frepl;
4505d9de2d3SDavid du Colombier 	orange->clipr = gscreen->r;
4515d9de2d3SDavid du Colombier 	orange->data->bdata[0] = 0x40;		/* magic: colour? */
4525d9de2d3SDavid du Colombier 	orange->data->bdata[1] = 0xfd;		/* magic: colour? */
4535d9de2d3SDavid du Colombier 
4545d9de2d3SDavid du Colombier 	w = memdefont->info[' '].width;
4555d9de2d3SDavid du Colombier 	h = memdefont->height;
4565d9de2d3SDavid du Colombier 
4575d9de2d3SDavid du Colombier 	r = insetrect(gscreen->r, 4);
4585d9de2d3SDavid du Colombier 
4595d9de2d3SDavid du Colombier 	memimagedraw(gscreen, r, memblack, ZP, memopaque, ZP, S);
4605d9de2d3SDavid du Colombier 	window = insetrect(r, 4);
4615d9de2d3SDavid du Colombier 	memimagedraw(gscreen, window, memwhite, ZP, memopaque, ZP, S);
4625d9de2d3SDavid du Colombier 
4635d9de2d3SDavid du Colombier 	memimagedraw(gscreen, Rect(window.min.x, window.min.y,
4645d9de2d3SDavid du Colombier 		window.max.x, window.min.y + h + 5 + 6), orange, ZP, nil, ZP, S);
4655d9de2d3SDavid du Colombier 	freememimage(orange);
4665d9de2d3SDavid du Colombier 	window = insetrect(window, 5);
4675d9de2d3SDavid du Colombier 
4685d9de2d3SDavid du Colombier 	greet = " Plan 9 Console ";
4695d9de2d3SDavid du Colombier 	p = addpt(window.min, Pt(10, 0));
4705d9de2d3SDavid du Colombier 	q = memsubfontwidth(memdefont, greet);
4715d9de2d3SDavid du Colombier 	memimagestring(gscreen, p, conscol, ZP, memdefont, greet);
4725d9de2d3SDavid du Colombier 	flushmemscreen(r);
4735d9de2d3SDavid du Colombier 	window.min.y += h + 6;
4745d9de2d3SDavid du Colombier 	curpos = window.min;
4755d9de2d3SDavid du Colombier 	window.max.y = window.min.y + ((window.max.y - window.min.y) / h) * h;
4765d9de2d3SDavid du Colombier }
4775d9de2d3SDavid du Colombier 
4785d9de2d3SDavid du Colombier static void
scroll(void)4795d9de2d3SDavid du Colombier scroll(void)
4805d9de2d3SDavid du Colombier {
4815d9de2d3SDavid du Colombier 	int o;
4825d9de2d3SDavid du Colombier 	Point p;
4835d9de2d3SDavid du Colombier 	Rectangle r;
4845d9de2d3SDavid du Colombier 
4855d9de2d3SDavid du Colombier 	o = Scroll*h;
4865d9de2d3SDavid du Colombier 	r = Rpt(window.min, Pt(window.max.x, window.max.y-o));
4875d9de2d3SDavid du Colombier 	p = Pt(window.min.x, window.min.y+o);
4885d9de2d3SDavid du Colombier 	memimagedraw(gscreen, r, gscreen, p, nil, p, S);
4895d9de2d3SDavid du Colombier 	flushmemscreen(r);
490*5c47fe09SDavid du Colombier 	if(lcd)
491*5c47fe09SDavid du Colombier 		lcd->draw(r);
4925d9de2d3SDavid du Colombier 	r = Rpt(Pt(window.min.x, window.max.y-o), window.max);
4935d9de2d3SDavid du Colombier 	memimagedraw(gscreen, r, back, ZP, nil, ZP, S);
4945d9de2d3SDavid du Colombier 	flushmemscreen(r);
495*5c47fe09SDavid du Colombier 	if(lcd)
496*5c47fe09SDavid du Colombier 		lcd->draw(r);
4975d9de2d3SDavid du Colombier 
4985d9de2d3SDavid du Colombier 	curpos.y -= o;
4995d9de2d3SDavid du Colombier }
5005d9de2d3SDavid du Colombier 
5015d9de2d3SDavid du Colombier static void
screenputc(char * buf)5025d9de2d3SDavid du Colombier screenputc(char *buf)
5035d9de2d3SDavid du Colombier {
5045d9de2d3SDavid du Colombier 	int w;
5055d9de2d3SDavid du Colombier 	uint pos;
5065d9de2d3SDavid du Colombier 	Point p;
5075d9de2d3SDavid du Colombier 	Rectangle r;
5085d9de2d3SDavid du Colombier 	static int *xp;
5095d9de2d3SDavid du Colombier 	static int xbuf[256];
5105d9de2d3SDavid du Colombier 
5115d9de2d3SDavid du Colombier 	if (xp < xbuf || xp >= &xbuf[sizeof(xbuf)])
5125d9de2d3SDavid du Colombier 		xp = xbuf;
5135d9de2d3SDavid du Colombier 
5145d9de2d3SDavid du Colombier 	switch (buf[0]) {
5155d9de2d3SDavid du Colombier 	case '\n':
5165d9de2d3SDavid du Colombier 		if (curpos.y + h >= window.max.y)
5175d9de2d3SDavid du Colombier 			scroll();
5185d9de2d3SDavid du Colombier 		curpos.y += h;
5195d9de2d3SDavid du Colombier 		screenputc("\r");
5205d9de2d3SDavid du Colombier 		break;
5215d9de2d3SDavid du Colombier 	case '\r':
5225d9de2d3SDavid du Colombier 		xp = xbuf;
5235d9de2d3SDavid du Colombier 		curpos.x = window.min.x;
5245d9de2d3SDavid du Colombier 		break;
5255d9de2d3SDavid du Colombier 	case '\t':
5265d9de2d3SDavid du Colombier 		p = memsubfontwidth(memdefont, " ");
5275d9de2d3SDavid du Colombier 		w = p.x;
5285d9de2d3SDavid du Colombier 		if (curpos.x >= window.max.x - Tabstop * w)
5295d9de2d3SDavid du Colombier 			screenputc("\n");
5305d9de2d3SDavid du Colombier 
5315d9de2d3SDavid du Colombier 		pos = (curpos.x - window.min.x) / w;
5325d9de2d3SDavid du Colombier 		pos = Tabstop - pos % Tabstop;
5335d9de2d3SDavid du Colombier 		*xp++ = curpos.x;
5345d9de2d3SDavid du Colombier 		r = Rect(curpos.x, curpos.y, curpos.x + pos * w, curpos.y + h);
5355d9de2d3SDavid du Colombier 		memimagedraw(gscreen, r, back, back->r.min, nil, back->r.min, S);
5365d9de2d3SDavid du Colombier 		flushmemscreen(r);
5375d9de2d3SDavid du Colombier 		curpos.x += pos * w;
5385d9de2d3SDavid du Colombier 		break;
5395d9de2d3SDavid du Colombier 	case '\b':
5405d9de2d3SDavid du Colombier 		if (xp <= xbuf)
5415d9de2d3SDavid du Colombier 			break;
5425d9de2d3SDavid du Colombier 		xp--;
5435d9de2d3SDavid du Colombier 		r = Rect(*xp, curpos.y, curpos.x, curpos.y + h);
5445d9de2d3SDavid du Colombier 		memimagedraw(gscreen, r, back, back->r.min, nil, back->r.min, S);
5455d9de2d3SDavid du Colombier 		flushmemscreen(r);
5465d9de2d3SDavid du Colombier 		curpos.x = *xp;
5475d9de2d3SDavid du Colombier 		break;
5485d9de2d3SDavid du Colombier 	case '\0':
5495d9de2d3SDavid du Colombier 		break;
5505d9de2d3SDavid du Colombier 	default:
5515d9de2d3SDavid du Colombier 		p = memsubfontwidth(memdefont, buf);
5525d9de2d3SDavid du Colombier 		w = p.x;
5535d9de2d3SDavid du Colombier 
5545d9de2d3SDavid du Colombier 		if (curpos.x >= window.max.x - w)
5555d9de2d3SDavid du Colombier 			screenputc("\n");
5565d9de2d3SDavid du Colombier 
5575d9de2d3SDavid du Colombier 		*xp++ = curpos.x;
5585d9de2d3SDavid du Colombier 		r = Rect(curpos.x, curpos.y, curpos.x + w, curpos.y + h);
5595d9de2d3SDavid du Colombier 		memimagedraw(gscreen, r, back, back->r.min, nil, back->r.min, S);
5605d9de2d3SDavid du Colombier 		memimagestring(gscreen, curpos, conscol, ZP, memdefont, buf);
5615d9de2d3SDavid du Colombier 		flushmemscreen(r);
5625d9de2d3SDavid du Colombier 		curpos.x += w;
5635d9de2d3SDavid du Colombier 		break;
5645d9de2d3SDavid du Colombier 	}
5655d9de2d3SDavid du Colombier }
566