]> git.lizzy.rs Git - plan9front.git/commitdiff
vga: softscreen
authorcinap_lenrek <cinap_lenrek@gmx.de>
Wed, 18 Jul 2012 08:16:00 +0000 (10:16 +0200)
committercinap_lenrek <cinap_lenrek@gmx.de>
Wed, 18 Jul 2012 08:16:00 +0000 (10:16 +0200)
allow the shadow framebuffer (softscreen) to be used with any
vga driver, not just vesa. this removes the ugly scr->paddr = 0
hack employed by vesa driver to force softscreen and adds a
softscreen vgactl message that can switch the feature on and off
at runtime.

softscreen can greatly improve graphics performance when bus
reads are slow even tho it disables hardware acceleration.

sys/man/3/vga
sys/man/8/plan9.ini
sys/src/9/pc/devvga.c
sys/src/9/pc/screen.c
sys/src/9/pc/screen.h
sys/src/9/pc/vganvidia.c
sys/src/9/pc/vgavesa.c

index 3910f45ab36fe62f8e0abf1a0be57fe36841053a..d17858008a811046a99bbe3ad5996c7073d72ed6 100644 (file)
@@ -170,6 +170,22 @@ used by the graphics engine.
 The default setting is
 .BR on .
 .TP
+.BI softscreen " mode"
+Depending on whether
+.I mode
+is 
+.B on
+or
+.BR off ,
+enable or disable shadow framebuffer to reduce
+slow bus reads. Enabling
+.BI softscreen
+disables hardware acceleration. The default setting is
+.BR off
+except for the
+.BR vesa
+driver. 
+.TP
 .BI hwblank " mode"
 Depending on whether
 .I mode
index 042ceff292bf784c84fe0a9f1e1495b2e75b07c0..f41878b1832d2f23547db9be7e290eb71745e34d 100644 (file)
@@ -781,10 +781,6 @@ and
 .BR off .
 The first two specify differing levels of power saving;
 the third turns the monitor off completely.
-.SS \fL*novesashadow=\fP
-This disables the shadow framebuffer or softscreen of the VESA
-video driver. This can improve performance on some graphics
-cards.
 .SS NVRAM
 .SS \fLnvram=\fIfile\fP
 .SS \fLnvrlen=\fIlength\fP
index d9ddf92393cac4e74493ae32be34560bd05d89e1..0870884347133e131bf53d8492a49e1daaa67402 100644 (file)
@@ -46,6 +46,7 @@ enum {
        CMtextmode,
        CMtype,
        CMunblank,
+       CMsoftscreen,
 };
 
 static Cmdtab vgactlmsg[] = {
@@ -63,6 +64,7 @@ static Cmdtab vgactlmsg[] = {
        CMtextmode,     "textmode",     1,
        CMtype,         "type",         2,
        CMunblank,      "unblank",      1,
+       CMsoftscreen,   "softscreen",   2,
 };
 
 static void
@@ -200,6 +202,7 @@ vgaread(Chan* c, void* a, long n, vlong off)
                len += snprint(p+len, READSTR-len, "hwblank %s\n", hwblank ? "on" : "off");
                len += snprint(p+len, READSTR-len, "panning %s\n", panning ? "on" : "off");
                len += snprint(p+len, READSTR-len, "addr p 0x%lux v 0x%p size 0x%ux\n", scr->paddr, scr->vaddr, scr->apsize);
+               len += snprint(p+len, READSTR-len, "softscreen %s\n", scr->softscreen ? "on" : "off");
                USED(len);
 
                n = readstr(offset, a, n, p);
@@ -352,18 +355,36 @@ vgactl(Cmdbuf *cb)
                scr->palettedepth = x;
                return;
 
+       case CMsoftscreen:
+               if(strcmp(cb->f[1], "on") == 0)
+                       scr->softscreen = 1;
+               else if(strcmp(cb->f[1], "off") == 0)
+                       scr->softscreen = 0;
+               else
+                       break;
+               if(scr->gscreen == nil)
+                       return;
+               x = scr->gscreen->r.max.x;
+               y = scr->gscreen->r.max.y;
+               z = scr->gscreen->depth;
+               chan = scr->gscreen->chan;
+               cursoroff(1);
+               deletescreenimage();
+               if(screensize(x, y, z, chan))
+                       error(Egreg);
+               /* no break */
        case CMdrawinit:
                if(scr->gscreen == nil)
                        error("drawinit: no gscreen");
                if(scr->dev && scr->dev->drawinit)
                        scr->dev->drawinit(scr);
                hwblank = scr->blank != nil;
-               hwaccel = scr->scroll || scr->fill;
+               hwaccel = !scr->softscreen && (scr->scroll || scr->fill);
                vgascreenwin(scr);
                resetscreenimage();
                cursoron(1);
                return;
-       
+
        case CMlinear:
                if(cb->nf!=2 && cb->nf!=3)
                        error(Ebadarg);
index b585c36ceef6c0068cf1332eb880887c71b33b93..219c6eb580e88c9ab209ef799d2e287a441d792a 100644 (file)
@@ -67,17 +67,21 @@ screensize(int x, int y, int, ulong chan)
        }
 
        if(scr->paddr == 0){
-               gscreen = allocmemimage(Rect(0,0,x,y), chan);
                if(scr->dev && scr->dev->page){
                        scr->vaddr = KADDR(VGAMEM());
                        scr->apsize = 1<<16;
                }
+               scr->softscreen = 1;
+       }
+       if(scr->softscreen){
+               gscreen = allocmemimage(Rect(0,0,x,y), chan);
                scr->useflush = 1;
        }else{
                static Memdata md;
 
                md.ref = 1;
-               md.bdata = scr->vaddr;
+               if((md.bdata = scr->vaddr) == 0)
+                       error("framebuffer not maped");
                gscreen = allocmemimaged(Rect(0,0,x,y), chan, &md);
                scr->useflush = scr->dev && scr->dev->flush;
        }
