devvga: implement screen tilting, remove panning and overlays

Tilting allows using left/right rotated or invetrted display orientation.
This can be changed at runtime such as: echo tilt right > /dev/vgactl
This removes the old panning and vga overlays as they are only implemented
with some ancient vga controllers.
This commit is contained in:
cinap_lenrek 2020-12-27 23:08:59 +01:00
parent 874e71c8dc
commit 806353ec9e
15 changed files with 352 additions and 659 deletions

View file

@ -6,8 +6,6 @@ vga \- VGA controller device
.B bind #v /dev .B bind #v /dev
.B /dev/vgactl .B /dev/vgactl
.B /dev/vgaovl
.B /dev/vgaovlctl
.fi .fi
.SH DESCRIPTION .SH DESCRIPTION
The VGA device allows configuration of a graphics controller The VGA device allows configuration of a graphics controller
@ -48,31 +46,25 @@ pixels wide by
.I Y .I Y
pixels high. pixels high.
This message is optional; This message is optional;
it is used to implement panning and to accommodate it is used to accommodate displays that require the
displays that require the in-memory screen image in-memory screen image to have certain alignment properties.
to have certain alignment properties.
For example, a 1400x1050 screen with a 1408x1050 in-memory image For example, a 1400x1050 screen with a 1408x1050 in-memory image
will use will use
.B "size 1408x1050 .B "size 1408x1050
but but
.BR "actualsize 1400x1050" . .BR "actualsize 1400x1050" .
.TP .TP
.BI panning " mode" .BI tilt " value"
Depending on whether Set the tilt of the screen,
.I mode altering the screen's orientation.
is The
.B on .I value
or can be one of:
.BR off , .BR none ,
enable or disable panning in a virtual screen. .BR left ,
If panning is on and the screen's .B inverted
.B size and
is larger than its .BR right .
.BR actualsize ,
the displayed portion of the screen will pan to follow the mouse.
Setting the panning mode after the first attach of the
.B #i
driver has no effect.
.TP .TP
.BI type " ctlr" .BI type " ctlr"
Set the type of VGA controller being used. Set the type of VGA controller being used.
@ -206,46 +198,6 @@ This must be sent after setting the
Reading Reading
.B vgactl .B vgactl
returns the current settings, one per line. returns the current settings, one per line.
.PP
Some VGA cards support overlay graphics.
Writing strings to
.B vgaovlctl
configures such cards.
The following are valid overlay control commands:
.TP
.BI openctl
opens the overlay device.
.TP
.BI configure " w h format"
allocates resources inside the driver to support an overlay area
of width
.I w
and height
.I h
pixels. Currently, the only supported
.I format
is
.B YUYV
packed.
In
.B YUYV
two pixels are encoded by their separate Y values
and their combined U and V values.
The size of the two pixels is 32 bits.
.TP
.BI enable " x y w h"
enables drawing data on the display through the overlay mode. The data
is drawn at position
.IR x , y
and has a width and height of
.IR w , h
respectively.
.TP
.BI closectl
terminates overlay control.
.PP
Overlay data can be written to
.BR vgaovl .
.SH EXAMPLES .SH EXAMPLES
The following disables hardware acceleration. The following disables hardware acceleration.
.IP .IP

View file

