]> git.lizzy.rs Git - plan9front.git/blobdiff - sys/src/9/zynq/screen.c
truetypefs: fall back to width if advance is zero
[plan9front.git] / sys / src / 9 / zynq / screen.c
index 872ab88f81794f031d00331aec069e6fa0602d4f..fcf3a365cb780480d8702a6bea49d9804734d621 100644 (file)
 #include <cursor.h>
 #include "screen.h"
 
-Cursor arrow = {
-       { -1, -1 },
-       { 0xFF, 0xFF, 0x80, 0x01, 0x80, 0x02, 0x80, 0x0C,
-         0x80, 0x10, 0x80, 0x10, 0x80, 0x08, 0x80, 0x04,
-         0x80, 0x02, 0x80, 0x01, 0x80, 0x02, 0x8C, 0x04,
-         0x92, 0x08, 0x91, 0x10, 0xA0, 0xA0, 0xC0, 0x40,
-       },
-       { 0x00, 0x00, 0x7F, 0xFE, 0x7F, 0xFC, 0x7F, 0xF0,
-         0x7F, 0xE0, 0x7F, 0xE0, 0x7F, 0xF0, 0x7F, 0xF8,
-         0x7F, 0xFC, 0x7F, 0xFE, 0x7F, 0xFC, 0x73, 0xF8,
-         0x61, 0xF0, 0x60, 0xE0, 0x40, 0x40, 0x00, 0x00,
-       },
-};
-
 Memimage *gscreen;
-static Memdata xgdata;
 
-static Memimage xgscreen =
-{
-       { 0, 0, 800, 600 },     /* r */
-       { 0, 0, 800, 600 },     /* clipr */
-       24,                     /* depth */
-       3,                      /* nchan */
-       BGR24,                  /* chan */
-       nil,                    /* cmap */
-       &xgdata,                /* data */
-       0,                      /* zero */
-       0,                      /* width in words of a single scan line */
-       0,                      /* layer */
-       0,                      /* flags */
-};
+static struct {
+       Rendez;
+
+       Rectangle       rect;
+       Proc            *proc;
+
+       uintptr         addr;
+} fbscreen;
+
+static struct {
+       Rendez;
+
+       Cursor;
+
+       Proc            *proc;
+       uintptr         addr;
+} hwcursor;
 
 void
 cursoron(void)
 {
+       wakeup(&hwcursor);
 }
 
 void
@@ -55,51 +44,41 @@ cursoroff(void)
 }
 
 void
-setcursor(Cursor*)
+setcursor(Cursor *curs)
 {
+       hwcursor.Cursor = *curs;
 }
 
 void
-flushmemscreen(Rectangle)
+flushmemscreen(Rectangle r)
 {
-}
-
-void
-drawflushreal(void)
-{
-       uchar *fb, *fbe;
-       
-       fb = xgdata.bdata;
-       fbe = fb + Dx(xgscreen.r) * Dy(xgscreen.r) * 3;
-       cleandse(fb, fbe);
-       clean2pa(PADDR(fb), PADDR(fbe));
+       if(badrect(fbscreen.rect))
+               fbscreen.rect = r;
+       else
+               combinerect(&fbscreen.rect, r);
+       wakeup(&fbscreen);
 }
 
 void
 screeninit(void)
 {
-       uchar *fb;
-
-       fb = xspanalloc(Dx(xgscreen.r) * Dy(xgscreen.r) * 3, 64, 0);
-       print("%p\n", PADDR(fb));
-       memsetchan(&xgscreen, BGR24);
        conf.monitor = 1;
-       xgdata.bdata = fb;
-       xgdata.ref = 1;
-       gscreen = &xgscreen;
-       gscreen->width = wordsperline(gscreen->r, gscreen->depth);
-
-       memimageinit();
 }
 
 uchar*
 attachscreen(Rectangle *r, ulong *chan, int* d, int *width, int *softscreen)
 {
+       if(gscreen == nil)
+               return nil;
+
        *r = gscreen->r;
        *d = gscreen->depth;
        *chan = gscreen->chan;
        *width = gscreen->width;
-       *softscreen = 0;
+
+       /* make devdraw use gscreen->data */
+       *softscreen = 0xa110c;
+       gscreen->data->ref++;
 
        return gscreen->data->bdata;
 }
