diff --git a/sys/man/3/vga b/sys/man/3/vga index 3910f45ab..d17858008 100644 --- a/sys/man/3/vga +++ b/sys/man/3/vga @@ -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 diff --git a/sys/man/8/plan9.ini b/sys/man/8/plan9.ini index 042ceff29..f41878b18 100644 --- a/sys/man/8/plan9.ini +++ b/sys/man/8/plan9.ini @@ -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 diff --git a/sys/src/9/pc/devvga.c b/sys/src/9/pc/devvga.c index d9ddf9239..087088434 100644 --- a/sys/src/9/pc/devvga.c +++ b/sys/src/9/pc/devvga.c @@ -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); diff --git a/sys/src/9/pc/screen.c b/sys/src/9/pc/screen.c index b585c36ce..219c6eb58 100644 --- a/sys/src/9/pc/screen.c +++ b/sys/src/9/pc/screen.c @@ -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) - return; - 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; + + /* + * 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; + } + + + /* + * 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, }; - diff --git a/sys/src/9/pc/screen.h b/sys/src/9/pc/screen.h index 87771f60b..9afb280c6 100644 --- a/sys/src/9/pc/screen.h +++ b/sys/src/9/pc/screen.h @@ -120,6 +120,7 @@ struct VGAscr { ulong id; /* internal identifier for driver use */ int isblank; int overlayinit; + int softscreen; }; extern VGAscr vgascreen[]; diff --git a/sys/src/9/pc/vganvidia.c b/sys/src/9/pc/vganvidia.c index 5ef910451..d4ce5b889 100644 --- a/sys/src/9/pc/vganvidia.c +++ b/sys/src/9/pc/vganvidia.c @@ -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; } diff --git a/sys/src/9/pc/vgavesa.c b/sys/src/9/pc/vgavesa.c index 3e7546801..98cd84dde 100644 --- a/sys/src/9/pc/vgavesa.c +++ b/sys/src/9/pc/vgavesa.c @@ -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, };