]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/zynq/screen.c
0b1affce26adf016a0d1c19b4e267d88b24928ea
[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 void
27 cursoron(void)
28 {
29 }
30
31 void
32 cursoroff(void)
33 {
34 }
35
36 void
37 setcursor(Cursor*)
38 {
39 }
40
41 void
42 flushmemscreen(Rectangle r)
43 {
44         combinerect(&fbscreen.rect, r);
45         wakeup(&fbscreen);
46 }
47
48 void
49 screeninit(void)
50 {
51         conf.monitor = 1;
52 }
53
54 uchar*
55 attachscreen(Rectangle *r, ulong *chan, int* d, int *width, int *softscreen)
56 {
57         if(gscreen == nil)
58                 return nil;
59
60         *r = gscreen->r;
61         *d = gscreen->depth;
62         *chan = gscreen->chan;
63         *width = gscreen->width;
64
65         /* make devdraw use gscreen->data */
66         *softscreen = 0xa110c;
67         gscreen->data->ref++;
68
69         return gscreen->data->bdata;
70 }
71
72 void
73 getcolor(ulong, ulong *, ulong *, ulong *)
74 {
75 }
76
77 int
78 setcolor(ulong, ulong, ulong, ulong)
79 {
80         return 0;
81 }
82
83 void
84 blankscreen(int)
85 {
86 }
87
88 void
89 mousectl(Cmdbuf *)
90 {
91 }
92
93 static int
94 isflush(void *)
95 {
96         return !badrect(fbscreen.rect);
97 }
98
99 static void
100 flushproc(void *arg)
101 {
102         int sno, n, w;
103         uchar *sp, *dp, *top;
104         Rectangle r;
105
106         for(sno = 0; sno < NSEG; sno++)
107                 if(up->seg[sno] == nil && sno != ESEG)
108                         break;
109         if(sno == NSEG)
110                 panic("flushproc");
111
112         up->seg[sno] = arg;
113
114         cclose(up->dot);
115         up->dot = up->slash;
116         incref(up->dot);
117
118         fbscreen.proc = up;
119         if(waserror()){
120                 print("flushproc: %s\n", up->errstr);
121                 fbscreen.addr = 0;
122                 fbscreen.proc = nil;
123                 return;
124         }
125
126         for(;;){
127                 sleep(&fbscreen, isflush, nil);
128
129                 eqlock(&drawlock);
130                 r = fbscreen.rect;
131                 fbscreen.rect = ZR;
132                 if(badrect(r) || gscreen == nil || rectclip(&r, gscreen->r) == 0){
133                         qunlock(&drawlock);
134                         continue;
135                 }
136                 w = sizeof(ulong)*gscreen->width;
137                 n = bytesperline(r, gscreen->depth);
138                 sp = byteaddr(gscreen, r.min);
139                 dp = (uchar*)fbscreen.addr + (sp - &gscreen->data->bdata[gscreen->zero]);
140                 top = (uchar*)up->seg[sno]->top;
141                 if(dp+(Dy(r)-1)*w+n > top)
142                         r.max.y = (top-(uchar*)fbscreen.addr)/w;
143                 qunlock(&drawlock);
144
145                 while(r.min.y < r.max.y) {
146                         memmove(dp, sp, n);
147                         sp += w;
148                         dp += w;
149                         r.min.y++;
150                 }
151         }
152 }
153
154 enum {
155         CMaddr,
156         CMsize,
157         CMinit,
158 };
159
160 static Cmdtab fbctlmsg[] = {
161         CMaddr,         "addr",         2,
162         CMsize,         "size",         3,
163         CMinit,         "init",         1,
164 };
165
166 long
167 fbctlwrite(Chan*, void *a, long n, vlong)
168 {
169         Cmdbuf *cb;
170         Cmdtab *ct;
171         ulong x, y, z, chan;
172         Segment *s;
173         uintptr addr;
174         char *p;
175
176         cb = parsecmd(a, n);
177         if(waserror()){
178                 free(cb);
179                 nexterror();
180         }
181         ct = lookupcmd(cb, fbctlmsg, nelem(fbctlmsg));
182         switch(ct->index){
183         case CMaddr:
184                 addr = strtoul(cb->f[1], 0, 0);
185
186                 eqlock(&up->seglock);
187                 if((s = seg(up, addr, 0)) == nil || (s->type&SG_RONLY) != 0){
188                         qunlock(&up->seglock);
189                         error(Ebadarg);
190                 }
191                 incref(s);
192                 qunlock(&up->seglock);
193
194                 if(fbscreen.proc != nil){
195                         postnote(fbscreen.proc, 0, "die", NUser);
196                         while(fbscreen.proc != nil)
197                                 sched();
198                 }
199                 fbscreen.addr = addr;
200                 kproc("fbflush", flushproc, s);
201                 break;
202
203         case CMsize:
204                 x = strtoul(cb->f[1], &p, 0);
205                 if(x == 0 || x > 10240)
206                         error(Ebadarg);
207                 if(*p)
208                         p++;
209                 y = strtoul(p, &p, 0);
210                 if(y == 0 || y > 10240)
211                         error(Ebadarg);
212                 if(*p)
213                         p++;
214                 z = strtoul(p, &p, 0);
215
216                 if((chan = strtochan(cb->f[2])) == 0)
217                         error("bad channel");
218                 if(chantodepth(chan) != z)
219                         error("depth, channel do not match");
220
221                 cursoroff();
222                 deletescreenimage();
223                 eqlock(&drawlock);
224                 if(memimageinit() < 0){
225                         qunlock(&drawlock);
226                         error("memimageinit failed");
227                 }
228                 if(gscreen != nil){
229                         freememimage(gscreen);
230                         gscreen = nil;
231                 }
232                 gscreen = allocmemimage(Rect(0,0,x,y), chan);
233                 qunlock(&drawlock);
234                 /* wet floor */
235
236         case CMinit:
237                 if(gscreen == nil)
238                         error("no framebuffer");
239                 resetscreenimage();
240                 cursoron();
241                 break;
242         }
243         free(cb);
244         poperror();
245         return n;
246 }
247
248 long
249 fbctlread(Chan*, void *a, long n, vlong offset)
250 {
251         char buf[256], chan[32], *p, *e;
252
253         p = buf;
254         e = p + sizeof(buf);
255         qlock(&drawlock);
256         if(gscreen != nil){
257                 p = seprint(p, e, "size %dx%dx%d %s\n",
258                         Dx(gscreen->r), Dy(gscreen->r), gscreen->depth,
259                         chantostr(chan, gscreen->chan));
260         }
261         qunlock(&drawlock);
262         seprint(p, e, "addr %#p\n", fbscreen.addr);
263         return readstr(offset, a, n, buf);
264 }
265