17dd7cddfSDavid du Colombier #include "u.h" 27dd7cddfSDavid du Colombier #include "../port/lib.h" 37dd7cddfSDavid du Colombier #include "mem.h" 47dd7cddfSDavid du Colombier #include "dat.h" 57dd7cddfSDavid du Colombier #include "fns.h" 67dd7cddfSDavid du Colombier #include "io.h" 77dd7cddfSDavid du Colombier #include "ureg.h" 87dd7cddfSDavid du Colombier #include "../port/error.h" 97dd7cddfSDavid du Colombier 107dd7cddfSDavid du Colombier #define Image IMAGE 117dd7cddfSDavid du Colombier #include <draw.h> 127dd7cddfSDavid du Colombier #include <memdraw.h> 137dd7cddfSDavid du Colombier #include <cursor.h> 147dd7cddfSDavid du Colombier #include "screen.h" 157dd7cddfSDavid du Colombier 167dd7cddfSDavid du Colombier #define RGB2K(r,g,b) ((156763*(r)+307758*(g)+59769*(b))>>19) 177dd7cddfSDavid du Colombier 187dd7cddfSDavid du Colombier Point ZP = {0, 0}; 197dd7cddfSDavid du Colombier 207dd7cddfSDavid du Colombier Rectangle physgscreenr; 217dd7cddfSDavid du Colombier 227dd7cddfSDavid du Colombier Memdata gscreendata; 237dd7cddfSDavid du Colombier Memimage *gscreen; 247dd7cddfSDavid du Colombier 257dd7cddfSDavid du Colombier VGAscr vgascreen[1]; 267dd7cddfSDavid du Colombier 277dd7cddfSDavid du Colombier Cursor arrow = { 287dd7cddfSDavid du Colombier { -1, -1 }, 297dd7cddfSDavid du Colombier { 0xFF, 0xFF, 0x80, 0x01, 0x80, 0x02, 0x80, 0x0C, 307dd7cddfSDavid du Colombier 0x80, 0x10, 0x80, 0x10, 0x80, 0x08, 0x80, 0x04, 317dd7cddfSDavid du Colombier 0x80, 0x02, 0x80, 0x01, 0x80, 0x02, 0x8C, 0x04, 327dd7cddfSDavid du Colombier 0x92, 0x08, 0x91, 0x10, 0xA0, 0xA0, 0xC0, 0x40, 337dd7cddfSDavid du Colombier }, 347dd7cddfSDavid du Colombier { 0x00, 0x00, 0x7F, 0xFE, 0x7F, 0xFC, 0x7F, 0xF0, 357dd7cddfSDavid du Colombier 0x7F, 0xE0, 0x7F, 0xE0, 0x7F, 0xF0, 0x7F, 0xF8, 367dd7cddfSDavid du Colombier 0x7F, 0xFC, 0x7F, 0xFE, 0x7F, 0xFC, 0x73, 0xF8, 377dd7cddfSDavid du Colombier 0x61, 0xF0, 0x60, 0xE0, 0x40, 0x40, 0x00, 0x00, 387dd7cddfSDavid du Colombier }, 397dd7cddfSDavid du Colombier }; 407dd7cddfSDavid du Colombier 414de34a7eSDavid du Colombier int didswcursorinit; 424de34a7eSDavid du Colombier 437dd7cddfSDavid du Colombier int 447dd7cddfSDavid du Colombier screensize(int x, int y, int z, ulong chan) 457dd7cddfSDavid du Colombier { 467dd7cddfSDavid du Colombier VGAscr *scr; 477dd7cddfSDavid du Colombier 484de34a7eSDavid du Colombier lock(&vgascreenlock); 497dd7cddfSDavid du Colombier memimageinit(); 507dd7cddfSDavid du Colombier scr = &vgascreen[0]; 517dd7cddfSDavid du Colombier 527dd7cddfSDavid du Colombier /* 537dd7cddfSDavid du Colombier * BUG: need to check if any xalloc'ed memory needs to 547dd7cddfSDavid du Colombier * be given back if aperture is set. 557dd7cddfSDavid du Colombier */ 564de34a7eSDavid du Colombier if(scr->paddr == 0){ 577dd7cddfSDavid du Colombier int width = (x*z)/BI2WD; 587dd7cddfSDavid du Colombier 597dd7cddfSDavid du Colombier gscreendata.bdata = xalloc(width*BY2WD*y); 607dd7cddfSDavid du Colombier if(gscreendata.bdata == 0) 617dd7cddfSDavid du Colombier error("screensize: vga soft memory"); 627dd7cddfSDavid du Colombier /* memset(gscreendata.bdata, 0x72, width*BY2WD*y); /* not really black */ 637dd7cddfSDavid du Colombier scr->useflush = 1; 644de34a7eSDavid du Colombier scr->paddr = VGAMEM(); 654de34a7eSDavid du Colombier scr->vaddr = KADDR(scr->paddr); 667dd7cddfSDavid du Colombier scr->apsize = 1<<16; 677dd7cddfSDavid du Colombier } 687dd7cddfSDavid du Colombier else 694de34a7eSDavid du Colombier gscreendata.bdata = scr->vaddr; 707dd7cddfSDavid du Colombier 717dd7cddfSDavid du Colombier if(gscreen) 727dd7cddfSDavid du Colombier freememimage(gscreen); 734de34a7eSDavid du Colombier scr->gscreen = nil; 747dd7cddfSDavid du Colombier 757dd7cddfSDavid du Colombier gscreen = allocmemimaged(Rect(0,0,x,y), chan, &gscreendata); 767dd7cddfSDavid du Colombier vgaimageinit(chan); 774de34a7eSDavid du Colombier if(gscreen == nil){ 784de34a7eSDavid du Colombier unlock(&vgascreenlock); 797dd7cddfSDavid du Colombier return -1; 804de34a7eSDavid du Colombier } 817dd7cddfSDavid du Colombier 829a747e4fSDavid du Colombier if(scr->dev && scr->dev->flush) 839a747e4fSDavid du Colombier scr->useflush = 1; 847dd7cddfSDavid du Colombier 857dd7cddfSDavid du Colombier scr->palettedepth = 6; /* default */ 867dd7cddfSDavid du Colombier scr->gscreendata = &gscreendata; 877dd7cddfSDavid du Colombier scr->memdefont = getmemdefont(); 887dd7cddfSDavid du Colombier scr->gscreen = gscreen; 897dd7cddfSDavid du Colombier 907dd7cddfSDavid du Colombier physgscreenr = gscreen->r; 914de34a7eSDavid du Colombier unlock(&vgascreenlock); 927dd7cddfSDavid du Colombier 934de34a7eSDavid du Colombier if(didswcursorinit) 944de34a7eSDavid du Colombier swcursorinit(); 957dd7cddfSDavid du Colombier drawcmap(); 967dd7cddfSDavid du Colombier return 0; 977dd7cddfSDavid du Colombier } 987dd7cddfSDavid du Colombier 997dd7cddfSDavid du Colombier int 1007dd7cddfSDavid du Colombier screenaperture(int size, int align) 1017dd7cddfSDavid du Colombier { 1027dd7cddfSDavid du Colombier VGAscr *scr; 1037dd7cddfSDavid du Colombier 1047dd7cddfSDavid du Colombier scr = &vgascreen[0]; 1057dd7cddfSDavid du Colombier 1064de34a7eSDavid du Colombier if(scr->paddr) /* set up during enable */ 1074de34a7eSDavid du Colombier return 0; 1084de34a7eSDavid du Colombier 1094de34a7eSDavid du Colombier if(size == 0) 1104de34a7eSDavid du Colombier return 0; 1114de34a7eSDavid du Colombier 1124de34a7eSDavid du Colombier if(scr->dev && scr->dev->linear){ 1134de34a7eSDavid du Colombier scr->dev->linear(scr, size, align); 1147dd7cddfSDavid du Colombier return 0; 1157dd7cddfSDavid du Colombier } 1167dd7cddfSDavid du Colombier 1174de34a7eSDavid du Colombier /* 1184de34a7eSDavid du Colombier * Need to allocate some physical address space. 1194de34a7eSDavid du Colombier * The driver will tell the card to use it. 1204de34a7eSDavid du Colombier */ 1214de34a7eSDavid du Colombier size = PGROUND(size); 1224de34a7eSDavid du Colombier scr->paddr = upaalloc(size, align); 1234de34a7eSDavid du Colombier if(scr->paddr == 0) 1244de34a7eSDavid du Colombier return -1; 1254de34a7eSDavid du Colombier scr->vaddr = vmap(scr->paddr, size); 1264de34a7eSDavid du Colombier if(scr->vaddr == nil) 1274de34a7eSDavid du Colombier return -1; 1287dd7cddfSDavid du Colombier scr->apsize = size; 1297dd7cddfSDavid du Colombier 1307dd7cddfSDavid du Colombier return 0; 1317dd7cddfSDavid du Colombier } 1327dd7cddfSDavid du Colombier 1337dd7cddfSDavid du Colombier uchar* 1347dd7cddfSDavid du Colombier attachscreen(Rectangle* r, ulong* chan, int* d, int* width, int *softscreen) 1357dd7cddfSDavid du Colombier { 1367dd7cddfSDavid du Colombier VGAscr *scr; 1377dd7cddfSDavid du Colombier 1387dd7cddfSDavid du Colombier scr = &vgascreen[0]; 1397dd7cddfSDavid du Colombier if(scr->gscreen == nil || scr->gscreendata == nil) 1407dd7cddfSDavid du Colombier return nil; 1417dd7cddfSDavid du Colombier 1429a747e4fSDavid du Colombier *r = scr->gscreen->clipr; 1437dd7cddfSDavid du Colombier *chan = scr->gscreen->chan; 1447dd7cddfSDavid du Colombier *d = scr->gscreen->depth; 1457dd7cddfSDavid du Colombier *width = scr->gscreen->width; 1467dd7cddfSDavid du Colombier *softscreen = scr->useflush; 1477dd7cddfSDavid du Colombier 1487dd7cddfSDavid du Colombier return scr->gscreendata->bdata; 1497dd7cddfSDavid du Colombier } 1507dd7cddfSDavid du Colombier 1517dd7cddfSDavid du Colombier /* 1527dd7cddfSDavid du Colombier * It would be fair to say that this doesn't work for >8-bit screens. 1537dd7cddfSDavid du Colombier */ 1547dd7cddfSDavid du Colombier void 1557dd7cddfSDavid du Colombier flushmemscreen(Rectangle r) 1567dd7cddfSDavid du Colombier { 1577dd7cddfSDavid du Colombier VGAscr *scr; 1587dd7cddfSDavid du Colombier uchar *sp, *disp, *sdisp, *edisp; 1597dd7cddfSDavid du Colombier int y, len, incs, off, page; 1607dd7cddfSDavid du Colombier 1617dd7cddfSDavid du Colombier scr = &vgascreen[0]; 1629a747e4fSDavid du Colombier if(scr->dev && scr->dev->flush){ 1639a747e4fSDavid du Colombier scr->dev->flush(scr, r); 1649a747e4fSDavid du Colombier return; 1659a747e4fSDavid du Colombier } 1667dd7cddfSDavid du Colombier if(scr->gscreen == nil || scr->useflush == 0) 1677dd7cddfSDavid du Colombier return; 1687dd7cddfSDavid du Colombier if(scr->dev == nil || scr->dev->page == nil) 1697dd7cddfSDavid du Colombier return; 1707dd7cddfSDavid du Colombier 1717dd7cddfSDavid du Colombier if(rectclip(&r, scr->gscreen->r) == 0) 1727dd7cddfSDavid du Colombier return; 1737dd7cddfSDavid du Colombier 1747dd7cddfSDavid du Colombier incs = scr->gscreen->width * BY2WD; 1757dd7cddfSDavid du Colombier 1767dd7cddfSDavid du Colombier switch(scr->gscreen->depth){ 1777dd7cddfSDavid du Colombier default: 1787dd7cddfSDavid du Colombier len = 0; 1797dd7cddfSDavid du Colombier panic("flushmemscreen: depth\n"); 1807dd7cddfSDavid du Colombier break; 1817dd7cddfSDavid du Colombier case 8: 1827dd7cddfSDavid du Colombier len = Dx(r); 1837dd7cddfSDavid du Colombier break; 1847dd7cddfSDavid du Colombier } 1857dd7cddfSDavid du Colombier if(len < 1) 1867dd7cddfSDavid du Colombier return; 1877dd7cddfSDavid du Colombier 1887dd7cddfSDavid du Colombier off = r.min.y*scr->gscreen->width*BY2WD+(r.min.x*scr->gscreen->depth)/8; 1897dd7cddfSDavid du Colombier page = off/scr->apsize; 1907dd7cddfSDavid du Colombier off %= scr->apsize; 1914de34a7eSDavid du Colombier disp = scr->vaddr; 1927dd7cddfSDavid du Colombier sdisp = disp+off; 1937dd7cddfSDavid du Colombier edisp = disp+scr->apsize; 1947dd7cddfSDavid du Colombier 1957dd7cddfSDavid du Colombier off = r.min.y*scr->gscreen->width*BY2WD+(r.min.x*scr->gscreen->depth)/8; 1967dd7cddfSDavid du Colombier 1977dd7cddfSDavid du Colombier sp = scr->gscreendata->bdata + off; 1987dd7cddfSDavid du Colombier 1997dd7cddfSDavid du Colombier scr->dev->page(scr, page); 2007dd7cddfSDavid du Colombier for(y = r.min.y; y < r.max.y; y++) { 2017dd7cddfSDavid du Colombier if(sdisp + incs < edisp) { 2027dd7cddfSDavid du Colombier memmove(sdisp, sp, len); 2037dd7cddfSDavid du Colombier sp += incs; 2047dd7cddfSDavid du Colombier sdisp += incs; 2057dd7cddfSDavid du Colombier } 2067dd7cddfSDavid du Colombier else { 2077dd7cddfSDavid du Colombier off = edisp - sdisp; 2087dd7cddfSDavid du Colombier page++; 2097dd7cddfSDavid du Colombier if(off <= len){ 2107dd7cddfSDavid du Colombier if(off > 0) 2117dd7cddfSDavid du Colombier memmove(sdisp, sp, off); 2127dd7cddfSDavid du Colombier scr->dev->page(scr, page); 2137dd7cddfSDavid du Colombier if(len - off > 0) 2147dd7cddfSDavid du Colombier memmove(disp, sp+off, len - off); 2157dd7cddfSDavid du Colombier } 2167dd7cddfSDavid du Colombier else { 2177dd7cddfSDavid du Colombier memmove(sdisp, sp, len); 2187dd7cddfSDavid du Colombier scr->dev->page(scr, page); 2197dd7cddfSDavid du Colombier } 2207dd7cddfSDavid du Colombier sp += incs; 2217dd7cddfSDavid du Colombier sdisp += incs - scr->apsize; 2227dd7cddfSDavid du Colombier } 2237dd7cddfSDavid du Colombier } 2247dd7cddfSDavid du Colombier } 2257dd7cddfSDavid du Colombier 2267dd7cddfSDavid du Colombier void 2277dd7cddfSDavid du Colombier getcolor(ulong p, ulong* pr, ulong* pg, ulong* pb) 2287dd7cddfSDavid du Colombier { 2297dd7cddfSDavid du Colombier VGAscr *scr; 2307dd7cddfSDavid du Colombier ulong x; 2317dd7cddfSDavid du Colombier 2327dd7cddfSDavid du Colombier scr = &vgascreen[0]; 2337dd7cddfSDavid du Colombier if(scr->gscreen == nil) 2347dd7cddfSDavid du Colombier return; 2357dd7cddfSDavid du Colombier 2367dd7cddfSDavid du Colombier switch(scr->gscreen->depth){ 2377dd7cddfSDavid du Colombier default: 2387dd7cddfSDavid du Colombier x = 0x0F; 2397dd7cddfSDavid du Colombier break; 2407dd7cddfSDavid du Colombier case 8: 2417dd7cddfSDavid du Colombier x = 0xFF; 2427dd7cddfSDavid du Colombier break; 2437dd7cddfSDavid du Colombier } 2447dd7cddfSDavid du Colombier p &= x; 2457dd7cddfSDavid du Colombier 2467dd7cddfSDavid du Colombier lock(&cursor); 2477dd7cddfSDavid du Colombier *pr = scr->colormap[p][0]; 2487dd7cddfSDavid du Colombier *pg = scr->colormap[p][1]; 2497dd7cddfSDavid du Colombier *pb = scr->colormap[p][2]; 2507dd7cddfSDavid du Colombier unlock(&cursor); 2517dd7cddfSDavid du Colombier } 2527dd7cddfSDavid du Colombier 2537dd7cddfSDavid du Colombier int 2547dd7cddfSDavid du Colombier setpalette(ulong p, ulong r, ulong g, ulong b) 2557dd7cddfSDavid du Colombier { 2567dd7cddfSDavid du Colombier VGAscr *scr; 2577dd7cddfSDavid du Colombier int d; 2587dd7cddfSDavid du Colombier 2597dd7cddfSDavid du Colombier scr = &vgascreen[0]; 2607dd7cddfSDavid du Colombier d = scr->palettedepth; 2617dd7cddfSDavid du Colombier 2627dd7cddfSDavid du Colombier lock(&cursor); 2637dd7cddfSDavid du Colombier scr->colormap[p][0] = r; 2647dd7cddfSDavid du Colombier scr->colormap[p][1] = g; 2657dd7cddfSDavid du Colombier scr->colormap[p][2] = b; 2667dd7cddfSDavid du Colombier vgao(PaddrW, p); 2677dd7cddfSDavid du Colombier vgao(Pdata, r>>(32-d)); 2687dd7cddfSDavid du Colombier vgao(Pdata, g>>(32-d)); 2697dd7cddfSDavid du Colombier vgao(Pdata, b>>(32-d)); 2707dd7cddfSDavid du Colombier unlock(&cursor); 2717dd7cddfSDavid du Colombier 2727dd7cddfSDavid du Colombier return ~0; 2737dd7cddfSDavid du Colombier } 2747dd7cddfSDavid du Colombier 2757dd7cddfSDavid du Colombier /* 2767dd7cddfSDavid du Colombier * On some video cards (e.g. Mach64), the palette is used as the 2777dd7cddfSDavid du Colombier * DAC registers for >8-bit modes. We don't want to set them when the user 2787dd7cddfSDavid du Colombier * is trying to set a colormap and the card is in one of these modes. 2797dd7cddfSDavid du Colombier */ 2807dd7cddfSDavid du Colombier int 2817dd7cddfSDavid du Colombier setcolor(ulong p, ulong r, ulong g, ulong b) 2827dd7cddfSDavid du Colombier { 2837dd7cddfSDavid du Colombier VGAscr *scr; 2847dd7cddfSDavid du Colombier int x; 2857dd7cddfSDavid du Colombier 2867dd7cddfSDavid du Colombier scr = &vgascreen[0]; 2877dd7cddfSDavid du Colombier if(scr->gscreen == nil) 2887dd7cddfSDavid du Colombier return 0; 2897dd7cddfSDavid du Colombier 2907dd7cddfSDavid du Colombier switch(scr->gscreen->depth){ 2917dd7cddfSDavid du Colombier case 1: 2927dd7cddfSDavid du Colombier case 2: 2937dd7cddfSDavid du Colombier case 4: 2947dd7cddfSDavid du Colombier x = 0x0F; 2957dd7cddfSDavid du Colombier break; 2967dd7cddfSDavid du Colombier case 8: 2977dd7cddfSDavid du Colombier x = 0xFF; 2987dd7cddfSDavid du Colombier break; 2997dd7cddfSDavid du Colombier default: 3007dd7cddfSDavid du Colombier return 0; 3017dd7cddfSDavid du Colombier } 3027dd7cddfSDavid du Colombier p &= x; 3037dd7cddfSDavid du Colombier 3047dd7cddfSDavid du Colombier return setpalette(p, r, g, b); 3057dd7cddfSDavid du Colombier } 3067dd7cddfSDavid du Colombier 3077dd7cddfSDavid du Colombier int 3087dd7cddfSDavid du Colombier cursoron(int dolock) 3097dd7cddfSDavid du Colombier { 3107dd7cddfSDavid du Colombier VGAscr *scr; 3117dd7cddfSDavid du Colombier int v; 3127dd7cddfSDavid du Colombier 3137dd7cddfSDavid du Colombier scr = &vgascreen[0]; 3147dd7cddfSDavid du Colombier if(scr->cur == nil || scr->cur->move == nil) 3157dd7cddfSDavid du Colombier return 0; 3167dd7cddfSDavid du Colombier 3177dd7cddfSDavid du Colombier if(dolock) 3187dd7cddfSDavid du Colombier lock(&cursor); 3197dd7cddfSDavid du Colombier v = scr->cur->move(scr, mousexy()); 3207dd7cddfSDavid du Colombier if(dolock) 3217dd7cddfSDavid du Colombier unlock(&cursor); 3227dd7cddfSDavid du Colombier 3237dd7cddfSDavid du Colombier return v; 3247dd7cddfSDavid du Colombier } 3257dd7cddfSDavid du Colombier 3267dd7cddfSDavid du Colombier void 3277dd7cddfSDavid du Colombier cursoroff(int) 3287dd7cddfSDavid du Colombier { 3297dd7cddfSDavid du Colombier } 3307dd7cddfSDavid du Colombier 3317dd7cddfSDavid du Colombier void 3327dd7cddfSDavid du Colombier setcursor(Cursor* curs) 3337dd7cddfSDavid du Colombier { 3347dd7cddfSDavid du Colombier VGAscr *scr; 3357dd7cddfSDavid du Colombier 3367dd7cddfSDavid du Colombier scr = &vgascreen[0]; 3377dd7cddfSDavid du Colombier if(scr->cur == nil || scr->cur->load == nil) 3387dd7cddfSDavid du Colombier return; 3397dd7cddfSDavid du Colombier 3407dd7cddfSDavid du Colombier scr->cur->load(scr, curs); 3417dd7cddfSDavid du Colombier } 3427dd7cddfSDavid du Colombier 3437dd7cddfSDavid du Colombier int hwaccel = 1; 3449a747e4fSDavid du Colombier int hwblank = 0; /* turned on by drivers that are known good */ 3459a747e4fSDavid du Colombier int panning = 0; 3467dd7cddfSDavid du Colombier 3477dd7cddfSDavid du Colombier int 3487dd7cddfSDavid du Colombier hwdraw(Memdrawparam *par) 3497dd7cddfSDavid du Colombier { 3507dd7cddfSDavid du Colombier VGAscr *scr; 3514de34a7eSDavid du Colombier Memimage *dst, *src, *mask; 35259cc4ca5SDavid du Colombier int m; 3537dd7cddfSDavid du Colombier 3547dd7cddfSDavid du Colombier if(hwaccel == 0) 3557dd7cddfSDavid du Colombier return 0; 3567dd7cddfSDavid du Colombier 3577dd7cddfSDavid du Colombier scr = &vgascreen[0]; 3584de34a7eSDavid du Colombier if((dst=par->dst) == nil || dst->data == nil) 3597dd7cddfSDavid du Colombier return 0; 3604de34a7eSDavid du Colombier if((src=par->src) == nil || src->data == nil) 3614de34a7eSDavid du Colombier return 0; 3624de34a7eSDavid du Colombier if((mask=par->mask) == nil || mask->data == nil) 3634de34a7eSDavid du Colombier return 0; 3644de34a7eSDavid du Colombier 3654de34a7eSDavid du Colombier if(scr->cur == &swcursor){ 3664de34a7eSDavid du Colombier if(dst->data->bdata == gscreendata.bdata) 3674de34a7eSDavid du Colombier swcursoravoid(par->r); 3684de34a7eSDavid du Colombier if(src->data->bdata == gscreendata.bdata) 3694de34a7eSDavid du Colombier swcursoravoid(par->sr); 3704de34a7eSDavid du Colombier if(mask->data->bdata == gscreendata.bdata) 3714de34a7eSDavid du Colombier swcursoravoid(par->mr); 3724de34a7eSDavid du Colombier } 3737dd7cddfSDavid du Colombier 3747dd7cddfSDavid du Colombier if(dst->data->bdata != gscreendata.bdata) 3757dd7cddfSDavid du Colombier return 0; 3767dd7cddfSDavid du Colombier 3777dd7cddfSDavid du Colombier if(scr->fill==nil && scr->scroll==nil) 3787dd7cddfSDavid du Colombier return 0; 3797dd7cddfSDavid du Colombier 3807dd7cddfSDavid du Colombier /* 3817dd7cddfSDavid du Colombier * If we have an opaque mask and source is one opaque 3827dd7cddfSDavid du Colombier * pixel we can convert to the destination format and just 3837dd7cddfSDavid du Colombier * replicate with memset. 3847dd7cddfSDavid du Colombier */ 38559cc4ca5SDavid du Colombier m = Simplesrc|Simplemask|Fullmask; 3866a9fc400SDavid du Colombier if(scr->fill 3876a9fc400SDavid du Colombier && (par->state&m)==m 3886a9fc400SDavid du Colombier && ((par->srgba&0xFF) == 0xFF) 3896a9fc400SDavid du Colombier && (par->op&S) == S) 3907dd7cddfSDavid du Colombier return scr->fill(scr, par->r, par->sdval); 3917dd7cddfSDavid du Colombier 3927dd7cddfSDavid du Colombier /* 3937dd7cddfSDavid du Colombier * If no source alpha, an opaque mask, we can just copy the 3947dd7cddfSDavid du Colombier * source onto the destination. If the channels are the same and 3957dd7cddfSDavid du Colombier * the source is not replicated, memmove suffices. 3967dd7cddfSDavid du Colombier */ 3976a9fc400SDavid du Colombier m = Simplemask|Fullmask; 3986a9fc400SDavid du Colombier if(scr->scroll 3996a9fc400SDavid du Colombier && src->data->bdata==dst->data->bdata 4006a9fc400SDavid du Colombier && !(src->flags&Falpha) 4016a9fc400SDavid du Colombier && (par->state&m)==m 4026a9fc400SDavid du Colombier && (par->op&S) == S) 4037dd7cddfSDavid du Colombier return scr->scroll(scr, par->r, par->sr); 4047dd7cddfSDavid du Colombier 4057dd7cddfSDavid du Colombier return 0; 4067dd7cddfSDavid du Colombier } 4077dd7cddfSDavid du Colombier 4087dd7cddfSDavid du Colombier void 4097dd7cddfSDavid du Colombier blankscreen(int blank) 4107dd7cddfSDavid du Colombier { 4117dd7cddfSDavid du Colombier VGAscr *scr; 4127dd7cddfSDavid du Colombier 4137dd7cddfSDavid du Colombier scr = &vgascreen[0]; 4149a747e4fSDavid du Colombier if(hwblank){ 4159a747e4fSDavid du Colombier if(scr->blank) 4167dd7cddfSDavid du Colombier scr->blank(scr, blank); 4179a747e4fSDavid du Colombier else 4189a747e4fSDavid du Colombier vgablank(scr, blank); 4199a747e4fSDavid du Colombier } 4207dd7cddfSDavid du Colombier } 4214de34a7eSDavid du Colombier 4224de34a7eSDavid du Colombier void 4234de34a7eSDavid du Colombier vgalinearpciid(VGAscr *scr, int vid, int did) 4244de34a7eSDavid du Colombier { 4254de34a7eSDavid du Colombier Pcidev *p; 4264de34a7eSDavid du Colombier 4274de34a7eSDavid du Colombier p = nil; 4284de34a7eSDavid du Colombier while((p = pcimatch(p, vid, 0)) != nil){ 4294de34a7eSDavid du Colombier if(p->ccrb != 3) /* video card */ 4304de34a7eSDavid du Colombier continue; 4314de34a7eSDavid du Colombier if(did != 0 && p->did != did) 4324de34a7eSDavid du Colombier continue; 4334de34a7eSDavid du Colombier break; 4344de34a7eSDavid du Colombier } 4354de34a7eSDavid du Colombier if(p == nil) 4364de34a7eSDavid du Colombier error("pci video card not found"); 4374de34a7eSDavid du Colombier 4384de34a7eSDavid du Colombier scr->pci = p; 4394de34a7eSDavid du Colombier vgalinearpci(scr); 4404de34a7eSDavid du Colombier } 4414de34a7eSDavid du Colombier 4424de34a7eSDavid du Colombier void 4434de34a7eSDavid du Colombier vgalinearpci(VGAscr *scr) 4444de34a7eSDavid du Colombier { 4454de34a7eSDavid du Colombier ulong paddr; 4464de34a7eSDavid du Colombier int i, size, best; 4474de34a7eSDavid du Colombier Pcidev *p; 4484de34a7eSDavid du Colombier 4494de34a7eSDavid du Colombier p = scr->pci; 4504de34a7eSDavid du Colombier if(p == nil) 4514de34a7eSDavid du Colombier return; 4524de34a7eSDavid du Colombier 4534de34a7eSDavid du Colombier /* 4544de34a7eSDavid du Colombier * Scan for largest memory region on card. 4554de34a7eSDavid du Colombier * Some S3 cards (e.g. Savage) have enormous 4564de34a7eSDavid du Colombier * mmio regions (but even larger frame buffers). 457*9c06fe1dSDavid du Colombier * Some 3dfx cards (e.g., Voodoo3) have mmio 458*9c06fe1dSDavid du Colombier * buffers the same size as the frame buffer, 459*9c06fe1dSDavid du Colombier * but only the frame buffer is marked as 460*9c06fe1dSDavid du Colombier * prefetchable (bar&8). If a card doesn't fit 461*9c06fe1dSDavid du Colombier * into these heuristics, its driver will have to 462*9c06fe1dSDavid du Colombier * call vgalinearaddr directly. 4634de34a7eSDavid du Colombier */ 4644de34a7eSDavid du Colombier best = -1; 4654de34a7eSDavid du Colombier for(i=0; i<nelem(p->mem); i++){ 4664de34a7eSDavid du Colombier if(p->mem[i].bar&1) /* not memory */ 4674de34a7eSDavid du Colombier continue; 4684de34a7eSDavid du Colombier if(p->mem[i].size < 640*480) /* not big enough */ 4694de34a7eSDavid du Colombier continue; 470*9c06fe1dSDavid du Colombier if(best==-1 471*9c06fe1dSDavid du Colombier || p->mem[i].size > p->mem[best].size 472*9c06fe1dSDavid du Colombier || (p->mem[i].size == p->mem[best].size && (p->mem[i].bar&8))) 4734de34a7eSDavid du Colombier best = i; 4744de34a7eSDavid du Colombier } 4754de34a7eSDavid du Colombier if(best >= 0){ 4764de34a7eSDavid du Colombier paddr = p->mem[best].bar & ~0x0F; 4774de34a7eSDavid du Colombier size = p->mem[best].size; 4784de34a7eSDavid du Colombier vgalinearaddr(scr, paddr, size); 4794de34a7eSDavid du Colombier return; 4804de34a7eSDavid du Colombier } 4814de34a7eSDavid du Colombier error("no video memory found on pci card"); 4824de34a7eSDavid du Colombier } 4834de34a7eSDavid du Colombier 4844de34a7eSDavid du Colombier void 4854de34a7eSDavid du Colombier vgalinearaddr(VGAscr *scr, ulong paddr, int size) 4864de34a7eSDavid du Colombier { 4874de34a7eSDavid du Colombier int x, nsize; 4884de34a7eSDavid du Colombier ulong npaddr; 4894de34a7eSDavid du Colombier 4904de34a7eSDavid du Colombier /* 4914de34a7eSDavid du Colombier * new approach. instead of trying to resize this 4924de34a7eSDavid du Colombier * later, let's assume that we can just allocate the 4934de34a7eSDavid du Colombier * entire window to start with. 4944de34a7eSDavid du Colombier */ 4954de34a7eSDavid du Colombier 4964de34a7eSDavid du Colombier if(scr->paddr == paddr && size <= scr->apsize) 4974de34a7eSDavid du Colombier return; 4984de34a7eSDavid du Colombier 4994de34a7eSDavid du Colombier if(scr->paddr){ 5004de34a7eSDavid du Colombier /* 5014de34a7eSDavid du Colombier * could call vunmap and vmap, 5024de34a7eSDavid du Colombier * but worried about dangling pointers in devdraw 5034de34a7eSDavid du Colombier */ 5044de34a7eSDavid du Colombier error("cannot grow vga frame buffer"); 5054de34a7eSDavid du Colombier } 5064de34a7eSDavid du Colombier 5074de34a7eSDavid du Colombier /* round to page boundary, just in case */ 5084de34a7eSDavid du Colombier x = paddr&(BY2PG-1); 5094de34a7eSDavid du Colombier npaddr = paddr-x; 5104de34a7eSDavid du Colombier nsize = PGROUND(size+x); 5114de34a7eSDavid du Colombier 5124de34a7eSDavid du Colombier scr->vaddr = vmap(npaddr, nsize); 5134de34a7eSDavid du Colombier if(scr->vaddr == 0) 5144de34a7eSDavid du Colombier error("cannot allocate vga frame buffer"); 5154de34a7eSDavid du Colombier scr->vaddr = (char*)scr->vaddr+x; 5164de34a7eSDavid du Colombier scr->paddr = paddr; 5174de34a7eSDavid du Colombier scr->apsize = nsize; 5184de34a7eSDavid du Colombier } 5194de34a7eSDavid du Colombier 5204de34a7eSDavid du Colombier 5214de34a7eSDavid du Colombier /* 5224de34a7eSDavid du Colombier * Software cursor. 5234de34a7eSDavid du Colombier */ 5244de34a7eSDavid du Colombier int swvisible; /* is the cursor visible? */ 5254de34a7eSDavid du Colombier int swenabled; /* is the cursor supposed to be on the screen? */ 5264de34a7eSDavid du Colombier Memimage* swback; /* screen under cursor */ 5274de34a7eSDavid du Colombier Memimage* swimg; /* cursor image */ 5284de34a7eSDavid du Colombier Memimage* swmask; /* cursor mask */ 5294de34a7eSDavid du Colombier Memimage* swimg1; 5304de34a7eSDavid du Colombier Memimage* swmask1; 5314de34a7eSDavid du Colombier 5324de34a7eSDavid du Colombier Point swoffset; 5334de34a7eSDavid du Colombier Rectangle swrect; /* screen rectangle in swback */ 5344de34a7eSDavid du Colombier Point swpt; /* desired cursor location */ 5354de34a7eSDavid du Colombier Point swvispt; /* actual cursor location */ 5364de34a7eSDavid du Colombier int swvers; /* incremented each time cursor image changes */ 5374de34a7eSDavid du Colombier int swvisvers; /* the version on the screen */ 5384de34a7eSDavid du Colombier 5394de34a7eSDavid du Colombier /* 5404de34a7eSDavid du Colombier * called with drawlock locked for us, most of the time. 5414de34a7eSDavid du Colombier * kernel prints at inopportune times might mean we don't 5424de34a7eSDavid du Colombier * hold the lock, but memimagedraw is now reentrant so 5434de34a7eSDavid du Colombier * that should be okay: worst case we get cursor droppings. 5444de34a7eSDavid du Colombier */ 5454de34a7eSDavid du Colombier void 5464de34a7eSDavid du Colombier swcursorhide(void) 5474de34a7eSDavid du Colombier { 5484de34a7eSDavid du Colombier if(swvisible == 0) 5494de34a7eSDavid du Colombier return; 5504de34a7eSDavid du Colombier if(swback == nil) 5514de34a7eSDavid du Colombier return; 5524de34a7eSDavid du Colombier swvisible = 0; 5534de34a7eSDavid du Colombier memimagedraw(gscreen, swrect, swback, ZP, memopaque, ZP, S); 5544de34a7eSDavid du Colombier } 5554de34a7eSDavid du Colombier 5564de34a7eSDavid du Colombier void 5574de34a7eSDavid du Colombier swcursoravoid(Rectangle r) 5584de34a7eSDavid du Colombier { 5594de34a7eSDavid du Colombier if(swvisible && rectXrect(r, swrect)) 5604de34a7eSDavid du Colombier swcursorhide(); 5614de34a7eSDavid du Colombier } 5624de34a7eSDavid du Colombier 5634de34a7eSDavid du Colombier void 5644de34a7eSDavid du Colombier swcursordraw(void) 5654de34a7eSDavid du Colombier { 5664de34a7eSDavid du Colombier if(swvisible) 5674de34a7eSDavid du Colombier return; 5684de34a7eSDavid du Colombier if(swenabled == 0) 5694de34a7eSDavid du Colombier return; 5704de34a7eSDavid du Colombier if(swback == nil || swimg1 == nil || swmask1 == nil) 5714de34a7eSDavid du Colombier return; 5724de34a7eSDavid du Colombier assert(!canqlock(&drawlock)); 5734de34a7eSDavid du Colombier swvispt = swpt; 5744de34a7eSDavid du Colombier swvisvers = swvers; 5754de34a7eSDavid du Colombier swrect = rectaddpt(Rect(0,0,16,16), swvispt); 5764de34a7eSDavid du Colombier memimagedraw(swback, swback->r, gscreen, swpt, memopaque, ZP, S); 5774de34a7eSDavid du Colombier memimagedraw(gscreen, swrect, swimg1, ZP, swmask1, ZP, SoverD); 5784de34a7eSDavid du Colombier swvisible = 1; 5794de34a7eSDavid du Colombier } 5804de34a7eSDavid du Colombier 5814de34a7eSDavid du Colombier /* 5824de34a7eSDavid du Colombier * Need to lock drawlock for ourselves. 5834de34a7eSDavid du Colombier */ 5844de34a7eSDavid du Colombier void 5854de34a7eSDavid du Colombier swenable(VGAscr*) 5864de34a7eSDavid du Colombier { 5874de34a7eSDavid du Colombier swenabled = 1; 5884de34a7eSDavid du Colombier if(canqlock(&drawlock)){ 5894de34a7eSDavid du Colombier swcursordraw(); 5904de34a7eSDavid du Colombier qunlock(&drawlock); 5914de34a7eSDavid du Colombier } 5924de34a7eSDavid du Colombier } 5934de34a7eSDavid du Colombier 5944de34a7eSDavid du Colombier void 5954de34a7eSDavid du Colombier swdisable(VGAscr*) 5964de34a7eSDavid du Colombier { 5974de34a7eSDavid du Colombier swenabled = 0; 5984de34a7eSDavid du Colombier if(canqlock(&drawlock)){ 5994de34a7eSDavid du Colombier swcursorhide(); 6004de34a7eSDavid du Colombier qunlock(&drawlock); 6014de34a7eSDavid du Colombier } 6024de34a7eSDavid du Colombier } 6034de34a7eSDavid du Colombier 6044de34a7eSDavid du Colombier void 6054de34a7eSDavid du Colombier swload(VGAscr*, Cursor *curs) 6064de34a7eSDavid du Colombier { 6074de34a7eSDavid du Colombier uchar *ip, *mp; 6084de34a7eSDavid du Colombier int i, j, set, clr; 6094de34a7eSDavid du Colombier 6104de34a7eSDavid du Colombier if(!swimg || !swmask || !swimg1 || !swmask1) 6114de34a7eSDavid du Colombier return; 6124de34a7eSDavid du Colombier /* 6134de34a7eSDavid du Colombier * Build cursor image and mask. 6144de34a7eSDavid du Colombier * Image is just the usual cursor image 6154de34a7eSDavid du Colombier * but mask is a transparent alpha mask. 6164de34a7eSDavid du Colombier * 6174de34a7eSDavid du Colombier * The 16x16x8 memimages do not have 6184de34a7eSDavid du Colombier * padding at the end of their scan lines. 6194de34a7eSDavid du Colombier */ 6204de34a7eSDavid du Colombier ip = byteaddr(swimg, ZP); 6214de34a7eSDavid du Colombier mp = byteaddr(swmask, ZP); 6224de34a7eSDavid du Colombier for(i=0; i<32; i++){ 6234de34a7eSDavid du Colombier set = curs->set[i]; 6244de34a7eSDavid du Colombier clr = curs->clr[i]; 6254de34a7eSDavid du Colombier for(j=0x80; j; j>>=1){ 6264de34a7eSDavid du Colombier *ip++ = set&j ? 0x00 : 0xFF; 6274de34a7eSDavid du Colombier *mp++ = (clr|set)&j ? 0xFF : 0x00; 6284de34a7eSDavid du Colombier } 6294de34a7eSDavid du Colombier } 6304de34a7eSDavid du Colombier swoffset = curs->offset; 6314de34a7eSDavid du Colombier swvers++; 6324de34a7eSDavid du Colombier memimagedraw(swimg1, swimg1->r, swimg, ZP, memopaque, ZP, S); 6334de34a7eSDavid du Colombier memimagedraw(swmask1, swmask1->r, swmask, ZP, memopaque, ZP, S); 6344de34a7eSDavid du Colombier } 6354de34a7eSDavid du Colombier 6364de34a7eSDavid du Colombier int 6374de34a7eSDavid du Colombier swmove(VGAscr*, Point p) 6384de34a7eSDavid du Colombier { 6394de34a7eSDavid du Colombier swpt = addpt(p, swoffset); 6404de34a7eSDavid du Colombier return 0; 6414de34a7eSDavid du Colombier } 6424de34a7eSDavid du Colombier 6434de34a7eSDavid du Colombier void 6444de34a7eSDavid du Colombier swcursorclock(void) 6454de34a7eSDavid du Colombier { 6464de34a7eSDavid du Colombier int x; 6474de34a7eSDavid du Colombier 6484de34a7eSDavid du Colombier if(!swenabled) 6494de34a7eSDavid du Colombier return; 6504de34a7eSDavid du Colombier if(swvisible && eqpt(swpt, swvispt) && swvers==swvisvers) 6514de34a7eSDavid du Colombier return; 6524de34a7eSDavid du Colombier 6534de34a7eSDavid du Colombier x = splhi(); 6544de34a7eSDavid du Colombier if(swenabled) 6554de34a7eSDavid du Colombier if(!swvisible || !eqpt(swpt, swvispt) || swvers!=swvisvers) 6564de34a7eSDavid du Colombier if(canqlock(&drawlock)){ 6574de34a7eSDavid du Colombier swcursorhide(); 6584de34a7eSDavid du Colombier swcursordraw(); 6594de34a7eSDavid du Colombier qunlock(&drawlock); 6604de34a7eSDavid du Colombier } 6614de34a7eSDavid du Colombier splx(x); 6624de34a7eSDavid du Colombier } 6634de34a7eSDavid du Colombier 6644de34a7eSDavid du Colombier void 6654de34a7eSDavid du Colombier swcursorinit(void) 6664de34a7eSDavid du Colombier { 6674de34a7eSDavid du Colombier static int init, warned; 6684de34a7eSDavid du Colombier VGAscr *scr; 6694de34a7eSDavid du Colombier 6704de34a7eSDavid du Colombier didswcursorinit = 1; 6714de34a7eSDavid du Colombier if(!init){ 6724de34a7eSDavid du Colombier init = 1; 67326ad7229SDavid du Colombier addclock0link(swcursorclock, 10); 6744de34a7eSDavid du Colombier } 6754de34a7eSDavid du Colombier scr = &vgascreen[0]; 6764de34a7eSDavid du Colombier if(scr==nil || scr->gscreen==nil) 6774de34a7eSDavid du Colombier return; 6784de34a7eSDavid du Colombier 6794de34a7eSDavid du Colombier if(scr->dev == nil || scr->dev->linear == nil){ 6804de34a7eSDavid du Colombier if(!warned){ 6814de34a7eSDavid du Colombier print("cannot use software cursor on non-linear vga screen\n"); 6824de34a7eSDavid du Colombier warned = 1; 6834de34a7eSDavid du Colombier } 6844de34a7eSDavid du Colombier return; 6854de34a7eSDavid du Colombier } 6864de34a7eSDavid du Colombier 6874de34a7eSDavid du Colombier if(swback){ 6884de34a7eSDavid du Colombier freememimage(swback); 6894de34a7eSDavid du Colombier freememimage(swmask); 6904de34a7eSDavid du Colombier freememimage(swmask1); 6914de34a7eSDavid du Colombier freememimage(swimg); 6924de34a7eSDavid du Colombier freememimage(swimg1); 6934de34a7eSDavid du Colombier } 6944de34a7eSDavid du Colombier 6954de34a7eSDavid du Colombier swback = allocmemimage(Rect(0,0,32,32), gscreen->chan); 6964de34a7eSDavid du Colombier swmask = allocmemimage(Rect(0,0,16,16), GREY8); 6974de34a7eSDavid du Colombier swmask1 = allocmemimage(Rect(0,0,16,16), GREY1); 6984de34a7eSDavid du Colombier swimg = allocmemimage(Rect(0,0,16,16), GREY8); 6994de34a7eSDavid du Colombier swimg1 = allocmemimage(Rect(0,0,16,16), GREY1); 7004de34a7eSDavid du Colombier if(swback==nil || swmask==nil || swmask1==nil || swimg==nil || swimg1 == nil){ 7014de34a7eSDavid du Colombier print("software cursor: allocmemimage: %r"); 7024de34a7eSDavid du Colombier return; 7034de34a7eSDavid du Colombier } 7044de34a7eSDavid du Colombier 7054de34a7eSDavid du Colombier memfillcolor(swmask, DOpaque); 7064de34a7eSDavid du Colombier memfillcolor(swmask1, DOpaque); 7074de34a7eSDavid du Colombier memfillcolor(swimg, DBlack); 7084de34a7eSDavid du Colombier memfillcolor(swimg1, DBlack); 7094de34a7eSDavid du Colombier } 7104de34a7eSDavid du Colombier 7114de34a7eSDavid du Colombier VGAcur swcursor = 7124de34a7eSDavid du Colombier { 7134de34a7eSDavid du Colombier "soft", 7144de34a7eSDavid du Colombier swenable, 7154de34a7eSDavid du Colombier swdisable, 7164de34a7eSDavid du Colombier swload, 7174de34a7eSDavid du Colombier swmove, 7184de34a7eSDavid du Colombier }; 7194de34a7eSDavid du Colombier 720