ref: 90b4fe9cf65bb24b55472ce2e32a7dbc3c5e7f97
parent: cda46731d8166e5b113a8acdf90479a03bb6a3a8
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Tue Jun 9 05:17:55 EDT 2015
zynq: add /dev/fbctl to attach framebuffer to devdraw
--- a/sys/src/9/zynq/devarch.c
+++ b/sys/src/9/zynq/devarch.c
@@ -11,6 +11,7 @@
Qdir = 0,
Qtemp,
Qpl,
+ Qfbctl,
Qbase,
Qmax = 16,
@@ -20,6 +21,7 @@
".", { Qdir, 0, QTDIR }, 0, 0555,
"temp", { Qtemp, 0}, 0, 0440,
"pl", { Qpl, 0 }, 0, 0660,
+ "fbctl", { Qfbctl, 0 }, 0, 0660,
};
static int narchdir = Qbase;
@@ -291,6 +293,8 @@
qunlock(&plrlock);
poperror();
return 0;
+ case Qfbctl:
+ return fbctlread(c, a, n, offset);
default:
error(Egreg);
return -1;
@@ -298,11 +302,13 @@
}
static long
-archwrite(Chan *c, void *a, long n, vlong)
+archwrite(Chan *c, void *a, long n, vlong offset)
{
switch((ulong)c->qid.path){
case Qpl:
return plcopy(a, n);
+ case Qfbctl:
+ return fbctlwrite(c, a, n, offset);
default:
error(Egreg);
return -1;
--- a/sys/src/9/zynq/fns.h
+++ b/sys/src/9/zynq/fns.h
@@ -53,6 +53,8 @@
void intrinit(void);
void intr(Ureg *);
int uartconsole(void);
+long fbctlread(Chan*,void*,long,vlong);
+long fbctlwrite(Chan*,void*,long,vlong);
void fpoff(void);
void fpsave(FPsave *);
void fprestore(FPsave *);
--- a/sys/src/9/zynq/screen.c
+++ b/sys/src/9/zynq/screen.c
@@ -13,23 +13,16 @@
#include "screen.h"
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;
+
void
cursoron(void)
{
@@ -46,47 +39,33 @@
}
void
-flushmemscreen(Rectangle)
+flushmemscreen(Rectangle r)
{
+ combinerect(&fbscreen.rect, r);
+ wakeup(&fbscreen);
}
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));
-}
-
-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;
}
@@ -110,3 +89,177 @@
mousectl(Cmdbuf *)
{
}
+
+static int
+isflush(void *)
+{
+ return !badrect(fbscreen.rect);
+}
+
+static void
+flushproc(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("flushproc");
+
+ up->seg[sno] = arg;
+
+ cclose(up->dot);
+ up->dot = up->slash;
+ incref(up->dot);
+
+ fbscreen.proc = up;
+ if(waserror()){
+ print("flushproc: %s\n", up->errstr);
+ fbscreen.addr = 0;
+ fbscreen.proc = nil;
+ return;
+ }
+
+ 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:
+ addr = strtoul(cb->f[1], 0, 0);
+
+ eqlock(&up->seglock);
+ if((s = seg(up, addr, 0)) == nil || (s->type&SG_RONLY) != 0){
+ qunlock(&up->seglock);
+ error(Ebadarg);
+ }
+ incref(s);
+ qunlock(&up->seglock);
+
+ if(fbscreen.proc != nil){
+ postnote(fbscreen.proc, 0, "die", NUser);
+ while(fbscreen.proc != nil)
+ sched();
+ }
+ fbscreen.addr = addr;
+ kproc("fbflush", flushproc, 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");
+
+ cursoroff();
+ 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();
+ cursoron();
+ 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);
+}
+
--- a/sys/src/9/zynq/screen.h
+++ b/sys/src/9/zynq/screen.h
@@ -32,6 +32,8 @@
extern void setcursor(Cursor*);
/* devdraw.c */
+extern void deletescreenimage(void);
+extern void resetscreenimage(void);
extern QLock drawlock;
#define ishwimage(i) 1 /* for ../port/devdraw.c */