use sk_sp<SkStrike> instead of SkStrikeSpec

This CL focuses on removing the SkStrikeSpec from the GlyphVector.
Now the GlyphVector can use an SkStrike directly. This CL
is mostly a bunch of tricky plumbing.

Change-Id: I4eb8ccfc44d9e8b7f35578bf754c188a7fd55596
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/469176
Reviewed-by: Ben Wagner <bungeman@google.com>
Commit-Queue: Herb Derby <herb@google.com>
diff --git a/src/core/SkGlyphRunPainter.cpp b/src/core/SkGlyphRunPainter.cpp
index 0cb1529..2bbe812 100644
--- a/src/core/SkGlyphRunPainter.cpp
+++ b/src/core/SkGlyphRunPainter.cpp
@@ -267,7 +267,7 @@
                 // processSourceSDFT must be called even if there are no glyphs to make sure
                 // runs are set correctly.
                 process->processSourceSDFT(fDrawable.drawable(),
-                                           strikeSpec,
+                                           strike->getUnderlyingStrike(),
                                            strikeToSourceScale,
                                            runFont,
                                            minScale, maxScale);
@@ -297,7 +297,7 @@
         if (process && !fDrawable.drawableIsEmpty()) {
             // processDeviceMasks must be called even if there are no glyphs to make sure runs
             // are set correctly.
-            process->processDeviceMasks(fDrawable.drawable(), strikeSpec);
+            process->processDeviceMasks(fDrawable.drawable(), strike->getUnderlyingStrike());
         }
     }
 
@@ -357,7 +357,8 @@
             SkASSERT(fRejects.source().empty());
 
             if (process && !fDrawable.drawableIsEmpty()) {
-                process->processSourceMasks(fDrawable.drawable(), strikeSpec, strikeToSourceScale);
+                process->processSourceMasks(
+                        fDrawable.drawable(), strike->getUnderlyingStrike(), strikeToSourceScale);
             }
         }
     }
