zynq: add /dev/fbctl to attach framebuffer to devdraw
This commit is contained in:
parent
cda46731d8
commit
90b4fe9cf6
4 changed files with 203 additions and 40 deletions
|
@ -11,6 +11,7 @@ enum {
|
||||||
Qdir = 0,
|
Qdir = 0,
|
||||||
Qtemp,
|
Qtemp,
|
||||||
Qpl,
|
Qpl,
|
||||||
|
Qfbctl,
|
||||||
Qbase,
|
Qbase,
|
||||||
|
|
||||||
Qmax = 16,
|
Qmax = 16,
|
||||||
|
@ -20,6 +21,7 @@ static Dirtab archdir[Qmax] = {
|
||||||
".", { Qdir, 0, QTDIR }, 0, 0555,
|
".", { Qdir, 0, QTDIR }, 0, 0555,
|
||||||
"temp", { Qtemp, 0}, 0, 0440,
|
"temp", { Qtemp, 0}, 0, 0440,
|
||||||
"pl", { Qpl, 0 }, 0, 0660,
|
"pl", { Qpl, 0 }, 0, 0660,
|
||||||
|
"fbctl", { Qfbctl, 0 }, 0, 0660,
|
||||||
};
|
};
|
||||||
static int narchdir = Qbase;
|
static int narchdir = Qbase;
|
||||||
|
|
||||||
|
@ -291,6 +293,8 @@ archread(Chan *c, void *a, long n, vlong offset)
|
||||||
qunlock(&plrlock);
|
qunlock(&plrlock);
|
||||||
poperror();
|
poperror();
|
||||||
return 0;
|
return 0;
|
||||||
|
case Qfbctl:
|
||||||
|
return fbctlread(c, a, n, offset);
|
||||||
default:
|
default:
|
||||||
error(Egreg);
|
error(Egreg);
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -298,11 +302,13 @@ archread(Chan *c, void *a, long n, vlong offset)
|
||||||
}
|
}
|
||||||
|
|
||||||
static long
|
static long
|
||||||
archwrite(Chan *c, void *a, long n, vlong)
|
archwrite(Chan *c, void *a, long n, vlong offset)
|
||||||
{
|
{
|
||||||
switch((ulong)c->qid.path){
|
switch((ulong)c->qid.path){
|
||||||
case Qpl:
|
case Qpl:
|
||||||
return plcopy(a, n);
|
return plcopy(a, n);
|
||||||
|
case Qfbctl:
|
||||||
|
return fbctlwrite(c, a, n, offset);
|
||||||
default:
|
default:
|
||||||
error(Egreg);
|
error(Egreg);
|
||||||
return -1;
|
return -1;
|
||||||
|
|
|
@ -53,6 +53,8 @@ void intrenable(int, void (*)(Ureg *, void *), void *, int, char *);
|
||||||
void intrinit(void);
|
void intrinit(void);
|
||||||
void intr(Ureg *);
|
void intr(Ureg *);
|
||||||
int uartconsole(void);
|
int uartconsole(void);
|
||||||
|
long fbctlread(Chan*,void*,long,vlong);
|
||||||
|
long fbctlwrite(Chan*,void*,long,vlong);
|
||||||
void fpoff(void);
|
void fpoff(void);
|
||||||
void fpsave(FPsave *);
|
void fpsave(FPsave *);
|
||||||
void fprestore(FPsave *);
|
void fprestore(FPsave *);
|
||||||
|
|
|
@ -13,22 +13,15 @@
|
||||||
#include "screen.h"
|
#include "screen.h"
|
||||||
|
|
||||||
Memimage *gscreen;
|
Memimage *gscreen;
|
||||||
static Memdata xgdata;
|
|
||||||
|
|
||||||
static Memimage xgscreen =
|
static struct {
|
||||||
{
|
Rendez;
|
||||||
{ 0, 0, 800, 600 }, /* r */
|
|
||||||
{ 0, 0, 800, 600 }, /* clipr */
|
Rectangle rect;
|
||||||
24, /* depth */
|
Proc *proc;
|
||||||
3, /* nchan */
|
|
||||||
BGR24, /* chan */
|
uintptr addr;
|
||||||
nil, /* cmap */
|
} fbscreen;
|
||||||
&xgdata, /* data */
|
|
||||||
0, /* zero */
|
|
||||||
0, /* width in words of a single scan line */
|
|
||||||
0, /* layer */
|
|
||||||
0, /* flags */
|
|
||||||
};
|
|
||||||
|
|
||||||
void
|
void
|
||||||
cursoron(void)
|
cursoron(void)
|
||||||
|
@ -46,46 +39,32 @@ setcursor(Cursor*)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
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
|
void
|
||||||
screeninit(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;
|
conf.monitor = 1;
|
||||||
xgdata.bdata = fb;
|
|
||||||
xgdata.ref = 1;
|
|
||||||
gscreen = &xgscreen;
|
|
||||||
gscreen->width = wordsperline(gscreen->r, gscreen->depth);
|
|
||||||
|
|
||||||
memimageinit();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uchar*
|
uchar*
|
||||||
attachscreen(Rectangle *r, ulong *chan, int* d, int *width, int *softscreen)
|
attachscreen(Rectangle *r, ulong *chan, int* d, int *width, int *softscreen)
|
||||||
{
|
{
|
||||||
|
if(gscreen == nil)
|
||||||
|
return nil;
|
||||||
|
|
||||||
*r = gscreen->r;
|
*r = gscreen->r;
|
||||||
*d = gscreen->depth;
|
*d = gscreen->depth;
|
||||||
*chan = gscreen->chan;
|
*chan = gscreen->chan;
|
||||||
*width = gscreen->width;
|
*width = gscreen->width;
|
||||||
*softscreen = 0;
|
|
||||||
|
/* make devdraw use gscreen->data */
|
||||||
|
*softscreen = 0xa110c;
|
||||||
|
gscreen->data->ref++;
|
||||||
|
|
||||||
return gscreen->data->bdata;
|
return gscreen->data->bdata;
|
||||||
}
|
}
|
||||||
|
@ -110,3 +89,177 @@ void
|
||||||
mousectl(Cmdbuf *)
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,6 +32,8 @@ extern void cursoroff(void);
|
||||||
extern void setcursor(Cursor*);
|
extern void setcursor(Cursor*);
|
||||||
|
|
||||||
/* devdraw.c */
|
/* devdraw.c */
|
||||||
|
extern void deletescreenimage(void);
|
||||||
|
extern void resetscreenimage(void);
|
||||||
extern QLock drawlock;
|
extern QLock drawlock;
|
||||||
|
|
||||||
#define ishwimage(i) 1 /* for ../port/devdraw.c */
|
#define ishwimage(i) 1 /* for ../port/devdraw.c */
|
||||||
|
|
Loading…
Reference in a new issue