]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/bcm/screen.c
kernel: fix bounds check in screenputc()
[plan9front.git] / sys / src / 9 / bcm / screen.c
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 Memimage *gscreen;
26
27 static Memdata xgdata;
28
29 static Memimage xgscreen =
30 {
31         { 0, 0, Wid, Ht },      /* r */
32         { 0, 0, Wid, Ht },      /* clipr */
33         Depth,                  /* depth */
34         3,                      /* nchan */
35         RGB16,                  /* chan */
36         nil,                    /* cmap */
37         &xgdata,                /* data */
38         0,                      /* zero */
39         0,                      /* width in words of a single scan line */
40         0,                      /* layer */
41         0,                      /* flags */
42 };
43
44 static Memimage *conscol;
45 static Memimage *back;
46 static Memsubfont *memdefont;
47
48 static Lock screenlock;
49
50 static Point    curpos;
51 static int      h, w;
52 static Rectangle window;
53
54 static void myscreenputs(char *s, int n);
55 static void screenputc(char *buf);
56 static void screenwin(void);
57
58 void
59 cursoron(void)
60 {
61         qlock(&drawlock);
62         lock(&cursor);
63         swcursorhide();
64         swcursordraw(mousexy());
65         unlock(&cursor);
66         qunlock(&drawlock);
67 }
68
69 void
70 cursoroff(void)
71 {
72         qlock(&drawlock);
73         lock(&cursor);
74         swcursorhide();
75         unlock(&cursor);
76         qunlock(&drawlock);
77 }
78
79 /* called from devmouse */
80 void
81 setcursor(Cursor* curs)
82 {
83         swcursorload(curs);
84 }
85
86 int
87 hwdraw(Memdrawparam *par)
88 {
89         Memimage *dst, *src, *mask;
90
91         if((dst=par->dst) == nil || dst->data == nil)
92                 return 0;
93         if((src=par->src) == nil || src->data == nil)
94                 return 0;
95         if((mask=par->mask) == nil || mask->data == nil)
96                 return 0;
97
98         if(dst->data->bdata == xgdata.bdata)
99                 swcursoravoid(par->r);
100         if(src->data->bdata == xgdata.bdata)
101                 swcursoravoid(par->sr);
102         if(mask->data->bdata == xgdata.bdata)
103                 swcursoravoid(par->mr);
104
105         return 0;
106 }
107
108 static int
109 screensize(void)
110 {
111         char *p;
112         char *f[3];
113         int width, height, depth;
114
115         p = getconf("vgasize");
116         if(p == nil || getfields(p, f, nelem(f), 0, "x") != nelem(f) ||
117             (width = atoi(f[0])) < 16 || (height = atoi(f[1])) <= 0 ||
118             (depth = atoi(f[2])) <= 0)
119                 return -1;
120         xgscreen.r.max = Pt(width, height);
121         xgscreen.depth = depth;
122         return 0;
123 }
124
125 void
126 screeninit(void)
127 {
128         uchar *fb;
129         int set;
130         ulong chan;
131
132         set = screensize() == 0;
133         fb = fbinit(set, &xgscreen.r.max.x, &xgscreen.r.max.y, &xgscreen.depth);
134         if(fb == nil){
135                 print("can't initialise %dx%dx%d framebuffer \n",
136                         xgscreen.r.max.x, xgscreen.r.max.y, xgscreen.depth);
137                 return;
138         }
139         xgscreen.clipr = xgscreen.r;
140         switch(xgscreen.depth){
141         default:
142                 print("unsupported screen depth %d\n", xgscreen.depth);
143                 xgscreen.depth = 16;
144                 /* fall through */
145         case 16:
146                 chan = RGB16;
147                 break;
148         case 24:
149                 chan = BGR24;
150                 break;
151         case 32:
152                 chan = ARGB32;
153                 break;
154         }
155         memsetchan(&xgscreen, chan);
156         conf.monitor = 1;
157         xgdata.bdata = fb;
158         xgdata.ref = 1;
159         gscreen = &xgscreen;
160         gscreen->width = wordsperline(gscreen->r, gscreen->depth);
161
162         memimageinit();
163         memdefont = getmemdefont();
164         screenwin();
165         screenputs = myscreenputs;
166         swcursorinit();
167 }
168
169 void
170 flushmemscreen(Rectangle)
171 {
172 }
173
174 uchar*
175 attachscreen(Rectangle *r, ulong *chan, int* d, int *width, int *softscreen)
176 {
177         *r = gscreen->r;
178         *d = gscreen->depth;
179         *chan = gscreen->chan;
180         *width = gscreen->width;
181         *softscreen = 0;
182
183         return gscreen->data->bdata;
184 }
185
186 void
187 getcolor(ulong p, ulong *pr, ulong *pg, ulong *pb)
188 {
189         USED(p, pr, pg, pb);
190 }
191
192 int
193 setcolor(ulong p, ulong r, ulong g, ulong b)
194 {
195         USED(p, r, g, b);
196         return 0;
197 }
198
199 void
200 blankscreen(int blank)
201 {
202         fbblank(blank);
203 }
204
205 static void
206 myscreenputs(char *s, int n)
207 {
208         int i;
209         Rune r;
210         char buf[4];
211
212         if(!islo()) {
213                 /* don't deadlock trying to print in interrupt */
214                 if(!canlock(&screenlock))
215                         return; 
216         }
217         else
218                 lock(&screenlock);
219
220         while(n > 0){
221                 i = chartorune(&r, s);
222                 if(i == 0){
223                         s++;
224                         --n;
225                         continue;
226                 }
227                 memmove(buf, s, i);
228                 buf[i] = 0;
229                 n -= i;
230                 s += i;
231                 screenputc(buf);
232         }
233         unlock(&screenlock);
234 }
235
236 static void
237 screenwin(void)
238 {
239         char *greet;
240         Memimage *orange;
241         Point p, q;
242         Rectangle r;
243
244         back = memwhite;
245         conscol = memblack;
246
247         orange = allocmemimage(Rect(0, 0, 1, 1), RGB16);
248         orange->flags |= Frepl;
249         orange->clipr = gscreen->r;
250         orange->data->bdata[0] = 0x40;          /* magic: colour? */
251         orange->data->bdata[1] = 0xfd;          /* magic: colour? */
252
253         w = memdefont->info[' '].width;
254         h = memdefont->height;
255
256         r = insetrect(gscreen->r, 4);
257
258         memimagedraw(gscreen, r, memblack, ZP, memopaque, ZP, S);
259         window = insetrect(r, 4);
260         memimagedraw(gscreen, window, memwhite, ZP, memopaque, ZP, S);
261
262         memimagedraw(gscreen, Rect(window.min.x, window.min.y,
263                 window.max.x, window.min.y + h + 5 + 6), orange, ZP, nil, ZP, S);
264         freememimage(orange);
265         window = insetrect(window, 5);
266
267         greet = " Plan 9 Console ";
268         p = addpt(window.min, Pt(10, 0));
269         q = memsubfontwidth(memdefont, greet);
270         memimagestring(gscreen, p, conscol, ZP, memdefont, greet);
271         flushmemscreen(r);
272         window.min.y += h + 6;
273         curpos = window.min;
274         window.max.y = window.min.y + ((window.max.y - window.min.y) / h) * h;
275 }
276
277 static void
278 scroll(void)
279 {
280         int o;
281         Point p;
282         Rectangle r;
283
284         o = Scroll*h;
285         r = Rpt(window.min, Pt(window.max.x, window.max.y-o));
286         p = Pt(window.min.x, window.min.y+o);
287         memimagedraw(gscreen, r, gscreen, p, nil, p, S);
288         flushmemscreen(r);
289         r = Rpt(Pt(window.min.x, window.max.y-o), window.max);
290         memimagedraw(gscreen, r, back, ZP, nil, ZP, S);
291         flushmemscreen(r);
292
293         curpos.y -= o;
294 }
295
296 static void
297 screenputc(char *buf)
298 {
299         int w;
300         uint pos;
301         Point p;
302         Rectangle r;
303         static int *xp;
304         static int xbuf[256];
305
306         if (xp < xbuf || xp >= &xbuf[nelem(xbuf)])
307                 xp = xbuf;
308
309         switch (buf[0]) {
310         case '\n':
311                 if (curpos.y + h >= window.max.y)
312                         scroll();
313                 curpos.y += h;
314                 screenputc("\r");
315                 break;
316         case '\r':
317                 xp = xbuf;
318                 curpos.x = window.min.x;
319                 break;
320         case '\t':
321                 p = memsubfontwidth(memdefont, " ");
322                 w = p.x;
323                 if (curpos.x >= window.max.x - Tabstop * w)
324                         screenputc("\n");
325
326                 pos = (curpos.x - window.min.x) / w;
327                 pos = Tabstop - pos % Tabstop;
328                 *xp++ = curpos.x;
329                 r = Rect(curpos.x, curpos.y, curpos.x + pos * w, curpos.y + h);
330                 memimagedraw(gscreen, r, back, back->r.min, nil, back->r.min, S);
331                 flushmemscreen(r);
332                 curpos.x += pos * w;
333                 break;
334         case '\b':
335                 if (xp <= xbuf)
336                         break;
337                 xp--;
338                 r = Rect(*xp, curpos.y, curpos.x, curpos.y + h);
339                 memimagedraw(gscreen, r, back, back->r.min, nil, back->r.min, S);
340                 flushmemscreen(r);
341                 curpos.x = *xp;
342                 break;
343         case '\0':
344                 break;
345         default:
346                 p = memsubfontwidth(memdefont, buf);
347                 w = p.x;
348
349                 if (curpos.x >= window.max.x - w)
350                         screenputc("\n");
351
352                 *xp++ = curpos.x;
353                 r = Rect(curpos.x, curpos.y, curpos.x + w, curpos.y + h);
354                 memimagedraw(gscreen, r, back, back->r.min, nil, back->r.min, S);
355                 memimagestring(gscreen, curpos, conscol, ZP, memdefont, buf);
356                 flushmemscreen(r);
357                 curpos.x += w;
358                 break;
359         }
360 }