Add path bounds to SW path mask key
This was a potential issue before but DDLs greatly exacerbate
the situation. If the same path is rasterized multiple times
w/ a slightly different offset or w/ slightly different floating
point math, the actual size of the mask can change slightly.
This causes problems when the mask is cached since, if a prior
differently sized version is found in the cache, the fulfillment
code will assert.
Since our DDL test harness renders using tiles, this problem
arises more often in that configuration especially when
CCPR is unavailable.
Change-Id: Ie344b031cb49fedd9527f66b17ff610afa4a2f12
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/286902
Reviewed-by: Brian Osman <brianosman@google.com>
Commit-Queue: Robert Phillips <robertphillips@google.com>
diff --git a/src/gpu/GrSoftwarePathRenderer.cpp b/src/gpu/GrSoftwarePathRenderer.cpp
index ed7227d..36994fc 100644
--- a/src/gpu/GrSoftwarePathRenderer.cpp
+++ b/src/gpu/GrSoftwarePathRenderer.cpp
@@ -279,8 +279,13 @@
SkScalar kx = args.fViewMatrix->get(SkMatrix::kMSkewX);
SkScalar ky = args.fViewMatrix->get(SkMatrix::kMSkewY);
static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain();
- GrUniqueKey::Builder builder(&maskKey, kDomain, 5 + args.fShape->unstyledKeySize(),
+ GrUniqueKey::Builder builder(&maskKey, kDomain, 9 + args.fShape->unstyledKeySize(),
"SW Path Mask");
+ builder[0] = boundsForMask->fLeft;
+ builder[1] = boundsForMask->fTop;
+ builder[2] = boundsForMask->fRight;
+ builder[3] = boundsForMask->fBottom;
+
#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
// Fractional translate does not affect caching on Android. This is done for better cache
// hit ratio and speed, but it is matching HWUI behavior, which doesn't consider the matrix
@@ -294,18 +299,18 @@
SkFixed fracX = SkScalarToFixed(SkScalarFraction(tx)) & 0x0000FF00;
SkFixed fracY = SkScalarToFixed(SkScalarFraction(ty)) & 0x0000FF00;
#endif
- builder[0] = SkFloat2Bits(sx);
- builder[1] = SkFloat2Bits(sy);
- builder[2] = SkFloat2Bits(kx);
- builder[3] = SkFloat2Bits(ky);
+ builder[4] = SkFloat2Bits(sx);
+ builder[5] = SkFloat2Bits(sy);
+ builder[6] = SkFloat2Bits(kx);
+ builder[7] = SkFloat2Bits(ky);
// Distinguish between hairline and filled paths. For hairlines, we also need to include
// the cap. (SW grows hairlines by 0.5 pixel with round and square caps). Note that
// stroke-and-fill of hairlines is turned into pure fill by SkStrokeRec, so this covers
// all cases we might see.
uint32_t styleBits = args.fShape->style().isSimpleHairline() ?
((args.fShape->style().strokeRec().getCap() << 1) | 1) : 0;
- builder[4] = fracX | (fracY >> 8) | (styleBits << 16);
- args.fShape->writeUnstyledKey(&builder[5]);
+ builder[8] = fracX | (fracY >> 8) | (styleBits << 16);
+ args.fShape->writeUnstyledKey(&builder[9]);
}
sk_sp<GrTextureProxy> proxy;