add matrix compare to text blob key
In multi-threaded use, the cache would return a blob with direct
sub runs without comparing matrices. If two direct blobs have
different matrices, then they are incompatible. The original
code would find that the blob did not exist in the cache.
It would then make a new blob and insert it into the cache.
During that time, a different thread would create an
incompatible blob and insert it into the cache. The original
thread would insert the new blob into the cache, but the cache
finding an existing blob would return the incompatible blob.
The solution was to make the matrix, and drawing type part of
the key. Now, only compatible blobs are returned from the cache.
Change-Id: I318c756f07c84dd48b353b25639f9dcbe80c7b4b
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/377976
Commit-Queue: Herb Derby <herb@google.com>
Reviewed-by: Robert Phillips <robertphillips@google.com>
diff --git a/src/gpu/GrSurfaceDrawContext.cpp b/src/gpu/GrSurfaceDrawContext.cpp
index 46189c6..2f2fdc4 100644
--- a/src/gpu/GrSurfaceDrawContext.cpp
+++ b/src/gpu/GrSurfaceDrawContext.cpp
@@ -386,6 +386,9 @@
SkScalerContextFlags scalerContextFlags = this->colorInfo().isLinearlyBlended()
? SkScalerContextFlags::kBoostContrast
: SkScalerContextFlags::kFakeGammaAndBoostContrast;
+ SkMatrix drawMatrix(viewMatrix.localToDevice());
+ SkPoint drawOrigin = glyphRunList.origin();
+ drawMatrix.preTranslate(drawOrigin.x(), drawOrigin.y());
sk_sp<GrTextBlob> blob;
GrTextBlob::Key key;
@@ -412,14 +415,33 @@
}
key.fCanonicalColor = canonicalColor;
key.fScalerContextFlags = scalerContextFlags;
+
+ // Calculate the set of drawing types.
+ key.fSetOfDrawingTypes = 0;
+ for (auto& run : glyphRunList) {
+ key.fSetOfDrawingTypes |= options.drawingType(run.font(), drawPaint, drawMatrix);
+ }
+
+ if (key.fSetOfDrawingTypes & GrSDFTOptions::kDirect) {
+ // Store the fractional offset of the position. We know that the matrix can't be
+ // perspective at this point.
+ SkPoint mappedOrigin = drawMatrix.mapOrigin();
+ key.fDrawMatrix = drawMatrix;
+ key.fDrawMatrix.setTranslateX(
+ mappedOrigin.x() - SkScalarFloorToScalar(mappedOrigin.x()));
+ key.fDrawMatrix.setTranslateY(
+ mappedOrigin.y() - SkScalarFloorToScalar(mappedOrigin.y()));
+ } else {
+ // For path and SDFT, the matrix doesn't matter.
+ key.fDrawMatrix = SkMatrix::I();
+ }
+
blob = textBlobCache->find(key);
}
- SkMatrix drawMatrix(viewMatrix.localToDevice());
- SkPoint drawOrigin = glyphRunList.origin();
- drawMatrix.preTranslate(drawOrigin.x(), drawOrigin.y());
if (blob == nullptr || !blob->canReuse(drawPaint, drawMatrix)) {
if (blob != nullptr) {
+ SkASSERT(!drawMatrix.hasPerspective());
// We have to remake the blob because changes may invalidate our masks.
// TODO we could probably get away with reuse most of the time if the pointer is unique,
// but we'd have to clear the SubRun information