2 #include "../port/lib.h"
8 #include "../port/error.h"
16 #define RGB2K(r,g,b) ((156763*(r)+307758*(g)+59769*(b))>>19)
20 Rectangle physgscreenr;
28 { 0xFF, 0xFF, 0x80, 0x01, 0x80, 0x02, 0x80, 0x0C,
29 0x80, 0x10, 0x80, 0x10, 0x80, 0x08, 0x80, 0x04,
30 0x80, 0x02, 0x80, 0x01, 0x80, 0x02, 0x8C, 0x04,
31 0x92, 0x08, 0x91, 0x10, 0xA0, 0xA0, 0xC0, 0x40,
33 { 0x00, 0x00, 0x7F, 0xFE, 0x7F, 0xFC, 0x7F, 0xF0,
34 0x7F, 0xE0, 0x7F, 0xE0, 0x7F, 0xF0, 0x7F, 0xF8,
35 0x7F, 0xFC, 0x7F, 0xFE, 0x7F, 0xFC, 0x73, 0xF8,
36 0x61, 0xF0, 0x60, 0xE0, 0x40, 0x40, 0x00, 0x00,
41 screensize(int x, int y, int, ulong chan)
51 if(memimageinit() < 0)
52 error("memimageinit failed");
56 unlock(&vgascreenlock);
61 scr->gscreendata = nil;
64 freememimage(gscreen);
69 if(scr->dev && scr->dev->page){
70 scr->vaddr = KADDR(VGAMEM());
76 gscreen = allocmemimage(Rect(0,0,x,y), chan);
82 if((md.bdata = scr->vaddr) == 0)
83 error("framebuffer not maped");
84 gscreen = allocmemimaged(Rect(0,0,x,y), chan, &md);
85 scr->useflush = scr->dev && scr->dev->flush;
88 error("no memory for vga memimage");
90 scr->palettedepth = 6; /* default */
91 scr->memdefont = getmemdefont();
92 scr->gscreen = gscreen;
93 scr->gscreendata = gscreen->data;
95 physgscreenr = gscreen->r;
99 unlock(&vgascreenlock);
112 screenaperture(int size, int align)
118 if(scr->paddr) /* set up during enable */
124 if(scr->dev && scr->dev->linear){
125 scr->dev->linear(scr, size, align);
130 * Need to allocate some physical address space.
131 * The driver will tell the card to use it.
133 size = PGROUND(size);
134 scr->paddr = upaalloc(size, align);
137 scr->vaddr = vmap(scr->paddr, size);
138 if(scr->vaddr == nil)
146 attachscreen(Rectangle* r, ulong* chan, int* d, int* width, int *softscreen)
151 if(scr->gscreen == nil || scr->gscreendata == nil)
154 *r = scr->gscreen->clipr;
155 *chan = scr->gscreen->chan;
156 *d = scr->gscreen->depth;
157 *width = scr->gscreen->width;
158 if(scr->gscreendata->allocd){
160 * we use a memimage as softscreen. devdraw will create its own
161 * screen image on the backing store of that image. when our gscreen
162 * and devdraws screenimage gets freed, the imagedata will
165 *softscreen = 0xa110c;
166 scr->gscreendata->ref++;
168 *softscreen = scr->useflush ? 1 : 0;
169 return scr->gscreendata->bdata;
173 flushmemscreen(Rectangle r)
176 uchar *sp, *disp, *sdisp, *edisp;
177 int y, len, incs, off, page;
180 if(scr->gscreen == nil || scr->useflush == 0)
182 if(scr->dev && scr->dev->flush){
183 scr->dev->flush(scr, r);
186 if(rectclip(&r, scr->gscreen->r) == 0)
189 incs = scr->gscreen->width*sizeof(ulong);
190 off = (r.min.x*scr->gscreen->depth) / 8;
191 len = (r.max.x*scr->gscreen->depth + 7) / 8;
194 sp = scr->gscreendata->bdata + scr->gscreen->zero + off;
197 * Linear framebuffer with softscreen.
201 for(y = r.min.y; y < r.max.y; y++) {
202 memmove(sdisp, sp, len);
210 * Paged framebuffer window.
212 if(scr->dev == nil || scr->dev->page == nil)
215 page = off/scr->apsize;
218 edisp = disp+scr->apsize;
220 scr->dev->page(scr, page);
221 for(y = r.min.y; y < r.max.y; y++) {
222 if(sdisp + incs < edisp) {
223 memmove(sdisp, sp, len);
232 memmove(sdisp, sp, off);
233 scr->dev->page(scr, page);
235 memmove(disp, sp+off, len - off);
238 memmove(sdisp, sp, len);
239 scr->dev->page(scr, page);
242 sdisp += incs - scr->apsize;
248 getcolor(ulong p, ulong* pr, ulong* pg, ulong* pb)
254 if(scr->gscreen == nil)
257 switch(scr->gscreen->depth){
268 *pr = scr->colormap[p][0];
269 *pg = scr->colormap[p][1];
270 *pb = scr->colormap[p][2];
275 setpalette(ulong p, ulong r, ulong g, ulong b)
281 d = scr->palettedepth;
284 scr->colormap[p][0] = r;
285 scr->colormap[p][1] = g;
286 scr->colormap[p][2] = b;
288 vgao(Pdata, r>>(32-d));
289 vgao(Pdata, g>>(32-d));
290 vgao(Pdata, b>>(32-d));
297 * On some video cards (e.g. Mach64), the palette is used as the
298 * DAC registers for >8-bit modes. We don't want to set them when the user
299 * is trying to set a colormap and the card is in one of these modes.
302 setcolor(ulong p, ulong r, ulong g, ulong b)
308 if(scr->gscreen == nil)
311 switch(scr->gscreen->depth){
325 return setpalette(p, r, g, b);
331 swcursorload(&arrow);
340 swload(VGAscr*, Cursor *curs)
346 swmove(VGAscr*, Point p)
371 if(cur == nil || cur->move == nil)
377 cur->move(scr, mousexy());
389 setcursor(Cursor* curs)
394 if(scr->cur == nil || scr->cur->load == nil)
397 scr->cur->load(scr, curs);
401 int hwblank = 0; /* turned on by drivers that are known good */
405 hwdraw(Memdrawparam *par)
408 Memimage *dst, *src, *mask;
413 scrd = scr->gscreendata;
414 if(scr->gscreen == nil || scrd == nil)
416 if((dst = par->dst) == nil || dst->data == nil)
418 if((src = par->src) && src->data == nil)
420 if((mask = par->mask) && mask->data == nil)
422 if(scr->cur == &swcursor){
423 if(dst->data->bdata == scrd->bdata)
424 swcursoravoid(par->r);
425 if(src && src->data->bdata == scrd->bdata)
426 swcursoravoid(par->sr);
427 if(mask && mask->data->bdata == scrd->bdata)
428 swcursoravoid(par->mr);
432 if(dst->data->bdata != scrd->bdata || src == nil || mask == nil)
434 if(scr->fill==nil && scr->scroll==nil)
438 * If we have an opaque mask and source is one opaque
439 * pixel we can convert to the destination format and just
440 * replicate with memset.
442 m = Simplesrc|Simplemask|Fullmask;
445 && ((par->srgba&0xFF) == 0xFF)
447 return scr->fill(scr, par->r, par->sdval);
450 * If no source alpha, an opaque mask, we can just copy the
451 * source onto the destination. If the channels are the same and
452 * the source is not replicated, memmove suffices.
454 m = Simplemask|Fullmask;
456 && src->data->bdata==dst->data->bdata
457 && !(src->flags&Falpha)
460 return scr->scroll(scr, par->r, par->sr);
466 blankscreen(int blank)
473 scr->blank(scr, blank);
475 vgablank(scr, blank);
480 vgalinearpci(VGAscr *scr)
491 * Scan for largest memory region on card.
492 * Some S3 cards (e.g. Savage) have enormous
493 * mmio regions (but even larger frame buffers).
494 * Some 3dfx cards (e.g., Voodoo3) have mmio
495 * buffers the same size as the frame buffer,
496 * but only the frame buffer is marked as
497 * prefetchable (bar&8). If a card doesn't fit
498 * into these heuristics, its driver will have to
499 * call vgalinearaddr directly.
502 for(i=0; i<nelem(p->mem); i++){
503 if(p->mem[i].bar&1) /* not memory */
505 if(p->mem[i].size < 640*480) /* not big enough */
508 || p->mem[i].size > p->mem[best].size
509 || (p->mem[i].size == p->mem[best].size
511 && !(p->mem[best].bar&8)))
515 paddr = p->mem[best].bar & ~0x0F;
516 size = p->mem[best].size;
517 vgalinearaddr(scr, paddr, size);
520 error("no video memory found on pci card");
524 vgalinearaddr(VGAscr *scr, ulong paddr, int size)
530 * new approach. instead of trying to resize this
531 * later, let's assume that we can just allocate the
532 * entire window to start with.
535 if(scr->paddr == paddr && size <= scr->apsize)
540 * could call vunmap and vmap,
541 * but worried about dangling pointers in devdraw
543 error("cannot grow vga frame buffer");
546 /* round to page boundary, just in case */
549 nsize = PGROUND(size+x);
552 * Don't bother trying to map more than 4000x4000x32 = 64MB.
553 * We only have a 256MB window.
557 scr->vaddr = vmap(npaddr, nsize);
559 error("cannot allocate vga frame buffer");
560 scr->vaddr = (char*)scr->vaddr+x;
563 /* let mtrr harmlessly fail on old CPUs, e.g., P54C */
565 mtrr(npaddr, nsize, "wc");