diff --git a/src/core/SkGlyphRunPainter.h b/src/core/SkGlyphRunPainter.h
index 44fde79..f2336c5 100644
--- a/src/core/SkGlyphRunPainter.h
+++ b/src/core/SkGlyphRunPainter.h
@@ -140,10 +140,10 @@
     virtual ~SkGlyphRunPainterInterface() = default;
 
     virtual void processDeviceMasks(const SkZip<SkGlyphVariant, SkPoint>& drawables,
-                                    const SkStrikeSpec& strikeSpec) = 0;
+                                    sk_sp<SkStrike>&& strike) = 0;
 
     virtual void processSourceMasks(const SkZip<SkGlyphVariant, SkPoint>& drawables,
-                                    const SkStrikeSpec& strikeSpec,
+                                    sk_sp<SkStrike>&& strike,
                                     SkScalar strikeToSourceScale) = 0;
 
     virtual void processSourcePaths(const SkZip<SkGlyphVariant, SkPoint>& drawables,
@@ -151,7 +151,7 @@
                                     SkScalar strikeToSourceScale) = 0;
 
     virtual void processSourceSDFT(const SkZip<SkGlyphVariant, SkPoint>& drawables,
-                                   const SkStrikeSpec& strikeSpec,
+                                   sk_sp<SkStrike>&& strike,
                                    SkScalar strikeToSourceScale,
                                    const SkFont& runFont,
                                    SkScalar minScale,
diff --git a/src/core/SkStrikeCache.cpp b/src/core/SkStrikeCache.cpp
index 098571d..149bdba 100644
--- a/src/core/SkStrikeCache.cpp
+++ b/src/core/SkStrikeCache.cpp
@@ -18,6 +18,10 @@
 #include "src/core/SkGlyphRunPainter.h"
 #include "src/core/SkScalerCache.h"
 
+#if SK_SUPPORT_GPU
+#include "src/gpu/text/GrStrikeCache.h"
+#endif
+
 bool gSkUseThreadLocalStrikeCaches_IAcknowledgeThisIsIncrediblyExperimental = false;
 
 SkStrikeCache* SkStrikeCache::GlobalStrikeCache() {
@@ -340,6 +344,12 @@
 #endif
 }
 
+#if SK_SUPPORT_GPU
+    sk_sp<GrTextStrike> SkStrike::findOrCreateGrStrike(GrStrikeCache* grStrikeCache) const {
+        return grStrikeCache->findOrCreateStrike(fStrikeSpec);
+    }
+#endif
+
 void SkStrike::updateDelta(size_t increase) {
     if (increase != 0) {
         SkAutoMutexExclusive lock{fStrikeCache->fLock};
diff --git a/src/core/SkStrikeCache.h b/src/core/SkStrikeCache.h
index df7d6e8..f484cf2 100644
--- a/src/core/SkStrikeCache.h
+++ b/src/core/SkStrikeCache.h
@@ -109,6 +109,14 @@
         return fStrikeSpec.descriptor();
     }
 
+    const SkStrikeSpec& strikeSpec() const {
+        return fStrikeSpec;
+    }
+
+#if SK_SUPPORT_GPU
+    sk_sp<GrTextStrike> findOrCreateGrStrike(GrStrikeCache* grStrikeCache) const;
+#endif
+
     void prepareForMaskDrawing(
             SkDrawableGlyphBuffer* drawbles, SkSourceGlyphBuffer* rejects) override {
         size_t increase = fScalerCache.prepareForMaskDrawing(drawbles, rejects);
diff --git a/src/gpu/text/GrStrikeCache.h b/src/gpu/text/GrStrikeCache.h
index bc2f89e..289cf58 100644
--- a/src/gpu/text/GrStrikeCache.h
+++ b/src/gpu/text/GrStrikeCache.h
@@ -25,8 +25,12 @@
     GrTextStrike(const SkStrikeSpec& strikeSpec);
 
     GrGlyph* getGlyph(SkPackedGlyphID);
+    const SkStrikeSpec& strikeSpec() const { return fStrikeSpec; }
 
 private:
+    // Key for retrieving the SkStrike for creating new atlas data.
+    const SkStrikeSpec fStrikeSpec;
+
     struct HashTraits {
         static const SkPackedGlyphID& GetKey(const GrGlyph* glyph);
         static uint32_t Hash(SkPackedGlyphID key);
@@ -34,9 +38,6 @@
     // Map SkPackedGlyphID -> GrGlyph*.
     SkTHashTable<GrGlyph*, SkPackedGlyphID, HashTraits> fCache;
 
-    // Key for retrieving the SkStrike for creating new atlas data.
-    SkStrikeSpec fStrikeSpec;
-
     // Store for the glyph information.
     SkArenaAlloc fAlloc{512};
 
diff --git a/src/gpu/text/GrTextBlob.cpp b/src/gpu/text/GrTextBlob.cpp
index 21b5abd..719df68 100644
--- a/src/gpu/text/GrTextBlob.cpp
+++ b/src/gpu/text/GrTextBlob.cpp
@@ -11,6 +11,7 @@
 #include "src/core/SkMaskFilterBase.h"
 #include "src/core/SkMatrixProvider.h"
 #include "src/core/SkPaintPriv.h"
+#include "src/core/SkStrikeCache.h"
 #include "src/core/SkStrikeSpec.h"
 #include "src/gpu/GrClip.h"
 #include "src/gpu/GrGlyph.h"
@@ -298,6 +299,9 @@
         , fOrigin(origin) {}
 
 // -- GlyphVector ----------------------------------------------------------------------------------
+// GlyphVector provides a way to delay the lookup of GrGlyphs until the code is running on the
+// GPU in single threaded mode. The GlyphVector is created in a multi-threaded environment, but
+// the GrStrikeCache is only single threaded (and must be single threaded because of the atlas).
 class GlyphVector {
 public:
     union Variant {
@@ -309,10 +313,10 @@
         Variant(SkPackedGlyphID id) : packedGlyphID{id} {}
     };
 
-    GlyphVector(const SkStrikeSpec& spec, SkSpan<Variant> glyphs);
+    GlyphVector(sk_sp<SkStrike>&& strike, SkSpan<Variant> glyphs);
 
     static GlyphVector Make(
-            const SkStrikeSpec& spec, SkSpan<SkGlyphVariant> glyphs, GrSubRunAllocator* alloc);
+            sk_sp<SkStrike>&& strike, SkSpan<SkGlyphVariant> glyphs, GrSubRunAllocator* alloc);
     SkSpan<const GrGlyph*> glyphs() const;
 
     void packedGlyphIDToGrGlyph(GrStrikeCache* cache);
@@ -329,39 +333,45 @@
     }
 
 private:
-    const SkStrikeSpec fStrikeSpec;
+    sk_sp<SkStrike> fStrike;
     SkSpan<Variant> fGlyphs;
-    sk_sp<GrTextStrike> fStrike{nullptr};
+    sk_sp<GrTextStrike> fGrStrike{nullptr};
     uint64_t fAtlasGeneration{GrDrawOpAtlas::kInvalidAtlasGeneration};
     GrDrawOpAtlas::BulkUseTokenUpdater fBulkUseToken;
 };
 
-GlyphVector::GlyphVector(const SkStrikeSpec& spec, SkSpan<Variant> glyphs)
-    : fStrikeSpec{spec}
-    , fGlyphs{glyphs} { }
+GlyphVector::GlyphVector(sk_sp<SkStrike>&& strike, SkSpan<Variant> glyphs)
+        : fStrike{std::move(strike)}
+        , fGlyphs{glyphs} {
+    SkASSERT(fStrike != nullptr);
+}
 
 GlyphVector GlyphVector::Make(
-        const SkStrikeSpec &spec, SkSpan<SkGlyphVariant> glyphs, GrSubRunAllocator* alloc) {
-
+        sk_sp<SkStrike>&& strike, SkSpan<SkGlyphVariant> glyphs, GrSubRunAllocator* alloc) {
     Variant* variants = alloc->makePODArray<Variant>(glyphs.size());
     for (auto [i, gv] : SkMakeEnumerate(glyphs)) {
         variants[i] = gv.glyph()->getPackedID();
     }
 
-    return GlyphVector{spec, SkMakeSpan(variants, glyphs.size())};
+    return GlyphVector{std::move(strike), SkMakeSpan(variants, glyphs.size())};
 }
 
 SkSpan<const GrGlyph*> GlyphVector::glyphs() const {
     return SkMakeSpan(reinterpret_cast<const GrGlyph**>(fGlyphs.data()), fGlyphs.size());
 }
 
+// packedGlyphIDToGrGlyph must be run in single-threaded mode.
+// If fStrike != nullptr then the conversion to GrGlyph* has not happened.
 void GlyphVector::packedGlyphIDToGrGlyph(GrStrikeCache* cache) {
-    if (fStrike == nullptr) {
-        fStrike = fStrikeSpec.findOrCreateGrStrike(cache);
+    if (fStrike != nullptr) {
+        fGrStrike = cache->findOrCreateStrike(fStrike->strikeSpec());
 
         for (auto& variant : fGlyphs) {
-            variant.grGlyph = fStrike->getGlyph(variant.packedGlyphID);
+            variant.grGlyph = fGrStrike->getGlyph(variant.packedGlyphID);
         }
+
+        // Drop the ref on the strike that was taken in the SkGlyphRunPainter process* methods.
+        fStrike = nullptr;
     }
 }
 
@@ -382,7 +392,7 @@
         // is set to kInvalidAtlasGeneration) or the atlas has changed in subsequent calls..
         fBulkUseToken.reset();
 
-        SkBulkGlyphMetricsAndImages metricsAndImages{fStrikeSpec};
+        SkBulkGlyphMetricsAndImages metricsAndImages{fGrStrike->strikeSpec()};
 
         // Update the atlas information in the GrStrike.
         auto tokenTracker = uploadTarget->tokenTracker();
@@ -443,7 +453,7 @@
                      bool glyphsOutOfBounds);
 
     static GrSubRunOwner Make(const SkZip<SkGlyphVariant, SkPoint>& drawables,
-                              const SkStrikeSpec& strikeSpec,
+                              sk_sp<SkStrike>&& strike,
                               SkScalar,
                               GrMaskFormat format,
                               GrTextBlob* blob,
@@ -509,7 +519,7 @@
         , fGlyphs{glyphs} {}
 
 GrSubRunOwner DirectMaskSubRun::Make(const SkZip<SkGlyphVariant, SkPoint>& drawables,
-                                     const SkStrikeSpec& strikeSpec,
+                                     sk_sp<SkStrike>&& strike,
                                      SkScalar,
                                      GrMaskFormat format,
                                      GrTextBlob* blob,
@@ -551,7 +561,7 @@
     SkSpan<const DevicePosition> leftTop{glyphLeftTop, goodPosCount};
     return alloc->makeUnique<DirectMaskSubRun>(
             format, blob, runBounds, leftTop,
-            GlyphVector{strikeSpec, {glyphIDs, goodPosCount}}, glyphsExcluded);
+            GlyphVector{std::move(strike), {glyphIDs, goodPosCount}}, glyphsExcluded);
 }
 
 bool DirectMaskSubRun::canReuse(const SkPaint& paint, const SkMatrix& drawMatrix) const {
@@ -837,7 +847,7 @@
                           GlyphVector glyphs);
 
     static GrSubRunOwner Make(const SkZip<SkGlyphVariant, SkPoint>& drawables,
-                              const SkStrikeSpec& strikeSpec,
+                              sk_sp<SkStrike>&& strike,
                               SkScalar strikeToSourceScale,
                               GrMaskFormat format,
                               GrTextBlob* blob,
@@ -905,7 +915,7 @@
         , fGlyphs{glyphs} { }
 
 GrSubRunOwner TransformedMaskSubRun::Make(const SkZip<SkGlyphVariant, SkPoint>& drawables,
-                                          const SkStrikeSpec& strikeSpec,
+                                          sk_sp<SkStrike>&& strike,
                                           SkScalar strikeToSourceScale,
                                           GrMaskFormat format,
                                           GrTextBlob* blob,
@@ -930,7 +940,7 @@
 
     return alloc->makeUnique<TransformedMaskSubRun>(
             format, blob, strikeToSourceScale, bounds, vertexData,
-            GlyphVector::Make(strikeSpec, drawables.get<0>(), alloc));
+            GlyphVector::Make(std::move(strike), drawables.get<0>(), alloc));
 }
 
 void TransformedMaskSubRun::draw(const GrClip* clip,
@@ -1098,7 +1108,7 @@
 
     static GrSubRunOwner Make(const SkZip<SkGlyphVariant, SkPoint>& drawables,
                               const SkFont& runFont,
-                              const SkStrikeSpec& strikeSpec,
+                              sk_sp<SkStrike>&& strike,
                               SkScalar strikeToSourceScale,
                               GrTextBlob* blob,
                               GrSubRunAllocator* alloc);
@@ -1178,7 +1188,7 @@
 
 GrSubRunOwner SDFTSubRun::Make(const SkZip<SkGlyphVariant, SkPoint>& drawables,
                                const SkFont& runFont,
-                               const SkStrikeSpec& strikeSpec,
+                               sk_sp<SkStrike>&& strike,
                                SkScalar strikeToSourceScale,
                                GrTextBlob* blob,
                                GrSubRunAllocator* alloc) {
@@ -1205,7 +1215,7 @@
             strikeToSourceScale,
             bounds,
             vertexData,
-            GlyphVector::Make(strikeSpec, drawables.get<0>(), alloc),
+            GlyphVector::Make(std::move(strike), drawables.get<0>(), alloc),
             runFont.getEdging() == SkFont::Edging::kSubpixelAntiAlias,
             has_some_antialiasing(runFont));
 }
@@ -1571,13 +1581,15 @@
 void GrTextBlob::addMultiMaskFormat(
         AddSingleMaskFormat addSingle,
         const SkZip<SkGlyphVariant, SkPoint>& drawables,
-        const SkStrikeSpec& strikeSpec,
+        sk_sp<SkStrike>&& strike,
         SkScalar strikeToSourceScale) {
     if (drawables.empty()) { return; }
 
-    auto addSameFormat = [&](const SkZip<SkGlyphVariant, SkPoint>& drawable, GrMaskFormat format) {
+    auto addSameFormat = [&](const SkZip<SkGlyphVariant, SkPoint>& drawable,
+                             GrMaskFormat format,
+                             sk_sp<SkStrike>&& runStrike) {
         GrSubRunOwner subRun = addSingle(
-                drawable, strikeSpec, strikeToSourceScale, format, this, &fAlloc);
+                drawable, std::move(runStrike), strikeToSourceScale, format, this, &fAlloc);
         if (subRun != nullptr) {
             fSubRunList.append(std::move(subRun));
         } else {
@@ -1594,13 +1606,14 @@
         GrMaskFormat nextFormat = GrGlyph::FormatFromSkGlyph(glyph->maskFormat());
         if (format != nextFormat) {
             auto sameFormat = drawables.subspan(startIndex, i - startIndex);
-            addSameFormat(sameFormat, format);
+            // Take a ref on the strike. This should rarely happen.
+            addSameFormat(sameFormat, format, sk_sp<SkStrike>(strike));
             format = nextFormat;
             startIndex = i;
         }
     }
     auto sameFormat = drawables.last(drawables.size() - startIndex);
-    addSameFormat(sameFormat, format);
+    addSameFormat(sameFormat, format, std::move(strike));
 }
 
 GrTextBlob::GrTextBlob(int allocSize,
@@ -1612,9 +1625,9 @@
         , fInitialLuminance{initialLuminance} { }
 
 void GrTextBlob::processDeviceMasks(const SkZip<SkGlyphVariant, SkPoint>& drawables,
-                                    const SkStrikeSpec& strikeSpec) {
-
-    this->addMultiMaskFormat(DirectMaskSubRun::Make, drawables, strikeSpec, 1);
+                                    sk_sp<SkStrike>&& strike) {
+    SkASSERT(strike != nullptr);
+    this->addMultiMaskFormat(DirectMaskSubRun::Make, drawables, std::move(strike), 1);
 }
 
 void GrTextBlob::processSourcePaths(const SkZip<SkGlyphVariant, SkPoint>& drawables,
@@ -1628,7 +1641,7 @@
 }
 
 void GrTextBlob::processSourceSDFT(const SkZip<SkGlyphVariant, SkPoint>& drawables,
-                                   const SkStrikeSpec& strikeSpec,
+                                   sk_sp<SkStrike>&& strike,
                                    SkScalar strikeToSourceScale,
                                    const SkFont& runFont,
                                    SkScalar minScale,
@@ -1637,14 +1650,14 @@
     fMaxMinScale = std::max(minScale, fMaxMinScale);
     fMinMaxScale = std::min(maxScale, fMinMaxScale);
     fSubRunList.append(
-            SDFTSubRun::Make(drawables, runFont, strikeSpec, strikeToSourceScale,this, &fAlloc));
+        SDFTSubRun::Make(drawables, runFont, std::move(strike), strikeToSourceScale,this, &fAlloc));
 }
 
 void GrTextBlob::processSourceMasks(const SkZip<SkGlyphVariant, SkPoint>& drawables,
-                                    const SkStrikeSpec& strikeSpec,
+                                    sk_sp<SkStrike>&& strike,
                                     SkScalar strikeToSourceScale) {
     this->addMultiMaskFormat(
-            TransformedMaskSubRun::Make, drawables, strikeSpec, strikeToSourceScale);
+            TransformedMaskSubRun::Make, drawables, std::move(strike), strikeToSourceScale);
 }
 
 // ----------------------------- Begin no cache implementation -------------------------------------
@@ -1660,7 +1673,7 @@
                             GlyphVector glyphs);
 
     static GrAtlasSubRunOwner Make(const SkZip<SkGlyphVariant, SkPoint>& drawables,
-                                   const SkStrikeSpec& strikeSpec,
+                                   sk_sp<SkStrike>&& strike,
                                    GrMaskFormat format,
                                    GrSubRunAllocator* alloc);
 
@@ -1709,7 +1722,7 @@
         , fGlyphs{glyphs} { }
 
 GrAtlasSubRunOwner DirectMaskSubRunNoCache::Make(const SkZip<SkGlyphVariant, SkPoint>& drawables,
-                                                 const SkStrikeSpec& strikeSpec,
+                                                 sk_sp<SkStrike>&& strike,
                                                  GrMaskFormat format,
                                                  GrSubRunAllocator* alloc) {
     DevicePosition* glyphLeftTop = alloc->makePODArray<DevicePosition>(drawables.size());
@@ -1749,7 +1762,7 @@
     SkSpan<const DevicePosition> leftTop{glyphLeftTop, goodPosCount};
     return alloc->makeUnique<DirectMaskSubRunNoCache>(
             format, runBounds.rect(), leftTop,
-            GlyphVector{strikeSpec, {glyphIDs, goodPosCount}});
+            GlyphVector{std::move(strike), {glyphIDs, goodPosCount}});
 }
 
 size_t DirectMaskSubRunNoCache::vertexStride(const SkMatrix&) const {
@@ -1901,7 +1914,7 @@
                                  GlyphVector glyphs);
 
     static GrAtlasSubRunOwner Make(const SkZip<SkGlyphVariant, SkPoint>& drawables,
-                                   const SkStrikeSpec& strikeSpec,
+                                   sk_sp<SkStrike>&& strike,
                                    SkScalar strikeToSourceScale,
                                    GrMaskFormat format,
                                    GrSubRunAllocator* alloc);
