aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu/GrPathUtils.cpp
diff options
context:
space:
mode:
authorGravatar Chris Dalton <csmartdalton@google.com>2017-08-07 09:00:46 -0600
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-08-07 15:21:30 +0000
commitb072bb6a5c84fecf652ab5f32a197247219efca2 (patch)
treed9c476eb632464efd2d28c34999104fa2e07fae8 /src/gpu/GrPathUtils.cpp
parent399b3c2a01cb34c8b9e444ccb5fe5ef3153074c0 (diff)
CCPR: Process quadratic flat edges without soft msaa
The artifacts previously thought to require msaa can be handled by (1) converting near-linear quadratics into lines, and (2) ensuring all quadratic segments are monotonic with respect to the vector of their closing edge [P2 -> P0]. No. 1 was already in effect. No. 2 is implemented by this change. Now we only fall back on soft msaa for the two corner pixels. This change also does some generic housekeeping in the quadratic processor. Bug: skia: Change-Id: Ib3309c2ed86d3d8bec5f451125a69326e82eeb1c Reviewed-on: https://skia-review.googlesource.com/29721 Commit-Queue: Chris Dalton <csmartdalton@google.com> Reviewed-by: Greg Daniel <egdaniel@google.com>
Diffstat (limited to 'src/gpu/GrPathUtils.cpp')
-rw-r--r--src/gpu/GrPathUtils.cpp60
1 files changed, 60 insertions, 0 deletions
diff --git a/src/gpu/GrPathUtils.cpp b/src/gpu/GrPathUtils.cpp
index b6711a0df4..9a79f2061e 100644
--- a/src/gpu/GrPathUtils.cpp
+++ b/src/gpu/GrPathUtils.cpp
@@ -567,6 +567,66 @@ void GrPathUtils::convertCubicToQuadsConstrainToTangents(const SkPoint p[4],
}
}
+static inline Sk2f normalize(const Sk2f& n) {
+ Sk2f nn = n*n;
+ return n * (nn + SkNx_shuffle<1,0>(nn)).rsqrt();
+}
+
+bool GrPathUtils::chopMonotonicQuads(const SkPoint p[3], SkPoint dst[5]) {
+ GR_STATIC_ASSERT(SK_SCALAR_IS_FLOAT);
+ GR_STATIC_ASSERT(2 * sizeof(float) == sizeof(SkPoint));
+ GR_STATIC_ASSERT(0 == offsetof(SkPoint, fX));
+
+ Sk2f p0 = Sk2f::Load(&p[0]);
+ Sk2f p1 = Sk2f::Load(&p[1]);
+ Sk2f p2 = Sk2f::Load(&p[2]);
+
+ Sk2f tan0 = p1 - p0;
+ Sk2f tan1 = p2 - p1;
+ Sk2f v = p2 - p0;
+
+ // Check if the curve is already monotonic (i.e. (tan0 dot v) >= 0 and (tan1 dot v) >= 0).
+ // This should almost always be this case for well-behaved curves in the real world.
+ float dot0[2], dot1[2];
+ (tan0 * v).store(dot0);
+ (tan1 * v).store(dot1);
+ if (dot0[0] + dot0[1] >= 0 && dot1[0] + dot1[1] >= 0) {
+ return false;
+ }
+
+ // Chop the curve into two segments with equal curvature. To do this we find the T value whose
+ // tangent is perpendicular to the vector that bisects tan0 and -tan1.
+ Sk2f n = normalize(tan0) - normalize(tan1);
+
+ // This tangent can be found where (dQ(t) dot n) = 0:
+ //
+ // 0 = (dQ(t) dot n) = | 2*t 1 | * | p0 - 2*p1 + p2 | * | n |
+ // | -2*p0 + 2*p1 | | . |
+ //
+ // = | 2*t 1 | * | tan1 - tan0 | * | n |
+ // | 2*tan0 | | . |
+ //
+ // = 2*t * ((tan1 - tan0) dot n) + (2*tan0 dot n)
+ //
+ // t = (tan0 dot n) / ((tan0 - tan1) dot n)
+ Sk2f dQ1n = (tan0 - tan1) * n;
+ Sk2f dQ0n = tan0 * n;
+ Sk2f t = (dQ0n + SkNx_shuffle<1,0>(dQ0n)) / (dQ1n + SkNx_shuffle<1,0>(dQ1n));
+ t = Sk2f::Min(Sk2f::Max(t, 0), 1); // Clamp for FP error.
+
+ Sk2f p01 = SkNx_fma(t, tan0, p0);
+ Sk2f p12 = SkNx_fma(t, tan1, p1);
+ Sk2f p012 = SkNx_fma(t, p12 - p01, p01);
+
+ p0.store(&dst[0]);
+ p01.store(&dst[1]);
+ p012.store(&dst[2]);
+ p12.store(&dst[3]);
+ p2.store(&dst[4]);
+
+ return true;
+}
+
////////////////////////////////////////////////////////////////////////////////
/**