]> git.lizzy.rs Git - plan9front.git/blobdiff - sys/src/9/pc/screen.c
kernel: cleanup the software mouse cursor mess
[plan9front.git] / sys / src / 9 / pc / screen.c
index 37fcc5b91f88b76aa2f72afee33a4f42209f3967..2242494b6b45b3a2c1c3c887cdbf401198508ac3 100644 (file)
 #include <cursor.h>
 #include "screen.h"
 
+extern VGAcur vgasoftcur;
+
 Rectangle physgscreenr;
 
 Memimage *gscreen;
 
 VGAscr vgascreen[1];
 
-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, 
-       },
-};
-
 int
 screensize(int x, int y, int, ulong chan)
 {
@@ -96,7 +84,6 @@ screensize(int x, int y, int, ulong chan)
        poperror();
 
        drawcmap();
-       swcursorinit();
 
        qunlock(&drawlock);
        poperror();
@@ -108,6 +95,7 @@ int
 screenaperture(int size, int align)
 {
        VGAscr *scr;
+       ulong pa;
 
        scr = &vgascreen[0];
 
@@ -127,10 +115,11 @@ screenaperture(int size, int align)
         * The driver will tell the card to use it.
         */
        size = PGROUND(size);
-       scr->paddr = upaalloc(size, align);
-       if(scr->paddr == 0)
+       pa = upaalloc(-1, size, align);
+       if(pa == -1)
                return -1;
-       scr->vaddr = vmap(scr->paddr, size);
+       scr->paddr = pa;
+       scr->vaddr = vmap(pa, size);
        if(scr->vaddr == nil)
                return -1;
        scr->apsize = size;
@@ -138,7 +127,7 @@ screenaperture(int size, int align)
        return 0;
 }
 
-uchar*
+Memdata*
 attachscreen(Rectangle* r, ulong* chan, int* d, int* width, int *softscreen)
 {
        VGAscr *scr;
@@ -151,18 +140,10 @@ attachscreen(Rectangle* r, ulong* chan, int* d, int* width, int *softscreen)
        *chan = scr->gscreen->chan;
        *d = scr->gscreen->depth;
        *width = scr->gscreen->width;
-       if(scr->gscreendata->allocd){
-               /*
-                * we use a memimage as softscreen. devdraw will create its own
-                * screen image on the backing store of that image. when our gscreen
-                * and devdraws screenimage gets freed, the imagedata will
-                * be released.
-                */
-               *softscreen = 0xa110c;
-               scr->gscreendata->ref++;
-       } else
-               *softscreen = scr->useflush ? 1 : 0;
-       return scr->gscreendata->bdata;
+       *softscreen = (scr->gscreendata->allocd || scr->useflush) ? 1 : 0;
+
+       scr->gscreendata->ref++;
+       return scr->gscreendata;
 }
 
 void
@@ -260,11 +241,9 @@ getcolor(ulong p, ulong* pr, ulong* pg, ulong* pb)
        }
        p &= x;
 
-       lock(&cursor);
        *pr = scr->colormap[p][0];
        *pg = scr->colormap[p][1];
        *pb = scr->colormap[p][2];
-       unlock(&cursor);
 }
 
 int
@@ -276,7 +255,6 @@ setpalette(ulong p, ulong r, ulong g, ulong b)
        scr = &vgascreen[0];
        d = scr->palettedepth;
 
-       lock(&cursor);
        scr->colormap[p][0] = r;
        scr->colormap[p][1] = g;
        scr->colormap[p][2] = b;
@@ -284,7 +262,6 @@ setpalette(ulong p, ulong r, ulong g, ulong b)
        vgao(Pdata, r>>(32-d));
        vgao(Pdata, g>>(32-d));
        vgao(Pdata, b>>(32-d));
-       unlock(&cursor);
 
        return ~0;
 }
@@ -321,41 +298,6 @@ setcolor(ulong p, ulong r, ulong g, ulong b)
        return setpalette(p, r, g, b);
 }
 
-void
-swenable(VGAscr*)
-{
-       swcursorload(&arrow);
-}
-
-void
-swdisable(VGAscr*)
-{
-}
-
-void
-swload(VGAscr*, Cursor *curs)
-{
-       swcursorload(curs);
-}
-
-int
-swmove(VGAscr*, Point p)
-{
-       swcursorhide();
-       swcursordraw(p);
-       return 0;
-}
-
-VGAcur swcursor =
-{
-       "soft",
-       swenable,
-       swdisable,
-       swload,
-       swmove,
-};
-
-
 void
 cursoron(void)
 {
@@ -364,16 +306,8 @@ cursoron(void)
 
        scr = &vgascreen[0];
        cur = scr->cur;
-       if(cur == nil || cur->move == nil)
-               return;
-
-       if(cur == &swcursor)
-               qlock(&drawlock);
-       lock(&cursor);
-       cur->move(scr, mousexy());
-       unlock(&cursor);
-       if(cur == &swcursor)
-               qunlock(&drawlock);
+       if(cur && cur->move)
+               cur->move(scr, mousexy());
 }
 
 void
