ref: d0fb274a9820f51d4fe0eb8cd13c6f0c53c0a3df
dir: /screen.c/
#include "u.h" #include "../port/lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include "io.h" #define Image IMAGE #include <draw.h> #include <memdraw.h> #include "screen.h" enum { /* display controller registers */ RDrev = 0x400, RDsysconf = 0x410, DSCidle = 1<<0, DSCreset = 1<<1, DSCidlesmart = 2<<3, RDsysstat = 0x414, DSSreset = 1<<0, RDirqstat = 0x418, RDirqen = 0x41c, RDcontrol = 0x440, DClcdon = 1<<0, DClcdactive = 1<<3, DClcdclockrun = 1<<27, DClcdenable = 1<<28, DClcdenablehi = 1<<29, DClcdbits24 = 3<<8, RDconfig = 0x444, DCNgamma = 1<<3, RDdefcolor = 0x44c, RDtranscolor = 0x454, RDlinestat = 0x45c, RDlineintr = 0x460, RDtimeh = 0x464, RDtimev = 0x468, RDsize = 0x47c, /* display controller graphics layer registers */ RDgfxba = 0x480, RDgfxpos = 0x488, RDgfxsize = 0x48c, RDgfxattr = 0x4a0, DGAenable = 1<<0, DGAfmt = 0x6<<1, DGAburst = 0x2<<6, RDgfxrowinc = 0x4ac, RDgfxpixelinc = 0x4b0, }; enum { Tab = 4, Scroll = 8, }; #define RDdefcolorn(n) (RDdefcolor + (n)*4) #define RDtranscolorn(n) (RDtranscolor + (n)*4) #define RDgfxban(n) (RDgfxba + (n)*4) #define TIME(s, f, b) ((s & 0xff) | (f & 0xfff) << 8 | (b & 0xfff) << 20) #define POS(x, y) ((x)<<16 | (y)) #define SIZE(w, h) ((h-1)<<16 | (w-1)) typedef struct Ctlr Ctlr; struct Ctlr { Lock; u32int *io; Memdata scrdata; Memimage *scrimg; Memsubfont *scrfont; Rectangle win; Point font; Point pos; }; static Ctlr ctlr = { .io = (u32int*) PHYSDSS, }; #define csr32r(c, r) ((c)->io[(r)/4]) #define csr32w(c, r, w) ((c)->io[(r)/4] = (w)) static void myscreenputs(char *s, int n); static int screendatainit(Ctlr *ctlr) { Rectangle r; if(memimageinit() < 0) return -1; r = Rect(0, 0, 800, 480); ctlr->scrdata.ref = 1; ctlr->scrdata.bdata = ucalloc(r.max.x * r.max.y * 2); if(!ctlr->scrdata.bdata) return -1; ctlr->scrimg = allocmemimaged(r, RGB16, &ctlr->scrdata); if(!ctlr->scrimg) return -1; ctlr->scrfont = getmemdefont(); return 0; } static Memimage* screenmkcolor(Memimage *scr, ulong color) { Memimage *i; i = allocmemimage(Rect(0, 0, 1, 1), scr->chan); if(i) { i->flags |= Frepl; i->clipr = scr->r; memfillcolor(i, color); } return i; } static void screenwin(Ctlr *ctlr) { Rectangle r; Memimage *i; Point p; int h; ctlr->font.y = h = ctlr->scrfont->height; ctlr->font.x = ctlr->scrfont->info[' '].width; r = ctlr->scrimg->r; if(i = screenmkcolor(ctlr->scrimg, 0x0D686BFF)) { memimagedraw(ctlr->scrimg, r, i, ZP, memopaque, ZP, S); freememimage(i); } r = insetrect(r, 16); memimagedraw(ctlr->scrimg, r, memblack, ZP, memopaque, ZP, S); r = insetrect(r, 4); memimagedraw(ctlr->scrimg, r, memwhite, ZP, memopaque, ZP, S); if(i = screenmkcolor(ctlr->scrimg, 0xaaaaaaff)) { memimagedraw(ctlr->scrimg, Rpt(r.min, Pt(r.max.x, r.min.y+h+12)), i, ZP, memopaque, ZP, S); freememimage(i); r = insetrect(r, 6); p = r.min; memimagestring(ctlr->scrimg, p, memblack, ZP, getmemdefont(), " Plan 9 Console "); } ctlr->win = Rpt(addpt(r.min, Pt(0, h + 6)), subpt(r.max, Pt(6, 6))); ctlr->pos = ctlr->win.min; screenputs = myscreenputs; } void screeninit(void) { Ctlr *c; c = &ctlr; if(screendatainit(c) < 0) return; screenwin(c); screenputs(kmesg.buf, kmesg.n); /* reset the display controller */ csr32w(c, RDsysconf, DSCreset); while(!(csr32r(c, RDsysstat) & DSSreset)) ; /* configure the display controller */ csr32w(c, RDsysconf, DSCidle | DSCidlesmart); csr32w(c, RDcontrol, DClcdbits24); csr32w(c, RDconfig, DCNgamma); /* configure display size and timings */ csr32w(c, RDtimeh, TIME(3, 15, 11)); csr32w(c, RDtimev, TIME(2, 3, 3)); csr32w(c, RDsize, SIZE(800, 480)); /* enable the lcd interface */ csr32w(c, RDcontrol, csr32r(c, RDcontrol) | DClcdactive | DClcdclockrun | DClcdenablehi); csr32w(c, RDcontrol, csr32r(c, RDcontrol) | DClcdenable); /* configure the graphics layer */ csr32w(c, RDgfxban(0), (uintptr) c->scrdata.bdata); csr32w(c, RDgfxpos, POS(c->scrimg->r.min.x, c->scrimg->r.min.y)); csr32w(c, RDgfxsize, SIZE(c->scrimg->r.max.x, c->scrimg->r.max.y)); csr32w(c, RDgfxattr, DGAfmt | DGAburst); csr32w(c, RDgfxrowinc, 1); csr32w(c, RDgfxpixelinc, 1); /* enable gfx pipeline and turn lcd on */ csr32w(c, RDgfxattr, csr32r(c, RDgfxattr) | DGAenable); csr32w(c, RDcontrol, csr32r(c, RDcontrol) | DClcdon); conf.monitor = 1; } static void screenscroll(Ctlr *ctlr) { int o, h; Point p; Rectangle r; h = ctlr->font.y; o = Scroll * h; r = Rpt(ctlr->win.min, Pt(ctlr->win.max.x, ctlr->win.max.y - o)); p = Pt(ctlr->win.min.x, ctlr->win.min.y + o); memimagedraw(ctlr->scrimg, r, ctlr->scrimg, p, nil, p, S); flushmemscreen(r); r = Rpt(Pt(ctlr->win.min.x, ctlr->win.max.y - o), ctlr->win.max); memimagedraw(ctlr->scrimg, r, memwhite, ZP, nil, ZP, S); flushmemscreen(r); ctlr->pos.y -= o; } static void screenputc(Ctlr *ctlr, char *buf) { Point p; Rectangle r; uint chr; int w, h; static int *xp; static int xbuf[256]; w = ctlr->font.x; h = ctlr->font.y; if(xp < xbuf || xp >= &xbuf[nelem(xbuf)]) xp = xbuf; switch(buf[0]) { case '\n': if(ctlr->pos.y + h >= ctlr->win.max.y) screenscroll(ctlr); ctlr->pos.y += h; screenputc(ctlr, "\r"); break; case '\r': xp = xbuf; ctlr->pos.x = ctlr->win.min.x; break; case '\t': if(ctlr->pos.x >= ctlr->win.max.x - 4 * w) screenputc(ctlr, "\n"); chr = (ctlr->pos.x - ctlr->win.min.x) / w; chr = Tab - chr % Tab; *xp++ = ctlr->pos.x; r = Rect(ctlr->pos.x, ctlr->pos.y, ctlr->pos.x + chr * w, ctlr->pos.y + h); memimagedraw(ctlr->scrimg, r, memwhite, ZP, memopaque, ZP, S); flushmemscreen(r); ctlr->pos.x += chr * w; break; case '\b': if(xp <= xbuf) break; xp--; r = Rect(*xp, ctlr->pos.y, ctlr->pos.x, ctlr->pos.y + h); memimagedraw(ctlr->scrimg, r, memwhite, ZP, memopaque, ZP, S); ctlr->pos.x = *xp; break; case '\0': break; default: p = memsubfontwidth(getmemdefont(), buf); w = p.x; if(ctlr->pos.x >= ctlr->win.max.x - w) screenputc(ctlr, "\n"); *xp++ = ctlr->pos.x; r = Rect(ctlr->pos.x, ctlr->pos.y, ctlr->pos.x + w, ctlr->pos.y + h); memimagedraw(ctlr->scrimg, r, memwhite, ZP, memopaque, ZP, S); memimagestring(ctlr->scrimg, ctlr->pos, memblack, ZP, getmemdefont(), buf); ctlr->pos.x += w; break; } } static void myscreenputs(char *s, int n) { Ctlr *c; Rune r; int i; char buf[UTFmax]; c = &ctlr; if(!c->scrimg) return; if(!islo()) { /* don't deadlock trying to print in an interrupt */ if(!canlock(c)) return; } else { lock(c); } while(n > 0) { i = chartorune(&r, s); if(i == 0) { s++; n--; continue; } memmove(buf, s, i); buf[i] = 0; s += i; n -= i; screenputc(c, buf); } unlock(c); } Memdata* attachscreen(Rectangle *r, ulong *chan, int *d, int *width, int *softscreen) { Ctlr *c; c = &ctlr; if(!c->scrimg) return nil; *r = c->scrimg->r; *d = c->scrimg->depth; *chan = c->scrimg->chan; *width = c->scrimg->width; *softscreen = 1; c->scrdata.ref++; return &c->scrdata; } void getcolor(ulong, ulong *, ulong *, ulong *) { } int setcolor(ulong, ulong, ulong, ulong) { return 0; } void flushmemscreen(Rectangle) { } void mouseresize(void) { }