diff options
| author | Charles.Forsyth <devnull@localhost> | 2006-12-22 21:39:35 +0000 |
|---|---|---|
| committer | Charles.Forsyth <devnull@localhost> | 2006-12-22 21:39:35 +0000 |
| commit | 74a4d8c26dd3c1e9febcb717cfd6cb6512991a7a (patch) | |
| tree | c6e220ba61db3a6ea4052e6841296d829654e664 /os/pc/screen.c | |
| parent | 46439007cf417cbd9ac8049bb4122c890097a0fa (diff) | |
20060303
Diffstat (limited to 'os/pc/screen.c')
| -rw-r--r-- | os/pc/screen.c | 410 |
1 files changed, 410 insertions, 0 deletions
diff --git a/os/pc/screen.c b/os/pc/screen.c new file mode 100644 index 00000000..e879b050 --- /dev/null +++ b/os/pc/screen.c @@ -0,0 +1,410 @@ +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "io.h" +#include "ureg.h" +#include "../port/error.h" + +#include <draw.h> +#include <memdraw.h> +#include <cursor.h> +#include "screen.h" + +#define RGB2K(r,g,b) ((156763*(r)+307758*(g)+59769*(b))>>19) + +Point ZP = {0, 0}; + +Rectangle physgscreenr; +Cursorinfo cursor; /* TO DO */ + +Memdata gscreendata; +Memimage *gscreen; + +VGAscr vgascreen[1]; + +Cursor arrow = { + { -1, -1 }, + { 0xFF, 0xFF, 0x80, 0x01, 0x80, 0x02, 0x80, 0x0C, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x08, 0x80, 0x04, + 0x80, 0x02, 0x80, 0x01, 0x80, 0x02, 0x8C, 0x04, + 0x92, 0x08, 0x91, 0x10, 0xA0, 0xA0, 0xC0, 0x40, + }, + { 0x00, 0x00, 0x7F, 0xFE, 0x7F, 0xFC, 0x7F, 0xF0, + 0x7F, 0xE0, 0x7F, 0xE0, 0x7F, 0xF0, 0x7F, 0xF8, + 0x7F, 0xFC, 0x7F, 0xFE, 0x7F, 0xFC, 0x73, 0xF8, + 0x61, 0xF0, 0x60, 0xE0, 0x40, 0x40, 0x00, 0x00, + }, +}; + +int +screensize(int x, int y, int z, ulong chan) +{ + VGAscr *scr; + + memimageinit(); + scr = &vgascreen[0]; + + /* + * BUG: need to check if any xalloc'ed memory needs to + * be given back if aperture is set. + */ + if(scr->aperture == 0){ + int width = (x*z)/BI2WD; + + gscreendata.bdata = xalloc(width*BY2WD*y); + if(gscreendata.bdata == 0) + error("screensize: vga soft memory"); +/* memset(gscreendata.bdata, 0x72, width*BY2WD*y); /* not really black */ + scr->useflush = 1; + scr->aperture = VGAMEM(); + scr->apsize = 1<<16; + } + else + gscreendata.bdata = KADDR(scr->aperture); + + if(gscreen) + freememimage(gscreen); + + gscreen = allocmemimaged(Rect(0,0,x,y), chan, &gscreendata); + vgaimageinit(chan); + if(gscreen == nil) + return -1; + + if(scr->dev && scr->dev->flush) + scr->useflush = 1; + + scr->palettedepth = 6; /* default */ + scr->gscreendata = &gscreendata; + scr->memdefont = getmemdefont(); + scr->gscreen = gscreen; + + physgscreenr = gscreen->r; + + drawcmap(); + return 0; +} + +int +screenaperture(int size, int align) +{ + VGAscr *scr; + ulong aperture; + + scr = &vgascreen[0]; + + if(size == 0){ + if(scr->aperture && scr->isupamem) + upafree(scr->aperture, scr->apsize); + scr->aperture = 0; + scr->isupamem = 0; + return 0; + } + if(scr->dev && scr->dev->linear){ + aperture = scr->dev->linear(scr, &size, &align); + if(aperture == 0) + return 1; + }else{ + aperture = upamalloc(0, size, align); + if(aperture == 0) + return 1; + + if(scr->aperture && scr->isupamem) + upafree(scr->aperture, scr->apsize); + scr->isupamem = 1; + } + + scr->aperture = aperture; + scr->apsize = size; + + return 0; +} + +uchar* +attachscreen(Rectangle* r, ulong* chan, int* d, int* width, int *softscreen) +{ + VGAscr *scr; + + scr = &vgascreen[0]; + if(scr->gscreen == nil || scr->gscreendata == nil) + return nil; + + *r = scr->gscreen->clipr; + *chan = scr->gscreen->chan; + *d = scr->gscreen->depth; + *width = scr->gscreen->width; + *softscreen = scr->useflush; + + 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; + + scr = &vgascreen[0]; + 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; + + if(rectclip(&r, scr->gscreen->r) == 0) + return; + + incs = scr->gscreen->width * BY2WD; + + switch(scr->gscreen->depth){ + default: + len = 0; + panic("flushmemscreen: depth\n"); + break; + case 8: + len = Dx(r); + break; + } + 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 = KADDR(scr->aperture); + 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) { + memmove(sdisp, sp, len); + sp += incs; + sdisp += incs; + } + else { + off = edisp - sdisp; + page++; + if(off <= len){ + if(off > 0) + memmove(sdisp, sp, off); + scr->dev->page(scr, page); + if(len - off > 0) + memmove(disp, sp+off, len - off); + } + else { + memmove(sdisp, sp, len); + scr->dev->page(scr, page); + } + sp += incs; + sdisp += incs - scr->apsize; + } + } +} + +void +getcolor(ulong p, ulong* pr, ulong* pg, ulong* pb) +{ + VGAscr *scr; + ulong x; + + scr = &vgascreen[0]; + if(scr->gscreen == nil) + return; + + switch(scr->gscreen->depth){ + default: + x = 0x0F; + break; + case 8: + x = 0xFF; + break; + } + p &= x; + + lock(&cursor); + *pr = scr->colormap[p][0]; + *pg = scr->colormap[p][1]; + *pb = scr->colormap[p][2]; + unlock(&cursor); +} + +int +setpalette(ulong p, ulong r, ulong g, ulong b) +{ + VGAscr *scr; + int d; + + scr = &vgascreen[0]; + d = scr->palettedepth; + + lock(&cursor); + scr->colormap[p][0] = r; + scr->colormap[p][1] = g; + scr->colormap[p][2] = b; + vgao(PaddrW, p); + vgao(Pdata, r>>(32-d)); + vgao(Pdata, g>>(32-d)); + vgao(Pdata, b>>(32-d)); + unlock(&cursor); + + return ~0; +} + +/* + * On some video cards (e.g. Mach64), the palette is used as the + * DAC registers for >8-bit modes. We don't want to set them when the user + * is trying to set a colormap and the card is in one of these modes. + */ +int +setcolor(ulong p, ulong r, ulong g, ulong b) +{ + VGAscr *scr; + int x; + + scr = &vgascreen[0]; + if(scr->gscreen == nil) + return 0; + + switch(scr->gscreen->depth){ + case 1: + case 2: + case 4: + x = 0x0F; + break; + case 8: + x = 0xFF; + break; + default: + return 0; + } + p &= x; + + return setpalette(p, r, g, b); +} + +int +cursoron(int dolock) +{ + VGAscr *scr; + int v; + + scr = &vgascreen[0]; + if(scr->cur == nil || scr->cur->move == nil) + return 0; + + if(dolock) + lock(&cursor); + v = scr->cur->move(scr, mousexy()); + if(dolock) + unlock(&cursor); + + return v; +} + +void +cursoroff(int) +{ +} + +void +setcursor(Cursor* curs) +{ + VGAscr *scr; + + scr = &vgascreen[0]; + if(scr->cur == nil || scr->cur->load == nil) + return; + + scr->cur->load(scr, curs); +} + +int hwaccel = 1; +int hwblank = 0; /* turned on by drivers that are known good */ +int panning = 0; + +int +hwdraw(Memdrawparam *par) +{ + VGAscr *scr; + Memimage *dst, *src; + int m; + + if(hwaccel == 0) + return 0; + + dst = par->dst; + scr = &vgascreen[0]; + if(dst == nil || dst->data == nil) + return 0; + + if(dst->data->bdata != gscreendata.bdata) + return 0; + + if(scr->fill==nil && scr->scroll==nil) + return 0; + + /* + * If we have an opaque mask and source is one opaque + * pixel we can convert to the destination format and just + * replicate with memset. + */ + m = Simplesrc|Simplemask|Fullmask; + if(scr->fill + && (par->state&m)==m + && ((par->srgba&0xFF) == 0xFF) + && (par->op&S) == S) + return scr->fill(scr, par->r, par->sdval); + + /* + * If no source alpha, an opaque mask, we can just copy the + * source onto the destination. If the channels are the same and + * the source is not replicated, memmove suffices. + */ + m = Simplemask|Fullmask; + src = par->src; + if(scr->scroll + && src->data->bdata==dst->data->bdata + && !(src->flags&Falpha) + && (par->state&m)==m + && (par->op&S) == S) + return scr->scroll(scr, par->r, par->sr); + + return 0; +} + +void +blankscreen(int blank) +{ + VGAscr *scr; + + scr = &vgascreen[0]; + if(hwblank){ + if(scr->blank) + scr->blank(scr, blank); + else + vgablank(scr, blank); + } +} + +void +cursorenable(void) +{ +} + +void +cursordisable(void) +{ +} |
