shithub: libgraphics

Download patch

ref: 8806aad87f7be2d2e82c7db2b9f0978246e5a747
parent: 6d137698282ca2c04eff4b52ac8e69ac10164a90
author: rodri <rgl@antares-labs.eu>
date: Tue Sep 10 10:26:35 EDT 2024

fix a use-after-free when profiling rasterizer times.

this commit also includes the turbo drawing pool.
the experiment was successful in getting reasonable
drawing times to a fullhd image, but the process
causes glitches when moving the objects around,
which is unacceptable.

it's been commented out for now.

--- a/fb.c
+++ b/fb.c
@@ -163,6 +163,23 @@
 	free(blk);
 }
 
+//typedef struct Ldimgtask Ldimgtask;
+//struct Ldimgtask
+//{
+//	Image *dst;
+//	Rectangle dr;
+//	uchar *src;
+//	ulong len;
+//};
+//static void
+//ldimgtask(void *arg)
+//{
+//	Ldimgtask *t;
+//
+//	t = arg;
+//	loadimage(t->dst, t->dr, t->src, t->len);
+//}
+
 static void
 framebufctl_draw(Framebufctl *ctl, Image *dst, char *name, Point off, Point scale)
 {
@@ -195,9 +212,55 @@
 
 	sr = rectaddpt(fb->r, off);
 	dr = rectsubpt(dst->r, dst->r.min);
-	if(rectinrect(sr, dr))
+	if(rectinrect(sr, dr)){
+//		Ldimgtask *tasks;
+//		Rectangle blkr;
+//		ulong len, stride;
+//		int Δy, i;
+//		static Display **disps;
+//		static Image **imgs;
+//		static int loaded;
+//
+//		assert(turbodrawingpool != nil);
+//
+//		if(!loaded){
+//			disps = emalloc(turbodrawingpool->nprocs * sizeof(*disps));
+//			imgs = emalloc(turbodrawingpool->nprocs * sizeof(*imgs));
+//			for(i = 0; i < turbodrawingpool->nprocs; i++){
+//				disps[i] = initdisplay(nil, nil, nil);
+//				if(disps[i] == nil)
+//					sysfatal("initdisplay: %r");
+//				imgs[i] = namedimage(disps[i], "screenb");
+//				if(imgs[i] == nil)
+//					sysfatal("namedimage: %r");
+////fprint(2, "d %#p i %#p → %#p\n", disps[i], imgs[i], imgs[i]->display);
+//			}
+//			loaded++;
+//		}
+//
+//		len = Dx(r->r)*Dy(r->r)*4;
+//		Δy = Dy(sr)/turbodrawingpool->nprocs;
+//		dr = rectaddpt(sr, dst->r.min);
+//		blkr = dr;
+//		blkr.max.y = blkr.min.y + Δy;
+//		stride = Dx(blkr)*Dy(blkr)*4;
+//		tasks = emalloc(turbodrawingpool->nprocs * sizeof(*tasks));
+//
+//		for(i = 0; i < turbodrawingpool->nprocs; i++){
+//			tasks[i].dst = imgs[i];
+//			tasks[i].dr = rectaddpt(blkr, Pt(0, i*Δy));
+//			tasks[i].src = (uchar*)r->data + i*stride;
+//			tasks[i].len = stride;
+//			if(i == turbodrawingpool->nprocs-1){
+//				tasks[i].dr.max.y = dr.max.y;
+//				tasks[i].len = len - i*stride;
+//			}
+//			procpoolexec(turbodrawingpool, ldimgtask, &tasks[i]);
+//		}
+//		procpoolwait(turbodrawingpool);
+//		free(tasks);
 		loadimage(dst, rectaddpt(sr, dst->r.min), (uchar*)r->data, Dx(fb->r)*Dy(r->r)*4);
-	else if(rectclip(&sr, dr)){
+	}else if(rectclip(&sr, dr)){
 		dr = sr;
 		dr.max.y = dr.min.y + 1;
 		/* remove offset to get the actual rect within the framebuffer */
--- a/internal.h
+++ b/internal.h
@@ -39,6 +39,27 @@
 	Primitive p;
 };
 
+typedef struct Proctask Proctask;
+typedef struct Procpool Procpool;
+
+struct Proctask
+{
+	void (*fn)(void*);
+	void *arg;
+};
+
+struct Procpool
+{
+	ulong nprocs;
+	Ref issued;
+	Ref complete;
+
+	Channel *subq;	/* task submission queue */
+	Channel *done;	/* task completion signal */
+};
+
+extern Procpool *turbodrawingpool;
+
 /* alloc */
 void *emalloc(ulong);
 void *erealloc(void*, ulong);
@@ -78,6 +99,12 @@
 
 /* nanosec */
 uvlong nanosec(void);
+
+/* procpool */
+Procpool *mkprocpool(ulong);
+void procpoolexec(Procpool*, void(*)(void*), void*);
+void procpoolwait(Procpool*);
+void rmprocpool(Procpool*);
 
 #define getpixel(fb, p)		rastergetcolor(fb, p)
 #define putpixel(fb, p, c)	rasterputcolor(fb, p, c)
--- a/mkfile
+++ b/mkfile
@@ -17,6 +17,7 @@
 	color.$O\
 	util.$O\
 	nanosec.$O\
+	procpool.$O\
 
 HFILES=\
 	graphics.h\
--- a/render.c
+++ b/render.c
@@ -9,6 +9,7 @@
 #include "internal.h"
 
 Rectangle UR = {0,0,1,1};
+//Procpool *turbodrawingpool;
 
 static ulong col2ul(Color);
 
@@ -368,10 +369,11 @@
 			if(decref(job) < 1){
 				if(job->camera->enableAbuff)
 					squashAbuf(job->fb, job->camera->enableblend);
+				if(job->rctl->doprof)
+					job->times.Rn[rp->id].t1 = nanosec();
 				nbsend(job->donec, nil);
 				free(params);
-			}
-			if(job->rctl->doprof)
+			}else if(job->rctl->doprof)
 				job->times.Rn[rp->id].t1 = nanosec();
 			free(task);
 			continue;
@@ -748,6 +750,8 @@
 	if(nprocs == nil || (nproc = strtoul(nprocs, nil, 10)) < 2)
 		nproc = 1;
 	free(nprocs);
+
+//	turbodrawingpool = mkprocpool(nproc);
 
 	r = emalloc(sizeof *r);
 	memset(r, 0, sizeof *r);