diff --git a/sys/man/3/vga b/sys/man/3/vga index d17858008..6b148093e 100644 --- a/sys/man/3/vga +++ b/sys/man/3/vga @@ -198,6 +198,17 @@ enable or disable the use of DPMS blanking .B blank above). .TP +.BI scaling " mode" +Set the GPU scaling +.I mode +to +.BR off , +.B full +or +.B aspect +to either disable scaling, scale to full screen, or +to scale while preserving aspect ratio. +.TP .BI linear " size align" Use a linear screen aperture of size .I size diff --git a/sys/src/9/pc/devvga.c b/sys/src/9/pc/devvga.c index 3867d36dc..918da32b0 100644 --- a/sys/src/9/pc/devvga.c +++ b/sys/src/9/pc/devvga.c @@ -48,6 +48,7 @@ enum { CMunblank, CMsoftscreen, CMpcidev, + CMscaling, }; static Cmdtab vgactlmsg[] = { @@ -67,6 +68,7 @@ static Cmdtab vgactlmsg[] = { CMunblank, "unblank", 1, CMsoftscreen, "softscreen", 2, CMpcidev, "pcidev", 2, + CMscaling, "scaling", 2, }; static void @@ -305,6 +307,19 @@ vgactl(Cmdbuf *cb) error(Ebadarg); return; + case CMscaling: + if(scr != nil && scr->dev != nil){ + if(scr->dev->scaling == nil) + error("scaling not supported"); + else if(strcmp(cb->f[1], "aspect") == 0) + scr->dev->scaling(scr, Saspect); + else if(strcmp(cb->f[1], "full") == 0) + scr->dev->scaling(scr, Sfull); + else if(strcmp(cb->f[1], "off") == 0) + scr->dev->scaling(scr, Soff); + } + return; + case CMtype: for(i = 0; vgadev[i]; i++){ if(strcmp(cb->f[1], vgadev[i]->name)) diff --git a/sys/src/9/pc/screen.h b/sys/src/9/pc/screen.h index bbe6b2512..7928ca616 100644 --- a/sys/src/9/pc/screen.h +++ b/sys/src/9/pc/screen.h @@ -49,6 +49,15 @@ enum { Pwhite = 0xFF, }; +/* + * Scaling modes. + */ +enum { + Soff, + Sfull, + Saspect, +}; + #define VGAMEM() 0xA0000 #define vgai(port) inb(port) #define vgao(port, data) outb(port, data) @@ -74,6 +83,7 @@ struct VGAdev { void (*ovlctl)(VGAscr*, Chan*, void*, int); int (*ovlwrite)(VGAscr*, void*, int, vlong); void (*flush)(VGAscr*, Rectangle); + void (*scaling)(VGAscr*, int); }; struct VGAcur { diff --git a/sys/src/9/pc/vgavesa.c b/sys/src/9/pc/vgavesa.c index 794533a9d..4eeffbe85 100644 --- a/sys/src/9/pc/vgavesa.c +++ b/sys/src/9/pc/vgavesa.c @@ -23,6 +23,7 @@ enum { Cdisable = 0, Cenable, Cblank, + Cscaling, RealModeBuf = 0x9000, }; @@ -32,6 +33,7 @@ static Chan *creg, *cmem; static QLock vesaq; static Rendez vesar; static int vesactl; +static int scaling; #define WORD(p) ((p)[0] | ((p)[1]<<8)) #define LONG(p) ((p)[0] | ((p)[1]<<8) | ((p)[2]<<16) | ((p)[3]<<24)) @@ -183,11 +185,17 @@ vesaproc(void*) sleep(&vesar, gotctl, &ctl); ctl = vesactl; - vbesetup(&u, 0x4f10); - if(ctl == Cblank) - u.bx = 0x0101; - else - u.bx = 0x0001; + if(ctl == Cscaling){ + vbesetup(&u, 0x4f14); + u.bx = 0x102; + u.cx = scaling; + }else{ + vbesetup(&u, 0x4f10); + if(ctl == Cblank) + u.bx = 0x0101; + else + u.bx = 0x0001; + } /* * dont wait forever here. some BIOS get stuck @@ -252,6 +260,21 @@ vesablank(VGAscr *, int blank) } } +static void +vesascaling(VGAscr *, int mode) +{ + if(vesactl != Cdisable){ + vesactl = Cscaling; + if(mode == Soff) + scaling = 1; + else if(mode == Saspect) + scaling = 3; + else if(mode == Sfull) + scaling = 0; + wakeup(&vesar); + } +} + static void vesadrawinit(VGAscr *scr) { @@ -262,7 +285,12 @@ VGAdev vgavesadev = { "vesa", vesaenable, vesadisable, - 0, + nil, vesalinear, vesadrawinit, + nil, + nil, + nil, + nil, + vesascaling, };