@@ -385,16 +319,16 @@ void
 setcursor(Cursor* curs)
 {
        VGAscr *scr;
+       VGAcur *cur;
 
        scr = &vgascreen[0];
-       if(scr->cur == nil || scr->cur->load == nil)
-               return;
-
-       scr->cur->load(scr, curs);
+       cur = scr->cur;
+       if(cur && cur->load)
+               cur->load(scr, curs);
 }
 
-int hwaccel = 1;
-int hwblank = 0;       /* turned on by drivers that are known good */
+int hwaccel = 0;
+int hwblank = 0;
 int panning = 0;
 
 int
@@ -415,7 +349,7 @@ hwdraw(Memdrawparam *par)
                src = nil;
        if((mask = par->mask) && mask->data == nil)
                mask = nil;
-       if(scr->cur == &swcursor){
+       if(scr->cur == &vgasoftcur){
                if(dst->data->bdata == scrd->bdata)
                        swcursoravoid(par->r);
                if(src && src->data->bdata == scrd->bdata)
@@ -423,12 +357,10 @@ hwdraw(Memdrawparam *par)
                if(mask && mask->data->bdata == scrd->bdata)
                        swcursoravoid(par->mr);
        }
-       if(hwaccel == 0)
+       if(!hwaccel || scr->softscreen)
                return 0;
        if(dst->data->bdata != scrd->bdata || src == nil || mask == nil)
                return 0;
-       if(scr->fill==nil && scr->scroll==nil)
-               return 0;
 
        /*
         * If we have an opaque mask and source is one opaque
@@ -472,16 +404,62 @@ blankscreen(int blank)
        }
 }
 
-void
-vgalinearpci(VGAscr *scr)
+static char*
+vgalinearaddr0(VGAscr *scr, ulong paddr, int size)
+{
+       int x, nsize;
+       ulong npaddr;
+
+       /*
+        * new approach.  instead of trying to resize this
+        * later, let's assume that we can just allocate the
+        * entire window to start with.
+        */
+       if(scr->paddr == paddr && size <= scr->apsize)
+               return nil;
+
+       if(scr->paddr){
+               /*
+                * could call vunmap and vmap,
+                * but worried about dangling pointers in devdraw
+                */
+               return "cannot grow vga frame buffer";
+       }
+
+       /* round to page boundary, just in case */
+       x = paddr&(BY2PG-1);
+       npaddr = paddr-x;
+       nsize = PGROUND(size+x);
+
+       /*
+        * Don't bother trying to map more than 4000x4000x32 = 64MB.
+        * We only have a 256MB window.
+        */
+       if(nsize > 64*MB)
+               nsize = 64*MB;
+       scr->vaddr = vmap(npaddr, nsize);
+       if(scr->vaddr == nil)
+               return "cannot map vga frame buffer";
+
+       patwc(scr->vaddr, nsize);
+
+       scr->vaddr = (char*)scr->vaddr+x;
+       scr->paddr = paddr;
+       scr->apsize = nsize;
+
+       mtrr(npaddr, nsize, "wc");
+
+       return nil;
+}
+
+static char*
+vgalinearpci0(VGAscr *scr)
 {
        ulong paddr;
        int i, size, best;
        Pcidev *p;
        
        p = scr->pci;
-       if(p == nil)
-               return;
 
        /*
         * Scan for largest memory region on card.
@@ -510,62 +488,87 @@ vgalinearpci(VGAscr *scr)
        if(best >= 0){
                paddr = p->mem[best].bar & ~0x0F;
                size = p->mem[best].size;
-               vgalinearaddr(scr, paddr, size);
-               return;
+               return vgalinearaddr0(scr, paddr, size);
        }
-       error("no video memory found on pci card");
+       return "no video memory found on pci card";
 }
 
 void
-vgalinearaddr(VGAscr *scr, ulong paddr, int size)
+vgalinearpci(VGAscr *scr)
 {
-       int x, nsize;
-       ulong npaddr;
+       char *err;
 
-       /*
-        * new approach.  instead of trying to resize this
-        * later, let's assume that we can just allocate the
-        * entire window to start with.
-        */
-       if(scr->paddr == paddr && size <= scr->apsize)
+       if(scr->pci == nil)
                return;
+       if((err = vgalinearpci0(scr)) != nil)
+               error(err);
+}
 
-       if(scr->paddr){
-               /*
-                * could call vunmap and vmap,
-                * but worried about dangling pointers in devdraw
-                */
-               error("cannot grow vga frame buffer");
-       }
+void
+vgalinearaddr(VGAscr *scr, ulong paddr, int size)
+{
+       char *err;
 
-       /* round to page boundary, just in case */
-       x = paddr&(BY2PG-1);
-       npaddr = paddr-x;
-       nsize = PGROUND(size+x);
+       if((err = vgalinearaddr0(scr, paddr, size)) != nil)
+               error(err);
+}
 
