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.
This commit is contained in:
parent
5654f15e56
commit
b9ca8e8378
7 changed files with 96 additions and 87 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,13 +355,31 @@ 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);
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
|
@ -120,6 +120,7 @@ struct VGAscr {
|
|||
ulong id; /* internal identifier for driver use */
|
||||
int isblank;
|
||||
int overlayinit;
|
||||
int softscreen;
|
||||
};
|
||||
|
||||
extern VGAscr vgascreen[];
|
||||
|
|
|
@ -69,7 +69,7 @@ enum {
|
|||
|
||||
#define SKIPS 8
|
||||
|
||||
struct {
|
||||
static struct {
|
||||
ulong *dmabase;
|
||||
int dmacurrent;
|
||||
int dmaput;
|
||||
|
@ -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,12 +351,15 @@ 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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue