xref: /inferno-os/os/js/screen.c (revision b43c1ca5eb5fc65b93ae935a568432712797b049)
1 #include "u.h"
2 #include "../port/lib.h"
3 #include "mem.h"
4 #include "io.h"
5 #include "dat.h"
6 #include "fns.h"
7 #include "../port/error.h"
8 
9 #include <draw.h>
10 #include <memdraw.h>
11 #include <memlayer.h>
12 #include <cursor.h>
13 
14 #include "softcursor.h"
15 #include "screen.h"
16 
17 #define	Backgnd		(0xFF)
18 
19 
20 ulong	consbits = 0xC0;
21 Memdata consdata = {
22 	nil,
23 	&consbits
24 };
25 Memimage conscol =
26 {
27 	{ 0, 0, 1, 1 },
28 	{ -100000, -100000, 100000, 100000 },
29 	3,
30 	1,
31 	&consdata,
32 	0,
33 	1
34 };
35 
36 ulong	onesbits = ~0;
37 Memdata onesdata = {
38 	nil,
39 	&onesbits,
40 };
41 Memimage	xones =
42 {
43 	{ 0, 0, 1, 1 },
44 	{ -100000, -100000, 100000, 100000 },
45 	3,
46 	1,
47 	&onesdata,
48 	0,
49 	1
50 };
51 Memimage *memones = &xones;
52 
53 ulong	zerosbits = 0;
54 Memdata zerosdata = {
55 	nil,
56 	&zerosbits,
57 };
58 Memimage	xzeros =
59 {
60 	{ 0, 0, 1, 1 },
61 	{ -100000, -100000, 100000, 100000 },
62 	3,
63 	1,
64 	&zerosdata,
65 	0,
66 	1
67 };
68 Memimage *memzeros = &xzeros;
69 
70 ulong	backbits = (Backgnd<<24)|(Backgnd<<16)|(Backgnd<<8)|Backgnd;
71 Memdata backdata = {
72 	nil,
73 	&backbits
74 };
75 Memimage	xback =
76 {
77 	{ 0, 0, 1, 1 },
78 	{ -100000, -100000, 100000, 100000 },
79 	3,
80 	1,
81 	&backdata,
82 	0,
83 	1
84 };
85 Memimage *back = &xback;
86 
87 Video *vid;
88 static Memsubfont *memdefont;
89 static Lock screenlock;
90 Memimage gscreen;
91 Memdata gscreendata;
92 static Point curpos;
93 static Rectangle window;
94 
95 static Vctlr* vctlr;
96 
97 static Cursor arrow = {
98 	{ -1, -1 },
99 	{ 0xFF, 0xFF, 0x80, 0x01, 0x80, 0x02, 0x80, 0x0C,
100 	  0x80, 0x10, 0x80, 0x10, 0x80, 0x08, 0x80, 0x04,
101 	  0x80, 0x02, 0x80, 0x01, 0x80, 0x02, 0x8C, 0x04,
102 	  0x92, 0x08, 0x91, 0x10, 0xA0, 0xA0, 0xC0, 0x40,
103 	},
104 	{ 0x00, 0x00, 0x7F, 0xFE, 0x7F, 0xFC, 0x7F, 0xF0,
105 	  0x7F, 0xE0, 0x7F, 0xE0, 0x7F, 0xF0, 0x7F, 0xF8,
106 	  0x7F, 0xFC, 0x7F, 0xFE, 0x7F, 0xFC, 0x73, 0xF8,
107 	  0x61, 0xF0, 0x60, 0xE0, 0x40, 0x40, 0x00, 0x00,
108 	},
109 };
110 
111 
112 void
113 graphicscmap(int invert)
114 {
115 	int num, den, i, j;
116 	int r, g, b, cr, cg, cb, v;
117 
118 	if(vctlr->setcolor == nil)
119 		return;
120 
121 	for(r=0,i=0;r!=4;r++) for(v=0;v!=4;v++,i+=16){
122 		for(g=0,j=v-r;g!=4;g++) for(b=0;b!=4;b++,j++){
123 			den=r;
124 			if(g>den) den=g;
125 			if(b>den) den=b;
126 			if(den==0)	/* divide check -- pick grey shades */
127 				cr=cg=cb=v*17;
128 			else{
129 				num=17*(4*den+v);
130 				cr=r*num/den;
131 				cg=g*num/den;
132 				cb=b*num/den;
133 			}
134 			if(invert)
135 				vctlr->setcolor(255-i-(j&15),
136 					cr*0x01010101,
137 					cg*0x01010101,
138 					cb*0x01010101);
139 			else
140 				vctlr->setcolor(i+(j&15),
141 					cr*0x01010101,
142 					cg*0x01010101,
143 					cb*0x01010101);
144 		}
145 	}
146 }
147 
148 static char s1[] =
149 {
150 	0x00, 0x00, 0xC0, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
151 };
152 
153 
154 void
155 dacinit(void)
156 {
157 	int i;
158 
159 	/* Control registers */
160 	vid->addr = 0x01 << 24;
161 	vid->color = 0x02 << 24;
162 	for(i = 0; i < sizeof s1; i++)
163 		vid->cntrl = s1[i] << 24;
164 
165 	/* Cursor programming */
166 	vid->addr = 0x00 << 24;
167 	vid->color = 0x03 << 24;
168 	vid->cntrl = 0xC0 << 24;
169 	for(i = 0; i < 12; i++)
170 		vid->cntrl = 0 << 24;
171 
172 	/* Load Cursor Ram */
173 	vid->addr = 0x00 << 24;
174 	vid->color = 0x04 << 24;
175 	for(i = 0; i < 0x400; i++)
176 		vid->cntrl = 0xff << 24;
177 
178 	graphicscmap(1);
179 
180 	/* Overlay Palette Ram */
181 	vid->addr = 0x00 << 24;
182 	vid->color = 0x01 << 24;
183 	for(i = 0; i < 0x10; i++) {
184 		vid->cntrl = 0xff << 24;
185 		vid->cntrl = 0xff << 24;
186 		vid->cntrl = 0xff << 24;
187 	}
188 
189 	/* Overlay Palette Ram */
190 	vid->addr = 0x81;
191 	vid->color = 0x01;
192 	for(i = 0; i < 3; i++) {
193 		vid->cntrl = 0xff << 24;
194 		vid->cntrl = 0xff << 24;
195 		vid->cntrl = 0xff << 24;
196 	}
197 }
198 
199 void
200 vctlrinit(int x, int y, int d)
201 {
202 	int h;
203 	ulong va;
204 
205 	if(vctlr == nil){
206 		/*
207 		 * find a controller somehow
208 		 * and call its init routine
209 		 */
210 		extern Vctlr FSV;
211 
212 		vctlr = FSV.init(0, x, y, d);
213 		vctlr->load(&arrow);
214 	}
215 
216 	if(vctlr == nil)
217 		panic("%s",Ebadarg);
218 
219 	gscreen.data = &gscreendata;
220 	gscreen.r.min = Pt(0, 0);
221 	gscreen.r.max = Pt(vctlr->x, vctlr->y);
222 	gscreen.clipr = gscreen.r;
223 	gscreen.ldepth = vctlr->d;
224 	gscreen.repl = 0;
225 	va = kmapsbus(FSVSLOT);			/* FSV is in slot 2 */
226 	gscreendata.data = (ulong *)(va+0x800000);	/* Framebuffer Magic */
227 	gscreen.width = (vctlr->x *(1<<gscreen.ldepth)+31)/32;
228 
229 
230 	h = memdefont->height;
231 
232 	vid = (Video*)(va+0x240000);	/* RAMDAC Magic */
233 	memset(gscreendata.data, Backgnd, vctlr->x*vctlr->y);
234 	window = gscreen.r;
235 	window.max.x = vctlr->x;
236 	window.max.y = (vctlr->y/h) * h;
237 	curpos = window.min;
238 	if (gscreen.ldepth == 3){
239 		dacinit();
240 	}
241 
242 	memset(gscreendata.data, Backgnd, vctlr->x*vctlr->y);
243 	window = gscreen.r;
244 	window.max.x = vctlr->x;
245 	window.max.y = (vctlr->y/h) * h;
246 	curpos = window.min;
247 }
248 
249 void
250 screeninit(void)
251 {
252 	memdefont = getmemdefont();
253 	vctlrinit(1024, 768, 3);
254 }
255 
256 ulong*
257 attachscreen(Rectangle *r, int *ld, int *width, int *softscreen)
258 {
259 	*r = gscreen.r;
260 	*ld = gscreen.ldepth;
261 	*width = gscreen.width;
262 	*softscreen = 0;
263 	return gscreendata.data;
264 }
265 
266 void
267 detachscreen(void)
268 {
269 }
270 
271 void
272 flushmemscreen(Rectangle)
273 {
274 }
275 
276 static void
277 scroll(void)
278 {
279 	int o;
280 	Point p;
281 	Rectangle r;
282 
283 	o = 4*memdefont->height;
284 	r = Rpt(window.min, Pt(window.max.x, window.max.y-o));
285 	p = Pt(window.min.x, window.min.y+o);
286 	memdraw(&gscreen, r, &gscreen, p, memones, p);
287 	r = Rpt(Pt(window.min.x, window.max.y-o), window.max);
288 	memdraw(&gscreen, r, back, memzeros->r.min, memones, memzeros->r.min);
289 
290 	curpos.y -= o;
291 }
292 
293 void
294 screenputc(char *buf)
295 {
296 	Point p;
297 	int h, w, pos;
298 	Rectangle r;
299 	static int *xp;
300 	static int xbuf[256];
301 
302 	h = memdefont->height;
303 	if(xp < xbuf || xp >= &xbuf[sizeof(xbuf)])
304 		xp = xbuf;
305 
306 	switch(buf[0]) {
307 	case '\n':
308 		if(curpos.y+h >= window.max.y)
309 			scroll();
310 		curpos.y += h;
311 		screenputc("\r");
312 		break;
313 	case '\r':
314 		xp = xbuf;
315 		curpos.x = window.min.x;
316 		break;
317 	case '\t':
318 		p = memsubfontwidth(memdefont, " ");
319 		w = p.x;
320 		*xp++ = curpos.x;
321 		pos = (curpos.x-window.min.x)/w;
322 		pos = 8-(pos%8);
323 		curpos.x += pos*w;
324 		break;
325 	case '\b':
326 		if(xp <= xbuf)
327 			break;
328 		xp--;
329 		r = Rpt(Pt(*xp, curpos.y), Pt(curpos.x, curpos.y + h));
330 		memdraw(&gscreen, r, back, back->r.min, memones, back->r.min);
331 		curpos.x = *xp;
332 		break;
333 	default:
334 		p = memsubfontwidth(memdefont, buf);
335 		w = p.x;
336 
337 		if(curpos.x >= window.max.x-w)
338 			screenputc("\n");
339 
340 		*xp++ = curpos.x;
341 		memimagestring(&gscreen, curpos, &conscol, memdefont, buf);
342 		curpos.x += w;
343 	}
344 }
345 
346 void
347 screenputs(char *s, int n)
348 {
349 	int i;
350 	Rune r;
351 	char buf[4];
352 extern int cold;
353 
354 if(!cold)
355 	return;
356 
357 	if(islo() == 0) {
358 		/* don't deadlock trying to print in interrupt */
359 		if(!canlock(&screenlock))
360 			return;
361 	} else
362 		lock(&screenlock);
363 
364 	while(n > 0) {
365 		i = chartorune(&r, s);
366 		if(i == 0){
367 			s++;
368 			--n;
369 			continue;
370 		}
371 		memmove(buf, s, i);
372 		buf[i] = 0;
373 		n -= i;
374 		s += i;
375 		screenputc(buf);
376 	}
377 
378 	unlock(&screenlock);
379 }
380 
381 
382 void
383 cursorenable(void)
384 {
385 	if(vctlr->enable == nil)
386 		return;
387 
388 	vctlr->enable();
389 
390 	if(!vctlr->isloaded())
391 		vctlr->load(&arrow);
392 }
393 
394 void
395 cursordisable(void)
396 {
397 	if(vctlr->disable == nil)
398 		return;
399 
400 	vctlr->disable();
401 }
402 
403 static Rectangle cursoroffrect;
404 static int	cursorisoff;
405 static Point hot;
406 
407 void
408 cursorupdate0(void)
409 {
410 	int inrect, x, y;
411 
412 	x = mouse.x - hot.x;
413 	y = mouse.y - hot.y;
414 	inrect = (x >= cursoroffrect.min.x && x < cursoroffrect.max.x
415 		&& y >= cursoroffrect.min.y && y < cursoroffrect.max.y);
416 	if (cursorisoff == inrect)
417 		return;
418 	cursorisoff = inrect;
419 	if (inrect)
420 		cursordisable();
421 	else
422 		cursorenable();
423 }
424 
425 void
426 cursorupdate(Rectangle r)
427 {
428 	lock(&screenlock);
429 	r.min.x -= 16;
430 	r.min.y -= 16;
431 	cursoroffrect = r;
432 	if (swcursor)
433 		cursorupdate0();
434 	unlock(&screenlock);
435 }
436 
437 void
438 drawcursor(Drawcursor* c)
439 {
440 	Cursor curs;
441 	int j, i, h, bpl;
442 	uchar *bc, *bs, *cclr, *cset;
443 
444 	if(vctlr->load == nil)
445 		return;
446 
447 	/* Set the default system cursor */
448 	if(c->data == nil) {
449 		lock(&screenlock);
450 		vctlr->load(&arrow);
451 		unlock(&screenlock);
452 		return;
453 	}
454 
455 	hot.x = c->hotx;
456 	hot.y = c->hoty;
457 	curs.offset = hot;
458 	bpl = bytesperline(Rect(c->minx, c->miny, c->maxx, c->maxy), 0);
459 
460 	h = (c->maxy-c->miny)/2;
461 	if(h > 16)
462 		h = 16;
463 
464 	bc = c->data;
465 	bs = c->data + h*bpl;
466 
467 	cclr = curs.clr;
468 	cset = curs.set;
469 	for(i = 0; i < h; i++) {
470 		for(j = 0; j < 2; j++) {
471 			cclr[j] = bc[j];
472 			cset[j] = bs[j];
473 		}
474 		bc += bpl;
475 		bs += bpl;
476 		cclr += 2;
477 		cset += 2;
478 	}
479 	lock(&screenlock);
480 	vctlr->load(&curs);
481 	unlock(&screenlock);
482 }
483 
484