sw_engine/math: fine-tuning optimization

Try to minimize the use of sqrt() and arctan() calls
when possible. These calls can be relatively expensive
when accumulated within a single frame.

Also repalce the division with shift operation.
since split cubic function is one of the significant hot-spots
in the data processing, we could earn a noticable enhancement.

Tested on single thread local machine:

Lottie: 0.080 -> 0.052s (-0.028s)
Performance: 0.023 -> 0.022 (-0.001s)
Binary: +34
This commit is contained in:
Hermet Park 2023-10-19 18:56:28 +09:00
parent 7cccabad40
commit 35ddc5fe56

View file

@ -50,11 +50,17 @@ bool mathSmallCubic(const SwPoint* base, SwFixed& angleIn, SwFixed& angleMid, Sw
auto d2 = base[1] - base[2];
auto d3 = base[0] - base[1];
if (d1 == d2 || d2 == d3) {
if (d3.small()) angleIn = angleMid = angleOut = 0;
else angleIn = angleMid = angleOut = mathAtan(d3);
return true;
}
if (d1.small()) {
if (d2.small()) {
if (d3.small()) {
//basically a point.
//do nothing to retain original direction
angleIn = angleMid = angleOut = 0;
return true;
} else {
angleIn = angleMid = angleOut = mathAtan(d3);
}
@ -205,7 +211,14 @@ SwFixed mathLength(const SwPoint& pt)
if (pt.y == 0) return abs(pt.x);
auto v = pt.toPoint();
return static_cast<SwFixed>(sqrtf(v.x * v.x + v.y * v.y) / 64.0f);
//return static_cast<SwFixed>(sqrtf(v.x * v.x + v.y * v.y) * 65536.0f);
/* approximate sqrt(x*x + y*y) using alpha max plus beta min algorithm.
With alpha = 1, beta = 3/8, giving results with the largest error less
than 7% compared to the exact value. */
if (v.x < 0) v.x = -v.x;
if (v.y < 0) v.y = -v.y;
return (v.x > v.y) ? (v.x + v.y * 0.375f) : (v.y + v.x * 0.375f);
}
@ -216,22 +229,22 @@ void mathSplitCubic(SwPoint* base)
base[6].x = base[3].x;
c = base[1].x;
d = base[2].x;
base[1].x = a = (base[0].x + c) / 2;
base[5].x = b = (base[3].x + d) / 2;
c = (c + d) / 2;
base[2].x = a = (a + c) / 2;
base[4].x = b = (b + c) / 2;
base[3].x = (a + b) / 2;
base[1].x = a = (base[0].x + c) >> 1;
base[5].x = b = (base[3].x + d) >> 1;
c = (c + d) >> 1;
base[2].x = a = (a + c) >> 1;
base[4].x = b = (b + c) >> 1;
base[3].x = (a + b) >> 1;
base[6].y = base[3].y;
c = base[1].y;
d = base[2].y;
base[1].y = a = (base[0].y + c) / 2;
base[5].y = b = (base[3].y + d) / 2;
c = (c + d) / 2;
base[2].y = a = (a + c) / 2;
base[4].y = b = (b + c) / 2;
base[3].y = (a + b) / 2;
base[1].y = a = (base[0].y + c) >> 1;
base[5].y = b = (base[3].y + d) >> 1;
c = (c + d) >> 1;
base[2].y = a = (a + c) >> 1;
base[4].y = b = (b + c) >> 1;
base[3].y = (a + b) >> 1;
}