@ -19,15 +19,11 @@
enum { enum {
Qdir, Qdir,
Qvgactl, Qvgactl,
Qvgaovl,
Qvgaovlctl,
}; };
static Dirtab vgadir[] = { static Dirtab vgadir[] = {
".", { Qdir, 0, QTDIR }, 0, 0550, ".", { Qdir, 0, QTDIR }, 0, 0550,
"vgactl", { Qvgactl, 0 }, 0, 0660, "vgactl", { Qvgactl, 0 }, 0, 0660,
"vgaovl", { Qvgaovl, 0 }, 0, 0660,
"vgaovlctl", { Qvgaovlctl, 0 }, 0, 0660,
}; };
enum { enum {
@ -38,12 +34,12 @@ enum {
CMhwgc, CMhwgc,
CMlinear, CMlinear,
CMpalettedepth, CMpalettedepth,
CMpanning,
CMsize, CMsize,
CMtextmode, CMtextmode,
CMtype, CMtype,
CMsoftscreen, CMsoftscreen,
CMpcidev, CMpcidev,
CMtilt,
}; };
static Cmdtab vgactlmsg[] = { static Cmdtab vgactlmsg[] = {
@ -54,12 +50,12 @@ static Cmdtab vgactlmsg[] = {
CMhwgc, "hwgc", 2, CMhwgc, "hwgc", 2,
CMlinear, "linear", 0, CMlinear, "linear", 0,
CMpalettedepth, "palettedepth", 2, CMpalettedepth, "palettedepth", 2,
CMpanning, "panning", 2,
CMsize, "size", 3, CMsize, "size", 3,
CMtextmode, "textmode", 1, CMtextmode, "textmode", 1,
CMtype, "type", 2, CMtype, "type", 2,
CMsoftscreen, "softscreen", 2, CMsoftscreen, "softscreen", 2,
CMpcidev, "pcidev", 2, CMpcidev, "pcidev", 2,
CMtilt, "tilt", 2,
}; };
static void static void
@ -120,35 +116,12 @@ vgastat(Chan* c, uchar* dp, int n)
static Chan* static Chan*
vgaopen(Chan* c, int omode) vgaopen(Chan* c, int omode)
{ {
VGAscr *scr;
static char *openctl = "openctl\n";
scr = &vgascreen[0];
if ((ulong)c->qid.path == Qvgaovlctl) {
if (scr->dev && scr->dev->ovlctl)
scr->dev->ovlctl(scr, c, openctl, strlen(openctl));
else
error(Enonexist);
}
return devopen(c, omode, vgadir, nelem(vgadir), devgen); return devopen(c, omode, vgadir, nelem(vgadir), devgen);
} }
static void static void
vgaclose(Chan* c) vgaclose(Chan*)
{ {
VGAscr *scr;
static char *closectl = "closectl\n";
scr = &vgascreen[0];
if((ulong)c->qid.path == Qvgaovlctl)
if(scr->dev && scr->dev->ovlctl){
if(waserror()){
print("ovlctl error: %s\n", up->errstr);
return;
}
scr->dev->ovlctl(scr, c, closectl, strlen(closectl));
poperror();
}
} }
static long static long
@ -176,19 +149,20 @@ vgaread(Chan* c, void* a, long n, vlong off)
p = seprint(p, e, "type %s\n", p = seprint(p, e, "type %s\n",
scr->dev != nil ? scr->dev->name : "cga"); scr->dev != nil ? scr->dev->name : "cga");
if(scr->gscreen != nil) { if(scr->gscreen != nil) {
Rectangle r;
p = seprint(p, e, "size %dx%dx%d %s\n", p = seprint(p, e, "size %dx%dx%d %s\n",
scr->gscreen->r.max.x, scr->gscreen->r.max.y, scr->width, scr->height, scr->gscreen->depth,
scr->gscreen->depth, chantostr(chbuf, scr->gscreen->chan)); chantostr(chbuf, scr->gscreen->chan));
if(Dx(scr->gscreen->r) != Dx(physgscreenr) r = actualscreensize(scr);
|| Dy(scr->gscreen->r) != Dy(physgscreenr)) if(scr->width != r.max.x || scr->height != r.max.y)
p = seprint(p, e, "actualsize %dx%d\n", p = seprint(p, e, "actualsize %dx%d\n", r.max.x, r.max.y);
physgscreenr.max.x, physgscreenr.max.y); p = seprint(p, e, "tilt %s\n", tiltstr[scr->tilt]);
} }
p = seprint(p, e, "hwgc %s\n", p = seprint(p, e, "hwgc %s\n",
scr->cur != nil ? scr->cur->name : "off"); scr->cur != nil ? scr->cur->name : "off");
p = seprint(p, e, "hwaccel %s\n", hwaccel ? "on" : "off"); p = seprint(p, e, "hwaccel %s\n", hwaccel ? "on" : "off");
p = seprint(p, e, "hwblank %s\n", hwblank ? "on" : "off"); p = seprint(p, e, "hwblank %s\n", hwblank ? "on" : "off");
p = seprint(p, e, "panning %s\n", panning ? "on" : "off");
p = seprint(p, e, "addr p 0x%.8llux v %#p size %#ux\n", p = seprint(p, e, "addr p 0x%.8llux v %#p size %#ux\n",
scr->paddr, scr->vaddr, scr->apsize); scr->paddr, scr->vaddr, scr->apsize);
p = seprint(p, e, "softscreen %s\n", scr->softscreen ? "on" : "off"); p = seprint(p, e, "softscreen %s\n", scr->softscreen ? "on" : "off");
@ -199,11 +173,6 @@ vgaread(Chan* c, void* a, long n, vlong off)
return n; return n;
case Qvgaovl:
case Qvgaovlctl:
error(Ebadusefd);
break;
default: default:
error(Egreg); error(Egreg);
break; break;
@ -216,18 +185,16 @@ static char Ebusy[] = "vga already configured";
static char Enoscreen[] = "set the screen size first"; static char Enoscreen[] = "set the screen size first";
static void static void
vgactl(Cmdbuf *cb) vgactl(VGAscr *scr, Cmdbuf *cb)
{ {
int align, i, size, x, y, z; int align, size, tilt, z, i;
Rectangle r; Rectangle r;
char *chanstr, *p; char *chanstr, *p;
ulong chan; ulong chan;
Cmdtab *ct; Cmdtab *ct;
VGAscr *scr;
extern VGAdev *vgadev[]; extern VGAdev *vgadev[];
extern VGAcur *vgacur[]; extern VGAcur *vgacur[];
scr = &vgascreen[0];
ct = lookupcmd(cb, vgactlmsg, nelem(vgactlmsg)); ct = lookupcmd(cb, vgactlmsg, nelem(vgactlmsg));
switch(ct->index){ switch(ct->index){
case CMhwgc: case CMhwgc:
@ -298,14 +265,15 @@ vgactl(Cmdbuf *cb)
return; return;
case CMsize: case CMsize:
x = strtoul(cb->f[1], &p, 0); r.min = ZP;
r.max.x = strtoul(cb->f[1], &p, 0);
if(*p) if(*p)
p++; p++;
y = strtoul(p, &p, 0); r.max.y = strtoul(p, &p, 0);
if(*p) if(*p)
p++; p++;
z = strtoul(p, &p, 0); z = strtoul(p, &p, 0);
if(badrect(Rect(0,0,x,y))) if(badrect(r))
error(Ebadarg); error(Ebadarg);
chanstr = cb->f[2]; chanstr = cb->f[2];
if((chan = strtochan(chanstr)) == 0) if((chan = strtochan(chanstr)) == 0)
@ -313,32 +281,30 @@ vgactl(Cmdbuf *cb)
if(chantodepth(chan) != z) if(chantodepth(chan) != z)
error("depth, channel do not match"); error("depth, channel do not match");
deletescreenimage(); deletescreenimage();
if(screensize(x, y, z, chan)) setscreensize(scr, r.max.x, r.max.y, z, chan, scr->tilt);
error(Egreg);
bootscreenconf(scr);
return; return;
case CMactualsize: case CMactualsize:
if(scr->gscreen == nil) if(scr->gscreen == nil)
error(Enoscreen); error(Enoscreen);
x = strtoul(cb->f[1], &p, 0); r.min = ZP;
r.max.x = strtoul(cb->f[1], &p, 0);
if(*p) if(*p)
p++; p++;
y = strtoul(p, nil, 0); r.max.y = strtoul(p, nil, 0);
r = Rect(0,0,x,y);
if(badrect(r)) if(badrect(r))
error(Ebadarg); error(Ebadarg);
if(!rectinrect(r, scr->gscreen->r)) if(r.max.x > scr->width || r.max.y > scr->height)
error("physical screen bigger than virtual"); error("physical screen bigger than virtual");
deletescreenimage(); deletescreenimage();
physgscreenr = r; setactualsize(scr, r);
goto Resized; goto Resized;
case CMpalettedepth: case CMpalettedepth:
x = strtoul(cb->f[1], &p, 0); z = strtoul(cb->f[1], &p, 0);
if(x != 8 && x != 6) if(z != 8 && z != 6)
error(Ebadarg); error(Ebadarg);
scr->palettedepth = x; scr->palettedepth = z;
return; return;
case CMsoftscreen: case CMsoftscreen:
@ -348,17 +314,22 @@ vgactl(Cmdbuf *cb)
scr->softscreen = 0; scr->softscreen = 0;
else else
break; break;
if(0){
case CMtilt:
for(tilt = 0; tilt < nelem(tiltstr); tilt++)
if(strcmp(cb->f[1], tiltstr[tilt]) == 0)
break;
} else {
tilt = scr->tilt;
}
if(scr->gscreen == nil) if(scr->gscreen == nil)
return; return;
r = physgscreenr; r = actualscreensize(scr);
x = scr->gscreen->r.max.x;
y = scr->gscreen->r.max.y;
z = scr->gscreen->depth;
chan = scr->gscreen->chan; chan = scr->gscreen->chan;
z = scr->gscreen->depth;
deletescreenimage(); deletescreenimage();
if(screensize(x, y, z, chan)) setscreensize(scr, scr->width, scr->height, z, chan, tilt);
error(Egreg); setactualsize(scr, r);
physgscreenr = r;
/* no break */ /* no break */
case CMdrawinit: case CMdrawinit:
if(scr->gscreen == nil) if(scr->gscreen == nil)
@ -368,7 +339,6 @@ vgactl(Cmdbuf *cb)
hwblank = scr->blank != nil; hwblank = scr->blank != nil;
hwaccel = scr->fill != nil || scr->scroll != nil; hwaccel = scr->fill != nil || scr->scroll != nil;
Resized: Resized:
scr->gscreen->clipr = panning ? scr->gscreen->r : physgscreenr;
vgascreenwin(scr); vgascreenwin(scr);
resetscreenimage(); resetscreenimage();
return; return;
@ -381,27 +351,10 @@ vgactl(Cmdbuf *cb)
align = 0; align = 0;
else else
align = strtoul(cb->f[2], 0, 0); align = strtoul(cb->f[2], 0, 0);
if(screenaperture(size, align) < 0) if(screenaperture(scr, size, align) < 0)
error("not enough free address space"); error("not enough free address space");
return; return;
case CMpanning:
if(strcmp(cb->f[1], "on") == 0){
if(scr->cur == nil)
error("set cursor first");
if(!scr->cur->doespanning)
error("panning not supported");
panning = 1;
}
else if(strcmp(cb->f[1], "off") == 0){
panning = 0;
}else
break;
if(scr->gscreen == nil)
return;
deletescreenimage();
goto Resized;
case CMhwaccel: case CMhwaccel:
if(strcmp(cb->f[1], "on") == 0) if(strcmp(cb->f[1], "on") == 0)
hwaccel = 1; hwaccel = 1;
@ -424,14 +377,11 @@ vgactl(Cmdbuf *cb)
cmderror(cb, "bad VGA control message"); cmderror(cb, "bad VGA control message");
} }
char Enooverlay[] = "No overlay support";
static long static long
vgawrite(Chan* c, void* a, long n, vlong off) vgawrite(Chan* c, void* a, long n, vlong off)
{ {
ulong offset = off; ulong offset = off;
Cmdbuf *cb; Cmdbuf *cb;
VGAscr *scr;
switch((ulong)c->qid.path){ switch((ulong)c->qid.path){
@ -446,28 +396,11 @@ vgawrite(Chan* c, void* a, long n, vlong off)
free(cb); free(cb);
nexterror(); nexterror();
} }
vgactl(cb); vgactl(&vgascreen[0], cb);
poperror(); poperror();
free(cb); free(cb);
return n; return n;
case Qvgaovl:
scr = &vgascreen[0];
if (scr->dev == nil || scr->dev->ovlwrite == nil) {
error(Enooverlay);
break;
}
return scr->dev->ovlwrite(scr, a, n, off);
case Qvgaovlctl:
scr = &vgascreen[0];
if (scr->dev == nil || scr->dev->ovlctl == nil) {
error(Enooverlay);
break;
}
scr->dev->ovlctl(scr, c, a, n);
return n;
default: default:
error(Egreg); error(Egreg);
break; break;

View file

@ -16,16 +16,125 @@
extern VGAcur vgasoftcur; extern VGAcur vgasoftcur;
Rectangle physgscreenr;
Memimage *gscreen; Memimage *gscreen;
VGAscr vgascreen[1]; VGAscr vgascreen[1];
int char *tiltstr[4] = {
screensize(int x, int y, int, ulong chan) "none",
"left",
"inverted",
"right",
};
static Point
tiltpt(int tilt, Point dim, Point p)
{ {
VGAscr *scr; switch(tilt&3){
case 1: return Pt(dim.y-p.y-1, p.x);
case 2: return Pt(dim.x-p.x-1, dim.y-p.y-1);
case 3: return Pt(p.y, dim.x-p.x-1);
}
return p;
}
static Rectangle
tiltrect(int tilt, Point dim, Rectangle r)
{
switch(tilt&3){
case 1: return Rect(dim.y-r.max.y, r.min.x, dim.y-r.min.y, r.max.x);
case 2: return Rect(dim.x-r.max.x, dim.y-r.max.y, dim.x-r.min.x, dim.y-r.min.y);
case 3: return Rect(r.min.y, dim.x-r.max.x, r.max.y, dim.x-r.min.x);
}
return r;
}
static Point
tiltsize(int tilt, Point dim)
{
return (tilt & 1) != 0 ? Pt(dim.y, dim.x) : dim;
}
Rectangle
actualscreensize(VGAscr *scr)
{
return Rpt(ZP, tiltsize(-scr->tilt, scr->gscreen->clipr.max));
}
void
setactualsize(VGAscr *scr, Rectangle r)
{
qlock(&drawlock);
r.min = ZP;
r.max = tiltsize(scr->tilt, r.max);
if(rectclip(&r, scr->gscreen->r) == 0){
qunlock(&drawlock);
return;
}
scr->gscreen->clipr = r;
qunlock(&drawlock);
}
static char*
setscreensize0(VGAscr *scr, int width, int height, int depth, ulong chan, int tilt)
{
int bpp, pitch;
scr->gscreendata = nil;
scr->gscreen = nil;
if(gscreen != nil){
freememimage(gscreen);
gscreen = nil;
}
if(scr->paddr == 0){
if(scr->dev && scr->dev->page){
scr->vaddr = KADDR(VGAMEM());
scr->apsize = 1<<16;
}
scr->softscreen = 1;
}
depth = chantodepth(chan);
bpp = (depth+7) / 8;
pitch = ((width * depth+31) & ~31) / 8;
if(tilt)
scr->softscreen = 1;
if(scr->softscreen){
gscreen = allocmemimage(Rpt(ZP, tiltsize(tilt, Pt(width, height))), chan);
scr->useflush = 1;
}else{
static Memdata md;
md.ref = 1;
if((md.bdata = scr->vaddr) == 0)
error("framebuffer not maped");
gscreen = allocmemimaged(Rpt(ZP, Pt(width, height)), chan, &md);
scr->useflush = scr->dev && scr->dev->flush;
}
if(gscreen == nil)
return "no memory for vga memimage";
scr->bpp = bpp;
scr->pitch = pitch;
scr->width = width;
scr->height = height;
scr->tilt = tilt & 3;
scr->palettedepth = 6; /* default */
scr->memdefont = getmemdefont();
scr->gscreen = gscreen;
scr->gscreendata = gscreen->data;
return nil;
}
void
setscreensize(VGAscr *scr, int x, int y, int z, ulong chan, int tilt)
{
char *err;
qlock(&drawlock); qlock(&drawlock);
if(waserror()){ if(waserror()){
@ -42,68 +151,37 @@ screensize(int x, int y, int, ulong chan)
nexterror(); nexterror();
} }
scr = &vgascreen[0]; err = setscreensize0(scr, x, y, z, chan, tilt);
scr->gscreendata = nil; if(err != nil)
scr->gscreen = nil; error(err);
if(gscreen){
freememimage(gscreen);
gscreen = nil;
}
if(scr->paddr == 0){
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;
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;
}
if(gscreen == nil)
error("no memory for vga memimage");
scr->palettedepth = 6; /* default */
scr->memdefont = getmemdefont();
scr->gscreen = gscreen;
scr->gscreendata = gscreen->data;
physgscreenr = gscreen->r;
vgaimageinit(chan); vgaimageinit(chan);
bootscreenconf(scr);
unlock(&vgascreenlock); unlock(&vgascreenlock);
poperror(); poperror();
drawcmap(); drawcmap();
if(scr->cur && scr->cur != &vgasoftcur){
cursoroff();
setcursor(&cursor);
cursoron();
}
qunlock(&drawlock); qunlock(&drawlock);
poperror(); poperror();
return 0;
} }
int int
screenaperture(int size, int align) screenaperture(VGAscr *scr, int size, int align)
{ {
VGAscr *scr;
uvlong pa; uvlong pa;
scr = &vgascreen[0]; if(size == 0)
if(scr->paddr) /* set up during enable */
return 0; return 0;
if(size == 0) if(scr->paddr) /* set up during enable */
return 0; return 0;
if(scr->dev && scr->dev->linear){ if(scr->dev && scr->dev->linear){
@ -152,19 +230,61 @@ flushmemscreen(Rectangle r)
{ {
VGAscr *scr; VGAscr *scr;
uchar *sp, *disp, *sdisp, *edisp; uchar *sp, *disp, *sdisp, *edisp;
int y, len, incs, off, page; int x, y, len, incs, off, page;
scr = &vgascreen[0]; scr = &vgascreen[0];
if(scr->gscreen == nil || scr->useflush == 0) if(scr->gscreen == nil || scr->useflush == 0)
return; return;
if(rectclip(&r, scr->gscreen->r) == 0) if(rectclip(&r, scr->gscreen->clipr) == 0)
return; return;
if(scr->tilt){
Point size;
/* only supported on linear framebuffer */
disp = scr->vaddr;
if(scr->paddr == 0 || disp == nil)
return;
size = scr->gscreen->clipr.max;
r = tiltrect(-scr->tilt, size, r);
size = tiltsize(-scr->tilt, size);
sp = byteaddr(scr->gscreen, tiltpt(scr->tilt, size, r.min));
incs = byteaddr(scr->gscreen, tiltpt(scr->tilt, size, Pt(r.min.x+1, r.min.y))) - sp;
for(;;){
sdisp = disp + r.min.y * scr->pitch;
for(x = r.min.x; x < r.max.x; x++, sp += incs){
switch(scr->bpp){
case 4:
((ulong*)sdisp)[x] = *(ulong*)sp;
break;
case 3:
sdisp[x*3+0] = sp[0];
sdisp[x*3+1] = sp[1];
sdisp[x*3+2] = sp[2];
break;
case 2:
((ushort*)sdisp)[x] = *(ushort*)sp;
break;
case 1:
sdisp[x] = sp[0];
break;
}
}
if(++r.min.y >= r.max.y)
break;
sp = byteaddr(scr->gscreen, tiltpt(scr->tilt, size, r.min));
}
return;
}
if(scr->dev && scr->dev->flush){ if(scr->dev && scr->dev->flush){
scr->dev->flush(scr, r); scr->dev->flush(scr, r);
return; return;
} }
disp = scr->vaddr; disp = scr->vaddr;
incs = scr->gscreen->width*sizeof(ulong); incs = scr->pitch;
off = (r.min.x*scr->gscreen->depth) / 8; off = (r.min.x*scr->gscreen->depth) / 8;
len = (r.max.x*scr->gscreen->depth + 7) / 8; len = (r.max.x*scr->gscreen->depth + 7) / 8;
len -= off; len -= off;
@ -299,16 +419,48 @@ setcolor(ulong p, ulong r, ulong g, ulong b)
return setpalette(p, r, g, b); return setpalette(p, r, g, b);
} }
static void
tiltcursor(int t, Cursor *src, Cursor *dst)
{
static Point dim = {16, 16};
uint i, j, im, jm;
Point p;
for(i = 0; i < 16*16; i++){
p = tiltpt(t, dim, Pt(i&15,i>>4));
j = p.y<<4 | p.x;
im = 0x80>>(i&7);
jm = 0x80>>(j&7);
if(src->clr[i>>3] & im)
dst->clr[j>>3] |= jm;
else
dst->clr[j>>3] &= ~jm;
if(src->set[i>>3] & im)
dst->set[j>>3] |= jm;
else
dst->set[j>>3] &= ~jm;
}
p = Pt(-src->offset.x & 15, -src->offset.y & 15);
p = tiltpt(t, dim, p);
dst->offset = Pt(-p.x, -p.y);
}
void void
cursoron(void) cursoron(void)
{ {
VGAscr *scr; VGAscr *scr;
VGAcur *cur; VGAcur *cur;
Point p;
scr = &vgascreen[0]; scr = &vgascreen[0];
cur = scr->cur; cur = scr->cur;
if(cur && cur->move) if(cur && cur->move){
cur->move(scr, mousexy()); p = mousexy();
if(scr->tilt && cur != &vgasoftcur)
p = tiltpt(-scr->tilt, scr->gscreen->clipr.max, p);
cur->move(scr, p);
}
} }
void void
@ -324,13 +476,18 @@ setcursor(Cursor* curs)
scr = &vgascreen[0]; scr = &vgascreen[0];
cur = scr->cur; cur = scr->cur;
if(cur && cur->load) if(cur && cur->load){
if(scr->tilt && cur != &vgasoftcur){
static Cursor tmp;
tiltcursor(-scr->tilt, curs, &tmp);
curs = &tmp;
}
cur->load(scr, curs); cur->load(scr, curs);
} }
}
int hwaccel = 0; int hwaccel = 0;
int hwblank = 0; int hwblank = 0;
int panning = 0;
int int
hwdraw(Memdrawparam *par) hwdraw(Memdrawparam *par)
@ -358,7 +515,7 @@ hwdraw(Memdrawparam *par)
if(mask && mask->data->bdata == scrd->bdata) if(mask && mask->data->bdata == scrd->bdata)
swcursoravoid(par->mr); swcursoravoid(par->mr);
} }
if(!hwaccel || scr->softscreen) if(!hwaccel || scr->softscreen || scr->tilt)
return 0; return 0;
if(dst->data->bdata != scrd->bdata || src == nil || mask == nil) if(dst->data->bdata != scrd->bdata || src == nil || mask == nil)
return 0; return 0;
@ -396,14 +553,14 @@ blankscreen(int blank)
{ {
VGAscr *scr; VGAscr *scr;
if(!hwblank)
return;
scr = &vgascreen[0]; scr = &vgascreen[0];
if(hwblank){
if(scr->blank) if(scr->blank)
scr->blank(scr, blank); scr->blank(scr, blank);
else else
vgablank(scr, blank); vgablank(scr, blank);
} }
}
static char* static char*
vgalinearaddr0(VGAscr *scr, uvlong paddr, int size) vgalinearaddr0(VGAscr *scr, uvlong paddr, int size)
@ -461,6 +618,8 @@ vgalinearpci0(VGAscr *scr)
Pcidev *p; Pcidev *p;
p = scr->pci; p = scr->pci;
if(p == nil)
return "no pci card";
/* /*
* Scan for largest memory region on card. * Scan for largest memory region on card.
@ -575,7 +734,7 @@ void
bootscreeninit(void) bootscreeninit(void)
{ {
VGAscr *scr; VGAscr *scr;
int x, y, z; int x, y, z, tilt;
uvlong pa; uvlong pa;
ulong chan, sz; ulong chan, sz;
char *s, *p, *err; char *s, *p, *err;
@ -608,34 +767,36 @@ bootscreeninit(void)
pa = strtoull(p+1, &s, 0); pa = strtoull(p+1, &s, 0);
if(pa == 0) if(pa == 0)
return; return;
if(*s++ == ' ') if(*s == ' ')
sz = strtoul(s, nil, 0); sz = strtoul(s+1, nil, 0);
if(sz < x * y * (z+7)/8) if(sz < x * y * (z+7)/8)
sz = x * y * (z+7)/8; sz = x * y * (z+7)/8;
/* map framebuffer */ tilt = 0;
if((p = getconf("tiltscreen")) != nil){
for(; tilt < nelem(tiltstr); tilt++)
if(strcmp(p, tiltstr[tilt]) == 0)
break;
tilt &= 3;
}
scr = &vgascreen[0]; scr = &vgascreen[0];
scr->dev = nil;
scr->softscreen = 1;
if((err = bootmapfb(scr, pa, sz)) != nil){ if((err = bootmapfb(scr, pa, sz)) != nil){
print("bootmapfb: %s\n", err); print("bootmapfb: %s\n", err);
return; return;
} }
if(memimageinit() < 0) if(memimageinit() < 0){
print("memimageinit failed\n");
return; return;
}
gscreen = allocmemimage(Rect(0,0,x,y), chan); if((err = setscreensize0(scr, x, y, z, chan, tilt)) != nil){
if(gscreen == nil) print("setscreensize0: %s\n", err);
return; return;
}
scr->palettedepth = 6; /* default */
scr->memdefont = getmemdefont();
scr->gscreen = gscreen;
scr->gscreendata = gscreen->data;
scr->softscreen = 1;
scr->useflush = 1;
scr->dev = nil;
physgscreenr = gscreen->r;
vgaimageinit(chan); vgaimageinit(chan);
vgascreenwin(scr); vgascreenwin(scr);
@ -659,10 +820,11 @@ bootscreenconf(VGAscr *scr)
char conf[100], chan[30]; char conf[100], chan[30];
conf[0] = '\0'; conf[0] = '\0';
if(scr != nil && scr->paddr != 0 && scr->gscreen != nil) if(scr != nil && scr->paddr != 0 && scr->gscreen != nil){
snprint(conf, sizeof(conf), "%dx%dx%d %s 0x%.8llux %d\n", snprint(conf, sizeof(conf), "%dx%dx%d %s 0x%.8llux %d\n",
scr->gscreen->r.max.x, scr->gscreen->r.max.y, scr->width, scr->height, scr->gscreen->depth, chantostr(chan, scr->gscreen->chan),
scr->gscreen->depth, chantostr(chan, scr->gscreen->chan),
scr->paddr, scr->apsize); scr->paddr, scr->apsize);
ksetenv("tiltscreen", tiltstr[scr->tilt], 1);
}
ksetenv("*bootscreen", conf, 1); ksetenv("*bootscreen", conf, 1);
} }

View file

@ -75,8 +75,6 @@ struct VGAcur {
void (*disable)(VGAscr*); void (*disable)(VGAscr*);
void (*load)(VGAscr*, Cursor*); void (*load)(VGAscr*, Cursor*);
int (*move)(VGAscr*, Point); int (*move)(VGAscr*, Point);
int doespanning;
}; };
/* /*
@ -96,6 +94,12 @@ struct VGAscr {
void* vaddr; void* vaddr;
int apsize; int apsize;
int bpp;
int pitch;
int width;
int height;
ulong io; /* device specific registers */ ulong io; /* device specific registers */
ulong *mmio; ulong *mmio;
@ -110,8 +114,8 @@ struct VGAscr {
int (*scroll)(VGAscr*, Rectangle, Rectangle); int (*scroll)(VGAscr*, Rectangle, Rectangle);
void (*blank)(VGAscr*, int); void (*blank)(VGAscr*, int);
ulong id; /* internal identifier for driver use */ ulong id; /* internal identifier for driver use */
int overlayinit;
int softscreen; int softscreen;
int tilt;
}; };
extern VGAscr vgascreen[]; extern VGAscr vgascreen[];
@ -128,16 +132,17 @@ extern void mouseredraw(void);
/* screen.c */ /* screen.c */
extern int hwaccel; /* use hw acceleration */ extern int hwaccel; /* use hw acceleration */
extern int hwblank; /* use hw blanking */ extern int hwblank; /* use hw blanking */
extern int panning; /* use virtual screen panning */ extern char *tiltstr[4];
extern Rectangle actualscreensize(VGAscr*);
extern void setactualsize(VGAscr*, Rectangle);
extern void setscreensize(VGAscr*, int, int, int, ulong, int);
extern void addvgaseg(char*, uvlong, ulong); extern void addvgaseg(char*, uvlong, ulong);
extern Memdata* attachscreen(Rectangle*, ulong*, int*, int*, int*); extern Memdata* attachscreen(Rectangle*, ulong*, int*, int*, int*);
extern void flushmemscreen(Rectangle); extern void flushmemscreen(Rectangle);
extern void cursoron(void); extern void cursoron(void);
extern void cursoroff(void); extern void cursoroff(void);
extern void setcursor(Cursor*); extern void setcursor(Cursor*);
extern int screensize(int, int, int, ulong); extern int screenaperture(VGAscr*, int, int);
extern int screenaperture(int, int);
extern Rectangle physgscreenr; /* actual monitor size */
extern void blankscreen(int); extern void blankscreen(int);
extern char* rgbmask2chan(char *buf, int depth, u32int rm, u32int gm, u32int bm); extern char* rgbmask2chan(char *buf, int depth, u32int rm, u32int gm, u32int bm);
extern void bootscreeninit(void); extern void bootscreeninit(void);

View file

@ -34,7 +34,7 @@ ct65545enable(VGAscr* scr)
* Find a place for the cursor data in display memory. * Find a place for the cursor data in display memory.
* Must be on a 1024-byte boundary. * Must be on a 1024-byte boundary.
*/ */
storage = ROUND(scr->gscreen->width*sizeof(ulong)*scr->gscreen->r.max.y, 1024); storage = ROUND(scr->pitch*scr->height, 1024);
outl(0xB3D0, storage); outl(0xB3D0, storage);
scr->storage = storage; scr->storage = storage;

View file

@ -170,7 +170,7 @@ cyber938xcurenable(VGAscr* scr)
/* /*
* Find a place for the cursor data in display memory. * Find a place for the cursor data in display memory.
*/ */
storage = ((scr->gscreen->width*sizeof(ulong)*scr->gscreen->r.max.y+1023)/1024); storage = ((scr->pitch*scr->height+1023)/1024);
vgaxo(Crtx, 0x44, storage & 0xFF); vgaxo(Crtx, 0x44, storage & 0xFF);
vgaxo(Crtx, 0x45, (storage>>8) & 0xFF); vgaxo(Crtx, 0x45, (storage>>8) & 0xFF);
storage *= 1024; storage *= 1024;

View file

@ -79,7 +79,7 @@ et4000enable(VGAscr *scr)
* 1024-byte boundary so that there's no danger of it * 1024-byte boundary so that there's no danger of it
* crossing a page. * crossing a page.
*/ */
scr->storage = (scr->gscreen->width*sizeof(ulong)*scr->gscreen->r.max.y+1023)/1024; scr->storage = (scr->pitch*scr->height+1023)/1024;
scr->storage *= 1024/4; scr->storage *= 1024/4;
outb(0x217A, 0xE8); outb(0x217A, 0xE8);
outb(0x217B, scr->storage & 0xFF); outb(0x217B, scr->storage & 0xFF);

View file

@ -80,12 +80,6 @@ char Enotconfigured[] = "device not configured";
#define HOST_MEM_MODE_V 0xC0000000 #define HOST_MEM_MODE_V 0xC0000000
#define HOST_MEM_MODE_NORMAL HOST_YUV_APERTURE_UPPER #define HOST_MEM_MODE_NORMAL HOST_YUV_APERTURE_UPPER
static Chan *ovl_chan; /* Channel of controlling process */
static int ovl_width; /* Width of input overlay buffer */
static int ovl_height; /* Height of input overlay buffer */
static int ovl_format; /* Overlay format */
static ulong ovl_fib; /* Frame in bytes */
enum { enum {
VTGTB1S1 = 0x01, /* Asic description for VTB1S1 and GTB1S1. */ VTGTB1S1 = 0x01, /* Asic description for VTB1S1 and GTB1S1. */
VT4GTIIC = 0x3A, /* asic descr for VT4 and RAGE IIC */ VT4GTIIC = 0x3A, /* asic descr for VT4 and RAGE IIC */
@ -117,7 +111,6 @@ struct Mach64types {
static ulong mach64refclock; static ulong mach64refclock;
static Mach64types *mach64type; static Mach64types *mach64type;
static int mach64revb; /* Revision B or greater? */ static int mach64revb; /* Revision B or greater? */
static ulong mach64overlay; /* Overlay buffer */
static Mach64types mach64s[] = { static Mach64types mach64s[] = {
('C'<<8)|'T', 0, 1350000, /*?*/ 0, /* 4354: CT */ ('C'<<8)|'T', 0, 1350000, /*?*/ 0, /* 4354: CT */
@ -480,69 +473,10 @@ ptalmostinrect(Point p, Rectangle r)
p.y>=r.min.y && p.y<=r.max.y; p.y>=r.min.y && p.y<=r.max.y;
} }
/*
* If necessary, translate the rectangle physr
* some multiple of [dx dy] so that it includes p.
* Return 1 if the rectangle changed.
*/
static int
screenpan(Point p, Rectangle *physr, int dx, int dy)
{
int d;
if(ptalmostinrect(p, *physr))
return 0;
if(p.y < physr->min.y){
d = physr->min.y - (p.y&~(dy-1));
physr->min.y -= d;
physr->max.y -= d;
}
if(p.y > physr->max.y){
d = ((p.y+dy-1)&~(dy-1)) - physr->max.y;
physr->min.y += d;
physr->max.y += d;
}
if(p.x < physr->min.x){
d = physr->min.x - (p.x&~(dx-1));
physr->min.x -= d;
physr->max.x -= d;
}
if(p.x > physr->max.x){
d = ((p.x+dx-1)&~(dx-1)) - physr->max.x;
physr->min.x += d;
physr->max.x += d;
}
return 1;
}
static int static int
mach64xxcurmove(VGAscr* scr, Point p) mach64xxcurmove(VGAscr* scr, Point p)
{ {
int x, xo, y, yo; int x, xo, y, yo;
int dx;
ulong off, pitch;
/*
* If the point we want to display is outside the current
* screen rectangle, pan the screen to display it.
*
* We have to move in 64-bit chunks.
*/
if(scr->gscreen->depth == 24)
dx = (64*3)/24;
else
dx = 64 / scr->gscreen->depth;
if(panning && screenpan(p, &physgscreenr, dx, 1)){
off = (physgscreenr.min.y*Dx(scr->gscreen->r)+physgscreenr.min.x)/dx;
pitch = Dx(scr->gscreen->r)/8;
iow32(scr, CrtcOffPitch, (pitch<<22)|off);
}
p.x -= physgscreenr.min.x;
p.y -= physgscreenr.min.y;
/* /*
* Mustn't position the cursor offscreen even partially, * Mustn't position the cursor offscreen even partially,
@ -589,7 +523,7 @@ mach64xxcurenable(VGAscr* scr)
* Find a place for the cursor data in display memory. * Find a place for the cursor data in display memory.
* Must be 64-bit aligned. * Must be 64-bit aligned.
*/ */
storage = (scr->gscreen->width*sizeof(ulong)*scr->gscreen->r.max.y+7)/8; storage = (scr->pitch*scr->height+7)/8;
iow32(scr, CurOffset, storage); iow32(scr, CurOffset, storage);
scr->storage = storage*8; scr->storage = storage*8;
@ -643,64 +577,23 @@ resetengine(VGAscr *scr)
iow32(scr, BusCntl, ior32(scr, BusCntl)|0x00A00000); iow32(scr, BusCntl, ior32(scr, BusCntl)|0x00A00000);
} }
static void
init_overlayclock(VGAscr *scr)
{
uchar *cc, save, pll_ref_div, pll_vclk_cntl, vclk_post_div,
vclk_fb_div, ecp_div;
int i;
ulong dotclock;
/* Taken from GLX */
/* Get monitor dotclock, check for Overlay Scaler clock limit */
cc = (uchar *)&scr->mmio[mmoffset[ClockCntl]];
save = cc[1]; i = cc[0] & 3;
cc[1] = 2<<2; pll_ref_div = cc[2];
cc[1] = 5<<2; pll_vclk_cntl = cc[2];
cc[1] = 6<<2; vclk_post_div = (cc[2]>>(i+i)) & 3;
cc[1] = (7+i)<<2; vclk_fb_div = cc[2];
dotclock = 2 * mach64refclock * vclk_fb_div /
(pll_ref_div * (1 << vclk_post_div));
/* ecp_div: 0=dotclock, 1=dotclock/2, 2=dotclock/4 */
ecp_div = dotclock / mach64type->m64_ovlclock;
if (ecp_div>2) ecp_div = 2;
/* Force a scaler clock factor of 1 if refclock *
* is unknown (VCLK_SRC not PLLVCLK) */
if ((pll_vclk_cntl & 0x03) != 0x03)
ecp_div = 0;
if ((pll_vclk_cntl & 0x30) != ecp_div<<4) {
cc[1] = (5<<2)|2;
cc[2] = (pll_vclk_cntl&0xCF) | (ecp_div<<4);
}
/* Restore PLL Register Index */
cc[1] = save;
}
static void static void
initengine(VGAscr *scr) initengine(VGAscr *scr)
{ {
ulong pitch;
uchar *bios; uchar *bios;
ushort table; ushort table;
pitch = Dx(scr->gscreen->r)/8;
if(scr->gscreen->depth == 24)
pitch *= 3;
resetengine(scr); resetengine(scr);
waitforfifo(scr, 14); waitforfifo(scr, 14);
iow32(scr, ContextMask, ~0); iow32(scr, ContextMask, ~0);
iow32(scr, DstOffPitch, pitch<<22); iow32(scr, DstOffPitch, scr->pitch<<22);
iow32(scr, DstYX, 0); iow32(scr, DstYX, 0);
iow32(scr, DstHeight, 0); iow32(scr, DstHeight, 0);
iow32(scr, DstBresErr, 0); iow32(scr, DstBresErr, 0);
iow32(scr, DstBresInc, 0); iow32(scr, DstBresInc, 0);
iow32(scr, DstBresDec, 0); iow32(scr, DstBresDec, 0);
iow32(scr, DstCntl, 0x23); iow32(scr, DstCntl, 0x23);
iow32(scr, SrcOffPitch, pitch<<22); iow32(scr, SrcOffPitch, scr->pitch<<22);
iow32(scr, SrcYX, 0); iow32(scr, SrcYX, 0);
iow32(scr, SrcHeight1Width1, 1); iow32(scr, SrcHeight1Width1, 1);
iow32(scr, SrcYXstart, 0); iow32(scr, SrcYXstart, 0);
@ -793,19 +686,16 @@ initengine(VGAscr *scr)
static int static int
mach64hwfill(VGAscr *scr, Rectangle r, ulong sval) mach64hwfill(VGAscr *scr, Rectangle r, ulong sval)
{ {
ulong pitch;
ulong ctl; ulong ctl;
/* shouldn't happen */ /* shouldn't happen */
if(scr->io == 0x2EC || scr->io == 0x1C8 || scr->io == 0) if(scr->io == 0x2EC || scr->io == 0x1C8 || scr->io == 0)
return 0; return 0;
pitch = Dx(scr->gscreen->r)/8;
ctl = 1|2; /* left-to-right, top-to-bottom */ ctl = 1|2; /* left-to-right, top-to-bottom */
if(scr->gscreen->depth == 24){ if(scr->gscreen->depth == 24){
r.min.x *= 3; r.min.x *= 3;
r.max.x *= 3; r.max.x *= 3;
pitch *= 3;
ctl |= (1<<7)|(((r.min.x/4)%6)<<8); ctl |= (1<<7)|(((r.min.x/4)%6)<<8);
} }
@ -817,7 +707,7 @@ mach64hwfill(VGAscr *scr, Rectangle r, ulong sval)
iow32(scr, ClrCmpCntl, 0x00000000); iow32(scr, ClrCmpCntl, 0x00000000);
iow32(scr, ScLeftRight, 0x1FFF0000); iow32(scr, ScLeftRight, 0x1FFF0000);
iow32(scr, ScTopBottom, 0x1FFF0000); iow32(scr, ScTopBottom, 0x1FFF0000);
iow32(scr, DstOffPitch, pitch<<22); iow32(scr, DstOffPitch, scr->pitch<<22);
iow32(scr, DstCntl, ctl); iow32(scr, DstCntl, ctl);
iow32(scr, DstYX, (r.min.x<<16)|r.min.y); iow32(scr, DstYX, (r.min.x<<16)|r.min.y);
iow32(scr, DstHeightWidth, (Dx(r)<<16)|Dy(r)); iow32(scr, DstHeightWidth, (Dx(r)<<16)|Dy(r));
@ -829,17 +719,14 @@ mach64hwfill(VGAscr *scr, Rectangle r, ulong sval)
static int static int
mach64hwscroll(VGAscr *scr, Rectangle r, Rectangle sr) mach64hwscroll(VGAscr *scr, Rectangle r, Rectangle sr)
{ {
ulong pitch;
Point dp, sp; Point dp, sp;
ulong ctl; ulong ctl;
int dx, dy; int dx, dy;
dx = Dx(r); dx = Dx(r);
dy = Dy(r); dy = Dy(r);
pitch = Dx(scr->gscreen->r)/8;
if(scr->gscreen->depth == 24){ if(scr->gscreen->depth == 24){
dx *= 3; dx *= 3;
pitch *= 3;
r.min.x *= 3; r.min.x *= 3;
sr.min.x *= 3; sr.min.x *= 3;
} }
@ -875,11 +762,11 @@ mach64hwscroll(VGAscr *scr, Rectangle r, Rectangle sr)
iow32(scr, ClrCmpCntl, 0x00000000); iow32(scr, ClrCmpCntl, 0x00000000);
waitforfifo(scr, 8); waitforfifo(scr, 8);
iow32(scr, SrcOffPitch, pitch<<22); iow32(scr, SrcOffPitch, scr->pitch<<22);
iow32(scr, SrcCntl, 0x00000000); iow32(scr, SrcCntl, 0x00000000);
iow32(scr, SrcYX, (sp.x<<16)|sp.y); iow32(scr, SrcYX, (sp.x<<16)|sp.y);
iow32(scr, SrcWidth1, dx); iow32(scr, SrcWidth1, dx);
iow32(scr, DstOffPitch, pitch<<22); iow32(scr, DstOffPitch, scr->pitch<<22);
iow32(scr, DstCntl, ctl); iow32(scr, DstCntl, ctl);
iow32(scr, DstYX, (dp.x<<16)|dp.y); iow32(scr, DstYX, (dp.x<<16)|dp.y);
@ -957,222 +844,6 @@ mach64xxdrawinit(VGAscr *scr)
} }
} }
static void
ovl_configure(VGAscr *scr, Chan *c, char **field)
{
int w, h;
char *format;
w = (int)strtol(field[1], nil, 0);
h = (int)strtol(field[2], nil, 0);
format = field[3];
if (c != ovl_chan)
error(Einuse);
if (strcmp(format, "YUYV"))
error(Eunsupportedformat);
ovl_width = w;
ovl_height = h;
ovl_fib = w * h * sizeof(ushort);
waitforidle(scr);
scr->mmio[mmoffset[BusCntl]] |= 0x08000000; /* Enable regblock 1 */
scr->mmio[mmoffset[OverlayScaleCntl]] =
SCALE_ZERO_EXTEND|SCALE_RED_TEMP_6500K|
SCALE_HORZ_BLEND|SCALE_VERT_BLEND;
scr->mmio[mmoffset[!mach64revb? Buf0Pitch: ScalerBuf0Pitch]] = w;
scr->mmio[mmoffset[CaptureConfig]] =
SCALER_FRAME_READ_MODE_FULL|
SCALER_BUF_MODE_SINGLE|
SCALER_BUF_NEXT_0;
scr->mmio[mmoffset[OverlayKeyCntl]] = !mach64revb?
OVERLAY_MIX_ALWAYS_V|(OVERLAY_EXCLUSIVE_NORMAL << 28):
0x011;
if (mach64type->m64_pro) {
waitforfifo(scr, 6);
/* set the scaler co-efficient registers */
scr->mmio[mmoffset[ScalerColourCntl]] =
(0x00) | (0x10 << 8) | (0x10 << 16);
scr->mmio[mmoffset[ScalerHCoef0]] =
(0x00) | (0x20 << 8);
scr->mmio[mmoffset[ScalerHCoef1]] =
(0x0D) | (0x20 << 8) | (0x06 << 16) | (0x0D << 24);
scr->mmio[mmoffset[ScalerHCoef2]] =
(0x0D) | (0x1C << 8) | (0x0A << 16) | (0x0D << 24);
scr->mmio[mmoffset[ScalerHCoef3]] =
(0x0C) | (0x1A << 8) | (0x0E << 16) | (0x0C << 24);
scr->mmio[mmoffset[ScalerHCoef4]] =
(0x0C) | (0x14 << 8) | (0x14 << 16) | (0x0C << 24);
}
waitforfifo(scr, 3);
scr->mmio[mmoffset[VideoFormat]] = SCALE_IN_YVYU422 |
(!mach64revb? 0xC: 0);
if (mach64overlay == 0)
mach64overlay = scr->storage + 64 * 64 * sizeof(uchar);
scr->mmio[mmoffset[!mach64revb? Buf0Offset: ScalerBuf0Offset]] =
mach64overlay;
}
static void
ovl_enable(VGAscr *scr, Chan *c, char **field)
{
int x, y, w, h;
long h_inc, v_inc;
x = (int)strtol(field[1], nil, 0);
y = (int)strtol(field[2], nil, 0);
w = (int)strtol(field[3], nil, 0);
h = (int)strtol(field[4], nil, 0);
if (x < 0 || x + w > physgscreenr.max.x ||
y < 0 || y + h > physgscreenr.max.y)
error(Ebadarg);
if (c != ovl_chan)
error(Einuse);
if (scr->mmio[mmoffset[CrtcGenCntl]] & 1) { /* double scan enable */
y *= 2;
h *= 2;
}
waitforfifo(scr, 2);
scr->mmio[mmoffset[OverlayYX]] =
((x & 0xFFFF) << 16) | (y & 0xFFFF);
scr->mmio[mmoffset[OverlayYXEnd]] =
(((x + w) & 0xFFFF) << 16) | ((y + h) & 0xFFFF);
h_inc = (ovl_width << 12) / (w >> 1); /* ??? */
v_inc = (ovl_height << 12) / h;
waitforfifo(scr, 2);
scr->mmio[mmoffset[OverlayScaleInc]] =
((h_inc & 0xFFFF) << 16) | (v_inc & 0xFFFF);
scr->mmio[mmoffset[ScalerHeightWidth]] =
((ovl_width & 0xFFFF) << 16) | (ovl_height & 0xFFFF);
waitforidle(scr);
scr->mmio[mmoffset[OverlayScaleCntl]] |=
(SCALE_ENABLE|OVERLAY_ENABLE);
}
static void
ovl_status(VGAscr *scr, Chan *, char **field)
{
pprint("%s: %s %.4uX, VT/GT %s, PRO %s, ovlclock %lud, rev B %s, refclock %ld\n",
scr->dev->name, field[0], mach64type->m64_id,
mach64type->m64_vtgt? "yes": "no",
mach64type->m64_pro? "yes": "no",
mach64type->m64_ovlclock,
mach64revb? "yes": "no",
mach64refclock);
pprint("%s: storage @%.8luX, aperture @%8.ullX, ovl buf @%.8ulX\n",
scr->dev->name, scr->storage, scr->paddr,
mach64overlay);
}
static void
ovl_openctl(VGAscr *, Chan *c, char **)
{
if (ovl_chan)
error(Einuse);
ovl_chan = c;
}
static void
ovl_closectl(VGAscr *scr, Chan *c, char **)
{
if (c != ovl_chan) return;
waitforidle(scr);
scr->mmio[mmoffset[OverlayScaleCntl]] &=
~(SCALE_ENABLE|OVERLAY_ENABLE);
ovl_chan = nil;
ovl_width = ovl_height = ovl_fib = 0;
}
enum
{
CMclosectl,
CMconfigure,
CMenable,
CMopenctl,
CMstatus,
};
static void (*ovl_cmds[])(VGAscr *, Chan *, char **) =
{
[CMclosectl] ovl_closectl,
[CMconfigure] ovl_configure,
[CMenable] ovl_enable,
[CMopenctl] ovl_openctl,
[CMstatus] ovl_status,
};
static Cmdtab mach64xxcmd[] =
{
CMclosectl, "closectl", 1,
CMconfigure, "configure", 4,
CMenable, "enable", 5,
CMopenctl, "openctl", 1,
CMstatus, "status", 1,
};
static void
mach64xxovlctl(VGAscr *scr, Chan *c, void *a, int n)
{
Cmdbuf *cb;
Cmdtab *ct;
if(!mach64type->m64_vtgt)
error(Enodev);
if(!scr->overlayinit){
scr->overlayinit = 1;
init_overlayclock(scr);
}
cb = parsecmd(a, n);
if(waserror()){
free(cb);
nexterror();
}
ct = lookupcmd(cb, mach64xxcmd, nelem(mach64xxcmd));
ovl_cmds[ct->index](scr, c, cb->f);
poperror();
free(cb);
}
static int
mach64xxovlwrite(VGAscr *scr, void *a, int len, vlong offs)
{
uchar *src;
int _len;
if (ovl_chan == nil) return len; /* Acts as a /dev/null */
/* Calculate the destination address */
_len = len;
src = (uchar *)a;
while (len > 0) {
ulong _offs;
int nb;
_offs = (ulong)(offs % ovl_fib);
nb = (_offs + len > ovl_fib)? ovl_fib - _offs: len;
memmove((uchar *)scr->vaddr + mach64overlay + _offs,
src, nb);
offs += nb;
src += nb;
len -= nb;
}
return _len;
}
VGAdev vgamach64xxdev = { VGAdev vgamach64xxdev = {
"mach64xx", "mach64xx",
@ -1181,9 +852,6 @@ VGAdev vgamach64xxdev = {
0, /* page */ 0, /* page */
mach64xxlinear, /* linear */ mach64xxlinear, /* linear */
mach64xxdrawinit, /* drawinit */ mach64xxdrawinit, /* drawinit */
0,
mach64xxovlctl, /* overlay control */
mach64xxovlwrite, /* write the overlay */
}; };
VGAcur vgamach64xxcur = { VGAcur vgamach64xxcur = {
@ -1193,7 +861,5 @@ VGAcur vgamach64xxcur = {
mach64xxcurdisable, /* disable */ mach64xxcurdisable, /* disable */
mach64xxcurload, /* load */ mach64xxcurload, /* load */
mach64xxcurmove, /* move */ mach64xxcurmove, /* move */
1 /* doespanning */
}; };

View file

@ -405,7 +405,6 @@ static int
mga4xxscroll(VGAscr *scr, Rectangle dr, Rectangle sr) mga4xxscroll(VGAscr *scr, Rectangle dr, Rectangle sr)
{ {
uchar * mga; uchar * mga;
int pitch;
int width, height; int width, height;
ulong start, end, sgn; ulong start, end, sgn;
Point sp, dp; Point sp, dp;
@ -421,7 +420,6 @@ mga4xxscroll(VGAscr *scr, Rectangle dr, Rectangle sr)
if(eqpt(sp, dp)) if(eqpt(sp, dp))
return 1; return 1;
pitch = Dx(scr->gscreen->r);
width = Dx(sr); width = Dx(sr);
height = Dy(sr); height = Dy(sr);
sgn = 0; sgn = 0;
@ -433,7 +431,7 @@ mga4xxscroll(VGAscr *scr, Rectangle dr, Rectangle sr)
} }
width--; width--;
start = end = sp.x + (sp.y * pitch); start = end = sp.x + (sp.y * scr->width);
if(dp.x > sp.x && dp.x < sp.x + width){ if(dp.x > sp.x && dp.x < sp.x + width){
start += width; start += width;
@ -445,7 +443,7 @@ mga4xxscroll(VGAscr *scr, Rectangle dr, Rectangle sr)
mga_fifo(mga, 8); mga_fifo(mga, 8);
mgawrite32(mga, DWGCTL, 0); mgawrite32(mga, DWGCTL, 0);
mgawrite32(mga, SGN, sgn); mgawrite32(mga, SGN, sgn);
mgawrite32(mga, AR5, sgn & SGN_UP ? -pitch : pitch); mgawrite32(mga, AR5, sgn & SGN_UP ? -scr->width : scr->width);
mgawrite32(mga, AR0, end); mgawrite32(mga, AR0, end);
mgawrite32(mga, AR3, start); mgawrite32(mga, AR3, start);
mgawrite32(mga, FXBNDRY, ((dp.x + width) << 16) | dp.x); mgawrite32(mga, FXBNDRY, ((dp.x + width) << 16) | dp.x);

View file

@ -376,8 +376,8 @@ neomagichwfill(VGAscr *scr, Rectangle r, ulong sval)
| NEO_BC3_SKIP_MAPPING | NEO_BC3_SKIP_MAPPING
| GXcopy; | GXcopy;
mmio[DstStartOff] = scr->paddr mmio[DstStartOff] = scr->paddr
+ r.min.y*scr->gscreen->width*sizeof(ulong) + r.min.y*scr->pitch
+ r.min.x*scr->gscreen->depth/BI2BY; + r.min.x*scr->bpp;
mmio[XYExt] = (Dy(r) << 16) | (Dx(r) & 0xffff); mmio[XYExt] = (Dy(r) << 16) | (Dx(r) & 0xffff);
waitforidle(scr); waitforidle(scr);
return 1; return 1;
@ -387,13 +387,9 @@ static int
neomagichwscroll(VGAscr *scr, Rectangle r, Rectangle sr) neomagichwscroll(VGAscr *scr, Rectangle r, Rectangle sr)
{ {
ulong *mmio; ulong *mmio;
int pitch, pixel;
mmio = scr->mmio; mmio = scr->mmio;
pitch = scr->gscreen->width*sizeof(ulong);
pixel = scr->gscreen->depth/BI2BY;
waitforfifo(scr, 4); waitforfifo(scr, 4);
if (r.min.y < sr.min.y || (r.min.y == sr.min.y && r.min.x < sr.min.x)) { if (r.min.y < sr.min.y || (r.min.y == sr.min.y && r.min.x < sr.min.x)) {
/* start from upper-left */ /* start from upper-left */
@ -402,9 +398,9 @@ neomagichwscroll(VGAscr *scr, Rectangle r, Rectangle sr)
| NEO_BC3_SKIP_MAPPING | NEO_BC3_SKIP_MAPPING
| GXcopy; | GXcopy;
mmio[SrcStartOff] = scr->paddr mmio[SrcStartOff] = scr->paddr
+ sr.min.y*pitch + sr.min.x*pixel; + sr.min.y*scr->pitch + sr.min.x*scr->bpp;
mmio[DstStartOff] = scr->paddr mmio[DstStartOff] = scr->paddr
+ r.min.y*pitch + r.min.x*pixel; + r.min.y*scr->pitch + r.min.x*scr->bpp;
} else { } else {
/* start from lower-right */ /* start from lower-right */
mmio[BltCntl] = neomagicbltflags mmio[BltCntl] = neomagicbltflags
@ -415,9 +411,9 @@ neomagichwscroll(VGAscr *scr, Rectangle r, Rectangle sr)
| NEO_BC3_SKIP_MAPPING | NEO_BC3_SKIP_MAPPING
| GXcopy; | GXcopy;
mmio[SrcStartOff] = scr->paddr mmio[SrcStartOff] = scr->paddr
+ (sr.max.y-1)*pitch + (sr.max.x-1)*pixel; + (sr.max.y-1)*scr->pitch + (sr.max.x-1)*scr->bpp;
mmio[DstStartOff] = scr->paddr mmio[DstStartOff] = scr->paddr
+ (r.max.y-1)*pitch + (r.max.x-1)*pixel; + (r.max.y-1)*scr->pitch + (r.max.x-1)*scr->bpp;
} }
mmio[XYExt] = (Dy(r) << 16) | (Dx(r) & 0xffff); mmio[XYExt] = (Dy(r) << 16) | (Dx(r) & 0xffff);
waitforidle(scr); waitforidle(scr);
@ -428,12 +424,10 @@ static void
neomagicdrawinit(VGAscr *scr) neomagicdrawinit(VGAscr *scr)
{ {
ulong *mmio; ulong *mmio;
uint bltmode, pitch; uint bltmode;
mmio = scr->mmio; mmio = scr->mmio;
pitch = scr->gscreen->width*sizeof(ulong);
neomagicbltflags = bltmode = 0; neomagicbltflags = bltmode = 0;
switch(scr->gscreen->depth) { switch(scr->gscreen->depth) {
@ -450,7 +444,7 @@ neomagicdrawinit(VGAscr *scr)
return; return;
} }
switch(Dx(scr->gscreen->r)) { switch(scr->width) {
case 320: case 320:
bltmode |= NEO_MODE1_X_320; bltmode |= NEO_MODE1_X_320;
neomagicbltflags |= NEO_BC1_X_320; neomagicbltflags |= NEO_BC1_X_320;
@ -486,7 +480,7 @@ neomagicdrawinit(VGAscr *scr)
waitforidle(scr); waitforidle(scr);
mmio[BltStat] = bltmode << 16; mmio[BltStat] = bltmode << 16;
mmio[Pitch] = (pitch << 16) | (pitch & 0xffff); mmio[Pitch] = (scr->pitch << 16) | (scr->pitch & 0xffff);
scr->fill = neomagichwfill; scr->fill = neomagichwfill;
scr->scroll = neomagichwscroll; scr->scroll = neomagichwscroll;

View file

@ -343,13 +343,11 @@ static int
nvresetgraphics(VGAscr *scr) nvresetgraphics(VGAscr *scr)
{ {
ulong surfaceFormat, patternFormat, rectFormat, lineFormat; ulong surfaceFormat, patternFormat, rectFormat, lineFormat;
int pitch, i; int i;
if(scr->paddr == 0) if(scr->paddr == 0)
return -1; return -1;
pitch = scr->gscreen->width*sizeof(ulong);
/* /*
* DMA is at the end of the virtual window, * DMA is at the end of the virtual window,
* but we might have cut it short when mapping it. * but we might have cut it short when mapping it.
@ -416,7 +414,7 @@ nvresetgraphics(VGAscr *scr)
nvdmastart(scr, SURFACE_FORMAT, 4); nvdmastart(scr, SURFACE_FORMAT, 4);
nvdmanext(surfaceFormat); nvdmanext(surfaceFormat);
nvdmanext(pitch | (pitch << 16)); nvdmanext(scr->pitch | (scr->pitch << 16));
nvdmanext(0); nvdmanext(0);
nvdmanext(0); nvdmanext(0);

View file

@ -350,7 +350,7 @@ radeonscroll(VGAscr*scr, Rectangle dst, Rectangle src)
static void static void
radeondrawinit(VGAscr*scr) radeondrawinit(VGAscr*scr)
{ {
ulong bpp, dtype, i, pitch, clock_cntl_index, mclk_cntl, rbbm_soft_reset; ulong dtype, i, clock_cntl_index, mclk_cntl, rbbm_soft_reset;
if (scr->mmio == 0) if (scr->mmio == 0)
return; return;
@ -359,19 +359,15 @@ radeondrawinit(VGAscr*scr)
case 6: case 6:
case 8: case 8:
dtype = 2; dtype = 2;
bpp = 1;
break; break;
case 15: case 15:
dtype = 3; dtype = 3;
bpp = 2;
break; break;
case 16: case 16:
dtype = 4; dtype = 4;
bpp = 2;
break; break;
case 32: case 32:
dtype = 6; dtype = 6;
bpp = 4;
break; break;
default: default:
return; return;
@ -413,11 +409,10 @@ radeondrawinit(VGAscr*scr)
radeonwaitfifo(scr, 1); radeonwaitfifo(scr, 1);
OUTREG(scr->mmio, RB2D_DSTCACHE_MODE, 0); OUTREG(scr->mmio, RB2D_DSTCACHE_MODE, 0);
pitch = Dx(scr->gscreen->r) * bpp;
radeonwaitfifo(scr, 4); radeonwaitfifo(scr, 4);
OUTREG(scr->mmio, DEFAULT_PITCH, pitch); OUTREG(scr->mmio, DEFAULT_PITCH, scr->pitch);
OUTREG(scr->mmio, DST_PITCH, pitch); OUTREG(scr->mmio, DST_PITCH, scr->pitch);
OUTREG(scr->mmio, SRC_PITCH, pitch); OUTREG(scr->mmio, SRC_PITCH, scr->pitch);
OUTREG(scr->mmio, DST_PITCH_OFFSET_C, 0); OUTREG(scr->mmio, DST_PITCH_OFFSET_C, 0);
radeonwaitfifo(scr, 3); radeonwaitfifo(scr, 3);
@ -501,5 +496,4 @@ VGAcur vgaradeoncur = {
radeoncurdisable, radeoncurdisable,
radeoncurload, radeoncurload,
radeoncurmove, radeoncurmove,
0 /* doespanning */
}; };

View file

@ -309,7 +309,7 @@ s3enable(VGAscr* scr)
* Find a place for the cursor data in display memory. * Find a place for the cursor data in display memory.
* Must be on a 1024-byte boundary. * Must be on a 1024-byte boundary.
*/ */
storage = (scr->gscreen->width*sizeof(ulong)*scr->gscreen->r.max.y+1023)/1024; storage = (scr->pitch*scr->height+1023)/1024;
vgaxo(Crtx, 0x4C, storage>>8); vgaxo(Crtx, 0x4C, storage>>8);
vgaxo(Crtx, 0x4D, storage & 0xFF); vgaxo(Crtx, 0x4D, storage & 0xFF);
storage *= 1024; storage *= 1024;
@ -420,14 +420,12 @@ hwscroll(VGAscr *scr, Rectangle r, Rectangle sr)
{ {
enum { Bitbltop = 0xCC }; /* copy source */ enum { Bitbltop = 0xCC }; /* copy source */
ulong *mmio; ulong *mmio;
ulong cmd, stride; ulong cmd;
Point dp, sp; Point dp, sp;
int did, d; int did;
d = scr->gscreen->depth; did = (scr->gscreen->depth-8)/8;
did = (d-8)/8;
cmd = 0x00000020|(Bitbltop<<17)|(did<<2); cmd = 0x00000020|(Bitbltop<<17)|(did<<2);
stride = Dx(scr->gscreen->r)*d/8;
if(r.min.x <= sr.min.x){ if(r.min.x <= sr.min.x){
cmd |= 1<<25; cmd |= 1<<25;
@ -452,7 +450,7 @@ hwscroll(VGAscr *scr, Rectangle r, Rectangle sr)
waitforfifo(scr, 7); waitforfifo(scr, 7);
mmio[SrcBase] = scr->paddr; mmio[SrcBase] = scr->paddr;
mmio[DstBase] = scr->paddr; mmio[DstBase] = scr->paddr;
mmio[Stride] = (stride<<16)|stride; mmio[Stride] = (scr->pitch<<16)|scr->pitch;
mmio[WidthHeight] = ((Dx(r)-1)<<16)|Dy(r); mmio[WidthHeight] = ((Dx(r)-1)<<16)|Dy(r);
mmio[SrcXY] = (sp.x<<16)|sp.y; mmio[SrcXY] = (sp.x<<16)|sp.y;
mmio[DestXY] = (dp.x<<16)|dp.y; mmio[DestXY] = (dp.x<<16)|dp.y;
@ -466,20 +464,18 @@ hwfill(VGAscr *scr, Rectangle r, ulong sval)
{ {
enum { Bitbltop = 0xCC }; /* copy source */ enum { Bitbltop = 0xCC }; /* copy source */
ulong *mmio; ulong *mmio;
ulong cmd, stride; ulong cmd;
int did, d; int did;
d = scr->gscreen->depth; did = (scr->gscreen->depth-8)/8;
did = (d-8)/8;
cmd = 0x16000120|(Bitbltop<<17)|(did<<2); cmd = 0x16000120|(Bitbltop<<17)|(did<<2);
stride = Dx(scr->gscreen->r)*d/8;
mmio = scr->mmio; mmio = scr->mmio;
waitforlinearfifo(scr); waitforlinearfifo(scr);
waitforfifo(scr, 8); waitforfifo(scr, 8);
mmio[SrcBase] = scr->paddr; mmio[SrcBase] = scr->paddr;
mmio[DstBase] = scr->paddr; mmio[DstBase] = scr->paddr;
mmio[DstBase] = scr->paddr; mmio[DstBase] = scr->paddr;
mmio[Stride] = (stride<<16)|stride; mmio[Stride] = (scr->pitch<<16)|scr->pitch;
mmio[FgrdData] = sval; mmio[FgrdData] = sval;
mmio[WidthHeight] = ((Dx(r)-1)<<16)|Dy(r); mmio[WidthHeight] = ((Dx(r)-1)<<16)|Dy(r);
mmio[DestXY] = (r.min.x<<16)|r.min.y; mmio[DestXY] = (r.min.x<<16)|r.min.y;

View file

@ -540,7 +540,7 @@ savageinit(VGAscr *scr)
/* set bitmap descriptors */ /* set bitmap descriptors */
bd = (scr->gscreen->depth<<DepthShift) | bd = (scr->gscreen->depth<<DepthShift) |
(Dx(scr->gscreen->r)<<StrideShift) | BlockWriteDis (scr->width<<StrideShift) | BlockWriteDis
| BDS64; | BDS64;
*(ulong*)(mmio+GBD1) = 0; *(ulong*)(mmio+GBD1) = 0;

View file

@ -459,14 +459,9 @@ t2r4blank(VGAscr *scr, int blank)
static void static void
t2r4drawinit(VGAscr *scr) t2r4drawinit(VGAscr *scr)
{ {
ulong pitch;
int depth;
int fmt; int fmt;
ulong *d; ulong *d;
pitch = Dx(scr->gscreen->r);
depth = scr->gscreen->depth;
switch(scr->gscreen->chan){ switch(scr->gscreen->chan){
case RGB16: case RGB16:
fmt = 3; fmt = 3;
@ -488,8 +483,8 @@ t2r4drawinit(VGAscr *scr)
d[BufCtl] = fmt<<24; d[BufCtl] = fmt<<24;
d[DeSorg] = 0; d[DeSorg] = 0;
d[DeDorg] = 0; d[DeDorg] = 0;
d[DeSptch] = (pitch*depth)/8; d[DeSptch] = scr->pitch;
d[DeDptch] = (pitch*depth)/8; d[DeDptch] = scr->pitch;
d[CmdClp] = 0; /* 2 = inside rectangle */ d[CmdClp] = 0; /* 2 = inside rectangle */
d[Mask] = ~0; d[Mask] = ~0;
d[DeKey] = 0; d[DeKey] = 0;