Reland "Change how GrTextureOp computes outset vertices."
This is a reland of 42e086cd2d
Original change's description:
> Change how GrTextureOp computes outset vertices.
>
> Rather than intersecting outset edge equations we outset each vertex
> half a pixel along its two adjacent edges.
>
> This approach will allow for water tight seams along shared edges
> when we allow a subset of the quad edges to be antialiased.
>
> Bug: skia:
> Change-Id: I7f36ea658cc84dfcf364b138ec382bb709c278df
> Reviewed-on: https://skia-review.googlesource.com/156742
> Reviewed-by: Brian Osman <brianosman@google.com>
> Commit-Queue: Brian Salomon <bsalomon@google.com>
Bug: skia:
Change-Id: I518ddf1d1bd6d7b8234db9ccba3c495eb42f3f1d
Reviewed-on: https://skia-review.googlesource.com/157562
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Brian Salomon <bsalomon@google.com>
This commit is contained in:
parent
5dd47e4f15
commit
1620b87565
@ -275,37 +275,36 @@ static void compute_quad_edges_and_outset_vertices(Sk4f* x, Sk4f* y, Sk4f* a, Sk
|
|||||||
auto nextCW = [](const Sk4f& v) { return SkNx_shuffle<2, 0, 3, 1>(v); };
|
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 nextCCW = [](const Sk4f& v) { return SkNx_shuffle<1, 3, 0, 2>(v); };
|
||||||
|
|
||||||
|
// Compute edge equations for the quad.
|
||||||
auto xnext = nextCCW(*x);
|
auto xnext = nextCCW(*x);
|
||||||
auto ynext = nextCCW(*y);
|
auto ynext = nextCCW(*y);
|
||||||
*a = ynext - *y;
|
// xdiff and ydiff will comprise the normalized vectors pointing along each quad edge.
|
||||||
*b = *x - xnext;
|
auto xdiff = xnext - *x;
|
||||||
*c = fma(xnext, *y, -ynext * *x);
|
auto ydiff = ynext - *y;
|
||||||
Sk4f invNormLengths = (*a * *a + *b * *b).rsqrt();
|
Sk4f invLengths = fma(xdiff, xdiff, ydiff * ydiff).rsqrt();
|
||||||
|
xdiff *= invLengths;
|
||||||
|
ydiff *= invLengths;
|
||||||
|
|
||||||
|
// Use above vectors to compute edge equations.
|
||||||
|
*c = fma(xnext, *y, -ynext * *x) * invLengths;
|
||||||
// Make sure the edge equations have their normals facing into the quad in device space.
|
// 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));
|
auto test = fma(ydiff, nextCW(*x), fma(-xdiff, nextCW(*y), *c));
|
||||||
if ((test < Sk4f(0)).anyTrue()) {
|
if ((test < Sk4f(0)).anyTrue()) {
|
||||||
invNormLengths = -invNormLengths;
|
*a = -ydiff;
|
||||||
|
*b = xdiff;
|
||||||
|
*c = -*c;
|
||||||
|
} else {
|
||||||
|
*a = ydiff;
|
||||||
|
*b = -xdiff;
|
||||||
}
|
}
|
||||||
*a *= invNormLengths;
|
// Outset the edge equations so aa coverage evaluates to zero half a pixel away from the
|
||||||
*b *= invNormLengths;
|
// original quad edge.
|
||||||
*c *= invNormLengths;
|
*c += 0.5f;
|
||||||
|
|
||||||
// Here is the outset. This makes our edge equations compute coverage without requiring a
|
// Outset the corners by half a pixel along each of the two adjacent vectors to ensure all
|
||||||
// half pixel offset and is also used to compute the bloated quad that will cover all
|
// pixel centers are covered.
|
||||||
// pixels.
|
*x += 0.5f * (-xdiff + nextCW(xdiff));
|
||||||
*c += Sk4f(0.5f);
|
*y += 0.5f * (-ydiff + nextCW(ydiff));
|
||||||
|
|
||||||
// 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 {
|
namespace {
|
||||||
|
Loading…
Reference in New Issue
Block a user