shithub: front

Download patch

ref: a222ad25f1656a5d098028c11283cc7f8c67f0e4
parent: 2a0ed585ce506b55d90e1c10142c2150ffa892e2
author: rodri <rgl@antares-labs.eu>
date: Thu Aug 14 11:15:09 EDT 2025

libmemdraw: do the matrix inversion in mkwarp() instead of memaffinewarp()

With this we can get rid of the fixed-point reimplementation, and just
use invm(2) (in userspace) before creating the Warp.

--- a/sys/src/libmemdraw/mkfile
+++ b/sys/src/libmemdraw/mkfile
@@ -22,6 +22,7 @@
 	unload.$O\
 	write.$O\
 	warp.$O\
+	mkwarp.$O\
 
 </sys/src/cmd/mksyslib
 
--- /dev/null
+++ b/sys/src/libmemdraw/mkwarp.c
@@ -1,0 +1,22 @@
+#include <u.h>
+#include <libc.h>
+#include <draw.h>
+#include <memdraw.h>
+#include <geometry.h>
+
+/* 25.7 fixed-point number operations */
+
+#define flt2fix(n)	((long)((n)*(1<<7) + ((n) < 0? -0.5: 0.5)))
+
+void
+mkwarp(Warp w, double m0[3][3])
+{
+	Matrix m;
+
+	memmove(m, m0, sizeof(Matrix));
+	invm(m);
+
+	w[0][0] = flt2fix(m[0][0]); w[0][1] = flt2fix(m[0][1]); w[0][2] = flt2fix(m[0][2]);
+	w[1][0] = flt2fix(m[1][0]); w[1][1] = flt2fix(m[1][1]); w[1][2] = flt2fix(m[1][2]);
+	w[2][0] = 0; w[2][1] = 0; w[2][2] = 1<<7;
+}
--- a/sys/src/libmemdraw/warp.c
+++ b/sys/src/libmemdraw/warp.c
@@ -6,13 +6,10 @@
 /* 25.7 fixed-point number operations */
 
 #define FMASK		((1<<7) - 1)
-#define flt2fix(n)	((long)((n)*(1<<7) + ((n) < 0? -0.5: 0.5)))
 #define int2fix(n)	((vlong)(n)<<7)
 #define fix2int(n)	((n)>>7)
 #define fixmul(a,b)	((vlong)(a)*(vlong)(b) >> 7)
-#define fixdiv(a,b)	(((vlong)(a) << 7)/(vlong)(b))
 #define fixfrac(n)	((n)&FMASK)
-
 #define lerp(a,b,t)	((a) + ((((b) - (a))*(t))>>7))
 
 typedef struct Foint Foint;
@@ -32,55 +29,6 @@
 	int cmask;
 };
 
-static void
-fix_smulm(Warp m, long s)
-{
-	m[0][0] = fixmul(m[0][0], s); m[0][1] = fixmul(m[0][1], s); m[0][2] = fixmul(m[0][2], s);
-	m[1][0] = fixmul(m[1][0], s); m[1][1] = fixmul(m[1][1], s); m[1][2] = fixmul(m[1][2], s);
-	m[2][0] = fixmul(m[2][0], s); m[2][1] = fixmul(m[2][1], s); m[2][2] = fixmul(m[2][2], s);
-}
-
-static long
-fix_detm(Warp m)
-{
-	return fixmul(m[0][0], (fixmul(m[1][1], m[2][2]) - fixmul(m[1][2], m[2][1])))+
-	       fixmul(m[0][1], (fixmul(m[1][2], m[2][0]) - fixmul(m[1][0], m[2][2])))+
-	       fixmul(m[0][2], (fixmul(m[1][0], m[2][1]) - fixmul(m[1][1], m[2][0])));
-}
-
-static void
-fix_adjm(Warp m)
-{
-	Warp tmp;
-
-	tmp[0][0] =  fixmul(m[1][1], m[2][2]) - fixmul(m[1][2], m[2][1]);
-	tmp[0][1] = -fixmul(m[0][1], m[2][2]) + fixmul(m[0][2], m[2][1]);
-	tmp[0][2] =  fixmul(m[0][1], m[1][2]) - fixmul(m[0][2], m[1][1]);
-
-	tmp[1][0] = -fixmul(m[1][0], m[2][2]) + fixmul(m[1][2], m[2][0]);
-	tmp[1][1] =  fixmul(m[0][0], m[2][2]) - fixmul(m[0][2], m[2][0]);
-	tmp[1][2] = -fixmul(m[0][0], m[1][2]) + fixmul(m[0][2], m[1][0]);
-
-	tmp[2][0] =  fixmul(m[1][0], m[2][1]) - fixmul(m[1][1], m[2][0]);
-	tmp[2][1] = -fixmul(m[0][0], m[2][1]) + fixmul(m[0][1], m[2][0]);
-	tmp[2][2] =  fixmul(m[0][0], m[1][1]) - fixmul(m[0][1], m[1][0]);
-
-	memmove(m, tmp, sizeof tmp);
-}
-
-/* Cramer's */
-static void
-fix_invm(Warp m)
-{
-	long det;
-
-	det = fix_detm(m);
-	if(det == 0)
-		return; /* singular matrices are not invertible */
-	fix_adjm(m);
-	fix_smulm(m, fixdiv(1<<7, det));
-}
-
 static Foint
 fix_xform(Foint p, Warp m)
 {
@@ -91,14 +39,6 @@
 	};
 }
 
-void
-mkwarp(Warp w, double m[3][3])
-{
-	w[0][0] = flt2fix(m[0][0]); w[0][1] = flt2fix(m[0][1]); w[0][2] = flt2fix(m[0][2]);
-	w[1][0] = flt2fix(m[1][0]); w[1][1] = flt2fix(m[1][1]); w[1][2] = flt2fix(m[1][2]);
-	w[2][0] = 0; w[2][1] = 0; w[2][2] = 1<<7;
-}
-
 static ulong
 edgehandler(Sampler*, Point*)
 {
@@ -120,10 +60,9 @@
 }
 
 int
-memaffinewarp(Memimage *d, Rectangle r, Memimage *s, Point sp0, Warp ma)
+memaffinewarp(Memimage *d, Rectangle r, Memimage *s, Point sp0, Warp m)
 {
 	Sampler samp;
-	Warp m;
 	Point sp, dp;
 	Foint p2;
 	long Δx, Δy;
@@ -153,12 +92,11 @@
 	bpp = d->depth >> 3;
 	bploff = sizeof(ulong)*d->width - Dx(d->r)*bpp;
 
-	memmove(m, ma, sizeof(Warp));
-	fix_invm(m);
+	r = rectsubpt(r, r.min);
 
-	for(dp.y = r.min.y; dp.y < r.max.y; dp.y++, a += bploff)
-	for(dp.x = r.min.x; dp.x < r.max.x; dp.x++, a += bpp){
-		p2 = fix_xform((Foint){int2fix(dp.x - r.min.x), int2fix(dp.y - r.min.y), 1<<7}, m);
+	for(dp.y = 0; dp.y < r.max.y; dp.y++, a += bploff)
+	for(dp.x = 0; dp.x < r.max.x; dp.x++, a += bpp){
+		p2 = fix_xform((Foint){int2fix(dp.x), int2fix(dp.y), 1<<7}, m);
 
 		Δx = fixfrac(p2.x);
 		Δy = fixfrac(p2.y);
--