diff --git a/sys/src/9/pc/devvga.c b/sys/src/9/pc/devvga.c index ae28fdd79..8cd2f9583 100644 --- a/sys/src/9/pc/devvga.c +++ b/sys/src/9/pc/devvga.c @@ -368,11 +368,6 @@ vgactl(Cmdbuf *cb) if(screenaperture(size, align) < 0) error("not enough free address space"); return; -/* - case CMmemset: - memset((void*)strtoul(cb->f[1], 0, 0), atoi(cb->f[2]), atoi(cb->f[3])); - return; -*/ case CMblank: drawblankscreen(1); diff --git a/sys/src/9/pc/screen.c b/sys/src/9/pc/screen.c index d1d4ae729..b585c36ce 100644 --- a/sys/src/9/pc/screen.c +++ b/sys/src/9/pc/screen.c @@ -19,7 +19,6 @@ Point ZP = {0, 0}; Rectangle physgscreenr; -Memdata gscreendata; Memimage *gscreen; VGAscr vgascreen[1]; @@ -40,13 +39,18 @@ Cursor arrow = { int didswcursorinit; -static void *softscreen; - int -screensize(int x, int y, int z, ulong chan) +screensize(int x, int y, int, ulong chan) { VGAscr *scr; - void *oldsoft; + + qlock(&drawlock); + if(waserror()){ + qunlock(&drawlock); + nexterror(); + } + + memimageinit(); lock(&vgascreenlock); if(waserror()){ @@ -54,54 +58,51 @@ screensize(int x, int y, int z, ulong chan) nexterror(); } - memimageinit(); scr = &vgascreen[0]; - oldsoft = softscreen; + scr->gscreendata = nil; + scr->gscreen = nil; + if(gscreen){ + freememimage(gscreen); + gscreen = nil; + } if(scr->paddr == 0){ - int width = (x*z)/BI2WD; - void *p; - - p = xalloc(width*BY2WD*y); - if(p == nil) - error("no memory for vga soft screen"); - gscreendata.bdata = softscreen = p; + gscreen = allocmemimage(Rect(0,0,x,y), chan); if(scr->dev && scr->dev->page){ scr->vaddr = KADDR(VGAMEM()); scr->apsize = 1<<16; } scr->useflush = 1; - } - else{ - gscreendata.bdata = scr->vaddr; + }else{ + static Memdata md; + + md.ref = 1; + md.bdata = scr->vaddr; + gscreen = allocmemimaged(Rect(0,0,x,y), chan, &md); scr->useflush = scr->dev && scr->dev->flush; } - - scr->gscreen = nil; - if(gscreen) - freememimage(gscreen); - gscreen = allocmemimaged(Rect(0,0,x,y), chan, &gscreendata); if(gscreen == nil) error("no memory for vga memimage"); - vgaimageinit(chan); scr->palettedepth = 6; /* default */ - scr->gscreendata = &gscreendata; scr->memdefont = getmemdefont(); scr->gscreen = gscreen; + scr->gscreendata = gscreen->data; physgscreenr = gscreen->r; + + vgaimageinit(chan); + unlock(&vgascreenlock); poperror(); - if(oldsoft) - xfree(oldsoft); - - memimagedraw(gscreen, gscreen->r, memblack, ZP, nil, ZP, S); - flushmemscreen(gscreen->r); + drawcmap(); if(didswcursorinit) swcursorinit(); - drawcmap(); + + qunlock(&drawlock); + poperror(); + return 0; } @@ -152,8 +153,17 @@ attachscreen(Rectangle* r, ulong* chan, int* d, int* width, int *softscreen) *chan = scr->gscreen->chan; *d = scr->gscreen->depth; *width = scr->gscreen->width; - *softscreen = scr->useflush; - + if(scr->gscreendata->allocd){ + /* + * we use a memimage as softscreen. devdraw will create its own + * screen image on the backing store of that image. when our gscreen + * and devdraws screenimage gets freed, the imagedata will + * be released. + */ + *softscreen = 0xa110c; + scr->gscreendata->ref++; + } else + *softscreen = scr->useflush ? 1 : 0; return scr->gscreendata->bdata; } @@ -168,12 +178,12 @@ flushmemscreen(Rectangle r) int y, len, incs, off, page; scr = &vgascreen[0]; + if(scr->gscreen == nil || scr->useflush == 0) + return; if(scr->dev && scr->dev->flush){ scr->dev->flush(scr, r); return; } - if(scr->gscreen == nil || scr->useflush == 0) - return; if(scr->dev == nil || scr->dev->page == nil) return; @@ -185,7 +195,6 @@ flushmemscreen(Rectangle r) switch(scr->gscreen->depth){ default: len = 0; - panic("flushmemscreen: depth\n"); break; case 8: len = Dx(r); @@ -358,36 +367,31 @@ hwdraw(Memdrawparam *par) { VGAscr *scr; Memimage *dst, *src, *mask; + Memdata *scrd; int m; - if(hwaccel == 0) - return 0; - scr = &vgascreen[0]; - if((dst=par->dst) == nil || dst->data == nil) + scrd = scr->gscreendata; + if(scr->gscreen == nil || scrd == nil) return 0; - if((src=par->src) == nil || src->data == nil) + if((dst = par->dst) == nil || dst->data == nil) return 0; - if((mask=par->mask) == nil || mask->data == nil) - return 0; - + if((src = par->src) && src->data == nil) + src = nil; + if((mask = par->mask) && mask->data == nil) + mask = nil; if(scr->cur == &swcursor){ - /* - * always calling swcursorhide here doesn't cure - * leaving cursor tracks nor failing to refresh menus - * with the latest libmemdraw/draw.c. - */ - if(dst->data->bdata == gscreendata.bdata) + if(dst->data->bdata == scrd->bdata) swcursoravoid(par->r); - if(src->data->bdata == gscreendata.bdata) + if(src && src->data->bdata == scrd->bdata) swcursoravoid(par->sr); - if(mask->data->bdata == gscreendata.bdata) + if(mask && mask->data->bdata == scrd->bdata) swcursoravoid(par->mr); } - - if(dst->data->bdata != gscreendata.bdata) + if(hwaccel == 0) + return 0; + if(dst->data->bdata != scrd->bdata || src == nil || mask == nil) return 0; - if(scr->fill==nil && scr->scroll==nil) return 0; @@ -607,29 +611,6 @@ swcursordraw(void) swvisible = 1; } -/* - * Need to lock drawlock for ourselves. - */ -void -swenable(VGAscr*) -{ - swenabled = 1; - if(canqlock(&drawlock)){ - swcursordraw(); - qunlock(&drawlock); - } -} - -void -swdisable(VGAscr*) -{ - swenabled = 0; - if(canqlock(&drawlock)){ - swcursorhide(); - qunlock(&drawlock); - } -} - void swload(VGAscr*, Cursor *curs) { @@ -693,7 +674,7 @@ swcursorclock(void) void swcursorinit(void) { - static int init, warned; + static int init; VGAscr *scr; didswcursorinit = 1; @@ -701,42 +682,56 @@ swcursorinit(void) init = 1; addclock0link(swcursorclock, 10); } - scr = &vgascreen[0]; - if(scr==nil || scr->gscreen==nil) - return; - if(scr->dev == nil || scr->dev->linear == nil){ - if(!warned){ - print("cannot use software cursor on non-linear vga screen\n"); - warned = 1; - } + scr = &vgascreen[0]; + if(scr->gscreen==nil) return; - } if(swback){ freememimage(swback); freememimage(swmask); freememimage(swmask1); freememimage(swimg); - freememimage(swimg1); + freememimage(swimg1); } - swback = allocmemimage(Rect(0,0,32,32), gscreen->chan); swmask = allocmemimage(Rect(0,0,16,16), GREY8); swmask1 = allocmemimage(Rect(0,0,16,16), GREY1); swimg = allocmemimage(Rect(0,0,16,16), GREY8); swimg1 = allocmemimage(Rect(0,0,16,16), GREY1); - if(swback==nil || swmask==nil || swmask1==nil || swimg==nil || swimg1 == nil){ + if(swback==nil || swmask==nil || swmask1==nil || swimg==nil || swimg1 == nil) print("software cursor: allocmemimage fails"); - return; - } - + memfillcolor(swback, DTransparent); memfillcolor(swmask, DOpaque); memfillcolor(swmask1, DOpaque); memfillcolor(swimg, DBlack); memfillcolor(swimg1, DBlack); } +/* + * Need to lock drawlock for ourselves. + */ +void +swenable(VGAscr *scr) +{ + swenabled = 1; + if(canqlock(&drawlock)){ + swload(scr, &arrow); + swcursordraw(); + qunlock(&drawlock); + } +} + +void +swdisable(VGAscr*) +{ + swenabled = 0; + if(canqlock(&drawlock)){ + swcursorhide(); + qunlock(&drawlock); + } +} + VGAcur swcursor = { "soft", diff --git a/sys/src/9/pc/vga.c b/sys/src/9/pc/vga.c index 587d8c185..265b8455e 100644 --- a/sys/src/9/pc/vga.c +++ b/sys/src/9/pc/vga.c @@ -12,8 +12,8 @@ #include #include "screen.h" -static Memimage* back; static Memimage *conscol; +static Memimage *back; static Point curpos; static Rectangle window; @@ -23,25 +23,10 @@ Lock vgascreenlock; int drawdebug; void -vgaimageinit(ulong chan) +vgaimageinit(ulong) { - if(back == nil){ - back = allocmemimage(Rect(0,0,1,1), chan); /* RSC BUG */ - if(back == nil) - panic("back alloc"); /* RSC BUG */ - back->flags |= Frepl; - back->clipr = Rect(-0x3FFFFFF, -0x3FFFFFF, 0x3FFFFFF, 0x3FFFFFF); - memfillcolor(back, DBlack); - } - - if(conscol == nil){ - conscol = allocmemimage(Rect(0,0,1,1), chan); /* RSC BUG */ - if(conscol == nil) - panic("conscol alloc"); /* RSC BUG */ - conscol->flags |= Frepl; - conscol->clipr = Rect(-0x3FFFFFF, -0x3FFFFFF, 0x3FFFFFF, 0x3FFFFFF); - memfillcolor(conscol, DWhite); - } + conscol = memblack; + back = memwhite; } static void @@ -69,13 +54,11 @@ vgascreenputc(VGAscr* scr, char* buf, Rectangle *flushr) int h, w, pos; Rectangle r; -// drawdebug = 1; if(xp < xbuf || xp >= &xbuf[sizeof(xbuf)]) xp = xbuf; h = scr->memdefont->height; switch(buf[0]){ - case '\n': if(curpos.y+h >= window.max.y){ vgascroll(scr); @@ -100,7 +83,7 @@ vgascreenputc(VGAscr* scr, char* buf, Rectangle *flushr) pos = 4-(pos%4); *xp++ = curpos.x; r = Rect(curpos.x, curpos.y, curpos.x+pos*w, curpos.y + h); - memimagedraw(scr->gscreen, r, back, back->r.min, nil, back->r.min, S); + memimagedraw(scr->gscreen, r, back, ZP, nil, ZP, S); curpos.x += pos*w; break; @@ -109,7 +92,7 @@ vgascreenputc(VGAscr* scr, char* buf, Rectangle *flushr) break; xp--; r = Rect(*xp, curpos.y, curpos.x, curpos.y+h); - memimagedraw(scr->gscreen, r, back, back->r.min, nil, ZP, S); + memimagedraw(scr->gscreen, r, back, r.min, nil, ZP, S); combinerect(flushr, r); curpos.x = *xp; break; @@ -126,12 +109,11 @@ vgascreenputc(VGAscr* scr, char* buf, Rectangle *flushr) *xp++ = curpos.x; r = Rect(curpos.x, curpos.y, curpos.x+w, curpos.y+h); - memimagedraw(scr->gscreen, r, back, back->r.min, nil, back->r.min, S); + memimagedraw(scr->gscreen, r, back, r.min, nil, ZP, S); memimagestring(scr->gscreen, curpos, conscol, ZP, scr->memdefont, buf); combinerect(flushr, r); curpos.x += w; } -// drawdebug = 0; } static void @@ -184,19 +166,61 @@ vgascreenputs(char* s, int n) unlock(&vgascreenlock); } +static Memimage* +mkcolor(Memimage *screen, ulong color) +{ + Memimage *i; + + if(i = allocmemimage(Rect(0,0,1,1), screen->chan)){ + i->flags |= Frepl; + i->clipr = screen->r; + memfillcolor(i, color); + } + return i; +} + void vgascreenwin(VGAscr* scr) { - int h, w; + Memimage *i; + Rectangle r; + Point p; + int h; + qlock(&drawlock); + h = scr->memdefont->height; - w = scr->memdefont->info[' '].width; + r = scr->gscreen->r; - window = insetrect(scr->gscreen->r, 48); - window.max.x = window.min.x+((window.max.x-window.min.x)/w)*w; - window.max.y = window.min.y+((window.max.y-window.min.y)/h)*h; + if(i = mkcolor(scr->gscreen, 0x444488FF)){ + memimagedraw(scr->gscreen, r, i, ZP, nil, ZP, S); + freememimage(i); + } + + window = insetrect(r, 20); + memimagedraw(scr->gscreen, window, conscol, ZP, memopaque, ZP, S); + window = insetrect(window, 4); + memimagedraw(scr->gscreen, window, back, ZP, memopaque, ZP, S); + + if(i = mkcolor(scr->gscreen, 0xAAAAAAFF)){ + memimagedraw(scr->gscreen, Rect(window.min.x, window.min.y, + window.max.x, window.min.y+h+5+6), i, ZP, nil, ZP, S); + freememimage(i); + + window = insetrect(window, 5); + p = addpt(window.min, Pt(10, 0)); + memimagestring(scr->gscreen, p, memblack, ZP, scr->memdefont, " Plan 9 Console "); + window.min.y += h+6; + } else + window = insetrect(window, 5); + + window.max.y = window.min.y+(Dy(window)/h)*h; curpos = window.min; + flushmemscreen(r); + + qunlock(&drawlock); + screenputs = vgascreenputs; } @@ -240,24 +264,3 @@ addvgaseg(char *name, ulong pa, ulong size) seg.size = size; addphysseg(&seg); } - -void -cornerstring(char *s) -{ - int h, w; - VGAscr *scr; - Rectangle r; - Point p; - - scr = &vgascreen[0]; - if(scr->vaddr == nil || screenputs != vgascreenputs) - return; - p = memsubfontwidth(scr->memdefont, s); - w = p.x; - h = scr->memdefont->height; - - r = Rect(0, 0, w, h); - memimagedraw(scr->gscreen, r, back, back->r.min, nil, back->r.min, S); - memimagestring(scr->gscreen, r.min, conscol, ZP, scr->memdefont, s); -// flushmemscreen(r); -} diff --git a/sys/src/9/pc/vgavesa.c b/sys/src/9/pc/vgavesa.c index 3fe1bfb17..c2ea65138 100644 --- a/sys/src/9/pc/vgavesa.c +++ b/sys/src/9/pc/vgavesa.c @@ -62,15 +62,19 @@ vbecall(Ureg *u) nexterror(); } pa = PADDR(RMBUF); - /* TODO: check read and write return values */ - devtab[cmem->type]->write(cmem, modebuf, sizeof modebuf, pa); - u->trap = 0x10; - devtab[creg->type]->write(creg, u, sizeof *u, 0); + if(devtab[cmem->type]->write(cmem, modebuf, sizeof(modebuf), pa) != sizeof(modebuf)) + error("write modebuf"); - devtab[creg->type]->read(creg, u, sizeof *u, 0); + u->trap = 0x10; + if(devtab[creg->type]->write(creg, u, sizeof(*u), 0) != sizeof(*u)) + error("write ureg"); + if(devtab[creg->type]->read(creg, u, sizeof(*u), 0) != sizeof(*u)) + error("read ureg"); if((u->ax&0xFFFF) != 0x004F) error("vesa bios error"); - devtab[cmem->type]->read(cmem, modebuf, sizeof modebuf, pa); + + if(devtab[cmem->type]->read(cmem, modebuf, sizeof(modebuf), pa) != sizeof(modebuf)) + error("read modebuf"); poperror(); cclose(creg); @@ -124,7 +128,7 @@ vesalinear(VGAscr *scr, int, int) Pcidev *pci; if(hardscreen) { - scr->vaddr = 0; + scr->vaddr = hardscreen; scr->paddr = scr->apsize = 0; return; } @@ -180,7 +184,6 @@ vesalinear(VGAscr *scr, int, int) if(Usesoftscreen){ hardscreen = scr->vaddr; - scr->vaddr = 0; scr->paddr = scr->apsize = 0; } } diff --git a/sys/src/9/port/devdraw.c b/sys/src/9/port/devdraw.c index d11ab05a2..017942194 100644 --- a/sys/src/9/port/devdraw.c +++ b/sys/src/9/port/devdraw.c @@ -365,9 +365,8 @@ addflush(Rectangle r) int abb, ar, anbb; Rectangle nbb; - if(sdraw.softscreen==0 || !rectclip(&r, screenimage->r)) + if(sdraw.softscreen==0 || screenimage == nil || !rectclip(&r, screenimage->r)) return; - if(flushrect.min.x >= flushrect.max.x){ flushrect = r; waste = 0; @@ -413,13 +412,7 @@ dstflush(int dstid, Memimage *dst, Rectangle r) combinerect(&flushrect, r); return; } - /* how can this happen? -rsc, dec 12 2002 */ - if(dst == 0){ - print("nil dstflush\n"); - return; - } - l = dst->layer; - if(l == nil) + if(screenimage == nil || dst == nil || (l = dst->layer) == nil) return; do{ if(l->screen->image->data != screenimage->data) @@ -433,7 +426,7 @@ dstflush(int dstid, Memimage *dst, Rectangle r) void drawflush(void) { - if(flushrect.min.x < flushrect.max.x) + if(screenimage && flushrect.min.x < flushrect.max.x) flushmemscreen(flushrect); flushrect = Rect(10000, 10000, -10000, -10000); } @@ -676,12 +669,10 @@ drawfreedimage(DImage *dimage) drawfreedimage(dimage->fromname); goto Return; } -// if(dimage->image == screenimage) /* don't free the display */ -// goto Return; ds = dimage->dscreen; if(ds){ l = dimage->image; - if(l->data == screenimage->data) + if(screenimage && l->data == screenimage->data) addflush(l->layer->screenr); if(l->layer->refreshfn == drawrefresh) /* else true owner will clean up */ free(l->layer->refreshptr); @@ -929,26 +920,36 @@ makescreenimage(void) Memdata *md; Memimage *i; Rectangle r; + uchar *data; - md = malloc(sizeof *md); - if(md == nil) - return nil; - md->allocd = 1; - md->base = nil; - md->bdata = attachscreen(&r, &chan, &depth, &width, &sdraw.softscreen); - if(md->bdata == nil){ - free(md); - return nil; - } - md->ref = 1; - i = allocmemimaged(r, chan, md); - if(i == nil){ - free(md); + if((data = attachscreen(&r, &chan, &depth, &width, &sdraw.softscreen)) == nil) return nil; + if(sdraw.softscreen == 0xa110c){ + /* hack: softscreen is memimage. */ + md = *((Memdata**)(data - sizeof(ulong) - sizeof(Memdata*))); + + assert(md->bdata == data); + assert(md->ref > 1); + assert(md->allocd); + + if((i = allocmemimaged(r, chan, md)) == nil){ + md->ref--; + return nil; + } + }else{ + if((md = malloc(sizeof *md)) == nil) + return nil; + md->allocd = 1; + md->base = nil; + md->bdata = data; + md->ref = 1; + if((i = allocmemimaged(r, chan, md)) == nil){ + free(md); + return nil; + } } i->width = width; i->clipr = r; - di = allocdimage(i); if(di == nil){ freememimage(i); /* frees md */ @@ -1859,7 +1860,7 @@ drawmesg(Client *client, void *av, int n) if(pp == nil) error(Enomem); doflush = 0; - if(dstid==0 || (dst->layer && dst->layer->screen->image->data == screenimage->data)) + if(dstid==0 || (screenimage && dst->layer && dst->layer->screen->image->data == screenimage->data)) doflush = 1; /* simplify test in loop */ ox = oy = 0; esize = 0; @@ -2048,7 +2049,7 @@ drawmesg(Client *client, void *av, int n) memltofrontn(lp, nw); else memltorearn(lp, nw); - if(lp[0]->layer->screen->image->data == screenimage->data) + if(screenimage && lp[0]->layer->screen->image->data == screenimage->data) for(j=0; jlayer->screenr); ll = drawlookup(client, BGLONG(a+1+1+2), 1); diff --git a/sys/src/cmd/aux/vga/main.c b/sys/src/cmd/aux/vga/main.c index 77d6ba979..2d3c6a3e7 100644 --- a/sys/src/cmd/aux/vga/main.c +++ b/sys/src/cmd/aux/vga/main.c @@ -158,7 +158,7 @@ main(int argc, char** argv) { char *bios, buf[256], sizeb[256], *p, *vsize, *psize; char *type, *vtype; - int fd, virtual, len; + int virtual, len; Ctlr *ctlr; Vga *vga; @@ -455,12 +455,6 @@ main(int argc, char** argv) else vgactlw("hwgc", vga->hwgc->name); - /* might as well initialize the cursor */ - if((fd = open("/dev/cursor", OWRITE)) >= 0){ - write(fd, buf, 0); - close(fd); - } - if(vga->virtx != vga->mode->x || vga->virty != vga->mode->y){ sprint(buf, "%dx%d", vga->mode->x, vga->mode->y); vgactlw("actualsize", buf); diff --git a/sys/src/cmd/aux/vga/vesa.c b/sys/src/cmd/aux/vga/vesa.c index 4a4c362b8..6df1f8345 100644 --- a/sys/src/cmd/aux/vga/vesa.c +++ b/sys/src/cmd/aux/vga/vesa.c @@ -31,8 +31,8 @@ struct Vbe struct Vmode { - char name[32]; - char chan[32]; + char size[Namelen+1]; + char chan[Namelen+1]; int id; int attr; /* flags */ int bpl; @@ -89,7 +89,9 @@ enum { #define PLONG(p, v) (p)[0] = (v); (p)[1] = (v)>>8; (p)[2] = (v)>>16; (p)[3] = (v)>>24 static Vbe *vbe; -static Edid edid; +static Edid *edid; + +extern Mode *vesamodes[]; Vbe *mkvbe(void); int vbecheck(Vbe*); @@ -116,6 +118,7 @@ dbvesa(Vga* vga) fprint(2, "dbvesa: %r\n"); return 0; } + vga->link = alloc(sizeof(Ctlr)); *vga->link = vesa; vga->vesa = vga->link; @@ -129,32 +132,38 @@ dbvesa(Vga* vga) } Mode* -dbvesamode(char *mode) +dbvesamode(char *size) { - int i; + int i, width; uchar *p, *ep; + Attr *a; Vmode vm; Mode *m; + Modelist *l; if(vbe == nil) return nil; - p = vbemodes(vbe); - if(p == nil) - return nil; - for(ep=p+1024; (p[0]!=0xFF || p[1]!=0xFF) && ptype, "vesa"); - strcpy(m->size, vm.name); - strcpy(m->chan, vm.chan); - m->frequency = 100; m->x = vm.dx; m->y = vm.dy; - m->z = vm.depth; m->ht = m->x; m->shb = m->x; m->ehb = m->x; @@ -177,11 +181,49 @@ havemode: m->vt = m->y; m->vrs = m->y; m->vre = m->y; + m->frequency = m->ht * m->vt * 60; + + /* get default monitor timing */ + for(i=0; vesamodes[i]; i++){ + if(vesamodes[i]->x != vm.dx || vesamodes[i]->y != vm.dy) + continue; + *m = *vesamodes[i]; + break; + } + if(edid){ + for(l = edid->modelist; l; l = l->next){ + if(l->x != vm.dx || l->y != vm.dy) + continue; + *m = *((Mode*)l); + break; + } + } + + strcpy(m->type, "vesa"); + strcpy(m->size, vm.size); + strcpy(m->chan, vm.chan); + m->z = vm.depth; + + a = alloc(sizeof(Attr)); + a->attr = "id"; + a->val = alloc(32); + sprint(a->val, "0x%x", vm.id); + + a->next = nil; + m->attr = a; + + /* account for framebuffer stride */ + width = vm.bpl * 8 / m->z; + if(width > m->x){ + a = alloc(sizeof(Attr)); + a->attr = "virtx"; + a->val = alloc(32); + sprint(a->val, "%d", width); + + a->next = m->attr; + m->attr = a; + } - m->attr = alloc(sizeof(Attr)); - m->attr->attr = "id"; - m->attr->val = alloc(32); - sprint(m->attr->val, "0x%x", vm.id); return m; } @@ -194,7 +236,20 @@ snarf(Vga* vga, Ctlr* ctlr) vga->vesa = ctlr; vbesnarf(vbe, vga); vga->linear = 1; - ctlr->flag |= Hlinear|Ulinear; + ctlr->flag |= Hlinear|Ulinear|Fsnarf; +} + +static void +options(Vga *vga, Ctlr *ctlr) +{ + char *v; + + if(v = dbattr(vga->mode->attr, "virtx")){ + vga->virtx = atoi(v); + vga->virty = vga->mode->y; + vga->panning = 0; + } + ctlr->flag |= Foptions; } static void @@ -233,18 +288,14 @@ dump(Vga*, Ctlr*) for(i=0x100; i<0x1FF; i++) if(!did[i]) vbeprintmodeinfo(vbe, i, " (unoffered)"); - - - if(vbeddcedid(vbe, &edid) < 0) - fprint(2, "warning: reading edid: %r\n"); - else - printedid(&edid); + if(edid) + printedid(edid); } Ctlr vesa = { "vesa", /* name */ snarf, /* snarf */ - 0, /* options */ + options, /* options */ 0, /* init */ load, /* load */ dump, /* dump */ @@ -273,19 +324,34 @@ static Flag capabilityflag[] = { 0 }; +enum { + AttrSupported = 1<<0, + AttrTTY = 1<<2, + AttrColor = 1<<3, + AttrGraphics = 1<<4, + AttrNotVGA = 1<<5, + AttrNotWinVGA = 1<<6, + AttrLinear = 1<<7, + AttrDoublescan = 1<<8, + AttrInterlace = 1<<9, + AttrTriplebuf = 1<<10, + AttrStereo = 1<<11, + AttrDualAddr = 1<<12, +}; + static Flag modeattributesflags[] = { - 1<<0, "supported", - 1<<2, "tty", - 1<<3, "color", - 1<<4, "graphics", - 1<<5, "not-vga", - 1<<6, "no-windowed-vga", - 1<<7, "linear", - 1<<8, "double-scan", - 1<<9, "interlace", - 1<<10, "triple-buffer", - 1<<11, "stereoscopic", - 1<<12, "dual-start-addr", + AttrSupported, "supported", + AttrTTY, "tty", + AttrColor, "color", + AttrGraphics, "graphics", + AttrNotVGA, "not-vga", + AttrNotWinVGA, "no-windowed-vga", + AttrLinear, "linear", + AttrDoublescan, "double-scan", + AttrInterlace, "interlace", + AttrTriplebuf, "triple-buffer", + AttrStereo, "stereoscopic", + AttrDualAddr, "dual-start-addr", 0 }; @@ -302,10 +368,29 @@ static Flag directcolorflags[] = { 0 }; -static char *modelstr[] = { - "text", "cga", "hercules", "planar", "packed", "non-chain4", "direct", "YUV" +enum { + ModText = 0, + ModCGA, + ModHercules, + ModPlanar, + ModPacked, + ModNonChain4, + ModDirect, + ModYUV, }; +static char *modelstr[] = { + [ModText] "text", + [ModCGA] "cga", + [ModHercules] "hercules", + [ModPlanar] "planar", + [ModPacked] "packed", + [ModNonChain4] "non-chain4", + [ModDirect] "direct", + [ModYUV] "YUV", +}; + + static void printflags(Flag *f, int b) { @@ -402,8 +487,12 @@ vbecheck(Vbe *vbe) strcpy((char*)p, "VBE2"); if(vbecall(vbe, &u) < 0) return -1; - if(memcmp(p, "VESA", 4) != 0 || p[5] < 2){ - werrstr("invalid vesa signature %.4H %.4H\n", p, p+4); + if(memcmp(p, "VESA", 4)){ + werrstr("invalid vesa signature %.4H\n", p); + return -1; + } + if(p[5] < 2){ + werrstr("invalid vesa version: %.4H\n", p+4); return -1; } return 0; @@ -422,6 +511,13 @@ vbesnarf(Vbe *vbe, Vga *vga) if(memcmp(p, "VESA", 4) != 0 || p[5] < 2) return -1; vga->apz = WORD(p+18)*0x10000UL; + if(edid == nil){ + edid = alloc(sizeof(Edid)); + if(vbeddcedid(vbe, edid) < 0){ + free(edid); + edid = nil; + } + } return 0; } @@ -474,11 +570,9 @@ vbemodes(Vbe *vbe) int vbemodeinfo(Vbe *vbe, int id, Vmode *m) { - int o; - ulong d, c, x; uchar *p; - char tmp[sizeof m->chan]; Ureg u; + int mod; p = vbesetup(vbe, &u, 0x4F01); u.cx = id; @@ -487,11 +581,31 @@ vbemodeinfo(Vbe *vbe, int id, Vmode *m) m->id = id; m->attr = WORD(p); + if(!(m->attr & AttrSupported)) + goto Unsupported; + if(!(m->attr & AttrGraphics)) + goto Unsupported; + if(!(m->attr & AttrLinear)) + goto Unsupported; m->bpl = WORD(p+16); m->dx = WORD(p+18); m->dy = WORD(p+20); m->depth = p[25]; - m->model = p[27] < nelem(modelstr) ? modelstr[p[27]] : "unknown"; + if((m->dx * m->dy * m->depth) <= 0) + goto Unsupported; + mod = p[27]; + switch(mod){ + default: + Unsupported: + werrstr("mode unsupported"); + return -1; + case ModCGA: + case ModHercules: + case ModPacked: + case ModDirect: + m->model = modelstr[mod]; + break; + } m->r = p[31]; m->g = p[33]; m->b = p[35]; @@ -502,44 +616,49 @@ vbemodeinfo(Vbe *vbe, int id, Vmode *m) m->xo = p[38]; m->directcolor = p[39]; m->paddr = LONG(p+40); - snprint(m->name, sizeof m->name, "%dx%dx%d", - m->dx, m->dy, m->depth); - if(m->depth <= 8) { - snprint(m->chan, sizeof m->chan, "m%d", m->depth); - return 0; - } - m->xo = m->x = 0; - d = 1 << (m->depth - 1); - d |= d - 1; - c = ((1<r)-1) << m->ro; - c |= ((1<g)-1) << m->go; - c |= ((1<b)-1) << m->bo; - x = d ^ c; - if(x != 0){ - for(; (x & 1) == 0; x >>= 1) - m->xo++; - for(; x & 1; x >>= 1) - m->x++; - } + snprint(m->size, sizeof m->size, "%dx%dx%d", m->dx, m->dy, m->depth); + if(m->depth <= 8) + snprint(m->chan, sizeof m->chan, "%c%d", + (m->attr & AttrColor) ? 'm' : 'k', m->depth); + else { + int o; + ulong d, c, x; - m->chan[0] = o = 0; - while(o < m->depth){ - if(m->r && m->ro == o){ - snprint(tmp, sizeof tmp, "r%d%s", m->r, m->chan); - o += m->r; - }else if(m->g && m->go == o){ - snprint(tmp, sizeof tmp, "g%d%s", m->g, m->chan); - o += m->g; - }else if(m->b && m->bo == o){ - snprint(tmp, sizeof tmp, "b%d%s", m->b, m->chan); - o += m->b; - }else if(m->x && m->xo == o){ - snprint(tmp, sizeof tmp, "x%d%s", m->x, m->chan); - o += m->x; - }else - break; - strncpy(m->chan, tmp, sizeof m->chan); + m->xo = m->x = 0; + d = 1<depth-1; + d |= d-1; + c = ((1<r)-1) << m->ro; + c |= ((1<g)-1) << m->go; + c |= ((1<b)-1) << m->bo; + if(x = d ^ c){ + for(; (x & 1) == 0; x >>= 1) + m->xo++; + for(; (x & 1) == 1; x >>= 1) + m->x++; + } + + o = 0; + m->chan[0] = 0; + while(o < m->depth){ + char tmp[sizeof m->chan]; + + if(m->r && m->ro == o){ + snprint(tmp, sizeof tmp, "r%d%s", m->r, m->chan); + o += m->r; + }else if(m->g && m->go == o){ + snprint(tmp, sizeof tmp, "g%d%s", m->g, m->chan); + o += m->g; + }else if(m->b && m->bo == o){ + snprint(tmp, sizeof tmp, "b%d%s", m->b, m->chan); + o += m->b; + }else if(m->x && m->xo == o){ + snprint(tmp, sizeof tmp, "x%d%s", m->x, m->chan); + o += m->x; + }else + break; + strncpy(m->chan, tmp, sizeof m->chan); + } } return 0; } @@ -549,13 +668,11 @@ vbeprintmodeinfo(Vbe *vbe, int id, char *suffix) { Vmode m; - if(vbemodeinfo(vbe, id, &m) < 0){ - // Bprint(&stdout, "vesa: cannot get mode 0x%ux: %r\n", id); + if(vbemodeinfo(vbe, id, &m) < 0) return; - } printitem("vesa", "mode"); Bprint(&stdout, "0x%ux %s %s %s%s\n", - m.id, m.name, m.chan, m.model, suffix); + m.id, m.size, m.chan, m.model, suffix); } int @@ -572,33 +689,12 @@ vbegetmode(Vbe *vbe) int vbesetmode(Vbe *vbe, int id) { - uchar *p; Ureg u; - p = vbesetup(vbe, &u, 0x4F02); - if(id != 3) - id |= 3<<14; /* graphics: use linear, do not clear */ + vbesetup(vbe, &u, 0x4F02); u.bx = id; - USED(p); - /* - * can set mode specifics (ht hss hse vt vss vse 0 clockhz refreshhz): - * - u.bx |= 1<<11; - n = atoi(argv[2]); PWORD(p, n); p+=2; - n = atoi(argv[3]); PWORD(p, n); p+=2; - n = atoi(argv[4]); PWORD(p, n); p+=2; - n = atoi(argv[5]); PWORD(p, n); p+=2; - n = atoi(argv[6]); PWORD(p, n); p+=2; - n = atoi(argv[7]); PWORD(p, n); p+=2; - *p++ = atoi(argv[8]); - n = atoi(argv[9]); PLONG(p, n); p += 4; - n = atoi(argv[10]); PWORD(p, n); p += 2; - if(p != vbe.buf+19){ - fprint(2, "prog error\n"); - return; - } - * - */ + if(id != 3) + u.bx |= 3<<14; /* graphics: use linear, do not clear */ return vbecall(vbe, &u); } @@ -679,8 +775,16 @@ printedid(Edid *e) for(l=e->modelist; l; l=l->next){ printitem("edid", l->name); - Bprint(&stdout, "\n\t\tclock=%g\n\t\tshb=%d ehb=%d ht=%d\n\t\tvrs=%d vre=%d vt=%d\n\t\thsync=%c vsync=%c %s\n", - l->frequency/1.e6, l->shb, l->ehb, l->ht, l->vrs, l->vre, l->vt, l->hsync?l->hsync:'?', l->vsync?l->vsync:'?', l->interlace?"interlace=v" : ""); + Bprint(&stdout, "\n\t\tclock=%g\n" + "\t\tshb=%d ehb=%d ht=%d\n" + "\t\tvrs=%d vre=%d vt=%d\n" + "\t\thsync=%c vsync=%c %s\n", + l->frequency/1.e6, + l->shb, l->ehb, l->ht, + l->vrs, l->vre, l->vt, + l->hsync?l->hsync:'?', + l->vsync?l->vsync:'?', + l->interlace?"interlace=v" : ""); } } @@ -690,9 +794,8 @@ addmode(Modelist *l, Mode m) int rr; Modelist **lp; -//m.z = 8; // BUG rr = (m.frequency+m.ht*m.vt/2)/(m.ht*m.vt); - snprint(m.name, sizeof m.name, "%dx%dx%d@%dHz", m.x, m.y, m.z, rr); + snprint(m.name, sizeof m.name, "%dx%d@%dHz", m.x, m.y, rr); if(m.shs == 0) m.shs = m.shb; @@ -832,8 +935,6 @@ decodedtb(Mode *m, uchar *p) return 0; } -extern Mode *vesamodes[]; - int vesalookup(Mode *m, char *name) { diff --git a/sys/src/cmd/aux/vga/vesadb.c b/sys/src/cmd/aux/vga/vesadb.c index c7aaeebc0..53e461258 100644 --- a/sys/src/cmd/aux/vga/vesadb.c +++ b/sys/src/cmd/aux/vga/vesadb.c @@ -1,4 +1,4 @@ -/* this file was automatically generated from vesa.txt */ +// DO NOT EDIT; this file is automatically generated from vesa.txt #include #include @@ -6,16 +6,14 @@ #include "pci.h" #include "vga.h" -/* - * VESA Monitor Timing Standard mode definitions as per - * VESA and Industry Standards and Guidelines for Computer - * Display Monitor Timing, Version 1.0, Revision 0.8, 17 September 1998. - * - * See /public/doc/vesa/dmtv1r08.pdf. - * - * This might go back into vgadb at some point. It's here mainly - * so that people don't change it, and so that we can run without vgadb. - */ +// VESA Monitor Timing Standard mode definitions as per +// VESA and Industry Standards and Guidelines for Computer +// Display Monitor Timing, Version 1.0, Revision 0.8, 17 September 1998. +// +// See /lib/vesa/dmtv1r08.pdf. +// +// This might go back into vgadb at some point. It's here mainly +// so that people don't change it, and so that we can run without vgadb. static Mode vesa640x480x60 = { .name = "640x480@60Hz", diff --git a/sys/src/libmemdraw/draw.c b/sys/src/libmemdraw/draw.c index 1987c7713..574d597db 100644 --- a/sys/src/libmemdraw/draw.c +++ b/sys/src/libmemdraw/draw.c @@ -12,22 +12,34 @@ static int tablesbuilt; #define RGB2K(r,g,b) ((156763*(r)+307758*(g)+59769*(b))>>19) /* - * for 0 ≤ x ≤ 255*255, (x*0x0101+0x100)>>16 is a perfect approximation. - * for 0 ≤ x < (1<<16), x/255 = ((x+1)*0x0101)>>16 is a perfect approximation. - * the last one is perfect for all up to 1<<16, avoids a multiply, but requires a rathole. + * For 16-bit values, x / 255 == (t = x+1, (t+(t>>8)) >> 8). + * We add another 127 to round to the nearest value rather + * than truncate. + * + * CALCxy does x bytewise calculations on y input images (x=1,4; y=1,2). + * CALC2x does two parallel 16-bit calculations on y input images (y=1,2). */ -/* #define DIV255(x) (((x)*257+256)>>16) */ -#define DIV255(x) ((((x)+1)*257)>>16) -/* #define DIV255(x) (tmp=(x)+1, (tmp+(tmp>>8))>>8) */ +#define CALC11(a, v, tmp) \ + (tmp=(a)*(v)+128, (tmp+(tmp>>8))>>8) -#define MUL(x, y, t) (t = (x)*(y)+128, (t+(t>>8))>>8) -#define MASK13 0xFF00FF00 -#define MASK02 0x00FF00FF -#define MUL13(a, x, t) (t = (a)*(((x)&MASK13)>>8)+128, ((t+((t>>8)&MASK02))>>8)&MASK02) -#define MUL02(a, x, t) (t = (a)*(((x)&MASK02)>>0)+128, ((t+((t>>8)&MASK02))>>8)&MASK02) -#define MUL0123(a, x, s, t) ((MUL13(a, x, s)<<8)|MUL02(a, x, t)) +#define CALC12(a1, v1, a2, v2, tmp) \ + (tmp=(a1)*(v1)+(a2)*(v2)+128, (tmp+(tmp>>8))>>8) -#define MUL2(u, v, x, y) (t = (u)*(v)+(x)*(y)+256, (t+(t>>8))>>8) +#define MASK 0xFF00FF + +#define CALC21(a, vvuu, tmp) \ + (tmp=(a)*(vvuu)+0x00800080, ((tmp+((tmp>>8)&MASK))>>8)&MASK) + +#define CALC41(a, rgba, tmp1, tmp2) \ + (CALC21(a, rgba & MASK, tmp1) | \ + (CALC21(a, (rgba>>8)&MASK, tmp2)<<8)) + +#define CALC22(a1, vvuu1, a2, vvuu2, tmp) \ + (tmp=(a1)*(vvuu1)+(a2)*(vvuu2)+0x00800080, ((tmp+((tmp>>8)&MASK))>>8)&MASK) + +#define CALC42(a1, rgba1, a2, rgba2, tmp1, tmp2) \ + (CALC22(a1, rgba1 & MASK, a2, rgba2 & MASK, tmp1) | \ + (CALC22(a1, (rgba1>>8) & MASK, a2, (rgba2>>8) & MASK, tmp2)<<8)) static void mktables(void); typedef int Subdraw(Memdrawparam*); @@ -803,41 +815,85 @@ alphacalc0(Buffer bdst, Buffer b1, Buffer b2, int dx, int grey, int op) return bdst; } +/* + * Do the channels in the buffers match enough + * that we can do word-at-a-time operations + * on the pixels? + */ +static int +chanmatch(Buffer *bdst, Buffer *bsrc) +{ + uchar *drgb, *srgb; + + /* + * first, r, g, b must be in the same place + * in the rgba word. + */ + drgb = (uchar*)bdst->rgba; + srgb = (uchar*)bsrc->rgba; + if(bdst->red - drgb != bsrc->red - srgb + || bdst->blu - drgb != bsrc->blu - srgb + || bdst->grn - drgb != bsrc->grn - srgb) + return 0; + + /* + * that implies alpha is in the same place, + * if it is there at all (it might be == &ones). + * if the destination is &ones, we can scribble + * over the rgba slot just fine. + */ + if(bdst->alpha == &ones) + return 1; + + /* + * if the destination is not ones but the src is, + * then the simultaneous calculation will use + * bogus bytes from the src's rgba. no good. + */ + if(bsrc->alpha == &ones) + return 0; + + /* + * otherwise, alphas are in the same place. + */ + return 1; +} + static Buffer alphacalc14(Buffer bdst, Buffer bsrc, Buffer bmask, int dx, int grey, int op) { Buffer obdst; int fd, sadelta; int i, sa, ma, q; - ulong s, t; + ulong t, t1; obdst = bdst; sadelta = bsrc.alpha == &ones ? 0 : bsrc.delta; - q = bsrc.delta == 4 && bdst.delta == 4; + q = bsrc.delta == 4 && bdst.delta == 4 && chanmatch(&bdst, &bsrc); for(i=0; ir)) return -1; + + memset(&par, 0, sizeof par); + par.dst = i; + par.r = r; + hwdraw(&par); + l = bytesperline(r, i->depth); if(ndata < l*Dy(r)) return -1;