@@ -167,15 +171,12 @@ attachscreen(Rectangle* r, ulong* chan, int* d, int* width, int *softscreen)
        return scr->gscreendata->bdata;
 }
 
-/*
- * It would be fair to say that this doesn't work for >8-bit screens.
- */
 void
 flushmemscreen(Rectangle r)
 {
        VGAscr *scr;
        uchar *sp, *disp, *sdisp, *edisp;
-       int y, len, incs, off, page;
+       int y, len, incs, off, xoff, page;
 
        scr = &vgascreen[0];
        if(scr->gscreen == nil || scr->useflush == 0)
@@ -184,13 +185,37 @@ flushmemscreen(Rectangle r)
                scr->dev->flush(scr, r);
                return;
        }
-       if(scr->dev == nil || scr->dev->page == nil)
+       if(rectclip(&r, scr->gscreen->r) == 0)
                return;
+       disp = scr->vaddr;
+       incs = scr->gscreen->width * BY2WD;
+       xoff = (r.min.x*scr->gscreen->depth) / 8;
+       off = r.min.y*incs + xoff;
+       sp = scr->gscreendata->bdata + scr->gscreen->zero + off;
 
-       if(rectclip(&r, scr->gscreen->r) == 0)
+       /*
+        * Linear framebuffer but with softscreen.
+        */
+       if(scr->paddr){
+               len = (r.max.x*scr->gscreen->depth + 7) / 8;
+               len -= xoff;
+               sdisp = disp + off;
+               edisp = sdisp + Dy(r)*incs;
+               while(sdisp < edisp){
+                       memmove(sdisp, sp, len);
+                       sdisp += incs;
+                       sp += incs;
+               }
                return;
+       }
 
-       incs = scr->gscreen->width * BY2WD;
+
+       /*
+        * Paged access thru 64K window.
+        * It would be fair to say that this doesn't work for >8-bit screens.
+        */
+       if(scr->dev == nil || scr->dev->page == nil)
+               return;
 
        switch(scr->gscreen->depth){
        default:
@@ -202,18 +227,11 @@ flushmemscreen(Rectangle r)
        }
        if(len < 1)
                return;
-
-       off = r.min.y*scr->gscreen->width*BY2WD+(r.min.x*scr->gscreen->depth)/8;
        page = off/scr->apsize;
        off %= scr->apsize;
-       disp = scr->vaddr;
        sdisp = disp+off;
        edisp = disp+scr->apsize;
 