@@ -120,7 +99,247 @@ blankscreen(int)
 {
 }
 
+
+static void
+cursorproc(void *arg)
+{
+       uchar *set, *clr;
+       u32int *reg;
+       Point xy;
+       int i;
+
+       for(i = 0; i < NSEG; i++)
+               if(up->seg[i] == nil && i != ESEG)
+                       break;
+       if(i == NSEG)
+               panic(up->text);
+
+       up->seg[i] = arg;
+
+       hwcursor.proc = up;
+       if(waserror()){
+               hwcursor.addr = 0;
+               hwcursor.proc = nil;
+               pexit("detached", 1);
+       }
+
+       reg = (u32int*)hwcursor.addr;
+       for(;;){
+               eqlock(&drawlock);
+               xy = addpt(mousexy(), hwcursor.offset);
+               qunlock(&drawlock);
+
+               set = hwcursor.set;
+               clr = hwcursor.clr;
+               for(i=0; i<8; i++){
+                       reg[0x70/4 + i] = clr[i*4]<<24 | clr[i*4+1]<<16 | clr[i*4+2]<<8 | clr[i*4+3];
+                       reg[0x90/4 + i] = set[i*4]<<24 | set[i*4+1]<<16 | set[i*4+2]<<8 | set[i*4+3];
+               }
+               reg[0] = (xy.x<<16) | (xy.y&0xFFFF);
+
+               sleep(&hwcursor, return0, nil);
+       }
+}
+
 void
