Revert "Removing ref counting from GrXPFactory."

This reverts commit a8f80de2bc17672b4b6f26d3cf6b38123ac850c9.

Reason for revert: nanobench failing on windows bots, possibly others

Change-Id: Iacb8c650064a28654c165665be057377ffb02ba5
Reviewed-on: https://skia-review.googlesource.com/6802
Commit-Queue: Brian Salomon <bsalomon@google.com>
Reviewed-by: Brian Salomon <bsalomon@google.com>
diff --git a/src/core/SkBlendModePriv.h b/src/core/SkBlendModePriv.h
index 0d0589c..29df639 100644
--- a/src/core/SkBlendModePriv.h
+++ b/src/core/SkBlendModePriv.h
@@ -17,7 +17,7 @@
 
 #if SK_SUPPORT_GPU
 #include "GrXferProcessor.h"
-const GrXPFactory* SkBlendMode_AsXPFactory(SkBlendMode);
+sk_sp<GrXPFactory> SkBlendMode_AsXPFactory(SkBlendMode);
 #endif
 
 
diff --git a/src/core/SkXfermode.cpp b/src/core/SkXfermode.cpp
index 6f470f6..9c1ae44 100644
--- a/src/core/SkXfermode.cpp
+++ b/src/core/SkXfermode.cpp
@@ -1001,7 +1001,7 @@
     return nullptr;
 }
 
