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)
55 unlock(&vgascreenlock);
60 scr->gscreendata = nil;
63 freememimage(gscreen);
68 if(scr->dev && scr->dev->page){
69 scr->vaddr = KADDR(VGAMEM());
75 gscreen = allocmemimage(Rect(0,0,x,y), chan);
81 if((md.bdata = scr->vaddr) == 0)
82 error("framebuffer not maped");
83 gscreen = allocmemimaged(Rect(0,0,x,y), chan, &md);
84 scr->useflush = scr->dev && scr->dev->flush;
87 error("no memory for vga memimage");
89 scr->palettedepth = 6; /* default */
90 scr->memdefont = getmemdefont();
91 scr->gscreen = gscreen;
92 scr->gscreendata = gscreen->data;
94 physgscreenr = gscreen->r;
98 unlock(&vgascreenlock);
111 screenaperture(int size, int align)
117 if(scr->paddr) /* set up during enable */
123 if(scr->dev && scr->dev->linear){
124 scr->dev->linear(scr, size, align);
129 * Need to allocate some physical address space.
130 * The driver will tell the card to use it.
132 size = PGROUND(size);
133 scr->paddr = upaalloc(size, align);
136 scr->vaddr = vmap(scr->paddr, size);
137 if(scr->vaddr == nil)
145 attachscreen(Rectangle* r, ulong* chan, int* d, int* width, int *softscreen)
150 if(scr->gscreen == nil || scr->gscreendata == nil)
153 *r = scr->gscreen->clipr;
154 *chan = scr->gscreen->chan;
155 *d = scr->gscreen->depth;
156 *width = scr->gscreen->width;
157 if(scr->gscreendata->allocd){
159 * we use a memimage as softscreen. devdraw will create its own
160 * screen image on the backing store of that image. when our gscreen
161 * and devdraws screenimage gets freed, the imagedata will
164 *softscreen = 0xa110c;
165 scr->gscreendata->ref++;
167 *softscreen = scr->useflush ? 1 : 0;
168 return scr->gscreendata->bdata;
172 flushmemscreen(Rectangle r)
175 uchar *sp, *disp, *sdisp, *edisp;
176 int y, len, incs, off, page;
179 if(scr->gscreen == nil || scr->useflush == 0)
181 if(scr->dev && scr->dev->flush){
182 scr->dev->flush(scr, r);
185 if(rectclip(&r, scr->gscreen->r) == 0)
188 incs = scr->gscreen->width*BY2WD;
189 off = (r.min.x*scr->gscreen->depth) / 8;
190 len = (r.max.x*scr->gscreen->depth + 7) / 8;
193 sp = scr->gscreendata->bdata + scr->gscreen->zero + off;
196 * Linear framebuffer with softscreen.
200 for(y = r.min.y; y < r.max.y; y++) {
201 memmove(sdisp, sp, len);
209 * Paged framebuffer window.
211 if(scr->dev == nil || scr->dev->page == nil)
214 page = off/scr->apsize;
217 edisp = disp+scr->apsize;
219 scr->dev->page(scr, page);
220 for(y = r.min.y; y < r.max.y; y++) {
221 if(sdisp + incs < edisp) {
222 memmove(sdisp, sp, len);
231 memmove(sdisp, sp, off);
232 scr->dev->page(scr, page);
234 memmove(disp, sp+off, len - off);
237 memmove(sdisp, sp, len);
238 scr->dev->page(scr, page);
241 sdisp += incs - scr->apsize;
247 getcolor(ulong p, ulong* pr, ulong* pg, ulong* pb)
253 if(scr->gscreen == nil)
256 switch(scr->gscreen->depth){
267 *pr = scr->colormap[p][0];
268 *pg = scr->colormap[p][1];
269 *pb = scr->colormap[p][2];
274 setpalette(ulong p, ulong r, ulong g, ulong b)
280 d = scr->palettedepth;
283 scr->colormap[p][0] = r;
284 scr->colormap[p][1] = g;
285 scr->colormap[p][2] = b;
287 vgao(Pdata, r>>(32-d));
288 vgao(Pdata, g>>(32-d));
289 vgao(Pdata, b>>(32-d));
296 * On some video cards (e.g. Mach64), the palette is used as the
297 * DAC registers for >8-bit modes. We don't want to set them when the user
298 * is trying to set a colormap and the card is in one of these modes.
301 setcolor(ulong p, ulong r, ulong g, ulong b)
307 if(scr->gscreen == nil)
310 switch(scr->gscreen->depth){
324 return setpalette(p, r, g, b);
330 swcursorload(&arrow);
339 swload(VGAscr*, Cursor *curs)
345 swmove(VGAscr*, Point p)
370 if(cur == nil || cur->move == nil)
376 cur->move(scr, mousexy());
388 setcursor(Cursor* curs)
393 if(scr->cur == nil || scr->cur->load == nil)
396 scr->cur->load(scr, curs);
400 int hwblank = 0; /* turned on by drivers that are known good */
404 hwdraw(Memdrawparam *par)
407 Memimage *dst, *src, *mask;
412 scrd = scr->gscreendata;
413 if(scr->gscreen == nil || scrd == nil)
415 if((dst = par->dst) == nil || dst->data == nil)
417 if((src = par->src) && src->data == nil)
419 if((mask = par->mask) && mask->data == nil)
421 if(scr->cur == &swcursor){
422 if(dst->data->bdata == scrd->bdata)
423 swcursoravoid(par->r);
424 if(src && src->data->bdata == scrd->bdata)
425 swcursoravoid(par->sr);
426 if(mask && mask->data->bdata == scrd->bdata)
427 swcursoravoid(par->mr);
431 if(dst->data->bdata != scrd->bdata || src == nil || mask == nil)
433 if(scr->fill==nil && scr->scroll==nil)
437 * If we have an opaque mask and source is one opaque
438 * pixel we can convert to the destination format and just
439 * replicate with memset.
441 m = Simplesrc|Simplemask|Fullmask;
444 && ((par->srgba&0xFF) == 0xFF)
446 return scr->fill(scr, par->r, par->sdval);
449 * If no source alpha, an opaque mask, we can just copy the
450 * source onto the destination. If the channels are the same and
451 * the source is not replicated, memmove suffices.
453 m = Simplemask|Fullmask;
455 && src->data->bdata==dst->data->bdata
456 && !(src->flags&Falpha)
459 return scr->scroll(scr, par->r, par->sr);
465 blankscreen(int blank)
472 scr->blank(scr, blank);
474 vgablank(scr, blank);
479 vgalinearpci(VGAscr *scr)
490 * Scan for largest memory region on card.
491 * Some S3 cards (e.g. Savage) have enormous
492 * mmio regions (but even larger frame buffers).
493 * Some 3dfx cards (e.g., Voodoo3) have mmio
494 * buffers the same size as the frame buffer,
495 * but only the frame buffer is marked as
496 * prefetchable (bar&8). If a card doesn't fit
497 * into these heuristics, its driver will have to
498 * call vgalinearaddr directly.
501 for(i=0; i<nelem(p->mem); i++){
502 if(p->mem[i].bar&1) /* not memory */
504 if(p->mem[i].size < 640*480) /* not big enough */
507 || p->mem[i].size > p->mem[best].size
508 || (p->mem[i].size == p->mem[best].size
510 && !(p->mem[best].bar&8)))
514 paddr = p->mem[best].bar & ~0x0F;
515 size = p->mem[best].size;
516 vgalinearaddr(scr, paddr, size);
519 error("no video memory found on pci card");
523 vgalinearaddr(VGAscr *scr, ulong paddr, int size)
529 * new approach. instead of trying to resize this
530 * later, let's assume that we can just allocate the
531 * entire window to start with.
534 if(scr->paddr == paddr && size <= scr->apsize)
539 * could call vunmap and vmap,
540 * but worried about dangling pointers in devdraw
542 error("cannot grow vga frame buffer");
545 /* round to page boundary, just in case */
548 nsize = PGROUND(size+x);
551 * Don't bother trying to map more than 4000x4000x32 = 64MB.
552 * We only have a 256MB window.
556 scr->vaddr = vmap(npaddr, nsize);
558 error("cannot allocate vga frame buffer");
559 scr->vaddr = (char*)scr->vaddr+x;
562 /* let mtrr harmlessly fail on old CPUs, e.g., P54C */
564 mtrr(npaddr, nsize, "wc");