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)
{