]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/zynq/screen.c
25a4dffb5e448132b564d8641ab6c3d8f247ec6e
[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                 return;
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         error("unknown control message");
176 }
177
178 static int
179 isflush(void *)
180 {
181         return !badrect(fbscreen.rect);
182 }
183
184 static void
185 screenproc(void *arg)
186 {
187         int sno, n, w;
188         uchar *sp, *dp, *top;
189         Rectangle r;
190
191         for(sno = 0; sno < NSEG; sno++)
192                 if(up->seg[sno] == nil && sno != ESEG)
193                         break;
194         if(sno == NSEG)
195                 panic(up->text);
196
197         up->seg[sno] = arg;
198
199         cclose(up->dot);
200         up->dot = up->slash;
201         incref(up->dot);
202
203         fbscreen.proc = up;
204         if(waserror()){
205                 fbscreen.addr = 0;
206                 fbscreen.proc = nil;
207                 return;
208         }
209
210         for(;;){
211                 sleep(&fbscreen, isflush, nil);
212
213                 eqlock(&drawlock);
214                 r = fbscreen.rect;
215                 fbscreen.rect = ZR;
216                 if(badrect(r) || gscreen == nil || rectclip(&r, gscreen->r) == 0){
217                         qunlock(&drawlock);
218                         continue;
219                 }
220                 w = sizeof(ulong)*gscreen->width;
221                 n = bytesperline(r, gscreen->depth);
222                 sp = byteaddr(gscreen, r.min);
223                 dp = (uchar*)fbscreen.addr + (sp - &gscreen->data->bdata[gscreen->zero]);
224                 top = (uchar*)up->seg[sno]->top;
225                 if(dp+(Dy(r)-1)*w+n > top)
226                         r.max.y = (top-(uchar*)fbscreen.addr)/w;
227                 qunlock(&drawlock);
228
229                 while(r.min.y < r.max.y) {
230                         memmove(dp, sp, n);
231                         sp += w;
232                         dp += w;
233                         r.min.y++;
234                 }
235         }
236 }
237
238 enum {
239         CMaddr,
240         CMsize,
241         CMinit,
242 };
243
244 static Cmdtab fbctlmsg[] = {
245         CMaddr,         "addr",         2,
246         CMsize,         "size",         3,
247         CMinit,         "init",         1,
248 };
249
250 long
251 fbctlwrite(Chan*, void *a, long n, vlong)
252 {
253         Cmdbuf *cb;
254         Cmdtab *ct;
255         ulong x, y, z, chan;
256         Segment *s;
257         uintptr addr;
258         char *p;
259
260         cb = parsecmd(a, n);
261         if(waserror()){
262                 free(cb);
263                 nexterror();
264         }
265         ct = lookupcmd(cb, fbctlmsg, nelem(fbctlmsg));
266         switch(ct->index){
267         case CMaddr:
268                 s = nil;
269                 addr = strtoul(cb->f[1], 0, 0);
270                 if(addr != 0){
271                         if((s = seg(up, addr, 0)) == nil || (s->type&SG_RONLY) != 0)
272                                 error(Ebadarg);
273                         incref(s);
274                 }
275                 if(fbscreen.proc != nil){
276                         postnote(fbscreen.proc, 0, "die", NUser);
277                         while(fbscreen.proc != nil)
278                                 sched();
279                 }
280                 if(addr != 0){
281                         fbscreen.addr = addr;
282                         kproc("screen", screenproc, s);
283                 }
284                 break;
285
286         case CMsize:
287                 x = strtoul(cb->f[1], &p, 0);
288                 if(x == 0 || x > 10240)
289                         error(Ebadarg);
290                 if(*p)
291                         p++;
292                 y = strtoul(p, &p, 0);
293                 if(y == 0 || y > 10240)
294                         error(Ebadarg);
295                 if(*p)
296                         p++;
297                 z = strtoul(p, &p, 0);
298
299                 if((chan = strtochan(cb->f[2])) == 0)
300                         error("bad channel");
301                 if(chantodepth(chan) != z)
302                         error("depth, channel do not match");
303
304                 deletescreenimage();
305                 eqlock(&drawlock);
306                 if(memimageinit() < 0){
307                         qunlock(&drawlock);
308                         error("memimageinit failed");
309                 }
310                 if(gscreen != nil){
311                         freememimage(gscreen);
312                         gscreen = nil;
313                 }
314                 gscreen = allocmemimage(Rect(0,0,x,y), chan);
315                 qunlock(&drawlock);
316                 /* wet floor */
317
318         case CMinit:
319                 if(gscreen == nil)
320                         error("no framebuffer");
321                 resetscreenimage();
322                 break;
323         }
324         free(cb);
325         poperror();
326         return n;
327 }
328
329 long
330 fbctlread(Chan*, void *a, long n, vlong offset)
331 {
332         char buf[256], chan[32], *p, *e;
333
334         p = buf;
335         e = p + sizeof(buf);
336         qlock(&drawlock);
337         if(gscreen != nil){
338                 p = seprint(p, e, "size %dx%dx%d %s\n",
339                         Dx(gscreen->r), Dy(gscreen->r), gscreen->depth,
340                         chantostr(chan, gscreen->chan));
341         }
342         qunlock(&drawlock);
343         seprint(p, e, "addr %#p\n", fbscreen.addr);
344         return readstr(offset, a, n, buf);
345 }