plan9fox/sys/src/9/zynq/screen.c

344 lines
5.5 KiB
C
Raw Normal View History

2014-12-24 09:21:51 +00:00
#include "u.h"
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "../port/error.h"
#define Image IMAGE
#include <draw.h>
#include <memdraw.h>
#include <cursor.h>
#include "screen.h"
Memimage *gscreen;
static struct {
Rendez;
Rectangle rect;
Proc *proc;
uintptr addr;
} fbscreen;
2014-12-24 09:21:51 +00:00
static struct {
Rendez;
Cursor;
Proc *proc;
uintptr addr;
} hwcursor;
2014-12-24 09:21:51 +00:00
void
cursoron(void)
{
wakeup(&hwcursor);
2014-12-24 09:21:51 +00:00
}
void
cursoroff(void)
{
}
void
setcursor(Cursor *curs)
2014-12-24 09:21:51 +00:00
{
hwcursor.Cursor = *curs;
2014-12-24 09:21:51 +00:00
}
void
flushmemscreen(Rectangle r)
2014-12-24 09:21:51 +00:00
{
2015-06-09 23:27:44 +00:00
if(badrect(fbscreen.rect))
fbscreen.rect = r;
else
combinerect(&fbscreen.rect, r);
wakeup(&fbscreen);
2014-12-24 09:21:51 +00:00
}
void
screeninit(void)
{
conf.monitor = 1;
}
Memdata*
2014-12-24 09:21:51 +00:00
attachscreen(Rectangle *r, ulong *chan, int* d, int *width, int *softscreen)
{
if(gscreen == nil)
return nil;
2014-12-24 09:21:51 +00:00
*r = gscreen->r;
*d = gscreen->depth;
*chan = gscreen->chan;
*width = gscreen->width;
*softscreen = 1;
gscreen->data->ref++;
return gscreen->data;
2014-12-24 09:21:51 +00:00
}
void
getcolor(ulong, ulong *, ulong *, ulong *)
{
}
int
setcolor(ulong, ulong, ulong, ulong)
{
return 0;
}
void
blankscreen(int)
{
}
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);
}
}
2014-12-24 09:21:51 +00:00
void
mousectl(Cmdbuf *cb)
2014-12-24 09:21:51 +00:00
{
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;
}
2015-06-11 14:44:05 +00:00
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;
}
2014-12-24 09:21:51 +00:00
}
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);
}