shithub: libgraphics

Download patch

ref: cd6f51e699e261ce5d12163269d7e01ecb26ca11
parent: 298cd37c46019bfd22f9df201da47b84b6383bc9
author: rodri <rgl@antares-labs.eu>
date: Wed Apr 9 20:15:51 EDT 2025

many improvements

moved the raster routines into their own unit and removed
the switching on every raster(put|get); it's all 32-bit
values for now.

added faster versions of dotvec[23]

got rid of _memsetf, now we only use _memsetl for
clearing the rasters. i also put an optimized version
for amd64.

--- a/fb.c
+++ b/fb.c
@@ -136,41 +136,6 @@
 }
 
 static void
-fb_createraster(Framebuf *fb, char *name, ulong chan)
-{
-	Raster *r;
-
-	assert(name != nil);
-
-	/*
-	 * TODO might be better to keep a tail so it's O(1)
-	 *
-	 * in practice though, most users won't ever create
-	 * more than ten extra rasters.
-	 */
-	r = fb->rasters;
-	while(r->next != nil)
-		r = r->next;
-	r->next = _allocraster(name, fb->r, chan);
-}
-
-static Raster *
-fb_fetchraster(Framebuf *fb, char *name)
-{
-	Raster *r;
-
-	r = fb->rasters;
-	if(name == nil)
-		return r;
-
-	while((r = r->next) != nil)
-		if(strcmp(name, r->name) == 0)
-			return r;
-	return nil;
-
-}
-
-static void
 upscaledraw(Raster *fb, Image *dst, Point off, Point scale, uint filter)
 {
 	void (*filterfn)(ulong*, Raster*, Point, ulong);
@@ -427,13 +392,10 @@
 static void
 framebufctl_createraster(Framebufctl *ctl, char *name, ulong chan)
 {
-	Framebuf *fb;
-	int i;
+	Framebuf **fb;
 
-	for(i = 0; i < 2; i++){
-		fb = ctl->fb[i];
-		fb->createraster(fb, name, chan);
-	}
+	for(fb = ctl->fb; fb < ctl->fb+2; fb++)
+		(*fb)->createraster(*fb, name, chan);
 }
 
 static Raster *
@@ -445,105 +407,38 @@
 	return fb->fetchraster(fb, name);
 }
 
-Raster *
-_allocraster(char *name, Rectangle rr, ulong chan)
+static void
+fb_createraster(Framebuf *fb, char *name, ulong chan)
 {
 	Raster *r;
 
-	assert(chan <= FLOAT32);
+	assert(name != nil);
 
-	r = _emalloc(sizeof *r);
-	memset(r, 0, sizeof *r);
-	if(name != nil && (r->name = strdup(name)) == nil)
-		sysfatal("strdup: %r");
-	r->chan = chan;
-	r->r = rr;
-	r->data = _emalloc(Dx(rr)*Dy(rr)*sizeof(*r->data));
-	return r;
+	/*
+	 * TODO might be better to keep a tail so it's O(1)
+	 *
+	 * in practice though, most users won't ever create
+	 * more than ten extra rasters.
+	 */
+	r = fb->rasters;
+	while(r->next != nil)
+		r = r->next;
+	r->next = _allocraster(name, fb->r, chan);
 }
 
-void
-_clearraster(Raster *r, ulong v)
+static Raster *
+fb_fetchraster(Framebuf *fb, char *name)
 {
-	_memsetl(r->data, v, Dx(r->r)*Dy(r->r));
-}
+	Raster *r;
 
-void
-_fclearraster(Raster *r, float v)
-{
-	_memsetf(r->data, v, Dx(r->r)*Dy(r->r));
-}
+	r = fb->rasters;
+	if(name == nil)
+		return r;
 
