diff options
author | rodri <rgl@antares-labs.eu> | 2024-09-20 21:44:07 +0000 |
---|---|---|
committer | rodri <rgl@antares-labs.eu> | 2024-09-20 21:44:07 +0000 |
commit | d8f71404ffd54af08bc84dbb04e60cb07e83a021 (patch) | |
tree | 51eea850a374f92569332ddb3bca7fcc021f6142 | |
parent | 2fd16cbf190d5c37fc627f79bf586f66129fea46 (diff) | |
download | libgraphics-d8f71404ffd54af08bc84dbb04e60cb07e83a021.tar.gz libgraphics-d8f71404ffd54af08bc84dbb04e60cb07e83a021.tar.bz2 libgraphics-d8f71404ffd54af08bc84dbb04e60cb07e83a021.zip |
implement clipped drawing. take branching out of the upscaler loop.
the rasterizers now produce a bbox of used fragments/pixels that
are unified at the end of every job/frame. we use that when
drawing so only the part that was rasterized gets sent to devdraw.
-rw-r--r-- | camera.c | 1 | ||||
-rw-r--r-- | fb.c | 43 | ||||
-rw-r--r-- | graphics.h | 5 | ||||
-rw-r--r-- | internal.h | 1 | ||||
-rw-r--r-- | render.c | 51 | ||||
-rw-r--r-- | util.c | 18 |
6 files changed, 95 insertions, 24 deletions
@@ -273,6 +273,7 @@ shootcamera(Camera *c, Shadertab *s) free(job->times.Tn); free(job->times.Rn); + free(job->cliprects); chanfree(job->donec); free(job->camera); free(job); @@ -14,7 +14,7 @@ * see https://www.scale2x.it/algorithm */ static void -scale2x_filter(ulong *dst, Raster *fb, Point sp) +scale2x_filter(ulong *dst, Raster *fb, Point sp, ulong) { ulong B, D, E, F, H; @@ -34,7 +34,7 @@ scale2x_filter(ulong *dst, Raster *fb, Point sp) } static void -scale3x_filter(ulong *dst, Raster *fb, Point sp) +scale3x_filter(ulong *dst, Raster *fb, Point sp, ulong) { ulong A, B, C, D, E, F, G, H, I; @@ -71,11 +71,17 @@ scale3x_filter(ulong *dst, Raster *fb, Point sp) } //static void -//scale4x_filter(ulong *dst, Framebuf *fb, Point sp) +//scale4x_filter(ulong *dst, Raster *fb, Point sp, ulong) //{ // //} +static void +ident_filter(ulong *dst, Raster *fb, Point sp, ulong len) +{ + memsetl(dst, getpixel(fb, sp), len); +} + /* convert a float raster to a greyscale color one */ static void rasterconvF2C(Raster *dst, Raster *src) @@ -168,7 +174,7 @@ fb_fetchraster(Framebuf *fb, char *name) static void upscaledraw(Raster *fb, Image *dst, Point off, Point scale, uint filter) { - void (*filterfn)(ulong*, Raster*, Point); + void (*filterfn)(ulong*, Raster*, Point, ulong); Rectangle blkr; Point sp, dp; Image *tmp; @@ -177,7 +183,7 @@ upscaledraw(Raster *fb, Image *dst, Point off, Point scale, uint filter) filterfn = nil; blk = emalloc(scale.x*scale.y*4); blkr = Rect(0,0,scale.x,scale.y); - tmp = allocimage(display, dst->r, RGBA32, 0, DNofill); + tmp = allocimage(display, dst->r, RGBA32, 0, 0); if(tmp == nil) sysfatal("allocimage: %r"); @@ -190,14 +196,12 @@ upscaledraw(Raster *fb, Image *dst, Point off, Point scale, uint filter) if(scale.x == scale.y && scale.y == 3) filterfn = scale3x_filter; break; + default: filterfn = ident_filter; } for(sp.y = fb->r.min.y, dp.y = dst->r.min.y+off.y; sp.y < fb->r.max.y; sp.y++, dp.y += scale.y) for(sp.x = fb->r.min.x, dp.x = dst->r.min.x+off.x; sp.x < fb->r.max.x; sp.x++, dp.x += scale.x){ - if(filterfn != nil) - filterfn(blk, fb, sp); - else - memsetl(blk, getpixel(fb, sp), scale.x*scale.y); + filterfn(blk, fb, sp, scale.x*scale.y); loadimage(tmp, rectaddpt(blkr, dp), (uchar*)blk, scale.x*scale.y*4); } draw(dst, dst->r, tmp, nil, tmp->r.min); @@ -244,17 +248,10 @@ framebufctl_draw(Framebufctl *ctl, Image *dst, char *name, Point off, Point scal return; } - sr = rectaddpt(fb->r, off); + /* TODO use the clipr in upscaledraw too */ + sr = rectaddpt(fb->clipr, off); dr = rectsubpt(dst->r, dst->r.min); - if(rectinrect(sr, dr)){ - tmp = allocimage(display, sr, RGBA32, 0, DNofill); - if(tmp == nil) - sysfatal("allocimage: %r"); - - loadimage(tmp, sr, (uchar*)r->data, Dx(fb->r)*Dy(r->r)*4); - draw(dst, rectaddpt(sr, dst->r.min), tmp, nil, ZP); - freeimage(tmp); - }else if(rectclip(&sr, dr)){ + if(rectclip(&sr, dr)){ tmp = allocimage(display, sr, RGBA32, 0, DNofill); if(tmp == nil) sysfatal("allocimage: %r"); @@ -275,7 +272,7 @@ framebufctl_draw(Framebufctl *ctl, Image *dst, char *name, Point off, Point scal static void upscalememdraw(Raster *fb, Memimage *dst, Point off, Point scale, uint filter) { - void (*filterfn)(ulong*, Raster*, Point); + void (*filterfn)(ulong*, Raster*, Point, ulong); Rectangle blkr; Point sp, dp; Memimage *tmp; @@ -297,14 +294,12 @@ upscalememdraw(Raster *fb, Memimage *dst, Point off, Point scale, uint filter) if(scale.x == scale.y && scale.y == 3) filterfn = scale3x_filter; break; + default: filterfn = ident_filter; } for(sp.y = fb->r.min.y, dp.y = dst->r.min.y+off.y; sp.y < fb->r.max.y; sp.y++, dp.y += scale.y) for(sp.x = fb->r.min.x, dp.x = dst->r.min.x+off.x; sp.x < fb->r.max.x; sp.x++, dp.x += scale.x){ - if(filterfn != nil) - filterfn(blk, fb, sp); - else - memsetl(blk, getpixel(fb, sp), scale.x*scale.y); + filterfn(blk, fb, sp, scale.x*scale.y); loadmemimage(tmp, rectaddpt(blkr, dp), (uchar*)blk, scale.x*scale.y*4); } memimagedraw(dst, dst->r, tmp, tmp->r.min, nil, ZP, S); @@ -258,6 +258,8 @@ struct Renderjob Scene *scene; Shadertab *shaders; Channel *donec; + Rectangle *cliprects; /* one per rasterizer */ + int ncliprects; struct { /* renderer, entityproc, tilers, rasterizers */ @@ -302,6 +304,7 @@ struct Raster struct Framebuf { Rectangle r; + Rectangle clipr; Raster *rasters; /* [0] color, [1] depth, [n] user-defined */ Abuf abuf; /* A-buffer */ @@ -432,6 +435,8 @@ void freecubemap(Cubemap*); Color samplecubemap(Cubemap*, Point3, Color(*)(Texture*, Point2)); /* util */ +Point minpt(Point, Point); +Point maxpt(Point, Point); Point2 modulapt2(Point2, Point2); Point2 minpt2(Point2, Point2); Point2 maxpt2(Point2, Point2); @@ -36,6 +36,7 @@ struct Rastertask { SUparams *params; Rectangle wr; /* working rect */ + Rectangle *clipr; Primitive p; }; @@ -212,6 +212,14 @@ rasterize(Rastertask *task) pushtoAbuf(params->fb, p, c, z); else pixel(cr, p, c, ropts & ROBlend); + + if(task->clipr->min.x < 0){ + task->clipr->min = p; + task->clipr->max = addpt(p, Pt(1,1)); + }else{ + task->clipr->min = minpt(task->clipr->min, p); + task->clipr->max = maxpt(task->clipr->max, addpt(p, Pt(1,1))); + } delvattrs(fsp.v); break; case PLine: @@ -270,6 +278,14 @@ rasterize(Rastertask *task) pushtoAbuf(params->fb, p, c, z); else pixel(cr, p, c, ropts & ROBlend); + + if(task->clipr->min.x < 0){ + task->clipr->min = p; + task->clipr->max = addpt(p, Pt(1,1)); + }else{ + task->clipr->min = minpt(task->clipr->min, p); + task->clipr->max = maxpt(task->clipr->max, addpt(p, Pt(1,1))); + } discard: if(steep) SWAP(int, &p.x, &p.y); @@ -316,6 +332,14 @@ discard: pushtoAbuf(params->fb, p, c, z); else pixel(cr, p, c, ropts & ROBlend); + + if(task->clipr->min.x < 0){ + task->clipr->min = p; + task->clipr->max = addpt(p, Pt(1,1)); + }else{ + task->clipr->min = minpt(task->clipr->min, p); + task->clipr->max = maxpt(task->clipr->max, addpt(p, Pt(1,1))); + } } delvattrs(fsp.v); break; @@ -349,8 +373,23 @@ rasterizer(void *arg) if(decref(job) < 1){ if(job->camera->rendopts & ROAbuff) squashAbuf(job->fb, job->camera->rendopts & ROBlend); + + /* set the clipr to the union of bboxes from the rasterizers */ + for(i = 1; i < job->ncliprects; i++){ + if(job->cliprects[i].min.x < 0) + continue; + job->cliprects[0].min = job->cliprects[0].min.x < 0? + job->cliprects[i].min: + minpt(job->cliprects[0].min, job->cliprects[i].min); + job->cliprects[0].max = job->cliprects[0].max.x < 0? + job->cliprects[i].max: + maxpt(job->cliprects[0].max, job->cliprects[i].max); + } + job->fb->clipr = job->cliprects[0]; + if(job->rctl->doprof) job->times.Rn[rp->id].t1 = nanosec(); + nbsend(job->donec, nil); free(params); }else if(job->rctl->doprof) @@ -458,6 +497,7 @@ tiler(void *arg) *newparams = *params; task = emalloc(sizeof *task); task->params = newparams; + task->clipr = ¶ms->job->cliprects[i]; task->p = *p; task->p.v[0] = dupvertex(&p->v[0]); sendp(taskchans[i], task); @@ -501,6 +541,7 @@ tiler(void *arg) task = emalloc(sizeof *task); task->params = newparams; task->wr = wr[i]; + task->clipr = ¶ms->job->cliprects[i]; task->p = *p; task->p.v[0] = dupvertex(&p->v[0]); task->p.v[1] = dupvertex(&p->v[1]); @@ -554,6 +595,7 @@ tiler(void *arg) task->params = newparams; task->wr = bbox; rectclip(&task->wr, wr[i]); + task->clipr = ¶ms->job->cliprects[i]; task->p = *p; task->p.v[0] = dupvertex(&p->v[0]); task->p.v[1] = dupvertex(&p->v[1]); @@ -637,6 +679,15 @@ entityproc(void *arg) continue; } + if(params->job->cliprects == nil){ + params->job->cliprects = emalloc(nproc*sizeof(Rectangle)); + params->job->ncliprects = nproc; + for(i = 0; i < nproc; i++){ + params->job->cliprects[i].min = Pt(-1,-1); + params->job->cliprects[i].max = Pt(-1,-1); + } + } + eb = params->entity->mdl->prims; nprims = params->entity->mdl->nprims; ee = eb + nprims; @@ -8,6 +8,24 @@ #include "graphics.h" #include "internal.h" +Point +minpt(Point a, Point b) +{ + return (Point){ + min(a.x, b.x), + min(a.y, b.y) + }; +} + +Point +maxpt(Point a, Point b) +{ + return (Point){ + max(a.x, b.x), + max(a.y, b.y) + }; +} + Point2 modulapt2(Point2 a, Point2 b) { |