]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/zynq/screen.c
zynq: remove unused statistics fields from Mach structure
[plan9front.git] / sys / src / 9 / zynq / screen.c
1 #include "u.h"
2 #include "../port/lib.h"
3 #include "mem.h"
4 #include "dat.h"
5 #include "fns.h"
6 #include "io.h"
7 #include "../port/error.h"
8
9 #define Image   IMAGE
10 #include <draw.h>
11 #include <memdraw.h>
12 #include <cursor.h>
13 #include "screen.h"
14
15 Memimage *gscreen;
16
17 static struct {
18         Rendez;
19
20         Rectangle       rect;
21         Proc            *proc;
22
23         uintptr         addr;
24 } fbscreen;
25
26 static struct {
27         Rendez;
28
29         Cursor;
30
31         Proc            *proc;
32         uintptr         addr;
33 } hwcursor;
34
35 void
36 cursoron(void)
37 {
38         wakeup(&hwcursor);
39 }
40
41 void
42 cursoroff(void)
43 {
44 }
45
46 void
47 setcursor(Cursor *curs)
48 {
49         hwcursor.Cursor = *curs;
50 }
51
52 void
53 flushmemscreen(Rectangle r)
54 {
55         if(badrect(fbscreen.rect))
56                 fbscreen.rect = r;
57         else
58                 combinerect(&fbscreen.rect, r);
59         wakeup(&fbscreen);
60 }
61
62 void
63 screeninit(void)
64 {
65         conf.monitor = 1;
66 }
67
68 uchar*
69 attachscreen(Rectangle *r, ulong *chan, int* d, int *width, int *softscreen)
70 {
71         if(gscreen == nil)
72                 return nil;
73
74         *r = gscreen->r;
75         *d = gscreen->depth;
76         *chan = gscreen->chan;
77         *width = gscreen->width;
78
79         /* make devdraw use gscreen->data */
80         *softscreen = 0xa110c;
81         gscreen->data->ref++;
82
83         return gscreen->data->bdata;
84 }
85
86 void
87 getcolor(ulong, ulong *, ulong *, ulong *)
88 {
89 }
90
91 int
92 setcolor(ulong, ulong, ulong, ulong)
93 {
94         return 0;
95 }
96
97 void
98 blankscreen(int)
99 {
100 }
101
102
103 static void
104 cursorproc(void *arg)
105 {
106         uchar *set, *clr;
107         u32int *reg;
108         Point xy;
109         int i;
110
111         for(i = 0; i < NSEG; i++)
112                 if(up->seg[i] == nil && i != ESEG)
113                         break;
114         if(i == NSEG)
115                 panic(up->text);
116
117         up->seg[i] = arg;
118
119         cclose(up->dot);
120         up->dot = up->slash;
121         incref(up->dot);
122
123         hwcursor.proc = up;
124         if(waserror()){
125                 hwcursor.addr = 0;
126                 hwcursor.proc = nil;
127                 pexit("detached", 1);
128         }
129
130         reg = (u32int*)hwcursor.addr;
131         for(;;){
132                 eqlock(&drawlock);
133                 xy = addpt(mousexy(), hwcursor.offset);
134                 qunlock(&drawlock);
135
136                 set = hwcursor.set;
137                 clr = hwcursor.clr;
138                 for(i=0; i<8; i++){
139                         reg[0x70/4 + i] = clr[i*4]<<24 | clr[i*4+1]<<16 | clr[i*4+2]<<8 | clr[i*4+3];
140                         reg[0x90/4 + i] = set[i*4]<<24 | set[i*4+1]<<16 | set[i*4+2]<<8 | set[i*4+3];
141                 }
142                 reg[0] = (xy.x<<16) | (xy.y&0xFFFF);
143
144                 sleep(&hwcursor, return0, nil);
145         }
146 }
147
148 void
149 mousectl(Cmdbuf *cb)
150 {
151         Segment *s;
152         uintptr addr;
153
154         if(strcmp(cb->f[0], "addr") == 0 && cb->nf == 2){
155                 s = nil;
156                 addr = strtoul(cb->f[1], 0, 0);
157                 if(addr != 0){
158                         if((s = seg(up, addr, 0)) == nil || (s->type&SG_RONLY) != 0
159                         || (addr&3) != 0 || addr+0xB0 > s->top)
160                                 error(Ebadarg);
161                         incref(s);
162                 }
163                 if(hwcursor.proc != nil){
164                         postnote(hwcursor.proc, 0, "die", NUser);
165                         while(hwcursor.proc != nil)
166                                 sched();
167                 }
168                 if(addr != 0){
169                         hwcursor.addr = addr;
170                         kproc("cursor", cursorproc, s);
171                 }
172                 return;
173         }
174
175         if(strcmp(cb->f[0], "linear") == 0){
176                 mouseaccelerate(0);
177                 return;
178         }
179
180         if(strcmp(cb->f[0], "accelerated") == 0){
181                 mouseaccelerate(cb->nf == 1 ? 1 : atoi(cb->f[1]));
182                 return;
183         }
184 }
185
186 static int
187 isflush(void *)
188 {
189         return !badrect(fbscreen.rect);
190 }
191
192 static void
193 screenproc(void *arg)
194 {
195         int sno, n, w;
196         uchar *sp, *dp, *top;
197         Rectangle r;
198
199         for(sno = 0; sno < NSEG; sno++)
200                 if(up->seg[sno] == nil && sno != ESEG)
201                         break;
202         if(sno == NSEG)
203                 panic(up->text);
204
205         up->seg[sno] = arg;
206
207         cclose(up->dot);
208         up->dot = up->slash;
209         incref(up->dot);
210
211         fbscreen.proc = up;
212         if(waserror()){
213                 fbscreen.addr = 0;
214                 fbscreen.proc = nil;
215                 pexit("detached", 1);
216         }
217
218         for(;;){
219                 sleep(&fbscreen, isflush, nil);
220
221                 eqlock(&drawlock);
222                 r = fbscreen.rect;
223                 fbscreen.rect = ZR;
224                 if(badrect(r) || gscreen == nil || rectclip(&r, gscreen->r) == 0){
225                         qunlock(&drawlock);
226                         continue;
227                 }
228                 w = sizeof(ulong)*gscreen->width;
229                 n = bytesperline(r, gscreen->depth);
230                 sp = byteaddr(gscreen, r.min);
231                 dp = (uchar*)fbscreen.addr + (sp - &gscreen->data->bdata[gscreen->zero]);
232                 top = (uchar*)up->seg[sno]->top;
233                 if(dp+(Dy(r)-1)*w+n > top)
234                         r.max.y = (top-(uchar*)fbscreen.addr)/w;
235                 qunlock(&drawlock);
236
237                 while(r.min.y < r.max.y) {
238                         memmove(dp, sp, n);
239                         sp += w;
240                         dp += w;
241                         r.min.y++;
242                 }
243         }
244 }
245
246 enum {
247         CMaddr,
248         CMsize,
249         CMinit,
250 };
251
252 static Cmdtab fbctlmsg[] = {
253         CMaddr,         "addr",         2,
254         CMsize,         "size",         3,
255         CMinit,         "init",         1,
256 };
257
258 long
259 fbctlwrite(Chan*, void *a, long n, vlong)
260 {
261         Cmdbuf *cb;
262         Cmdtab *ct;
263         ulong x, y, z, chan;
264         Segment *s;
265         uintptr addr;
266         char *p;
267
268         cb = parsecmd(a, n);
269         if(waserror()){
270                 free(cb);
271                 nexterror();
272         }
273         ct = lookupcmd(cb, fbctlmsg, nelem(fbctlmsg));
274         switch(ct->index){
275         case CMaddr:
276                 s = nil;
277                 addr = strtoul(cb->f[1], 0, 0);
278                 if(addr != 0){
279                         if((s = seg(up, addr, 0)) == nil || (s->type&SG_RONLY) != 0)
280                                 error(Ebadarg);
281                         incref(s);
282                 }
283                 if(fbscreen.proc != nil){
284                         postnote(fbscreen.proc, 0, "die", NUser);
285                         while(fbscreen.proc != nil)
286                                 sched();
287                 }
288                 if(addr != 0){
289                         fbscreen.addr = addr;
290                         kproc("screen", screenproc, s);
291                 }
292                 break;
293
294         case CMsize:
295                 x = strtoul(cb->f[1], &p, 0);
296                 if(x == 0 || x > 10240)
297                         error(Ebadarg);
298                 if(*p)
299                         p++;
300                 y = strtoul(p, &p, 0);
301                 if(y == 0 || y > 10240)
302                         error(Ebadarg);
303                 if(*p)
304                         p++;
305                 z = strtoul(p, &p, 0);
306
307                 if((chan = strtochan(cb->f[2])) == 0)
308                         error("bad channel");
309                 if(chantodepth(chan) != z)
310                         error("depth, channel do not match");
311
312                 deletescreenimage();
313                 eqlock(&drawlock);
314                 if(memimageinit() < 0){
315                         qunlock(&drawlock);
316                         error("memimageinit failed");
317                 }
318                 if(gscreen != nil){
319                         freememimage(gscreen);
320                         gscreen = nil;
321                 }
322                 gscreen = allocmemimage(Rect(0,0,x,y), chan);
323                 qunlock(&drawlock);
324                 /* wet floor */
325
326         case CMinit:
327                 if(gscreen == nil)
328                         error("no framebuffer");
329                 resetscreenimage();
330                 break;
331         }
332         free(cb);
333         poperror();
334         return n;
335 }
336
337 long
338 fbctlread(Chan*, void *a, long n, vlong offset)
339 {
340         char buf[256], chan[32], *p, *e;
341
342         p = buf;
343         e = p + sizeof(buf);
344         qlock(&drawlock);
345         if(gscreen != nil){
346                 p = seprint(p, e, "size %dx%dx%d %s\n",
347                         Dx(gscreen->r), Dy(gscreen->r), gscreen->depth,
348                         chantostr(chan, gscreen->chan));
349         }
350         qunlock(&drawlock);
351         seprint(p, e, "addr %#p\n", fbscreen.addr);
352         return readstr(offset, a, n, buf);
353 }