-uchar *
-_rasterbyteaddr(Raster *r, Point p)
-{
-	return (uchar*)&r->data[p.y*Dx(r->r) + p.x];
-}
-
-void
-_rasterput(Raster *r, Point p, void *v)
-{
-	switch(r->chan){
-	case COLOR32:
-		*(ulong*)_rasterbyteaddr(r, p) = *(ulong*)v;
-		break;
-	case FLOAT32:
-		*(float*)_rasterbyteaddr(r, p) = *(float*)v;
-		break;
-	}
-}
-
-void
-_rasterget(Raster *r, Point p, void *v)
-{
-	switch(r->chan){
-	case COLOR32:
-		*(ulong*)v = *(ulong*)_rasterbyteaddr(r, p);
-		break;
-	case FLOAT32:
-		*(float*)v = *(float*)_rasterbyteaddr(r, p);
-		break;
-	}
-}
-
-void
-_rasterputcolor(Raster *r, Point p, ulong c)
-{
-	_rasterput(r, p, &c);
-}
-
-ulong
-_rastergetcolor(Raster *r, Point p)
-{
-	ulong c;
-
-	_rasterget(r, p, &c);
-	return c;
-}
-
-void
-_rasterputfloat(Raster *r, Point p, float v)
-{
-	_rasterput(r, p, &v);
-}
-
-float
-_rastergetfloat(Raster *r, Point p)
-{
-	float v;
-
-	_rasterget(r, p, &v);
-	return v;
-}
-
-void
-_freeraster(Raster *r)
-{
-	if(r == nil)
-		return;
-	free(r->data);
-	free(r->name);
-	free(r);
+	while((r = r->next) != nil)
+		if(strcmp(name, r->name) == 0)
+			return r;
+	return nil;
 }
 
 Framebuf *
--- a/graphics.h
+++ b/graphics.h
@@ -3,6 +3,10 @@
 #define min(a, b)	((a)<(b)?(a):(b))
 #define max(a, b)	((a)>(b)?(a):(b))
 
