aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar Brian Salomon <bsalomon@google.com>2018-05-18 10:29:54 -0400
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2018-05-18 15:29:44 +0000
commit6872e94606ff144faa789c6996d2383bf62276ae (patch)
tree31d72f8f51485c544bcfa17f94fed6692234193f /src
parent255ab8d9a55d68b7405280dae6b586d17e23cf71 (diff)
Modifications to GrTextureOp outsetting, edge equation code.
Factor out to its own function to be reused with perspective. Avoid initial shuffles to fan order using nextCW and nextCCW helpers that assume tri strip order. Make sign test stay in 4f. Use fmas. Change-Id: I60cff205f6193c4e01ea84218812a663ce74038f Reviewed-on: https://skia-review.googlesource.com/129175 Reviewed-by: Brian Osman <brianosman@google.com> Commit-Queue: Brian Salomon <bsalomon@google.com>
Diffstat (limited to 'src')
-rw-r--r--src/gpu/ops/GrTextureOp.cpp96
1 files changed, 49 insertions, 47 deletions
diff --git a/src/gpu/ops/GrTextureOp.cpp b/src/gpu/ops/GrTextureOp.cpp
index a4b79ac50f..f2efb95a92 100644
--- a/src/gpu/ops/GrTextureOp.cpp
+++ b/src/gpu/ops/GrTextureOp.cpp
@@ -285,6 +285,49 @@ private:
typedef GrGeometryProcessor INHERITED;
};
+// This computes the four edge equations for a quad, then outsets them and computes a new quad
+// as the intersection points of the outset edges. 'x' and 'y' contain the original points as input
+// and the outset points as output. 'a', 'b', and 'c' are the edge equation coefficients on output.
+static void compute_quad_edges_and_outset_vertices(Sk4f* x, Sk4f* y, Sk4f* a, Sk4f* b, Sk4f* c) {
+ static constexpr auto fma = SkNx_fma<4, float>;
+ // These rotate the points/edge values either clockwise or counterclockwise assuming tri strip
+ // order.
+ auto nextCW = [](const Sk4f& v) { return SkNx_shuffle<2, 0, 3, 1>(v); };
+ auto nextCCW = [](const Sk4f& v) { return SkNx_shuffle<1, 3, 0, 2>(v); };
+
+ auto xnext = nextCCW(*x);
+ auto ynext = nextCCW(*y);
+ *a = ynext - *y;
+ *b = *x - xnext;
+ *c = fma(xnext, *y, -ynext * *x);
+ Sk4f invNormLengths = (*a * *a + *b * *b).rsqrt();
+ // Make sure the edge equations have their normals facing into the quad in device space.
+ auto test = fma(*a, nextCW(*x), fma(*b, nextCW(*y), *c));
+ if ((test < Sk4f(0)).anyTrue()) {
+ invNormLengths = -invNormLengths;
+ }
+ *a *= invNormLengths;
+ *b *= invNormLengths;
+ *c *= invNormLengths;
+
+ // Here is the outset. This makes our edge equations compute coverage without requiring a
+ // half pixel offset and is also used to compute the bloated quad that will cover all
+ // pixels.
+ *c += Sk4f(0.5f);
+
+ // Reverse the process to compute the points of the bloated quad from the edge equations.
+ // This time the inputs don't have 1s as their third coord and we want to homogenize rather
+ // than normalize.
+ auto anext = nextCW(*a);
+ auto bnext = nextCW(*b);
+ auto cnext = nextCW(*c);
+ *x = fma(bnext, *c, -*b * cnext);
+ *y = fma(*a, cnext, -anext * *c);
+ auto ic = (fma(anext, *b, -bnext * *a)).invert();
+ *x *= ic;
+ *y *= ic;
+}
+
namespace {
// This is a class soley so it can be partially specialized (functions cannot be).
template<GrAA, typename Vertex> class VertexAAHandler;
@@ -308,59 +351,18 @@ template<typename Vertex> class VertexAAHandler<GrAA::kYes, Vertex> {
public:
static void AssignPositionsAndTexCoords(Vertex* vertices, const GrQuad& quad,
const SkRect& texRect) {
- // We compute the four edge equations for quad, then outset them and compute a new quad
- // as the intersection points of the outset edges.
-
- // GrQuad is in tristip order but we want the points to be in a fan order, so swap 2 and 3.
- Sk4f xs = SkNx_shuffle<0, 1, 3, 2>(quad.x4f());
- Sk4f ys = SkNx_shuffle<0, 1, 3, 2>(quad.y4f());
- Sk4f xsrot = SkNx_shuffle<1, 2, 3, 0>(xs);
- Sk4f ysrot = SkNx_shuffle<1, 2, 3, 0>(ys);
- Sk4f normXs = ysrot - ys;
- Sk4f normYs = xs - xsrot;
- Sk4f ds = xsrot * ys - ysrot * xs;
- Sk4f invNormLengths = (normXs * normXs + normYs * normYs).rsqrt();
- float test = normXs[0] * xs[2] + normYs[0] * ys[2] + ds[0];
- // Make sure the edge equations have their normals facing into the quad in device space
- if (test < 0) {
- invNormLengths = -invNormLengths;
- }
- normXs *= invNormLengths;
- normYs *= invNormLengths;
- ds *= invNormLengths;
-
- // Here is the bloat. This makes our edge equations compute coverage without requiring a
- // half pixel offset and is also used to compute the bloated quad that will cover all
- // pixels.
- ds += Sk4f(0.5f);
+ auto x = quad.x4f();
+ auto y = quad.y4f();
+ Sk4f a, b, c;
+ compute_quad_edges_and_outset_vertices(&x, &y, &a, &b, &c);
for (int i = 0; i < 4; ++i) {
+ vertices[i].fPosition = {x[i], y[i]};
for (int j = 0; j < 4; ++j) {
- vertices[j].fEdges[i].fX = normXs[i];
- vertices[j].fEdges[i].fY = normYs[i];
- vertices[j].fEdges[i].fZ = ds[i];
+ vertices[i].fEdges[j] = {a[j], b[j], c[j]};
}
}
- // Reverse the process to compute the points of the bloated quad from the edge equations.
- // This time the inputs don't have 1s as their third coord and we want to homogenize rather
- // than normalize the output since we need a GrQuad with 2D points.
- xsrot = SkNx_shuffle<3, 0, 1, 2>(normXs);
- ysrot = SkNx_shuffle<3, 0, 1, 2>(normYs);
- Sk4f dsrot = SkNx_shuffle<3, 0, 1, 2>(ds);
- xs = ysrot * ds - normYs * dsrot;
- ys = normXs * dsrot - xsrot * ds;
- ds = xsrot * normYs - ysrot * normXs;
- ds = ds.invert();
- xs *= ds;
- ys *= ds;
-
- // Go back to tri strip order when writing out the bloated quad to vertex positions.
- vertices[0].fPosition = {xs[0], ys[0]};
- vertices[1].fPosition = {xs[1], ys[1]};
- vertices[3].fPosition = {xs[2], ys[2]};
- vertices[2].fPosition = {xs[3], ys[3]};
-
AssignTexCoords(vertices, quad, texRect);
}