diff options
author | cinap_lenrek <cinap_lenrek@gmx.de> | 2012-07-18 10:16:00 +0200 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@gmx.de> | 2012-07-18 10:16:00 +0200 |
commit | b9ca8e83784b94e709e7d412eb4f87fa0a1885a8 (patch) | |
tree | e941217032e777d7ec33805930924d7fdd265aec /sys | |
parent | 5654f15e56087986812c557412d558482383fc8b (diff) |
vga: softscreen
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.
Diffstat (limited to 'sys')
-rw-r--r-- | sys/man/3/vga | 16 | ||||
-rw-r--r-- | sys/man/8/plan9.ini | 4 | ||||
-rw-r--r-- | sys/src/9/pc/devvga.c | 25 | ||||
-rw-r--r-- | sys/src/9/pc/screen.c | 51 | ||||
-rw-r--r-- | sys/src/9/pc/screen.h | 1 | ||||
-rw-r--r-- | sys/src/9/pc/vganvidia.c | 41 | ||||
-rw-r--r-- | sys/src/9/pc/vgavesa.c | 43 |
7 files changed, 95 insertions, 86 deletions
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) + 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, }; - 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* @@ -91,11 +91,6 @@ nvidiapci(void) } static void -nvidialinear(VGAscr*, int, int) -{ -} - -static void nvidiaenable(VGAscr* scr) { Pcidev *p; @@ -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: @@ -156,6 +149,11 @@ nvidiaenable(VGAscr* scr) } static void +nvidialinear(VGAscr *, int, int) +{ +} + +static void nvidiacurdisable(VGAscr* scr) { if(scr->mmio == 0) @@ -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, }; |