ref: c928eb5927903cb3e390aa5ff391ea91113517e1
parent: c33c843b142c1170c97d6dceb9abac91b01fe188
author: rodri <rgl@antares-labs.eu>
date: Sat Feb 14 21:48:39 EST 2026
fb: improve upscaledraw() performance by loading entire line blocks at a time. a line block is an upscaled scanline.
--- a/fb.c
+++ b/fb.c
@@ -13,7 +13,7 @@
* see https://www.scale2x.it/algorithm
*/
static void
-scale2x_filter(ulong *dst, Raster *fb, Point sp, ulong)
+scale2x_filter(ulong *dst, Raster *fb, Point sp, Point, ulong dx)
{ulong B, D, E, F, H;
@@ -24,16 +24,18 @@
H = sp.y == fb->r.max.y? E: getpixel(fb, addpt(sp, Pt( 0, 1)));
if(B != H && D != F){- dst[0] = D == B? D: E;
- dst[1] = B == F? F: E;
- dst[2] = D == H? D: E;
- dst[3] = H == F? F: E;
- }else
- _memsetl(dst, E, 4);
+ dst[0*dx+0] = D == B? D: E;
+ dst[0*dx+1] = B == F? F: E;
+ dst[1*dx+0] = D == H? D: E;
+ dst[1*dx+1] = H == F? F: E;
+ }else{+ _memsetl(dst + 0*dx, E, 2);
+ _memsetl(dst + 1*dx, E, 2);
+ }
}
static void
-scale3x_filter(ulong *dst, Raster *fb, Point sp, ulong)
+scale3x_filter(ulong *dst, Raster *fb, Point sp, Point, ulong dx)
{ulong A, B, C, D, E, F, G, H, I;
@@ -56,17 +58,20 @@
getpixel(fb, addpt(sp, Pt( 1, 1)));
if(B != H && D != F){- dst[0] = D == B? D: E;
- dst[1] = (D == B && E != C) || (B == F && E != A)? B: E;
- dst[2] = B == F? F: E;
- dst[3] = (D == B && E != G) || (D == H && E != A)? D: E;
- dst[4] = E;
- dst[5] = (B == F && E != I) || (H == F && E != C)? F: E;
- dst[6] = D == H? D: E;
- dst[7] = (D == H && E != I) || (H == F && E != G)? H: E;
- dst[8] = H == F? F: E;
- }else
- _memsetl(dst, E, 9);
+ dst[0*dx+0] = D == B? D: E;
+ dst[0*dx+1] = (D == B && E != C) || (B == F && E != A)? B: E;
+ dst[0*dx+2] = B == F? F: E;
+ dst[1*dx+0] = (D == B && E != G) || (D == H && E != A)? D: E;
+ dst[1*dx+1] = E;
+ dst[1*dx+2] = (B == F && E != I) || (H == F && E != C)? F: E;
+ dst[2*dx+0] = D == H? D: E;
+ dst[2*dx+1] = (D == H && E != I) || (H == F && E != G)? H: E;
+ dst[2*dx+2] = H == F? F: E;
+ }else{+ _memsetl(dst + 0*dx, E, 3);
+ _memsetl(dst + 1*dx, E, 3);
+ _memsetl(dst + 2*dx, E, 3);
+ }
}
//static void
@@ -76,9 +81,14 @@
//}
static void
-ident_filter(ulong *dst, Raster *fb, Point sp, ulong len)
+ident_filter(ulong *dst, Raster *fb, Point sp, Point s, ulong dx)
{- _memsetl(dst, getpixel(fb, sp), len);
+ ulong c;
+ int y;
+
+ c = getpixel(fb, sp);
+ for(y = 0; y < s.y; y++)
+ _memsetl(dst + y*dx, c, s.x);
}
/* convert a float raster to a greyscale color one */
@@ -138,15 +148,17 @@
static void
upscaledraw(Raster *fb, Image *dst, Point off, Point scale, uint filter)
{- void (*filterfn)(ulong*, Raster*, Point, ulong);
+ void (*filterfn)(ulong*, Raster*, Point, Point, ulong);
Rectangle blkr;
Point sp, dp;
Image *tmp;
- ulong *blk;
+ ulong *blk, *blkp;
+ int dx;
filterfn = nil;
- blk = _emalloc(scale.x*scale.y*4);
- blkr = Rect(0,0,scale.x,scale.y);
+ dx = Dx(fb->r);
+ blk = _emalloc(scale.x*dx*scale.y*4);
+ blkr = Rect(0,0,scale.x*dx,scale.y);
tmp = allocimage(display, dst->r, RGBA32, 0, 0);
if(tmp == nil)
sysfatal("allocimage: %r");@@ -160,14 +172,17 @@
if(scale.x == scale.y && scale.y == 3)
filterfn = scale3x_filter;
break;
- default: filterfn = ident_filter;
+ 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){- filterfn(blk, fb, sp, scale.x*scale.y);
- loadimage(tmp, rectaddpt(blkr, dp), (uchar*)blk, scale.x*scale.y*4);
+ dp.x = dst->r.min.x+off.x;
+ 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, blkp = blk; sp.x < fb->r.max.x; sp.x++, blkp += scale.x){+ filterfn(blkp, fb, sp, scale, scale.x*dx);
}
+ loadimage(tmp, rectaddpt(blkr, dp), (uchar*)blk, scale.x*dx*scale.y*4);
+ }
draw(dst, dst->r, tmp, nil, tmp->r.min);
freeimage(tmp);
free(blk);
@@ -236,7 +251,7 @@
static void
upscalememdraw(Raster *fb, Memimage *dst, Point off, Point scale, uint filter)
{- void (*filterfn)(ulong*, Raster*, Point, ulong);
+ void (*filterfn)(ulong*, Raster*, Point, Point, ulong);
Rectangle blkr;
Point sp, dp;
Memimage *tmp;
@@ -258,12 +273,13 @@
if(scale.x == scale.y && scale.y == 3)
filterfn = scale3x_filter;
break;
- default: filterfn = ident_filter;
+ 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){- filterfn(blk, fb, sp, scale.x*scale.y);
+ filterfn(blk, fb, sp, scale, scale.x);
loadmemimage(tmp, rectaddpt(blkr, dp), (uchar*)blk, scale.x*scale.y*4);
}
memimagedraw(dst, dst->r, tmp, tmp->r.min, nil, ZP, S);
--
⑨