@@ -1958,7 +1971,7 @@
 
 GrAtlasSubRunOwner TransformedMaskSubRunNoCache::Make(
         const SkZip<SkGlyphVariant, SkPoint>& drawables,
-        const SkStrikeSpec& strikeSpec,
+        sk_sp<SkStrike>&& strike,
         SkScalar strikeToSourceScale,
         GrMaskFormat format,
         GrSubRunAllocator* alloc) {
@@ -1981,7 +1994,7 @@
 
     return alloc->makeUnique<TransformedMaskSubRunNoCache>(
             format, strikeToSourceScale, bounds, vertexData,
-            GlyphVector::Make(strikeSpec, drawables.get<0>(), alloc));
+            GlyphVector::Make(std::move(strike), drawables.get<0>(), alloc));
 }
 
 std::tuple<const GrClip*, GrOp::Owner>
@@ -2129,7 +2142,7 @@
 
     static GrAtlasSubRunOwner Make(const SkZip<SkGlyphVariant, SkPoint>& drawables,
                                    const SkFont& runFont,
-                                   const SkStrikeSpec& strikeSpec,
+                                   sk_sp<SkStrike>&& strike,
                                    SkScalar strikeToSourceScale,
                                    GrSubRunAllocator* alloc);
 
@@ -2194,7 +2207,7 @@
 GrAtlasSubRunOwner SDFTSubRunNoCache::Make(
         const SkZip<SkGlyphVariant, SkPoint>& drawables,
         const SkFont& runFont,
-        const SkStrikeSpec& strikeSpec,
+        sk_sp<SkStrike>&& strike,
         SkScalar strikeToSourceScale,
         GrSubRunAllocator* alloc) {
 
@@ -2220,7 +2233,7 @@
             strikeToSourceScale,
             bounds,
             vertexData,
-            GlyphVector::Make(strikeSpec, drawables.get<0>(), alloc),
+            GlyphVector::Make(std::move(strike), drawables.get<0>(), alloc),
             runFont.getEdging() == SkFont::Edging::kSubpixelAntiAlias,
             has_some_antialiasing(runFont));
 }