+/* bootleg ripoffs for Xpeed */
+#define _Xdotvec2(a,b)		((a).x*(b).x + (a).y*(b).y)
+#define _Xdotvec3(a,b)		((a).x*(b).x + (a).y*(b).y + (a).z*(b).z)
+
 typedef enum {
 	ORTHOGRAPHIC,
 	PERSPECTIVE,
--- a/internal.h
+++ b/internal.h
@@ -51,7 +51,7 @@
 void *_erealloc(void*, ulong);
 Memimage *_eallocmemimage(Rectangle, ulong);
 
-/* fb */
+/* raster */
 Raster *_allocraster(char*, Rectangle, ulong);
 void _clearraster(Raster*, ulong);
 void _fclearraster(Raster*, float);
@@ -63,6 +63,8 @@
 void _rasterputfloat(Raster*, Point, float);
 float _rastergetfloat(Raster*, Point);
 void _freeraster(Raster*);
+
+/* fb */
 Framebuf *_mkfb(Rectangle);
 void _rmfb(Framebuf*);
 Framebufctl *_mkfbctl(Rectangle);
@@ -83,7 +85,6 @@
 int _rectclipline(Rectangle, Point*, Point*, Vertex*, Vertex*);
 
 /* util */
-void _memsetf(void*, float, usize);
 void _memsetl(void*, ulong, usize);
 
 #define getpixel(fb, p)		_rastergetcolor(fb, p)
@@ -91,5 +92,5 @@
 #define getdepth(fb, p)		_rastergetfloat(fb, p)
 #define putdepth(fb, p, z)	_rasterputfloat(fb, p, z)
 
-/* void SWAP(type t, type *a, type *b) */
+/* void SWAP(type, type *a, type *b) */
 #define SWAP(t, a, b) {t tmp; tmp = *(a); *(a) = *(b); *(b) = tmp;}
--- /dev/null
+++ b/memsetl-amd64.s
@@ -1,0 +1,8 @@
+TEXT _memsetl(SB),1,$0
+	CLD
+	MOVQ	RARG, DI
+	MOVL	c+8(FP), AX
+	MOVQ	n+16(FP), CX
+	REP;	STOSL
+	MOVQ	RARG,AX
+	RET
--- /dev/null
+++ b/memsetl.c
@@ -1,0 +1,12 @@
+#include <u.h>
+#include <libc.h>
+
+void
+_memsetl(void *dp, ulong v, usize len)
+{
+	ulong *p;
+
+	p = dp;
+	while(len--)
+		*p++ = v;
+}
--- a/mkfile
+++ b/mkfile
@@ -11,6 +11,7 @@
 	vertex.$O\
 	texture.$O\
 	alloc.$O\
+	raster.$O\
 	fb.$O\
 	shadeop.$O\
 	color.$O\
@@ -17,6 +18,9 @@
 	util.$O\
 	nanosec.$O\
 	marshal.$O\
+	`{~ $objtype amd64\
+		&& echo memsetl-$objtype.$O\
+		|| echo memsetl.$O}
 
 HFILES=\
 	graphics.h\
--- /dev/null
+++ b/raster.c
@@ -1,0 +1,95 @@
+#include <u.h>
+#include <libc.h>
+#include <thread.h>
+#include <draw.h>
+#include <memdraw.h>
+#include <geometry.h>
+#include "graphics.h"
+#include "internal.h"
+
+Raster *
+_allocraster(char *name, Rectangle rr, ulong chan)
+{
+	Raster *r;
+
+	assert(chan <= FLOAT32);
+
+	r = _emalloc(sizeof *r);
+	memset(r, 0, sizeof *r);
+	if(name != nil && (r->name = strdup(name)) == nil)
+		sysfatal("strdup: %r");
+	r->chan = chan;
+	r->r = rr;
+	r->data = _emalloc(Dx(rr)*Dy(rr)*sizeof(*r->data));
+	return r;
+}
+
+void
+_clearraster(Raster *r, ulong v)
+{
+	_memsetl(r->data, *(ulong*)&v, Dx(r->r)*Dy(r->r));
+}
+
+void
+_fclearraster(Raster *r, float v)
+{
+	_memsetl(r->data, *(ulong*)&v, Dx(r->r)*Dy(r->r));
+}
+
+uchar *
+_rasterbyteaddr(Raster *r, Point p)
+{
+	return (uchar*)&r->data[p.y*Dx(r->r) + p.x];
+}
+
+void
+_rasterput(Raster *r, Point p, void *v)
+{
+	*(u32int*)_rasterbyteaddr(r, p) = *(u32int*)v;
+}
+
+void
+_rasterget(Raster *r, Point p, void *v)
+{
+	*(u32int*)v = *(u32int*)_rasterbyteaddr(r, p);
+}
+
+void
+_rasterputcolor(Raster *r, Point p, ulong c)
+{
+	_rasterput(r, p, &c);
+}
+
+ulong
+_rastergetcolor(Raster *r, Point p)
+{
+	ulong c;
+
+	_rasterget(r, p, &c);
+	return c;
+}
+
+void
+_rasterputfloat(Raster *r, Point p, float v)
+{
+	_rasterput(r, p, &v);
+}
+
+float
+_rastergetfloat(Raster *r, Point p)
+{
+	float v;
+
+	_rasterget(r, p, &v);
+	return v;
+}
+
+void
+_freeraster(Raster *r)
+{
+	if(r == nil)
+		return;
+	free(r->data);
+	free(r->name);
+	free(r);
+}
--- a/shadeop.c
+++ b/shadeop.c
@@ -56,11 +56,12 @@
 
 	switch(l->type){
 	case LightDirectional:
-		t = max(0, dotvec3(mulpt3(l->dir, -1), n));
+		ldir = mulpt3(l->dir, -1);
+		t = max(0, _Xdotvec3(ldir, n));
 		c = mulpt3(l->c, t);
 		break;
 	case LightPoint:
-		t = max(0, dotvec3(ldir, n));
+		t = max(0, _Xdotvec3(ldir, n));
 		c = mulpt3(l->c, t);
 
 		/* attenuation */
@@ -68,7 +69,8 @@
 		break;
 	case LightSpot:
 		/* see “Spotlights”, Real-Time Rendering 4th ed. § 5.2.2 */
-		cθs = dotvec3(mulpt3(ldir, -1), l->dir);
+		ldir = mulpt3(l->dir, -1);
+		cθs = _Xdotvec3(ldir, l->dir);
 		cθu = cos(l->θu);
 		cθp = cos(l->θp);
 
--- a/util.c
+++ b/util.c
@@ -95,26 +95,6 @@
 	return vec3len(subpt3(a, b)) < ε2;
 }
 
-void
-_memsetf(void *dp, float v, usize len)
-{
-	float *p;
-
-	p = dp;
-	while(len--)
-		*p++ = v;
-}
-
-void
-_memsetl(void *dp, ulong v, usize len)
-{
-	ulong *p;
-
-	p = dp;
-	while(len--)
-		*p++ = v;
-}
-
 Memimage *
 rgba(ulong c)
 {