summaryrefslogtreecommitdiff
path: root/os/pc/screen.c
diff options
context:
space:
mode:
Diffstat (limited to 'os/pc/screen.c')
-rw-r--r--os/pc/screen.c410
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)
+{
+}