@@ -2322,7 +2335,7 @@
             , fPaint {paint} {}
 
 void GrSubRunNoCachePainter::processDeviceMasks(
-        const SkZip<SkGlyphVariant, SkPoint>& drawables, const SkStrikeSpec& strikeSpec) {
+        const SkZip<SkGlyphVariant, SkPoint>& drawables, sk_sp<SkStrike>&& strike) {
     if (drawables.empty()) { return; }
 
     auto glyphSpan = drawables.get<0>();
@@ -2334,17 +2347,19 @@
         GrMaskFormat nextFormat = GrGlyph::FormatFromSkGlyph(glyph->maskFormat());
         if (format != nextFormat) {
             auto sameFormat = drawables.subspan(startIndex, i - startIndex);
-            this->draw(DirectMaskSubRunNoCache::Make(sameFormat, strikeSpec, format, fAlloc));
+            // Take an extra ref on the strike. This should rarely happen.
+            this->draw(
+                DirectMaskSubRunNoCache::Make(sameFormat, sk_sp<SkStrike>(strike), format, fAlloc));
             format = nextFormat;
             startIndex = i;
         }
     }
     auto sameFormat = drawables.last(drawables.size() - startIndex);
-    this->draw(DirectMaskSubRunNoCache::Make(sameFormat, strikeSpec, format, fAlloc));
+    this->draw(DirectMaskSubRunNoCache::Make(sameFormat, std::move(strike), format, fAlloc));
 }
 
 void GrSubRunNoCachePainter::processSourceMasks(const SkZip<SkGlyphVariant, SkPoint>& drawables,
-                                                const SkStrikeSpec& strikeSpec,
+                                                sk_sp<SkStrike>&& strike,
                                                 SkScalar strikeToSourceScale) {
     if (drawables.empty()) {
         return;
@@ -2360,8 +2375,9 @@
         if (format != nextFormat) {
             auto sameFormat = drawables.subspan(startIndex, i - startIndex);
             this->draw(
-                    TransformedMaskSubRunNoCache::Make(
-                            sameFormat, strikeSpec, strikeToSourceScale, format, fAlloc));
+                // Add an extra ref to the strike. This should rarely happen.
+                TransformedMaskSubRunNoCache::Make(
+                    sameFormat, sk_sp<SkStrike>(strike), strikeToSourceScale, format, fAlloc));
             format = nextFormat;
             startIndex = i;
         }
@@ -2369,7 +2385,7 @@
     auto sameFormat = drawables.last(drawables.size() - startIndex);
     this->draw(
             TransformedMaskSubRunNoCache::Make(
-                    sameFormat, strikeSpec, strikeToSourceScale, format, fAlloc));
+                    sameFormat, std::move(strike), strikeToSourceScale, format, fAlloc));
 }
 
 void GrSubRunNoCachePainter::processSourcePaths(const SkZip<SkGlyphVariant, SkPoint>& drawables,
@@ -2425,7 +2441,7 @@
 }
 
 void GrSubRunNoCachePainter::processSourceSDFT(const SkZip<SkGlyphVariant, SkPoint>& drawables,
-                                               const SkStrikeSpec& strikeSpec,
+                                               sk_sp<SkStrike>&& strike,
                                                SkScalar strikeToSourceScale,
                                                const SkFont& runFont,
                                                SkScalar minScale, SkScalar maxScale) {
@@ -2433,7 +2449,7 @@
         return;
     }
     this->draw(SDFTSubRunNoCache::Make(
-            drawables, runFont, strikeSpec, strikeToSourceScale, fAlloc));
+            drawables, runFont, std::move(strike), strikeToSourceScale, fAlloc));
 }
 
 void GrSubRunNoCachePainter::draw(GrAtlasSubRunOwner subRun) {
diff --git a/src/gpu/text/GrTextBlob.h b/src/gpu/text/GrTextBlob.h
index 8a6db25..c766372 100644
--- a/src/gpu/text/GrTextBlob.h
+++ b/src/gpu/text/GrTextBlob.h
@@ -249,23 +249,23 @@
     void addMultiMaskFormat(
             AddSingleMaskFormat addSingle,
             const SkZip<SkGlyphVariant, SkPoint>& drawables,
-            const SkStrikeSpec& strikeSpec,
+            sk_sp<SkStrike>&& strike,
             SkScalar strikeToSourceScale);
 
     // Methods to satisfy SkGlyphRunPainterInterface
     void processDeviceMasks(const SkZip<SkGlyphVariant, SkPoint>& drawables,
-                            const SkStrikeSpec& strikeSpec) override;
+                            sk_sp<SkStrike>&& strike) override;
     void processSourcePaths(const SkZip<SkGlyphVariant, SkPoint>& drawables,
                             const SkFont& runFont,
                             SkScalar strikeToSourceScale) override;
     void processSourceSDFT(const SkZip<SkGlyphVariant, SkPoint>& drawables,
-                           const SkStrikeSpec& strikeSpec,
+                           sk_sp<SkStrike>&& strike,
                            SkScalar strikeToSourceScale,
                            const SkFont& runFont,
                            SkScalar minScale,
                            SkScalar maxScale) override;
     void processSourceMasks(const SkZip<SkGlyphVariant, SkPoint>& drawables,
-                            const SkStrikeSpec& strikeSpec,
+                            sk_sp<SkStrike>&& strike,
                             SkScalar strikeToSourceScale) override;
 
     // The allocator must come first because it needs to be destroyed last. Other fields of this
@@ -304,15 +304,15 @@
                            const SkGlyphRunList&,
                            const SkPaint&);
     void processDeviceMasks(const SkZip<SkGlyphVariant, SkPoint>& drawables,
-                            const SkStrikeSpec& strikeSpec) override;
+                            sk_sp<SkStrike>&& strike) override;
     void processSourceMasks(const SkZip<SkGlyphVariant, SkPoint>& drawables,
-                            const SkStrikeSpec& strikeSpec,
+                            sk_sp<SkStrike>&& strike,
                             SkScalar strikeToSourceScale) override;
     void processSourcePaths(const SkZip<SkGlyphVariant, SkPoint>& drawables,
                             const SkFont& runFont,
                             SkScalar strikeToSourceScale) override;
     void processSourceSDFT(const SkZip<SkGlyphVariant, SkPoint>& drawables,
-                           const SkStrikeSpec& strikeSpec,
+                           sk_sp<SkStrike>&& strike,
                            SkScalar strikeToSourceScale,
                            const SkFont& runFont,
                            SkScalar minScale, SkScalar maxScale) override;