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