ref: 2621771b920cecec2c0232a174a5aea4e1bd027f
parent: d8aaf562ad18d9401ca839ecea1866707d614686
author: rodri <rgl@antares-labs.eu>
date: Mon Dec 18 15:57:58 EST 2023
implemented double-buffering.
--- a/main.c
+++ b/main.c
@@ -15,6 +15,9 @@
typedef struct VSparams VSparams;
typedef struct FSparams FSparams;
typedef struct SUparams SUparams;
+typedef struct Shader Shader;
+typedef struct Framebuf Framebuf;
+typedef struct Framebufctl Framebufctl;
/* shader params */
struct VSparams
@@ -37,7 +40,7 @@
/* shader unit params */
struct SUparams
{
- Memimage *dst;
+ Framebuf *fb;
OBJElem **b, **e;
int id;
Channel *donec;
@@ -50,7 +53,6 @@
Memimage *(*fshader)(FSparams*);
};
-typedef struct Shader Shader;
struct Shader
{
char *name;
@@ -58,6 +60,26 @@
Memimage *(*fshader)(FSparams*);
};
+struct Framebuf
+{
+ Memimage *cb;
+ Memimage *zb;
+ double *zbuf;
+ Memimage *nb; /* XXX DBG */
+ Rectangle r;
+};
+
+struct Framebufctl
+{
+ Framebuf *fb[2];
+ uint idx;
+ Lock swplk;
+
+ int (*draw)(Framebufctl*, Memimage*, int);
+ void (*swap)(Framebufctl*);
+ void (*reset)(Framebufctl*);
+};
+
typedef struct Stats Stats;
struct Stats
{
@@ -66,15 +88,15 @@
Stats fps;
-Memimage *screenfb, *fb, *zfb, *nfb, *curfb;
-double *zbuf;
+Framebufctl *fbctl;
+Memimage *screenfb;
Lock zbuflk;
Memimage *red, *green, *blue;
OBJ *model;
Memimage *modeltex;
-Channel *drawc, *donedrawc;
+Channel *drawc;
int nprocs;
-int rendering;
+int showzbuffer;
int shownormals;
char winspec[32];
@@ -232,7 +254,72 @@
return i;
}
+static int
+framebufctl_draw(Framebufctl *ctl, Memimage *dst, int showz)
+{
+ if(canlock(&ctl->swplk)){
+ memimagedraw(dst, dst->r, showz? ctl->fb[ctl->idx]->zb: ctl->fb[ctl->idx]->cb, ZP, nil, ZP, SoverD);
+ /* XXX DBG */
+ if(shownormals)
+ memimagedraw(dst, dst->r, ctl->fb[ctl->idx]->nb, ZP, nil, ZP, SoverD);
+ unlock(&ctl->swplk);
+ return 0;
+ }
+ return -1;
+}
+
static void
+framebufctl_swap(Framebufctl *ctl)
+{
+ lock(&ctl->swplk);
+ ctl->idx ^= 1;
+ unlock(&ctl->swplk);
+}
+
+static void
+framebufctl_reset(Framebufctl *ctl)
+{
+ Framebuf *fb;
+
+ /* address the back buffer—resetting the front buffer is VERBOTEN */
+ fb = ctl->fb[ctl->idx^1];
+ memsetd(fb->zbuf, Inf(-1), Dx(fb->r)*Dy(fb->r));
+ memfillcolor(fb->cb, DTransparent);
+ memfillcolor(fb->zb, DTransparent);
+ memfillcolor(fb->nb, DTransparent); /* XXX DBG */
+}
+
+Framebuf *
+mkfb(Rectangle r)
+{
+ Framebuf *fb;
+
+ fb = emalloc(sizeof *fb);
+ fb->cb = eallocmemimage(r, RGBA32);
+ fb->zb = eallocmemimage(r, RGBA32);
+ fb->zbuf = emalloc(Dx(r)*Dy(r)*sizeof(*fb->zbuf));
+ memsetd(fb->zbuf, Inf(-1), Dx(r)*Dy(r));
+ fb->nb = eallocmemimage(r, RGBA32); /* XXX DBG */
+ fb->r = r;
+ return fb;
+}
+
+Framebufctl *
+newfbctl(Rectangle r)
+{
+ Framebufctl *fc;
+
+ fc = emalloc(sizeof *fc);
+ memset(fc, 0, sizeof *fc);
+ fc->fb[0] = mkfb(r);
+ fc->fb[1] = mkfb(r);
+ fc->draw = framebufctl_draw;
+ fc->swap = framebufctl_swap;
+ fc->reset = framebufctl_reset;
+ return fc;
+}
+
+static void
decproc(void *arg)
{
int fd, *pfd;
@@ -483,8 +570,10 @@
min(min(st₂.p0.x, st₂.p1.x), st₂.p2.x), min(min(st₂.p0.y, st₂.p1.y), st₂.p2.y),
max(max(st₂.p0.x, st₂.p1.x), st₂.p2.x)+1, max(max(st₂.p0.y, st₂.p1.y), st₂.p2.y)+1
);
- bbox.min.x = max(bbox.min.x, fb->r.min.x); bbox.min.y = max(bbox.min.y, fb->r.min.y);
- bbox.max.x = min(bbox.max.x, fb->r.max.x); bbox.max.y = min(bbox.max.y, fb->r.max.y);
+ bbox.min.x = max(bbox.min.x, params->fb->r.min.x);
+ bbox.min.y = max(bbox.min.y, params->fb->r.min.y);
+ bbox.max.x = min(bbox.max.x, params->fb->r.max.x);
+ bbox.max.y = min(bbox.max.y, params->fb->r.max.y);
cbuf[0] = 0xFF;
fsp.su = params;
fsp.frag = frag;
@@ -500,17 +589,17 @@
w = st.p0.w*bc.x + st.p1.w*bc.y + st.p2.w*bc.z;
depth = fclamp(z/w, 0, 1);
lock(&zbuflk);
- if(depth <= zbuf[p.x + p.y*Dx(params->dst->r)]){
+ if(depth <= params->fb->zbuf[p.x + p.y*Dx(params->fb->r)]){
unlock(&zbuflk);
continue;
}
- zbuf[p.x + p.y*Dx(params->dst->r)] = depth;
+ params->fb->zbuf[p.x + p.y*Dx(params->fb->r)] = depth;
cbuf[1] = 0xFF*depth;
cbuf[2] = 0xFF*depth;
cbuf[3] = 0xFF*depth;
memfillcolor(frag, *(ulong*)cbuf);
- pixel(zfb, p, frag);
+ pixel(params->fb->zb, p, frag);
unlock(&zbuflk);
cbuf[0] = 0xFF;
@@ -528,7 +617,7 @@
fsp.p = p;
fsp.bc = bc;
- pixel(params->dst, p, params->fshader(&fsp));
+ pixel(params->fb->cb, p, params->fshader(&fsp));
}
}
@@ -599,9 +688,9 @@
nt.p0.x*bc.x + nt.p1.x*bc.y + nt.p2.x*bc.z,
nt.p0.y*bc.x + nt.p1.y*bc.y + nt.p2.y*bc.z,
nt.p0.z*bc.x + nt.p1.z*bc.y + nt.p2.z*bc.z);
- np1 = addpt3(np0, mulpt3(np1, Dx(fb->r)/32));
- triangle(nfb, Pt(st₂.p0.x,st₂.p0.y), Pt(st₂.p1.x,st₂.p1.y), Pt(st₂.p2.x,st₂.p2.y), red);
- bresenham(nfb, Pt(np0.x,np0.y), Pt(np1.x,np1.y), green);
+ np1 = addpt3(np0, mulpt3(np1, Dx(params->fb->r)/32));
+ triangle(params->fb->nb, Pt(st₂.p0.x,st₂.p0.y), Pt(st₂.p1.x,st₂.p1.y), Pt(st₂.p2.x,st₂.p2.y), red);
+ bresenham(params->fb->nb, Pt(np0.x,np0.y), Pt(np1.x,np1.y), green);
idxtab = &(*ep)->indextab[OBJVTexture];
if(modeltex != nil && idxtab->nindex == 3){
@@ -621,7 +710,7 @@
}
void
-shade(Memimage *dst, Shader *s)
+shade(Framebuf *fb, Shader *s)
{
int i, nelems, nparts, nworkers;
uvlong time;
@@ -656,7 +745,7 @@
for(i = 0; i < nworkers; i++){
params = emalloc(sizeof *params);
- params->dst = dst;
+ params->fb = fb;
params->b = &elems[i*nparts];
params->e = params->b + nparts;
params->id = i;
@@ -726,8 +815,8 @@
uchar cbuf[4];
uv = Pt2(sp->p.x,sp->p.y,1);
- uv.x /= Dx(fb->r);
- uv.y /= Dy(fb->r);
+ uv.x /= Dx(sp->su->fb->r);
+ uv.y /= Dy(sp->su->fb->r);
// r = 0.3;
r = 0.3*sin(sp->su->uni_time/1e9);
@@ -752,8 +841,8 @@
uchar cbuf[4];
uv = Pt2(sp->p.x,sp->p.y,1);
- uv.x /= Dx(fb->r);
- uv.y /= Dy(fb->r);
+ uv.x /= Dx(sp->su->fb->r);
+ uv.y /= Dy(sp->su->fb->r);
uv.y = 1 - uv.y; /* make [0 0] the bottom-left corner */
// y = step(0.5, uv.x);
@@ -780,8 +869,8 @@
uchar cbuf[4];
uv = Pt2(sp->p.x,sp->p.y,1);
- uv.x /= Dx(fb->r);
- uv.y /= Dy(fb->r);
+ uv.x /= Dx(sp->su->fb->r);
+ uv.y /= Dy(sp->su->fb->r);
r = Vec2(0.2,0.4);
p = Pt2(fabs(uv.x - 0.5), fabs(uv.y - 0.5), 1);
@@ -833,17 +922,14 @@
void
redraw(void)
{
- lockdisplay(display);
memfillcolor(screenfb, 0x888888FF);
- memimagedraw(screenfb, screenfb->r, curfb, ZP, nil, ZP, SoverD);
- if(shownormals)
- memimagedraw(screenfb, screenfb->r, nfb, ZP, nil, ZP, SoverD);
+ if(fbctl->draw(fbctl, screenfb, showzbuffer) < 0)
+ return;
+ lockdisplay(display);
loadimage(screen, rectaddpt(screenfb->r, screen->r.min), byteaddr(screenfb, screenfb->r.min), bytesperline(screenfb->r, screenfb->depth)*Dy(screenfb->r));
drawstats();
flushimage(display, 1);
unlockdisplay(display);
-
- sendp(donedrawc, nil);
}
void
@@ -851,13 +937,10 @@
{
uvlong t0, t1;
- memsetd(zbuf, Inf(-1), Dx(fb->r)*Dy(fb->r));
- memfillcolor(fb, DTransparent);
- memfillcolor(zfb, DTransparent);
- memfillcolor(nfb, DTransparent);
+ fbctl->reset(fbctl);
t0 = nanosec();
- shade(fb, s);
+ shade(fbctl->fb[fbctl->idx^1], s); /* address the back buffer */
t1 = nanosec();
updatestats(&fps, t1-t0);
}
@@ -868,11 +951,9 @@
threadsetname("renderer");
for(;;){
- rendering = 1;
render((Shader*)arg);
- rendering = 0;
+ fbctl->swap(fbctl);
nbsendp(drawc, nil);
- recvp(donedrawc);
}
threadexits(nil);
}
@@ -887,7 +968,7 @@
switch(idx){
case TOGGLEZBUF:
- return curfb == zfb? "hide z-buffer": "show z-buffer";
+ return showzbuffer? "hide z-buffer": "show z-buffer";
case TOGGLENORM:
return shownormals? "hide normals": "show normals";
}
@@ -905,7 +986,7 @@
switch(menuhit(3, mc, &menu, _screen)){
case TOGGLEZBUF:
- curfb = curfb == fb? zfb: fb;
+ showzbuffer ^= 1;
break;
case TOGGLENORM:
shownormals ^= 1;
@@ -920,7 +1001,7 @@
Point p;
p = subpt(mc->xy, screen->r.min);
- fprint(2, "p %P z %g\n", p, zbuf[p.x + p.y*Dx(fb->r)]);
+ fprint(2, "p %P z %g\n", p, fbctl->fb[fbctl->idx]->zbuf[p.x + p.y*Dx(fbctl->fb[fbctl->idx]->r)]);
}
void
@@ -1037,16 +1118,12 @@
sysfatal("initkeyboard: %r");
screenfb = eallocmemimage(rectsubpt(screen->r, screen->r.min), screen->chan);
- fb = eallocmemimage(screenfb->r, RGBA32);
- zbuf = emalloc(Dx(fb->r)*Dy(fb->r)*sizeof(double));
- zfb = eallocmemimage(fb->r, fb->chan);
- curfb = fb;
- nfb = eallocmemimage(fb->r, fb->chan);
+ fbctl = newfbctl(screenfb->r);
red = rgb(DRed);
green = rgb(DGreen);
blue = rgb(DBlue);
- viewport(fb->r);
+ viewport(screenfb->r);
projection(-1.0/vec3len(subpt3(camera, center)));
identity3(rota);
lookat(camera, center, up);
@@ -1054,7 +1131,6 @@
light = normvec3(subpt3(light, center));
drawc = chancreate(sizeof(void*), 1);
- donedrawc = chancreate(sizeof(void*), 1);
display->locking = 1;
unlockdisplay(display);
@@ -1081,8 +1157,7 @@
key(r);
break;
case DRAW:
- if(!rendering)
- redraw();
+ redraw();
break;
}
}