-mousectl(Cmdbuf *)
+mousectl(Cmdbuf *cb)
+{
+       Segment *s;
+       uintptr addr;
+
+       if(strcmp(cb->f[0], "addr") == 0 && cb->nf == 2){
+               s = nil;
+               addr = strtoul(cb->f[1], 0, 0);
+               if(addr != 0){
+                       if((s = seg(up, addr, 0)) == nil || (s->type&SG_RONLY) != 0
+                       || (addr&3) != 0 || addr+0xB0 > s->top)
+                               error(Ebadarg);
+                       incref(s);
+               }
+               if(hwcursor.proc != nil){
+                       postnote(hwcursor.proc, 0, "die", NUser);
+                       while(hwcursor.proc != nil)
+                               sched();
+               }
+               if(addr != 0){
+                       hwcursor.addr = addr;
+                       kproc("cursor", cursorproc, s);
+               }
+               return;
+       }
+
+       if(strcmp(cb->f[0], "linear") == 0){
+               mouseaccelerate(0);
+               return;
+       }
+
+       if(strcmp(cb->f[0], "accelerated") == 0){
+               mouseaccelerate(cb->nf == 1 ? 1 : atoi(cb->f[1]));
+               return;
+       }
+}
+
+static int
+isflush(void *)
 {
+       return !badrect(fbscreen.rect);
+}
+
+static void
+screenproc(void *arg)
+{
+       int sno, n, w;
+       uchar *sp, *dp, *top;
+       Rectangle r;
+
+       for(sno = 0; sno < NSEG; sno++)
+               if(up->seg[sno] == nil && sno != ESEG)
+                       break;
+       if(sno == NSEG)
+               panic(up->text);
+
+       up->seg[sno] = arg;
+
+       fbscreen.proc = up;
+       if(waserror()){
+               fbscreen.addr = 0;
+               fbscreen.proc = nil;
+               pexit("detached", 1);
+       }
+
+       for(;;){
+               sleep(&fbscreen, isflush, nil);
+
+               eqlock(&drawlock);
+               r = fbscreen.rect;
+               fbscreen.rect = ZR;
+               if(badrect(r) || gscreen == nil || rectclip(&r, gscreen->r) == 0){
+                       qunlock(&drawlock);
+                       continue;
+               }
+               w = sizeof(ulong)*gscreen->width;
+               n = bytesperline(r, gscreen->depth);
+               sp = byteaddr(gscreen, r.min);
+               dp = (uchar*)fbscreen.addr + (sp - &gscreen->data->bdata[gscreen->zero]);
+               top = (uchar*)up->seg[sno]->top;
+               if(dp+(Dy(r)-1)*w+n > top)
+                       r.max.y = (top-(uchar*)fbscreen.addr)/w;
+               qunlock(&drawlock);
+
+               while(r.min.y < r.max.y) {
+                       memmove(dp, sp, n);
+                       sp += w;
+                       dp += w;
+                       r.min.y++;
+               }
+       }
+}
+
+enum {
+       CMaddr,
+       CMsize,
+       CMinit,
+};
+
+static Cmdtab fbctlmsg[] = {
+       CMaddr,         "addr",         2,
+       CMsize,         "size",         3,
+       CMinit,         "init",         1,
+};
+
+long
+fbctlwrite(Chan*, void *a, long n, vlong)
+{
+       Cmdbuf *cb;
+       Cmdtab *ct;
+       ulong x, y, z, chan;
+       Segment *s;
+       uintptr addr;
+       char *p;
+
+       cb = parsecmd(a, n);
+       if(waserror()){
+               free(cb);
+               nexterror();
+       }
+       ct = lookupcmd(cb, fbctlmsg, nelem(fbctlmsg));
+       switch(ct->index){
+       case CMaddr:
+               s = nil;
+               addr = strtoul(cb->f[1], 0, 0);
+               if(addr != 0){
+                       if((s = seg(up, addr, 0)) == nil || (s->type&SG_RONLY) != 0)
+                               error(Ebadarg);
+                       incref(s);
+               }
+               if(fbscreen.proc != nil){
+                       postnote(fbscreen.proc, 0, "die", NUser);
+                       while(fbscreen.proc != nil)
+                               sched();
+               }
+               if(addr != 0){
+                       fbscreen.addr = addr;
+                       kproc("screen", screenproc, s);
+               }
+               break;
+
+       case CMsize:
+               x = strtoul(cb->f[1], &p, 0);
+               if(x == 0 || x > 10240)
+                       error(Ebadarg);
+               if(*p)
+                       p++;
+               y = strtoul(p, &p, 0);
+               if(y == 0 || y > 10240)
+                       error(Ebadarg);
+               if(*p)
+                       p++;
+               z = strtoul(p, &p, 0);
+
+               if((chan = strtochan(cb->f[2])) == 0)
+                       error("bad channel");
+               if(chantodepth(chan) != z)
+                       error("depth, channel do not match");
+
+               deletescreenimage();
+               eqlock(&drawlock);
+               if(memimageinit() < 0){
+                       qunlock(&drawlock);
+                       error("memimageinit failed");
+               }
+               if(gscreen != nil){
+                       freememimage(gscreen);
+                       gscreen = nil;
+               }
+               gscreen = allocmemimage(Rect(0,0,x,y), chan);
+               qunlock(&drawlock);
+               /* wet floor */
+
+       case CMinit:
+               if(gscreen == nil)
+                       error("no framebuffer");
+               resetscreenimage();
+               break;
+       }
+       free(cb);
+       poperror();
+       return n;
+}
+
+long
+fbctlread(Chan*, void *a, long n, vlong offset)
+{
+       char buf[256], chan[32], *p, *e;
+
+       p = buf;
+       e = p + sizeof(buf);
+       qlock(&drawlock);
+       if(gscreen != nil){
+               p = seprint(p, e, "size %dx%dx%d %s\n",
+                       Dx(gscreen->r), Dy(gscreen->r), gscreen->depth,
+                       chantostr(chan, gscreen->chan));
+       }
+       qunlock(&drawlock);
+       seprint(p, e, "addr %#p\n", fbscreen.addr);
+       return readstr(offset, a, n, buf);
 }