Combine mask and edge distance in TessellationHelper
This also moves the corner scale factors (1 for rectangles, or 1/sin(theta)
into the EdgeVector state, since that is constant for a quad and can be
reused between different edge distance requests.
The OutsetRequest cached data now only needs to decide which codepath to
use for calculating the inset or outset (fast or degenerate). It is now
capable of distinguishing degeneracies for just the inset and not outset
(or vice versa). Previously, if the inset would cause a degeneracy, both
inset and outset operations would go through the slow path.
Change-Id: Idda859152b6f515f2b3d54875b9f40d9feb5da22
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/252816
Commit-Queue: Michael Ludwig <michaelludwig@google.com>
Reviewed-by: Brian Salomon <bsalomon@google.com>
diff --git a/src/gpu/ops/GrQuadPerEdgeAA.cpp b/src/gpu/ops/GrQuadPerEdgeAA.cpp
index 3b0dc25..ac0baa5 100644
--- a/src/gpu/ops/GrQuadPerEdgeAA.cpp
+++ b/src/gpu/ops/GrQuadPerEdgeAA.cpp
@@ -107,20 +107,43 @@
geomDomain.outset(0.5f, 0.5f); // account for AA expansion
}
- // TODO(michaelludwig) - Update TessellateHelper to select processing functions based on the
- // vertexspec once per op, and then burn through all quads with the selected function ptr.
- GrQuadUtils::TessellationHelper helper(deviceQuad,
- spec.hasLocalCoords() ? &localQuad : nullptr);
+ if (aaFlags == GrQuadAAFlags::kNone) {
+ // Have to write the coverage AA vertex structure, but there's no math to be done for a
+ // non-aa quad batched into a coverage AA op.
+ write_quad(&vb, spec, mode, 1.f, color4f, geomDomain, domain, deviceQuad, localQuad);
+ // Since we pass the same corners in, the outer vertex structure will have 0 area and
+ // the coverage interpolation from 1 to 0 will not be visible.
+ write_quad(&vb, spec, mode, 0.f, color4f, geomDomain, domain, deviceQuad, localQuad);
+ } else {
+ // TODO(michaelludwig) - Update TessellateHelper to select processing functions based on
+ // the vertexspec once per op, and then burn through all quads with the selected
+ // function ptr.
+ GrQuadUtils::TessellationHelper helper(deviceQuad,
+ spec.hasLocalCoords() ? &localQuad : nullptr);
- // Write inner vertices first
- GrQuad aaDeviceQuad, aaLocalQuad;
- skvx::Vec<4, float> coverage = helper.inset(aaFlags, &aaDeviceQuad, &aaLocalQuad);
- write_quad(&vb, spec, mode, coverage, color4f, geomDomain, domain,
- aaDeviceQuad, aaLocalQuad);
+ // Edge inset/outset distance ordered LBTR, set to 0.5 for a half pixel if the AA flag
+ // is turned on, or 0.0 if the edge is not anti-aliased.
+ skvx::Vec<4, float> edgeDistances;
+ if (aaFlags == GrQuadAAFlags::kAll) {
+ edgeDistances = 0.5f;
+ } else {
+ edgeDistances = { (aaFlags & GrQuadAAFlags::kLeft) ? 0.5f : 0.f,
+ (aaFlags & GrQuadAAFlags::kBottom) ? 0.5f : 0.f,
+ (aaFlags & GrQuadAAFlags::kTop) ? 0.5f : 0.f,
+ (aaFlags & GrQuadAAFlags::kRight) ? 0.5f : 0.f };
+ }
- // Then outer vertices, which use 0.f for their coverage
- helper.outset(aaFlags, &aaDeviceQuad, &aaLocalQuad);
- write_quad(&vb, spec, mode, 0.f, color4f, geomDomain, domain, aaDeviceQuad, aaLocalQuad);
+ // Write inner vertices first
+ GrQuad aaDeviceQuad, aaLocalQuad;
+ skvx::Vec<4, float> coverage = helper.inset(edgeDistances, &aaDeviceQuad, &aaLocalQuad);
+ write_quad(&vb, spec, mode, coverage, color4f, geomDomain, domain,
+ aaDeviceQuad, aaLocalQuad);
+
+ // Then outer vertices, which use 0.f for their coverage
+ helper.outset(edgeDistances, &aaDeviceQuad, &aaLocalQuad);
+ write_quad(&vb, spec, mode, 0.f, color4f, geomDomain, domain,
+ aaDeviceQuad, aaLocalQuad);
+ }
} else {
// No outsetting needed, just write a single quad with full coverage
SkASSERT(mode == CoverageMode::kNone && !spec.requiresGeometryDomain());