-       /*
-        * Don't bother trying to map more than 4000x4000x32 = 64MB.
-        * We only have a 256MB window.
-        */
-       if(nsize > 64*MB)
-               nsize = 64*MB;
-       scr->vaddr = vmap(npaddr, nsize);
-       if(scr->vaddr == 0)
-               error("cannot allocate vga frame buffer");
-       scr->vaddr = (char*)scr->vaddr+x;
-       scr->paddr = paddr;
-       scr->apsize = nsize;
+static char*
+bootmapfb(VGAscr *scr, ulong pa, ulong sz)
+{
+       ulong start, end;
+       Pcidev *p;
+       int i;
+
+       for(p = pcimatch(nil, 0, 0); p != nil; p = pcimatch(p, 0, 0)){
+               for(i=0; i<nelem(p->mem); i++){
+                       if(p->mem[i].bar & 1)
+                               continue;
+                       start = p->mem[i].bar & ~0xF;
+                       end = start + p->mem[i].size;
+                       if(pa == start && (pa + sz) <= end){
+                               scr->pci = p;
+                               return vgalinearpci0(scr);
+                       }
+               }
+       }
+       upaalloc(pa, sz, 0);
+       return vgalinearaddr0(scr, pa, sz);
+}
 
-       /* let mtrr harmlessly fail on old CPUs, e.g., P54C */
-       if(!waserror()){
-               mtrr(npaddr, nsize, "wc");
-               poperror();
+char*
+rgbmask2chan(char *buf, int depth, u32int rm, u32int gm, u32int bm)
+{
+       u32int m[4], dm;        /* r,g,b,x */
+       char tmp[32];
+       int c, n;
+
+       dm = 1<<depth-1;
+       dm |= dm-1;
+
+       m[0] = rm & dm;
+       m[1] = gm & dm;
+       m[2] = bm & dm;
+       m[3] = (~(m[0] | m[1] | m[2])) & dm;
+
+       buf[0] = 0;
+Next:
+       for(c=0; c<4; c++){
+               for(n = 0; m[c] & (1<<n); n++)
+                       ;
+               if(n){
+                       m[0] >>= n, m[1] >>= n, m[2] >>= n, m[3] >>= n;
+                       snprint(tmp, sizeof tmp, "%c%d%s", "rgbx"[c], n, buf);
+                       strcpy(buf, tmp);
+                       goto Next;
+               }
        }
+       return buf;
 }
 
 /*
  * called early on boot to attach to framebuffer
- * setup by bootloader or firmware.
+ * setup by bootloader/firmware or plan9.
  */
 void
 bootscreeninit(void)
@@ -574,7 +577,7 @@ bootscreeninit(void)
        VGAscr *scr;
        int x, y, z;
        ulong chan, pa, sz;
-       char *s, *p;
+       char *s, *p, *err;
 
        /* *bootscreen=WIDTHxHEIGHTxDEPTH CHAN PA [SZ] */
        s = getconf("*bootscreen");
@@ -609,21 +612,12 @@ bootscreeninit(void)
        if(sz < x * y * (z+7)/8)
                sz = x * y * (z+7)/8;
 
-       /* round to pages */
-       z = pa&(BY2PG-1);
-       pa -= z;
-       sz += z;
-
        /* map framebuffer */
        scr = &vgascreen[0];
-       scr->apsize = PGROUND(sz);
-       scr->vaddr = vmap(pa, scr->apsize);
-       if(scr->vaddr == 0){
-               scr->apsize = 0;
+       if((err = bootmapfb(scr, pa, sz)) != nil){
+               print("bootmapfb: %s\n", err);
                return;
        }
-       scr->vaddr = (char*)scr->vaddr + z;
-       scr->paddr = pa + z;
 
        if(memimageinit() < 0)
                return;
@@ -642,17 +636,32 @@ bootscreeninit(void)
        scr->useflush = 0;
        scr->dev = nil;
 
-       hwblank = 0;
-       hwaccel = 0;
-
        physgscreenr = gscreen->r;
 
        vgaimageinit(chan);
        vgascreenwin(scr);
 
-       /* turn mouse cursor on */
-       swcursorinit();
-       scr->cur = &swcursor;
+       scr->cur = &vgasoftcur;
        scr->cur->enable(scr);
-       cursoron();
+
+       conf.monitor = 1;
+}
+
+/*
+ * called from devvga when the framebuffer is setup
+ * to set *bootscreen= that can be passed on to a
+ * new kernel on reboot.
+ */
+void
+bootscreenconf(VGAscr *scr)
+{
+       char conf[100], chan[30];
+
+       conf[0] = '\0';
+       if(scr != nil && scr->paddr != 0 && scr->gscreen != nil)
+               snprint(conf, sizeof(conf), "%dx%dx%d %s %#p %d\n",
+                       scr->gscreen->r.max.x, scr->gscreen->r.max.y,
+                       scr->gscreen->depth, chantostr(chan, scr->gscreen->chan),
+                       scr->paddr, scr->apsize);
+       ksetenv("*bootscreen", conf, 1);
 }