-       off = r.min.y*scr->gscreen->width*BY2WD+(r.min.x*scr->gscreen->depth)/8;
-
-       sp = scr->gscreendata->bdata + off;
-
        scr->dev->page(scr, page);
        for(y = r.min.y; y < r.max.y; y++) {
                if(sdisp + incs < edisp) {
@@ -740,4 +758,3 @@ VGAcur swcursor =
        swload,
        swmove,
 };
-
index 87771f60ba9e5b66840cf36134cc62b03a245536..9afb280c6b14015e1bbbdca254304032729a2269 100644 (file)
@@ -120,6 +120,7 @@ struct VGAscr {
        ulong   id;     /* internal identifier for driver use */
        int isblank;
        int overlayinit;
+       int softscreen;
 };
 
 extern VGAscr vgascreen[];
index 5ef91045115bb62182573eb2cb430bb8c2f9dbb7..d4ce5b88999f1bddd6f82053d958f674180b8728 100644 (file)
@@ -69,12 +69,12 @@ enum {
 
 #define SKIPS 8
 
-struct {
+static struct {
        ulong   *dmabase;
-       int             dmacurrent;
-       int             dmaput;
-       int             dmafree;
-       int             dmamax;
+       int     dmacurrent;
+       int     dmaput;
+       int     dmafree;
+       int     dmamax;
 } nv;
 
 static Pcidev*
@@ -90,11 +90,6 @@ nvidiapci(void)
        return nil;
 }
 
-static void
-nvidialinear(VGAscr*, int, int)
-{
-}
-
 static void
 nvidiaenable(VGAscr* scr)
 {
@@ -114,11 +109,9 @@ nvidiaenable(VGAscr* scr)
        if(scr->mmio == nil)
                return;
        addvgaseg("nvidiammio", p->mem[0].bar&~0x0F, p->mem[0].size);
-
        vgalinearpci(scr);
        if(scr->apsize)
                addvgaseg("nvidiascreen", scr->paddr, scr->apsize);
-
        /* find video memory size */
        switch (scr->id & 0x0ff0) {
        case 0x0020:
@@ -155,6 +148,11 @@ nvidiaenable(VGAscr* scr)
        }
 }
 
+static void
+nvidialinear(VGAscr *, int, int)
+{
+}
+
 static void
 nvidiacurdisable(VGAscr* scr)
 {
@@ -223,8 +221,6 @@ nvidiacurload(VGAscr* scr, Cursor* curs)
 
        scr->offset = curs->offset;
        vgaxo(Crtx, 0x31, vgaxi(Crtx, 0x31) | 0x01);
-
-       return;
 }
 
 static int
@@ -355,11 +351,14 @@ waitforidle(VGAscr *scr)
                iprint("idle stat %lud scrio %#p scr %#p pc %#p\n", *pgraph, scr->mmio, scr, getcallerpc(&scr));
 }
 
-static void
+static int
 nvresetgraphics(VGAscr *scr)
 {
        ulong   surfaceFormat, patternFormat, rectFormat, lineFormat;
-       int             pitch, i;
+       int     pitch, i;
+
+       if(scr->paddr == 0)
+               return -1;
 
        pitch = scr->gscreen->width*BY2WD;
 
@@ -373,10 +372,8 @@ nvresetgraphics(VGAscr *scr)
                else{
                        nv.dmabase = (void*)vmap(scr->paddr + scr->storage - 128*1024, 128*1024);
                        if(nv.dmabase == 0){
-                               hwaccel = 0;
-                               hwblank = 0;
                                print("vmap nvidia dma failed\n");
-                               return;
+                               return -1;
                        }
                }
        }
@@ -455,6 +452,8 @@ nvresetgraphics(VGAscr *scr)
 
        nvdmakickoff(scr);
        waitforidle(scr);
+
+       return 0;
 }
 
 
@@ -513,9 +512,9 @@ nvidiablank(VGAscr*, int blank)
 static void
 nvidiadrawinit(VGAscr *scr)
 {
-       nvresetgraphics(scr);
        scr->blank = nvidiablank;
-       hwblank = 1;
+       if(nvresetgraphics(scr) < 0)
+               return;
        scr->fill = nvidiahwfill;
        scr->scroll = nvidiahwscroll;
 }
index 3e7546801e03a66e2fe71712a7d2f874baf7fde1..98cd84ddebfc88de34ff1505954f21eb7fb68a39 100644 (file)
@@ -24,7 +24,6 @@ enum {
        RealModeBuf = 0x9000,
 };
 
-static void *hardscreen;
 static uchar modebuf[0x1000];
 static Chan *creg, *cmem;
 static QLock vesaq;
@@ -108,12 +107,6 @@ vesalinear(VGAscr *scr, int, int)
        Pcidev *pci;
        uchar *p;
 
-       if(hardscreen) {
-               scr->vaddr = hardscreen;
-               scr->paddr = scr->apsize = 0;
-               return;
-       }
-
        vbecheck();
        mode = vbegetmode();
        /*
@@ -163,38 +156,8 @@ vesalinear(VGAscr *scr, int, int)
        vgalinearaddr(scr, paddr, size);
        if(scr->apsize)
                addvgaseg("vesascreen", scr->paddr, scr->apsize);
-       if(getconf("*novesashadow"))
-               return;
-       hardscreen = scr->vaddr;
-       scr->paddr = scr->apsize = 0;
-}
 
-static void
-vesaflush(VGAscr *scr, Rectangle r)
-{
-       int t, w, wid, off;
-       ulong *hp, *sp, *esp;
-
-       if(hardscreen == nil)
-               return;
-       if(rectclip(&r, scr->gscreen->r) == 0)
-               return;
-       sp = (ulong*)(scr->gscreendata->bdata + scr->gscreen->zero);
-       t = (r.max.x * scr->gscreen->depth + 2*BI2WD-1) / BI2WD;
-       w = (r.min.x * scr->gscreen->depth) / BI2WD;
-       w = (t - w) * BY2WD;
-       wid = scr->gscreen->width;
-       off = r.min.y * wid + (r.min.x * scr->gscreen->depth) / BI2WD;
-
-       hp = hardscreen;
-       hp += off;
-       sp += off;
-       esp = sp + Dy(r) * wid;
-       while(sp < esp){
-               memmove(hp, sp, w);
-               hp += wid;
-               sp += wid;
-       }
+       scr->softscreen = 1;
 }
 
 static int
@@ -285,8 +248,4 @@ VGAdev vgavesadev = {
        0,
        vesalinear,
        vesadrawinit,
-       0,
-       0,
-       0,
-       vesaflush,
 };