-const GrXPFactory* SkXfermode::asXPFactory() const {
+sk_sp<GrXPFactory> SkXfermode::asXPFactory() const {
     // This should never be called.
     // TODO: make pure virtual in SkXfermode once Android update lands
     SkASSERT(0);
@@ -1254,15 +1254,15 @@
     return GrXfermodeFragmentProcessor::MakeFromDstProcessor(std::move(dst), fMode);
 }
 
-const GrXPFactory* SkProcCoeffXfermode::asXPFactory() const {
+sk_sp<GrXPFactory> SkProcCoeffXfermode::asXPFactory() const {
     if (CANNOT_USE_COEFF != fSrcCoeff) {
-        const GrXPFactory* result(GrPorterDuffXPFactory::Get(fMode));
+        sk_sp<GrXPFactory> result(GrPorterDuffXPFactory::Make(fMode));
         SkASSERT(result);
         return result;
     }
 
     SkASSERT(GrCustomXfermode::IsSupportedMode(fMode));
-    return GrCustomXfermode::Get(fMode);
+    return GrCustomXfermode::MakeXPFactory(fMode);
 }
 #endif
 
@@ -1469,16 +1469,16 @@
 }
 
 #if SK_SUPPORT_GPU
-const GrXPFactory* SkBlendMode_AsXPFactory(SkBlendMode mode) {
+sk_sp<GrXPFactory> SkBlendMode_AsXPFactory(SkBlendMode mode) {
     const ProcCoeff rec = gProcCoeffs[(int)mode];
     if (CANNOT_USE_COEFF != rec.fSC) {
-        const GrXPFactory* result = GrPorterDuffXPFactory::Get(mode);
+        sk_sp<GrXPFactory> result(GrPorterDuffXPFactory::Make(mode));
         SkASSERT(result);
         return result;
     }
 
     SkASSERT(GrCustomXfermode::IsSupportedMode(mode));
-    return GrCustomXfermode::Get(mode);
+    return GrCustomXfermode::MakeXPFactory(mode);
 }
 #endif
 
diff --git a/src/core/SkXfermodePriv.h b/src/core/SkXfermodePriv.h
index 2fae2c0..208925e 100644
--- a/src/core/SkXfermodePriv.h
+++ b/src/core/SkXfermodePriv.h
@@ -246,7 +246,7 @@
         The xfermode will return a factory for which the caller will get a ref. It is up
         to the caller to install it. XferProcessors cannot use a background texture.
       */
-    virtual const GrXPFactory* asXPFactory() const;
+    virtual sk_sp<GrXPFactory> asXPFactory() const;
 #endif
 
     SK_TO_STRING_PUREVIRT()
diff --git a/src/core/SkXfermode_proccoeff.h b/src/core/SkXfermode_proccoeff.h
index 3724532..8a7b62f 100644
--- a/src/core/SkXfermode_proccoeff.h
+++ b/src/core/SkXfermode_proccoeff.h
@@ -46,7 +46,7 @@
 #if SK_SUPPORT_GPU
     sk_sp<GrFragmentProcessor> makeFragmentProcessorForImageFilter(
                                                         sk_sp<GrFragmentProcessor>) const override;
-    const GrXPFactory* asXPFactory() const override;
+    sk_sp<GrXPFactory> asXPFactory() const override;
 #endif
 
     SK_TO_STRING_OVERRIDE()
diff --git a/src/effects/SkArithmeticMode.cpp b/src/effects/SkArithmeticMode.cpp
index c85d5c3..3eaf3cc 100644
--- a/src/effects/SkArithmeticMode.cpp
+++ b/src/effects/SkArithmeticMode.cpp
@@ -36,7 +36,7 @@
 #if SK_SUPPORT_GPU
     sk_sp<GrFragmentProcessor> makeFragmentProcessorForImageFilter(
                                                 sk_sp<GrFragmentProcessor> dst) const override;
-    const GrXPFactory* asXPFactory() const override {
+    sk_sp<GrXPFactory> asXPFactory() const override {
         SkFAIL("This should only be used as a FP.");
         return nullptr;
     }
diff --git a/src/gpu/GrPaint.cpp b/src/gpu/GrPaint.cpp
index 8d9347b..0954505 100644
--- a/src/gpu/GrPaint.cpp
+++ b/src/gpu/GrPaint.cpp
@@ -13,14 +13,13 @@
 #include "effects/GrSimpleTextureEffect.h"
 
 GrPaint::GrPaint()
-        : fXPFactory(nullptr)
-        , fDisableOutputConversionToSRGB(false)
-        , fAllowSRGBInputs(false)
-        , fUsesDistanceVectorField(false)
-        , fColor(GrColor4f::OpaqueWhite()) {}
+    : fDisableOutputConversionToSRGB(false)
+    , fAllowSRGBInputs(false)
+    , fUsesDistanceVectorField(false)
+    , fColor(GrColor4f::OpaqueWhite()) {}
 
 void GrPaint::setCoverageSetOpXPFactory(SkRegion::Op regionOp, bool invertCoverage) {
-    fXPFactory = GrCoverageSetOpXPFactory::Get(regionOp, invertCoverage);
+    fXPFactory = GrCoverageSetOpXPFactory::Make(regionOp, invertCoverage);
 }
 
 void GrPaint::addColorTextureProcessor(GrTexture* texture,
diff --git a/src/gpu/GrPipelineBuilder.cpp b/src/gpu/GrPipelineBuilder.cpp
index 5741471..bd433fc 100644
--- a/src/gpu/GrPipelineBuilder.cpp
+++ b/src/gpu/GrPipelineBuilder.cpp
@@ -29,7 +29,7 @@
         fCoverageFragmentProcessors.emplace_back(SkRef(paint.getCoverageFragmentProcessor(i)));
     }
 
-    fXPFactory = paint.getXPFactory();
+    fXPFactory.reset(SkSafeRef(paint.getXPFactory()));
 
     this->setState(GrPipelineBuilder::kHWAntialias_Flag, GrAATypeIsHW(aaType));
     this->setState(GrPipelineBuilder::kDisableOutputConversionToSRGB_Flag,
diff --git a/src/gpu/GrPipelineBuilder.h b/src/gpu/GrPipelineBuilder.h
index 0d039f9..1bc9002 100644
--- a/src/gpu/GrPipelineBuilder.h
+++ b/src/gpu/GrPipelineBuilder.h
@@ -145,15 +145,21 @@
      * Installs a GrXPFactory. This object controls how src color, fractional pixel coverage,
      * and the dst color are blended.
      */
-    void setXPFactory(const GrXPFactory* xpFactory) { fXPFactory = xpFactory; }
+    void setXPFactory(sk_sp<GrXPFactory> xpFactory) {
+        fXPFactory = std::move(xpFactory);
+    }
 
     /**
      * Sets a GrXPFactory that disables color writes to the destination. This is useful when
      * rendering to the stencil buffer.
      */
-    void setDisableColorXPFactory() { fXPFactory = GrDisableColorXPFactory::Get(); }
+    void setDisableColorXPFactory() {
+        fXPFactory = GrDisableColorXPFactory::Make();
+    }
 
-    const GrXPFactory* getXPFactory() const { return fXPFactory; }
+    const GrXPFactory* getXPFactory() const {
+        return fXPFactory.get();
+    }
 
     /**
      * Checks whether the xp will need destination in a texture to correctly blend.
@@ -298,7 +304,7 @@
     uint32_t                                fFlags;
     const GrUserStencilSettings*            fUserStencilSettings;
     GrDrawFace                              fDrawFace;
-    const GrXPFactory*                      fXPFactory;
+    mutable sk_sp<GrXPFactory>              fXPFactory;
     FragmentProcessorArray                  fColorFragmentProcessors;
     FragmentProcessorArray                  fCoverageFragmentProcessors;
 
diff --git a/src/gpu/GrProcessor.cpp b/src/gpu/GrProcessor.cpp
index 0512aa8..991aa90 100644
--- a/src/gpu/GrProcessor.cpp
+++ b/src/gpu/GrProcessor.cpp
@@ -32,14 +32,16 @@
 }
 
 template<>
-SkTArray<GrProcessorTestFactory<GrGeometryProcessor>*, true>*
-GrProcessorTestFactory<GrGeometryProcessor>::GetFactories() {
-    static SkTArray<GrProcessorTestFactory<GrGeometryProcessor>*, true> gFactories;
+SkTArray<GrProcessorTestFactory<GrXPFactory>*, true>*
+GrProcessorTestFactory<GrXPFactory>::GetFactories() {
+    static SkTArray<GrProcessorTestFactory<GrXPFactory>*, true> gFactories;
     return &gFactories;
 }
 
-SkTArray<GrXPFactoryTestFactory*, true>* GrXPFactoryTestFactory::GetFactories() {
-    static SkTArray<GrXPFactoryTestFactory*, true> gFactories;
+template<>
+SkTArray<GrProcessorTestFactory<GrGeometryProcessor>*, true>*
+GrProcessorTestFactory<GrGeometryProcessor>::GetFactories() {
+    static SkTArray<GrProcessorTestFactory<GrGeometryProcessor>*, true> gFactories;
     return &gFactories;
 }
 
@@ -70,7 +72,8 @@
     }
 }
 
-void GrXPFactoryTestFactory::VerifyFactoryCount() {
+template<>
+void GrProcessorTestFactory<GrXPFactory>::VerifyFactoryCount() {
     if (kXPFactoryCount != GetFactories()->count()) {
         SkDebugf("\nExpected %d xp factory factories, found %d.\n",
                  kXPFactoryCount, GetFactories()->count());
@@ -226,3 +229,8 @@
             break;
     }
 }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+// Initial static variable from GrXPFactory
+int32_t GrXPFactory::gCurrXPFClassID = GrXPFactory::kIllegalXPFClassID;
diff --git a/src/gpu/GrReducedClip.cpp b/src/gpu/GrReducedClip.cpp
index 9f3b225..9802f87 100644
--- a/src/gpu/GrReducedClip.cpp
+++ b/src/gpu/GrReducedClip.cpp
@@ -780,7 +780,7 @@
                     GrShape shape(clipPath, GrStyle::SimpleFill());
                     if (canRenderDirectToStencil) {
                         GrPaint paint;
-                        paint.setXPFactory(GrDisableColorXPFactory::Get());
+                        paint.setXPFactory(GrDisableColorXPFactory::Make());
 
                         GrPathRenderer::DrawPathArgs args;
                         args.fResourceProvider = context->resourceProvider();
@@ -817,7 +817,7 @@
                 } else {
                     GrShape shape(clipPath, GrStyle::SimpleFill());
                     GrPaint paint;
-                    paint.setXPFactory(GrDisableColorXPFactory::Get());
+                    paint.setXPFactory(GrDisableColorXPFactory::Make());
                     GrPathRenderer::DrawPathArgs args;
                     args.fResourceProvider = context->resourceProvider();
                     args.fPaint = &paint;
diff --git a/src/gpu/GrRenderTargetContext.cpp b/src/gpu/GrRenderTargetContext.cpp
index 5e14f6b..e9325fa 100644
--- a/src/gpu/GrRenderTargetContext.cpp
+++ b/src/gpu/GrRenderTargetContext.cpp
@@ -268,7 +268,7 @@
         // target before the target is read.
         GrPaint paint;
         paint.setColor4f(GrColor4f::FromGrColor(color));
-        paint.setXPFactory(GrPorterDuffXPFactory::Get(SkBlendMode::kSrc));
+        paint.setXPFactory(GrPorterDuffXPFactory::Make(SkBlendMode::kSrc));
 
         // We don't call drawRect() here to avoid the cropping to the, possibly smaller,
         // RenderTargetProxy bounds
@@ -329,7 +329,7 @@
 
         GrPaint paint;
         paint.setColor4f(GrColor4f::FromGrColor(color));
-        paint.setXPFactory(GrPorterDuffXPFactory::Get(SkBlendMode::kSrc));
+        paint.setXPFactory(GrPorterDuffXPFactory::Make(SkBlendMode::kSrc));
 
         this->drawRect(clip, paint, GrAA::kNo, SkMatrix::I(), SkRect::Make(clearRect));
     } else if (isFull) {
@@ -675,7 +675,7 @@
     AutoCheckFlush acf(fRenderTargetContext->fDrawingManager);
 
     GrPaint paint;
-    paint.setXPFactory(GrDisableColorXPFactory::Get());
+    paint.setXPFactory(GrDisableColorXPFactory::Make());
 
     fRenderTargetContext->drawNonAAFilledRect(clip, paint, viewMatrix, rect, nullptr, nullptr, ss,
                                               aaType);
diff --git a/src/gpu/effects/GrCoverageSetOpXP.cpp b/src/gpu/effects/GrCoverageSetOpXP.cpp
index 5fbd046..73adc49 100644
--- a/src/gpu/effects/GrCoverageSetOpXP.cpp
+++ b/src/gpu/effects/GrCoverageSetOpXP.cpp
@@ -236,79 +236,77 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 //
-constexpr GrCoverageSetOpXPFactory::GrCoverageSetOpXPFactory(SkRegion::Op regionOp,
-                                                             bool invertCoverage)
-        : fRegionOp(regionOp), fInvertCoverage(invertCoverage) {}
+GrCoverageSetOpXPFactory::GrCoverageSetOpXPFactory(SkRegion::Op regionOp, bool invertCoverage)
+    : fRegionOp(regionOp)
+    , fInvertCoverage(invertCoverage) {
+    this->initClassID<GrCoverageSetOpXPFactory>();
+}
 
-const GrXPFactory* GrCoverageSetOpXPFactory::Get(SkRegion::Op regionOp, bool invertCoverage) {
+sk_sp<GrXPFactory> GrCoverageSetOpXPFactory::Make(SkRegion::Op regionOp, bool invertCoverage) {
     switch (regionOp) {
         case SkRegion::kReplace_Op: {
             if (invertCoverage) {
-                static constexpr const GrCoverageSetOpXPFactory gReplaceCDXPFI(
-                        SkRegion::kReplace_Op, true);
-                return &gReplaceCDXPFI;
+                static GrCoverageSetOpXPFactory gReplaceCDXPFI(regionOp, invertCoverage);
+                return sk_sp<GrXPFactory>(SkRef(&gReplaceCDXPFI));
             } else {
-                static constexpr const GrCoverageSetOpXPFactory gReplaceCDXPF(SkRegion::kReplace_Op,
-                                                                              false);
-                return &gReplaceCDXPF;
+                static GrCoverageSetOpXPFactory gReplaceCDXPF(regionOp, invertCoverage);
+                return sk_sp<GrXPFactory>(SkRef(&gReplaceCDXPF));
             }
+            break;
         }
         case SkRegion::kIntersect_Op: {
             if (invertCoverage) {
-                static constexpr const GrCoverageSetOpXPFactory gIntersectCDXPFI(
-                        SkRegion::kIntersect_Op, true);
-                return &gIntersectCDXPFI;
+                static GrCoverageSetOpXPFactory gIntersectCDXPFI(regionOp, invertCoverage);
+                return sk_sp<GrXPFactory>(SkRef(&gIntersectCDXPFI));
             } else {
-                static constexpr const GrCoverageSetOpXPFactory gIntersectCDXPF(
-                        SkRegion::kIntersect_Op, false);
-                return &gIntersectCDXPF;
+                static GrCoverageSetOpXPFactory gIntersectCDXPF(regionOp, invertCoverage);
+                return sk_sp<GrXPFactory>(SkRef(&gIntersectCDXPF));
             }
+            break;
         }
         case SkRegion::kUnion_Op: {
             if (invertCoverage) {
-                static constexpr const GrCoverageSetOpXPFactory gUnionCDXPFI(SkRegion::kUnion_Op,
-                                                                             true);
-                return &gUnionCDXPFI;
+                static GrCoverageSetOpXPFactory gUnionCDXPFI(regionOp, invertCoverage);
+                return sk_sp<GrXPFactory>(SkRef(&gUnionCDXPFI));
             } else {
-                static constexpr const GrCoverageSetOpXPFactory gUnionCDXPF(SkRegion::kUnion_Op,
-                                                                            false);
-                return &gUnionCDXPF;
+                static GrCoverageSetOpXPFactory gUnionCDXPF(regionOp, invertCoverage);
+                return sk_sp<GrXPFactory>(SkRef(&gUnionCDXPF));
             }
+            break;
         }
         case SkRegion::kXOR_Op: {
             if (invertCoverage) {
-                static constexpr const GrCoverageSetOpXPFactory gXORCDXPFI(SkRegion::kXOR_Op, true);
-                return &gXORCDXPFI;
+                static GrCoverageSetOpXPFactory gXORCDXPFI(regionOp, invertCoverage);
+                return sk_sp<GrXPFactory>(SkRef(&gXORCDXPFI));
             } else {
-                static constexpr const GrCoverageSetOpXPFactory gXORCDXPF(SkRegion::kXOR_Op, false);
-                return &gXORCDXPF;
+                static GrCoverageSetOpXPFactory gXORCDXPF(regionOp, invertCoverage);
+                return sk_sp<GrXPFactory>(SkRef(&gXORCDXPF));
             }
+            break;
         }
         case SkRegion::kDifference_Op: {
             if (invertCoverage) {
-                static constexpr const GrCoverageSetOpXPFactory gDifferenceCDXPFI(
-                        SkRegion::kDifference_Op, true);
-                return &gDifferenceCDXPFI;
+                static GrCoverageSetOpXPFactory gDifferenceCDXPFI(regionOp, invertCoverage);
+                return sk_sp<GrXPFactory>(SkRef(&gDifferenceCDXPFI));
             } else {
-                static constexpr const GrCoverageSetOpXPFactory gDifferenceCDXPF(
-                        SkRegion::kDifference_Op, false);
-                return &gDifferenceCDXPF;
+                static GrCoverageSetOpXPFactory gDifferenceCDXPF(regionOp, invertCoverage);
+                return sk_sp<GrXPFactory>(SkRef(&gDifferenceCDXPF));
             }
+            break;
         }
         case SkRegion::kReverseDifference_Op: {
             if (invertCoverage) {
-                static constexpr const GrCoverageSetOpXPFactory gRevDiffCDXPFI(
-                        SkRegion::kReverseDifference_Op, true);
-                return &gRevDiffCDXPFI;
+                static GrCoverageSetOpXPFactory gRevDiffCDXPFI(regionOp, invertCoverage);
+                return sk_sp<GrXPFactory>(SkRef(&gRevDiffCDXPFI));
             } else {
-                static constexpr const GrCoverageSetOpXPFactory gRevDiffCDXPF(
-                        SkRegion::kReverseDifference_Op, false);
-                return &gRevDiffCDXPF;
+                static GrCoverageSetOpXPFactory gRevDiffCDXPF(regionOp, invertCoverage);
+                return sk_sp<GrXPFactory>(SkRef(&gRevDiffCDXPF));
             }
+            break;
         }
+        default:
+            return nullptr;
     }
-    SkFAIL("Unknown region op.");
-    return nullptr;
 }
 
 GrXferProcessor* GrCoverageSetOpXPFactory::onCreateXferProcessor(const GrCaps& caps,
@@ -337,8 +335,8 @@
 
 GR_DEFINE_XP_FACTORY_TEST(GrCoverageSetOpXPFactory);
 
-const GrXPFactory* GrCoverageSetOpXPFactory::TestGet(GrProcessorTestData* d) {
+sk_sp<GrXPFactory> GrCoverageSetOpXPFactory::TestCreate(GrProcessorTestData* d) {
     SkRegion::Op regionOp = SkRegion::Op(d->fRandom->nextULessThan(SkRegion::kLastOp + 1));
     bool invertCoverage = !d->fRenderTargetContext->hasMixedSamples() && d->fRandom->nextBool();
-    return GrCoverageSetOpXPFactory::Get(regionOp, invertCoverage);
+    return GrCoverageSetOpXPFactory::Make(regionOp, invertCoverage);
 }
diff --git a/src/gpu/effects/GrCustomXfermode.cpp b/src/gpu/effects/GrCustomXfermode.cpp
index 8d1c5e8..239c304 100644
--- a/src/gpu/effects/GrCustomXfermode.cpp
+++ b/src/gpu/effects/GrCustomXfermode.cpp
@@ -31,26 +31,25 @@
 // Static helpers
 ///////////////////////////////////////////////////////////////////////////////
 
-static constexpr GrBlendEquation hw_blend_equation(SkBlendMode mode) {
-// In C++14 this could be a constexpr int variable.
-#define EQ_OFFSET (kOverlay_GrBlendEquation - (int)SkBlendMode::kOverlay)
-    GR_STATIC_ASSERT(kOverlay_GrBlendEquation == (int)SkBlendMode::kOverlay + EQ_OFFSET);
-    GR_STATIC_ASSERT(kDarken_GrBlendEquation == (int)SkBlendMode::kDarken + EQ_OFFSET);
-    GR_STATIC_ASSERT(kLighten_GrBlendEquation == (int)SkBlendMode::kLighten + EQ_OFFSET);
-    GR_STATIC_ASSERT(kColorDodge_GrBlendEquation == (int)SkBlendMode::kColorDodge + EQ_OFFSET);
-    GR_STATIC_ASSERT(kColorBurn_GrBlendEquation == (int)SkBlendMode::kColorBurn + EQ_OFFSET);
-    GR_STATIC_ASSERT(kHardLight_GrBlendEquation == (int)SkBlendMode::kHardLight + EQ_OFFSET);
-    GR_STATIC_ASSERT(kSoftLight_GrBlendEquation == (int)SkBlendMode::kSoftLight + EQ_OFFSET);
-    GR_STATIC_ASSERT(kDifference_GrBlendEquation == (int)SkBlendMode::kDifference + EQ_OFFSET);
-    GR_STATIC_ASSERT(kExclusion_GrBlendEquation == (int)SkBlendMode::kExclusion + EQ_OFFSET);
-    GR_STATIC_ASSERT(kMultiply_GrBlendEquation == (int)SkBlendMode::kMultiply + EQ_OFFSET);
-    GR_STATIC_ASSERT(kHSLHue_GrBlendEquation == (int)SkBlendMode::kHue + EQ_OFFSET);
-    GR_STATIC_ASSERT(kHSLSaturation_GrBlendEquation == (int)SkBlendMode::kSaturation + EQ_OFFSET);
-    GR_STATIC_ASSERT(kHSLColor_GrBlendEquation == (int)SkBlendMode::kColor + EQ_OFFSET);
-    GR_STATIC_ASSERT(kHSLLuminosity_GrBlendEquation == (int)SkBlendMode::kLuminosity + EQ_OFFSET);
-    GR_STATIC_ASSERT(kGrBlendEquationCnt == (int)SkBlendMode::kLastMode + 1 + EQ_OFFSET);
-    return static_cast<GrBlendEquation>((int)mode + EQ_OFFSET);
-#undef EQ_OFFSET
+static GrBlendEquation hw_blend_equation(SkBlendMode mode) {
+    enum { kOffset = kOverlay_GrBlendEquation - (int)SkBlendMode::kOverlay };
+    return static_cast<GrBlendEquation>((int)mode + kOffset);
+
+    GR_STATIC_ASSERT(kOverlay_GrBlendEquation == (int)SkBlendMode::kOverlay + kOffset);
+    GR_STATIC_ASSERT(kDarken_GrBlendEquation == (int)SkBlendMode::kDarken + kOffset);
+    GR_STATIC_ASSERT(kLighten_GrBlendEquation == (int)SkBlendMode::kLighten + kOffset);
+    GR_STATIC_ASSERT(kColorDodge_GrBlendEquation == (int)SkBlendMode::kColorDodge + kOffset);
+    GR_STATIC_ASSERT(kColorBurn_GrBlendEquation == (int)SkBlendMode::kColorBurn + kOffset);
+    GR_STATIC_ASSERT(kHardLight_GrBlendEquation == (int)SkBlendMode::kHardLight + kOffset);
+    GR_STATIC_ASSERT(kSoftLight_GrBlendEquation == (int)SkBlendMode::kSoftLight + kOffset);
+    GR_STATIC_ASSERT(kDifference_GrBlendEquation == (int)SkBlendMode::kDifference + kOffset);
+    GR_STATIC_ASSERT(kExclusion_GrBlendEquation == (int)SkBlendMode::kExclusion + kOffset);
+    GR_STATIC_ASSERT(kMultiply_GrBlendEquation == (int)SkBlendMode::kMultiply + kOffset);
+    GR_STATIC_ASSERT(kHSLHue_GrBlendEquation == (int)SkBlendMode::kHue + kOffset);
+    GR_STATIC_ASSERT(kHSLSaturation_GrBlendEquation == (int)SkBlendMode::kSaturation + kOffset);
+    GR_STATIC_ASSERT(kHSLColor_GrBlendEquation == (int)SkBlendMode::kColor + kOffset);
+    GR_STATIC_ASSERT(kHSLLuminosity_GrBlendEquation == (int)SkBlendMode::kLuminosity + kOffset);
+    GR_STATIC_ASSERT(kGrBlendEquationCnt == (int)SkBlendMode::kLastMode + 1 + kOffset);
 }
 
 static bool can_use_hw_blend_equation(GrBlendEquation equation,
@@ -320,16 +319,9 @@
 }
 
 ///////////////////////////////////////////////////////////////////////////////
-
-// See the comment above GrXPFactory's definition about this warning suppression.
-#if defined(__GNUC__) || defined(__clang)
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
-#endif
 class CustomXPFactory : public GrXPFactory {
 public:
-    constexpr CustomXPFactory(SkBlendMode mode)
-            : fMode(mode), fHWBlendEquation(hw_blend_equation(mode)) {}
+    CustomXPFactory(SkBlendMode mode);
 
     void getInvariantBlendedColor(const GrProcOptInfo& colorPOI,
                                   GrXPFactory::InvariantBlendedColor*) const override;
@@ -342,6 +334,10 @@
 
     bool onWillReadDstColor(const GrCaps&, const GrPipelineAnalysis&) const override;
 
+    bool onIsEqual(const GrXPFactory& xpfBase) const override {
+        const CustomXPFactory& xpf = xpfBase.cast<CustomXPFactory>();
+        return fMode == xpf.fMode;
+    }
 
     GR_DECLARE_XP_FACTORY_TEST;
 
@@ -350,15 +346,18 @@
 
     typedef GrXPFactory INHERITED;
 };
-#if defined(__GNUC__) || defined(__clang)
-#pragma GCC diagnostic pop
-#endif
+
+CustomXPFactory::CustomXPFactory(SkBlendMode mode)
+    : fMode(mode),
+      fHWBlendEquation(hw_blend_equation(mode)) {
+    SkASSERT(GrCustomXfermode::IsSupportedMode(fMode));
+    this->initClassID<CustomXPFactory>();
+}
 
 GrXferProcessor* CustomXPFactory::onCreateXferProcessor(const GrCaps& caps,
                                                         const GrPipelineAnalysis& analysis,
                                                         bool hasMixedSamples,
                                                         const DstTexture* dstTexture) const {
-    SkASSERT(GrCustomXfermode::IsSupportedMode(fMode));
     if (can_use_hw_blend_equation(fHWBlendEquation, analysis, caps)) {
         SkASSERT(!dstTexture || !dstTexture->texture());
         return new CustomXP(fMode, fHWBlendEquation);
@@ -378,16 +377,16 @@
 }
 
 GR_DEFINE_XP_FACTORY_TEST(CustomXPFactory);
-const GrXPFactory* CustomXPFactory::TestGet(GrProcessorTestData* d) {
+sk_sp<GrXPFactory> CustomXPFactory::TestCreate(GrProcessorTestData* d) {
     int mode = d->fRandom->nextRangeU((int)SkBlendMode::kLastCoeffMode + 1,
                                       (int)SkBlendMode::kLastSeparableMode);
 
-    return GrCustomXfermode::Get((SkBlendMode)mode);
+    return sk_sp<GrXPFactory>(new CustomXPFactory(static_cast<SkBlendMode>(mode)));
 }
 
 ///////////////////////////////////////////////////////////////////////////////
 
-const GrXPFactory* GrCustomXfermode::Get(SkBlendMode mode) {
+sk_sp<GrXPFactory> GrCustomXfermode::MakeXPFactory(SkBlendMode mode) {
     static CustomXPFactory gOverlay(SkBlendMode::kOverlay);
     static CustomXPFactory gDarken(SkBlendMode::kDarken);
     static CustomXPFactory gLighten(SkBlendMode::kLighten);
@@ -404,33 +403,33 @@
     static CustomXPFactory gLuminosity(SkBlendMode::kLuminosity);
     switch (mode) {
         case SkBlendMode::kOverlay:
-            return &gOverlay;
+            return sk_sp<GrXPFactory>(SkRef(&gOverlay));
         case SkBlendMode::kDarken:
-            return &gDarken;
+            return sk_sp<GrXPFactory>(SkRef(&gDarken));
         case SkBlendMode::kLighten:
-            return &gLighten;
+            return sk_sp<GrXPFactory>(SkRef(&gLighten));
         case SkBlendMode::kColorDodge:
-            return &gColorDodge;
+            return sk_sp<GrXPFactory>(SkRef(&gColorDodge));
         case SkBlendMode::kColorBurn:
-            return &gColorBurn;
+            return sk_sp<GrXPFactory>(SkRef(&gColorBurn));
         case SkBlendMode::kHardLight:
-            return &gHardLight;
+            return sk_sp<GrXPFactory>(SkRef(&gHardLight));
         case SkBlendMode::kSoftLight:
-            return &gSoftLight;
+             return sk_sp<GrXPFactory>(SkRef(&gSoftLight));
         case SkBlendMode::kDifference:
-            return &gDifference;
+            return sk_sp<GrXPFactory>(SkRef(&gDifference));
         case SkBlendMode::kExclusion:
-            return &gExclusion;
+            return sk_sp<GrXPFactory>(SkRef(&gExclusion));
         case SkBlendMode::kMultiply:
-            return &gMultiply;
+            return sk_sp<GrXPFactory>(SkRef(&gMultiply));
         case SkBlendMode::kHue:
-            return &gHue;
+            return sk_sp<GrXPFactory>(SkRef(&gHue));
         case SkBlendMode::kSaturation:
-            return &gSaturation;
+            return sk_sp<GrXPFactory>(SkRef(&gSaturation));
         case SkBlendMode::kColor:
-            return &gColor;
+            return sk_sp<GrXPFactory>(SkRef(&gColor));
         case SkBlendMode::kLuminosity:
-            return &gLuminosity;
+            return sk_sp<GrXPFactory>(SkRef(&gLuminosity));
         default:
             SkASSERT(!GrCustomXfermode::IsSupportedMode(mode));
             return nullptr;
diff --git a/src/gpu/effects/GrDisableColorXP.cpp b/src/gpu/effects/GrDisableColorXP.cpp
index 69c34ec..0182acc 100644
--- a/src/gpu/effects/GrDisableColorXP.cpp
+++ b/src/gpu/effects/GrDisableColorXP.cpp
@@ -88,6 +88,11 @@
 }
 
 ///////////////////////////////////////////////////////////////////////////////
+
+GrDisableColorXPFactory::GrDisableColorXPFactory() {
+    this->initClassID<GrDisableColorXPFactory>();
+}
+
 GrXferProcessor* GrDisableColorXPFactory::onCreateXferProcessor(const GrCaps& caps,
                                                                 const GrPipelineAnalysis& analysis,
                                                                 bool hasMixedSamples,
@@ -98,6 +103,6 @@
 
 GR_DEFINE_XP_FACTORY_TEST(GrDisableColorXPFactory);
 
-const GrXPFactory* GrDisableColorXPFactory::TestGet(GrProcessorTestData*) {
-    return GrDisableColorXPFactory::Get();
+sk_sp<GrXPFactory> GrDisableColorXPFactory::TestCreate(GrProcessorTestData*) {
+    return GrDisableColorXPFactory::Make();
 }
diff --git a/src/gpu/effects/GrDisableColorXP.h b/src/gpu/effects/GrDisableColorXP.h
index 38624e0..49e2459 100644
--- a/src/gpu/effects/GrDisableColorXP.h
+++ b/src/gpu/effects/GrDisableColorXP.h
@@ -14,14 +14,12 @@
 
 class GrProcOptInfo;
 
-// See the comment above GrXPFactory's definition about this warning suppression.
-#if defined(__GNUC__) || defined(__clang)
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
-#endif
 class GrDisableColorXPFactory : public GrXPFactory {
 public:
-    static const GrXPFactory* Get();
+    static sk_sp<GrXPFactory> Make() {
+        static GrDisableColorXPFactory gDisableColorXPFactory;
+        return sk_sp<GrXPFactory>(SkRef(&gDisableColorXPFactory));
+    }
 
     void getInvariantBlendedColor(const GrProcOptInfo& colorPOI,
                                   GrXPFactory::InvariantBlendedColor* blendedColor) const override {
@@ -30,7 +28,7 @@
     }
 
 private:
-    constexpr GrDisableColorXPFactory() {}
+    GrDisableColorXPFactory();
 
     GrXferProcessor* onCreateXferProcessor(const GrCaps& caps,
                                            const GrPipelineAnalysis&,
@@ -41,17 +39,13 @@
         return false;
     }
 
+    bool onIsEqual(const GrXPFactory& xpfBase) const override {
+        return true;
+    }
+
     GR_DECLARE_XP_FACTORY_TEST;
 
     typedef GrXPFactory INHERITED;
 };
-#if defined(__GNUC__) || defined(__clang)
-#pragma GCC diagnostic pop
-#endif
-
-inline const GrXPFactory* GrDisableColorXPFactory::Get() {
-    static constexpr const GrDisableColorXPFactory gDisableColorXPFactory;
-    return &gDisableColorXPFactory;
-}
 
 #endif
diff --git a/src/gpu/effects/GrPorterDuffXferProcessor.cpp b/src/gpu/effects/GrPorterDuffXferProcessor.cpp
index c8f7160..df8b96d 100644
--- a/src/gpu/effects/GrPorterDuffXferProcessor.cpp
+++ b/src/gpu/effects/GrPorterDuffXferProcessor.cpp
@@ -675,63 +675,40 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 
-constexpr GrPorterDuffXPFactory::GrPorterDuffXPFactory(SkBlendMode xfermode)
-        : fBlendMode(xfermode) {}
+GrPorterDuffXPFactory::GrPorterDuffXPFactory(SkBlendMode xfermode)
+    : fXfermode(xfermode) {
+    SkASSERT((unsigned)fXfermode <= (unsigned)SkBlendMode::kLastCoeffMode);
+    this->initClassID<GrPorterDuffXPFactory>();
+}
 
-const GrXPFactory* GrPorterDuffXPFactory::Get(SkBlendMode blendMode) {
-    SkASSERT((unsigned)blendMode <= (unsigned)SkBlendMode::kLastCoeffMode);
+sk_sp<GrXPFactory> GrPorterDuffXPFactory::Make(SkBlendMode xfermode) {
+    static GrPorterDuffXPFactory gClearPDXPF(SkBlendMode::kClear);
+    static GrPorterDuffXPFactory gSrcPDXPF(SkBlendMode::kSrc);
+    static GrPorterDuffXPFactory gDstPDXPF(SkBlendMode::kDst);
+    static GrPorterDuffXPFactory gSrcOverPDXPF(SkBlendMode::kSrcOver);
+    static GrPorterDuffXPFactory gDstOverPDXPF(SkBlendMode::kDstOver);
+    static GrPorterDuffXPFactory gSrcInPDXPF(SkBlendMode::kSrcIn);
+    static GrPorterDuffXPFactory gDstInPDXPF(SkBlendMode::kDstIn);
+    static GrPorterDuffXPFactory gSrcOutPDXPF(SkBlendMode::kSrcOut);
+    static GrPorterDuffXPFactory gDstOutPDXPF(SkBlendMode::kDstOut);
+    static GrPorterDuffXPFactory gSrcATopPDXPF(SkBlendMode::kSrcATop);
+    static GrPorterDuffXPFactory gDstATopPDXPF(SkBlendMode::kDstATop);
+    static GrPorterDuffXPFactory gXorPDXPF(SkBlendMode::kXor);
+    static GrPorterDuffXPFactory gPlusPDXPF(SkBlendMode::kPlus);
+    static GrPorterDuffXPFactory gModulatePDXPF(SkBlendMode::kModulate);
+    static GrPorterDuffXPFactory gScreenPDXPF(SkBlendMode::kScreen);
 
-    static constexpr const GrPorterDuffXPFactory gClearPDXPF(SkBlendMode::kClear);
-    static constexpr const GrPorterDuffXPFactory gSrcPDXPF(SkBlendMode::kSrc);
-    static constexpr const GrPorterDuffXPFactory gDstPDXPF(SkBlendMode::kDst);
-    static constexpr const GrPorterDuffXPFactory gSrcOverPDXPF(SkBlendMode::kSrcOver);
-    static constexpr const GrPorterDuffXPFactory gDstOverPDXPF(SkBlendMode::kDstOver);
-    static constexpr const GrPorterDuffXPFactory gSrcInPDXPF(SkBlendMode::kSrcIn);
-    static constexpr const GrPorterDuffXPFactory gDstInPDXPF(SkBlendMode::kDstIn);
-    static constexpr const GrPorterDuffXPFactory gSrcOutPDXPF(SkBlendMode::kSrcOut);
-    static constexpr const GrPorterDuffXPFactory gDstOutPDXPF(SkBlendMode::kDstOut);
-    static constexpr const GrPorterDuffXPFactory gSrcATopPDXPF(SkBlendMode::kSrcATop);
-    static constexpr const GrPorterDuffXPFactory gDstATopPDXPF(SkBlendMode::kDstATop);
-    static constexpr const GrPorterDuffXPFactory gXorPDXPF(SkBlendMode::kXor);
-    static constexpr const GrPorterDuffXPFactory gPlusPDXPF(SkBlendMode::kPlus);
-    static constexpr const GrPorterDuffXPFactory gModulatePDXPF(SkBlendMode::kModulate);
-    static constexpr const GrPorterDuffXPFactory gScreenPDXPF(SkBlendMode::kScreen);
+    static GrPorterDuffXPFactory* gFactories[] = {
+        &gClearPDXPF, &gSrcPDXPF, &gDstPDXPF, &gSrcOverPDXPF, &gDstOverPDXPF, &gSrcInPDXPF,
+        &gDstInPDXPF, &gSrcOutPDXPF, &gDstOutPDXPF, &gSrcATopPDXPF, &gDstATopPDXPF, &gXorPDXPF,
+        &gPlusPDXPF, &gModulatePDXPF, &gScreenPDXPF
+    };
+    GR_STATIC_ASSERT(SK_ARRAY_COUNT(gFactories) == (int)SkBlendMode::kLastCoeffMode + 1);
 
-    switch (blendMode) {
-        case SkBlendMode::kClear:
-            return &gClearPDXPF;
-        case SkBlendMode::kSrc:
-            return &gSrcPDXPF;
-        case SkBlendMode::kDst:
-            return &gDstPDXPF;
-        case SkBlendMode::kSrcOver:
-            return &gSrcOverPDXPF;
-        case SkBlendMode::kDstOver:
-            return &gDstOverPDXPF;
-        case SkBlendMode::kSrcIn:
-            return &gSrcInPDXPF;
-        case SkBlendMode::kDstIn:
-            return &gDstInPDXPF;
-        case SkBlendMode::kSrcOut:
-            return &gSrcOutPDXPF;
-        case SkBlendMode::kDstOut:
-            return &gDstOutPDXPF;
-        case SkBlendMode::kSrcATop:
-            return &gSrcATopPDXPF;
-        case SkBlendMode::kDstATop:
-            return &gDstATopPDXPF;
-        case SkBlendMode::kXor:
-            return &gXorPDXPF;
-        case SkBlendMode::kPlus:
-            return &gPlusPDXPF;
-        case SkBlendMode::kModulate:
-            return &gModulatePDXPF;
-        case SkBlendMode::kScreen:
-            return &gScreenPDXPF;
-        default:
-            SkFAIL("Unexpected blend mode.");
-            return nullptr;
+    if ((int)xfermode < 0 || (int)xfermode > (int)SkBlendMode::kLastCoeffMode) {
+        return nullptr;
     }
+    return sk_sp<GrXPFactory>(SkRef(gFactories[(int)xfermode]));
 }
 
 GrXferProcessor* GrPorterDuffXPFactory::onCreateXferProcessor(const GrCaps& caps,
@@ -739,27 +716,27 @@
                                                               bool hasMixedSamples,
                                                               const DstTexture* dstTexture) const {
     if (analysis.fUsesPLSDstRead) {
-        return new ShaderPDXferProcessor(dstTexture, hasMixedSamples, fBlendMode);
+        return new ShaderPDXferProcessor(dstTexture, hasMixedSamples, fXfermode);
     }
     BlendFormula blendFormula;
     if (analysis.fCoveragePOI.isFourChannelOutput()) {
-        if (SkBlendMode::kSrcOver == fBlendMode &&
+        if (SkBlendMode::kSrcOver == fXfermode &&
             kRGBA_GrColorComponentFlags == analysis.fColorPOI.validFlags() &&
             !caps.shaderCaps()->dualSourceBlendingSupport() &&
             !caps.shaderCaps()->dstReadInShaderSupport()) {
             // If we don't have dual source blending or in shader dst reads, we fall back to this
             // trick for rendering SrcOver LCD text instead of doing a dst copy.
             SkASSERT(!dstTexture || !dstTexture->texture());
-            return PDLCDXferProcessor::Create(fBlendMode, analysis.fColorPOI);
+            return PDLCDXferProcessor::Create(fXfermode, analysis.fColorPOI);
         }
-        blendFormula = get_lcd_blend_formula(analysis.fCoveragePOI, fBlendMode);
+        blendFormula = get_lcd_blend_formula(analysis.fCoveragePOI, fXfermode);
     } else {
         blendFormula = get_blend_formula(analysis.fColorPOI, analysis.fCoveragePOI, hasMixedSamples,
-                                         fBlendMode);
+                                         fXfermode);
     }
 
     if (blendFormula.hasSecondaryOutput() && !caps.shaderCaps()->dualSourceBlendingSupport()) {
-        return new ShaderPDXferProcessor(dstTexture, hasMixedSamples, fBlendMode);
+        return new ShaderPDXferProcessor(dstTexture, hasMixedSamples, fXfermode);
     }
 
     SkASSERT(!dstTexture || !dstTexture->texture());
@@ -769,7 +746,7 @@
 void GrPorterDuffXPFactory::getInvariantBlendedColor(const GrProcOptInfo& colorPOI,
                                                      InvariantBlendedColor* blendedColor) const {
     // Find the blended color info based on the formula that does not have coverage.
-    BlendFormula colorFormula = gBlendTable[colorPOI.isOpaque()][0][(int)fBlendMode];
+    BlendFormula colorFormula = gBlendTable[colorPOI.isOpaque()][0][(int)fXfermode];
     if (colorFormula.usesDstColor()) {
         blendedColor->fWillBlendWithDst = true;
         blendedColor->fKnownColorFlags = kNone_GrColorComponentFlags;
@@ -807,12 +784,12 @@
     // blend. The one exception is when we are using srcover mode and we know the input color into
     // the XP.
     if (analysis.fCoveragePOI.isFourChannelOutput()) {
-        if (SkBlendMode::kSrcOver == fBlendMode &&
+        if (SkBlendMode::kSrcOver == fXfermode &&
             kRGBA_GrColorComponentFlags == analysis.fColorPOI.validFlags() &&
             !caps.shaderCaps()->dstReadInShaderSupport()) {
             return false;
         }
-        return get_lcd_blend_formula(analysis.fCoveragePOI, fBlendMode).hasSecondaryOutput();
+        return get_lcd_blend_formula(analysis.fCoveragePOI, fXfermode).hasSecondaryOutput();
     }
 
     // We fallback on the shader XP when the blend formula would use dual source blending but we
@@ -820,15 +797,15 @@
     static const bool kHasMixedSamples = false;
     SkASSERT(!caps.usesMixedSamples()); // We never use mixed samples without dual source blending.
     auto formula = get_blend_formula(analysis.fColorPOI, analysis.fCoveragePOI, kHasMixedSamples,
-                                     fBlendMode);
+                                     fXfermode);
     return formula.hasSecondaryOutput();
 }
 
 GR_DEFINE_XP_FACTORY_TEST(GrPorterDuffXPFactory);
 
-const GrXPFactory* GrPorterDuffXPFactory::TestGet(GrProcessorTestData* d) {
+sk_sp<GrXPFactory> GrPorterDuffXPFactory::TestCreate(GrProcessorTestData* d) {
     SkBlendMode mode = SkBlendMode(d->fRandom->nextULessThan((int)SkBlendMode::kLastCoeffMode));
-    return GrPorterDuffXPFactory::Get(mode);
+    return GrPorterDuffXPFactory::Make(mode);
 }
 
 void GrPorterDuffXPFactory::TestGetXPOutputTypes(const GrXferProcessor* xp,
diff --git a/src/gpu/ops/GrDefaultPathRenderer.cpp b/src/gpu/ops/GrDefaultPathRenderer.cpp
index cbad5f2..d9e0110 100644
--- a/src/gpu/ops/GrDefaultPathRenderer.cpp
+++ b/src/gpu/ops/GrDefaultPathRenderer.cpp
@@ -596,7 +596,7 @@
     SkASSERT(!args.fShape->inverseFilled());
 
     GrPaint paint;
-    paint.setXPFactory(GrDisableColorXPFactory::Get());
+    paint.setXPFactory(GrDisableColorXPFactory::Make());
 
     this->internalDrawPath(args.fRenderTargetContext, paint, args.fAAType,
                            GrUserStencilSettings::kUnused, *args.fClip, *args.fViewMatrix,
diff --git a/src/gpu/ops/GrMSAAPathRenderer.cpp b/src/gpu/ops/GrMSAAPathRenderer.cpp
index cc6781c..207567b 100644
--- a/src/gpu/ops/GrMSAAPathRenderer.cpp
+++ b/src/gpu/ops/GrMSAAPathRenderer.cpp
@@ -718,7 +718,7 @@
     SkASSERT(!args.fShape->mayBeInverseFilledAfterStyling());
 
     GrPaint paint;
-    paint.setXPFactory(GrDisableColorXPFactory::Get());
+    paint.setXPFactory(GrDisableColorXPFactory::Make());
 
     this->internalDrawPath(args.fRenderTargetContext, paint, args.fAAType,
                            GrUserStencilSettings::kUnused, *args.fClip, *args.fViewMatrix,