#include <cursor.h>
#include "screen.h"
-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,
- },
-};
-
Memimage *gscreen;
-static Memdata xgdata;
-static Memimage xgscreen =
-{
- { 0, 0, 800, 600 }, /* r */
- { 0, 0, 800, 600 }, /* clipr */
- 24, /* depth */
- 3, /* nchan */
- BGR24, /* chan */
- nil, /* cmap */
- &xgdata, /* data */
- 0, /* zero */
- 0, /* width in words of a single scan line */
- 0, /* layer */
- 0, /* flags */
-};
+static struct {
+ Rendez;
+
+ Rectangle rect;
+ Proc *proc;
+
+ uintptr addr;
+} fbscreen;
+
+static struct {
+ Rendez;
+
+ Cursor;
+
+ Proc *proc;
+ uintptr addr;
+} hwcursor;
void
cursoron(void)
{
+ wakeup(&hwcursor);
}
void
}
void
-setcursor(Cursor*)
+setcursor(Cursor *curs)
{
+ hwcursor.Cursor = *curs;
}
void
-flushmemscreen(Rectangle)
+flushmemscreen(Rectangle r)
{
-}
-
-void
-drawflushreal(void)
-{
- uchar *fb, *fbe;
-
- fb = xgdata.bdata;
- fbe = fb + Dx(xgscreen.r) * Dy(xgscreen.r) * 3;
- cleandse(fb, fbe);
- clean2pa(PADDR(fb), PADDR(fbe));
+ if(badrect(fbscreen.rect))
+ fbscreen.rect = r;
+ else
+ combinerect(&fbscreen.rect, r);
+ wakeup(&fbscreen);
}
void
screeninit(void)
{
- uchar *fb;
-
- fb = xspanalloc(Dx(xgscreen.r) * Dy(xgscreen.r) * 3, 64, 0);
- print("%p\n", PADDR(fb));
- memsetchan(&xgscreen, BGR24);
conf.monitor = 1;
- xgdata.bdata = fb;
- xgdata.ref = 1;
- gscreen = &xgscreen;
- gscreen->width = wordsperline(gscreen->r, gscreen->depth);
-
- memimageinit();
}
uchar*
attachscreen(Rectangle *r, ulong *chan, int* d, int *width, int *softscreen)
{
+ if(gscreen == nil)
+ return nil;
+
*r = gscreen->r;
*d = gscreen->depth;
*chan = gscreen->chan;
*width = gscreen->width;
- *softscreen = 0;
+
+ /* make devdraw use gscreen->data */
+ *softscreen = 0xa110c;
+ gscreen->data->ref++;
return gscreen->data->bdata;
}
{
}
+
+static void
+cursorproc(void *arg)
+{
+ uchar *set, *clr;
+ u32int *reg;
+ Point xy;
+ int i;
+
+ for(i = 0; i < NSEG; i++)
+ if(up->seg[i] == nil && i != ESEG)
+ break;
+ if(i == NSEG)
+ panic(up->text);
+
+ up->seg[i] = arg;
+
+ hwcursor.proc = up;
+ if(waserror()){
+ hwcursor.addr = 0;
+ hwcursor.proc = nil;
+ pexit("detached", 1);
+ }
+
+ reg = (u32int*)hwcursor.addr;
+ for(;;){
+ eqlock(&drawlock);
+ xy = addpt(mousexy(), hwcursor.offset);
+ qunlock(&drawlock);
+
+ set = hwcursor.set;
+ clr = hwcursor.clr;
+ for(i=0; i<8; i++){
+ reg[0x70/4 + i] = clr[i*4]<<24 | clr[i*4+1]<<16 | clr[i*4+2]<<8 | clr[i*4+3];
+ reg[0x90/4 + i] = set[i*4]<<24 | set[i*4+1]<<16 | set[i*4+2]<<8 | set[i*4+3];
+ }
+ reg[0] = (xy.x<<16) | (xy.y&0xFFFF);
+
+ sleep(&hwcursor, return0, nil);
+ }
+}
+
void
-mousectl(Cmdbuf *)
+mousectl(Cmdbuf *cb)
+{
+ Segment *s;
+ uintptr addr;
+
+ if(strcmp(cb->f[0], "addr") == 0 && cb->nf == 2){
+ s = nil;
+ addr = strtoul(cb->f[1], 0, 0);
+ if(addr != 0){
+ if((s = seg(up, addr, 0)) == nil || (s->type&SG_RONLY) != 0
+ || (addr&3) != 0 || addr+0xB0 > s->top)
+ error(Ebadarg);
+ incref(s);
+ }
+ if(hwcursor.proc != nil){
+ postnote(hwcursor.proc, 0, "die", NUser);
+ while(hwcursor.proc != nil)
+ sched();
+ }
+ if(addr != 0){
+ hwcursor.addr = addr;
+ kproc("cursor", cursorproc, s);
+ }
+ return;
+ }
+
+ if(strcmp(cb->f[0], "linear") == 0){
+ mouseaccelerate(0);
+ return;
+ }
+
+ if(strcmp(cb->f[0], "accelerated") == 0){
+ mouseaccelerate(cb->nf == 1 ? 1 : atoi(cb->f[1]));
+ return;
+ }
+}
+
+static int
+isflush(void *)
{
+ return !badrect(fbscreen.rect);
+}
+
+static void
+screenproc(void *arg)
+{
+ int sno, n, w;
+ uchar *sp, *dp, *top;
+ Rectangle r;
+
+ for(sno = 0; sno < NSEG; sno++)
+ if(up->seg[sno] == nil && sno != ESEG)
+ break;
+ if(sno == NSEG)
+ panic(up->text);
+
+ up->seg[sno] = arg;
+
+ fbscreen.proc = up;
+ if(waserror()){
+ fbscreen.addr = 0;
+ fbscreen.proc = nil;
+ pexit("detached", 1);
+ }
+
+ for(;;){
+ sleep(&fbscreen, isflush, nil);
+
+ eqlock(&drawlock);
+ r = fbscreen.rect;
+ fbscreen.rect = ZR;
+ if(badrect(r) || gscreen == nil || rectclip(&r, gscreen->r) == 0){
+ qunlock(&drawlock);
+ continue;
+ }
+ w = sizeof(ulong)*gscreen->width;
+ n = bytesperline(r, gscreen->depth);
+ sp = byteaddr(gscreen, r.min);
+ dp = (uchar*)fbscreen.addr + (sp - &gscreen->data->bdata[gscreen->zero]);
+ top = (uchar*)up->seg[sno]->top;
+ if(dp+(Dy(r)-1)*w+n > top)
+ r.max.y = (top-(uchar*)fbscreen.addr)/w;
+ qunlock(&drawlock);
+
+ while(r.min.y < r.max.y) {
+ memmove(dp, sp, n);
+ sp += w;
+ dp += w;
+ r.min.y++;
+ }
+ }
+}
+
+enum {
+ CMaddr,
+ CMsize,
+ CMinit,
+};
+
+static Cmdtab fbctlmsg[] = {
+ CMaddr, "addr", 2,
+ CMsize, "size", 3,
+ CMinit, "init", 1,
+};
+
+long
+fbctlwrite(Chan*, void *a, long n, vlong)
+{
+ Cmdbuf *cb;
+ Cmdtab *ct;
+ ulong x, y, z, chan;
+ Segment *s;
+ uintptr addr;
+ char *p;
+
+ cb = parsecmd(a, n);
+ if(waserror()){
+ free(cb);
+ nexterror();
+ }
+ ct = lookupcmd(cb, fbctlmsg, nelem(fbctlmsg));
+ switch(ct->index){
+ case CMaddr:
+ s = nil;
+ addr = strtoul(cb->f[1], 0, 0);
+ if(addr != 0){
+ if((s = seg(up, addr, 0)) == nil || (s->type&SG_RONLY) != 0)
+ error(Ebadarg);
+ incref(s);
+ }
+ if(fbscreen.proc != nil){
+ postnote(fbscreen.proc, 0, "die", NUser);
+ while(fbscreen.proc != nil)
+ sched();
+ }
+ if(addr != 0){
+ fbscreen.addr = addr;
+ kproc("screen", screenproc, s);
+ }
+ break;
+
+ case CMsize:
+ x = strtoul(cb->f[1], &p, 0);
+ if(x == 0 || x > 10240)
+ error(Ebadarg);
+ if(*p)
+ p++;
+ y = strtoul(p, &p, 0);
+ if(y == 0 || y > 10240)
+ error(Ebadarg);
+ if(*p)
+ p++;
+ z = strtoul(p, &p, 0);
+
+ if((chan = strtochan(cb->f[2])) == 0)
+ error("bad channel");
+ if(chantodepth(chan) != z)
+ error("depth, channel do not match");
+
+ deletescreenimage();
+ eqlock(&drawlock);
+ if(memimageinit() < 0){
+ qunlock(&drawlock);
+ error("memimageinit failed");
+ }
+ if(gscreen != nil){
+ freememimage(gscreen);
+ gscreen = nil;
+ }
+ gscreen = allocmemimage(Rect(0,0,x,y), chan);
+ qunlock(&drawlock);
+ /* wet floor */
+
+ case CMinit:
+ if(gscreen == nil)
+ error("no framebuffer");
+ resetscreenimage();
+ break;
+ }
+ free(cb);
+ poperror();
+ return n;
+}
+
+long
+fbctlread(Chan*, void *a, long n, vlong offset)
+{
+ char buf[256], chan[32], *p, *e;
+
+ p = buf;
+ e = p + sizeof(buf);
+ qlock(&drawlock);
+ if(gscreen != nil){
+ p = seprint(p, e, "size %dx%dx%d %s\n",
+ Dx(gscreen->r), Dy(gscreen->r), gscreen->depth,
+ chantostr(chan, gscreen->chan));
+ }
+ qunlock(&drawlock);
+ seprint(p, e, "addr %#p\n", fbscreen.addr);
+ return readstr(offset, a, n, buf);
}