switch xfermodes over to sk_sp

waiting on https://codereview.chromium.org/1835163002/

BUG=skia:
GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1832223002

Review URL: https://codereview.chromium.org/1832223002
diff --git a/bench/RectBench.cpp b/bench/RectBench.cpp
index edd5ac7..46a515d 100644
--- a/bench/RectBench.cpp
+++ b/bench/RectBench.cpp
@@ -85,11 +85,7 @@
 class SrcModeRectBench : public RectBench {
 public:
     SrcModeRectBench() : INHERITED(1, 0) {
-        fMode = SkXfermode::Create(SkXfermode::kSrc_Mode);
-    }
-
-    virtual ~SrcModeRectBench() {
-        SkSafeUnref(fMode);
+        fMode = SkXfermode::Make(SkXfermode::kSrc_Mode);
     }
 
 protected:
@@ -108,7 +104,7 @@
 
 private:
     SkString fName;
-    SkXfermode* fMode;
+    sk_sp<SkXfermode> fMode;
 
     typedef RectBench INHERITED;
 };
diff --git a/bench/Xfer4fBench.cpp b/bench/Xfer4fBench.cpp
index ab04476..6ea7a4f 100644
--- a/bench/Xfer4fBench.cpp
+++ b/bench/Xfer4fBench.cpp
@@ -21,8 +21,7 @@
         : fDoN(doN)
         , fFlags(flags & ~USE_AA)
     {
-        fXfer.reset(SkXfermode::Create(mode));
-
+        fXfer = SkXfermode::Make(mode);
         fProc1 = SkXfermode::GetD32Proc(fXfer, fFlags | SkXfermode::kSrcIsSingle_D32Flag);
         fProcN = SkXfermode::GetD32Proc(fXfer, fFlags);
         fName.printf("xfer4f_%s_%s_%c_%s_%s",
@@ -53,15 +52,15 @@
     void onDraw(int loops, SkCanvas*) override {
         for (int i = 0; i < loops * INNER_LOOPS; ++i) {
             if (fDoN) {
-                fProcN(fXfer, fDst, fSrc, N, fAA);
+                fProcN(fXfer.get(), fDst, fSrc, N, fAA);
             } else {
-                fProc1(fXfer, fDst, fSrc, N, fAA);
+                fProc1(fXfer.get(), fDst, fSrc, N, fAA);
             }
         }
     }
 
 private:
-    SkAutoTUnref<SkXfermode> fXfer;
+    sk_sp<SkXfermode>   fXfer;
     SkString             fName;
     SkXfermode::D32Proc  fProc1;
     SkXfermode::D32Proc  fProcN;
diff --git a/bench/XferU64Bench.cpp b/bench/XferU64Bench.cpp
index 90aa328..324655b 100644
--- a/bench/XferU64Bench.cpp
+++ b/bench/XferU64Bench.cpp
@@ -21,7 +21,7 @@
         : fDoN(doN)
         , fFlags(flags & ~USE_AA)
     {
-        fXfer.reset(SkXfermode::Create(mode));
+        fXfer = SkXfermode::Make(mode);
 
         fProc1 = SkXfermode::GetD64Proc(fXfer, fFlags | SkXfermode::kSrcIsSingle_D64Flag);
         fProcN = SkXfermode::GetD64Proc(fXfer, fFlags);
@@ -53,15 +53,15 @@
     void onDraw(int loops, SkCanvas*) override {
         for (int i = 0; i < loops * INNER_LOOPS; ++i) {
             if (fDoN) {
-                fProcN(fXfer, fDst, fSrc, N, fAA);
+                fProcN(fXfer.get(), fDst, fSrc, N, fAA);
             } else {
-                fProc1(fXfer, fDst, fSrc, N, fAA);
+                fProc1(fXfer.get(), fDst, fSrc, N, fAA);
             }
         }
     }
 
 private:
-    SkAutoTUnref<SkXfermode> fXfer;
+    sk_sp<SkXfermode>   fXfer;
     SkString            fName;
     SkXfermode::D64Proc fProc1;
     SkXfermode::D64Proc fProcN;
diff --git a/bench/XfermodeBench.cpp b/bench/XfermodeBench.cpp
index 9eae7ce..829c437 100644
--- a/bench/XfermodeBench.cpp
+++ b/bench/XfermodeBench.cpp
@@ -16,7 +16,7 @@
 class XfermodeBench : public Benchmark {
 public:
     XfermodeBench(SkXfermode::Mode mode, bool aa) {
-        fXfermode.reset(SkXfermode::Create(mode));
+        fXfermode = SkXfermode::Make(mode);
         fAA = aa;
         SkASSERT(fXfermode.get() || SkXfermode::kSrcOver_Mode == mode);
         fName.printf("Xfermode_%s%s", SkXfermode::ModeName(mode), aa ? "_aa" : "");
@@ -39,7 +39,7 @@
         SkRandom random;
         for (int i = 0; i < loops; ++i) {
             SkPaint paint;
-            paint.setXfermode(fXfermode.get());
+            paint.setXfermode(fXfermode);
             paint.setColor(random.nextU());
             if (fAA) {
                 // Draw text to exercise AA code paths.
@@ -68,9 +68,9 @@
     }
 
 private:
-    SkAutoTUnref<SkXfermode> fXfermode;
-    SkString fName;
-    bool fAA;
+    sk_sp<SkXfermode>   fXfermode;
+    SkString            fName;
+    bool                fAA;
 
     typedef Benchmark INHERITED;
 };
@@ -87,8 +87,7 @@
     void onDraw(int loops, SkCanvas* canvas) override {
         for (int outer = 0; outer < loops * 10; ++outer) {
             for (int i = 0; i <= SkXfermode::kLastMode; ++i) {
-                SkXfermode* xfer = SkXfermode::Create(SkXfermode::Mode(i));
-                SkSafeUnref(xfer);
+                (void)SkXfermode::Make(SkXfermode::Mode(i));
             }
         }
     }
diff --git a/gm/aarectmodes.cpp b/gm/aarectmodes.cpp
index badd1ae..10fa15a 100644
--- a/gm/aarectmodes.cpp
+++ b/gm/aarectmodes.cpp
@@ -81,8 +81,7 @@
 const SkScalar W = SkIntToScalar(gWidth);
 const SkScalar H = SkIntToScalar(gHeight);
 
-static SkScalar drawCell(SkCanvas* canvas, SkXfermode* mode,
-                         SkAlpha a0, SkAlpha a1) {
+static SkScalar drawCell(SkCanvas* canvas, sk_sp<SkXfermode> mode, SkAlpha a0, SkAlpha a1) {
 
     SkPaint paint;
     paint.setAntiAlias(true);
@@ -96,7 +95,7 @@
 
     paint.setColor(SK_ColorRED);
     paint.setAlpha(a1);
-    paint.setXfermode(mode);
+    paint.setXfermode(std::move(mode));
 
     SkScalar offset = SK_Scalar1 / 3;
     SkRect rect = SkRect::MakeXYWH(W / 4 + offset,
@@ -154,17 +153,14 @@
                         canvas->translate(W * 5, 0);
                         canvas->save();
                     }
-                    SkXfermode* mode = SkXfermode::Create(gModes[i].fMode);
-
                     canvas->drawRect(bounds, fBGPaint);
                     canvas->saveLayer(&bounds, nullptr);
-                    SkScalar dy = drawCell(canvas, mode,
+                    SkScalar dy = drawCell(canvas, SkXfermode::Make(gModes[i].fMode),
                                            gAlphaValue[alpha & 1],
                                            gAlphaValue[alpha & 2]);
                     canvas->restore();
 
                     canvas->translate(0, dy * 5 / 4);
-                    SkSafeUnref(mode);
                 }
                 canvas->restore();
                 canvas->restore();
diff --git a/gm/aaxfermodes.cpp b/gm/aaxfermodes.cpp
index f1264db..2ea1844 100644
--- a/gm/aaxfermodes.cpp
+++ b/gm/aaxfermodes.cpp
@@ -210,7 +210,7 @@
             if (maxSum > 255) {
                 SkPaint dimPaint;
                 dimPaint.setAntiAlias(false);
-                dimPaint.setXfermode(SkXfermode::Create(SkXfermode::kDstIn_Mode));
+                dimPaint.setXfermode(SkXfermode::Make(SkXfermode::kDstIn_Mode));
                 if (255 != paint->getAlpha()) {
                     // Dim the src and dst colors.
                     dimPaint.setARGB(255 * 255 / maxSum, 0, 0, 0);
@@ -230,13 +230,13 @@
         SkPaint shapePaint(paint);
         shapePaint.setAntiAlias(kSquare_Shape != shape);
 
-        SkAutoTUnref<SkXfermode> xfermode;
+        sk_sp<SkXfermode> xfermode;
         if (mode <= SkXfermode::kLastMode) {
-            xfermode.reset(SkXfermode::Create(mode));
+            xfermode = SkXfermode::Make(mode);
         } else {
-            xfermode.reset(SkArithmeticMode::Create(+1.0f, +0.25f, -0.5f, +0.1f));
+            xfermode = SkArithmeticMode::Make(+1.0f, +0.25f, -0.5f, +0.1f);
         }
-        shapePaint.setXfermode(xfermode);
+        shapePaint.setXfermode(std::move(xfermode));
 
         switch (shape) {
             case kSquare_Shape:
diff --git a/gm/arithmode.cpp b/gm/arithmode.cpp
index bddd200..cd074d4 100644
--- a/gm/arithmode.cpp
+++ b/gm/arithmode.cpp
@@ -110,9 +110,8 @@
             SkRect rect = SkRect::MakeXYWH(x, y, SkIntToScalar(WW), SkIntToScalar(HH));
             canvas->saveLayer(&rect, nullptr);
             canvas->drawBitmap(dst, x, y, nullptr);
-            SkXfermode* xfer = SkArithmeticMode::Create(k[0], k[1], k[2], k[3]);
             SkPaint paint;
-            paint.setXfermode(xfer)->unref();
+            paint.setXfermode(SkArithmeticMode::Make(k[0], k[1], k[2], k[3]));
             canvas->drawBitmap(src, x, y, &paint);
             canvas->restore();
             x += gap;
@@ -133,13 +132,11 @@
             x += gap;
             SkRect rect = SkRect::MakeXYWH(x, y, SkIntToScalar(WW), SkIntToScalar(HH));
             canvas->saveLayer(&rect, nullptr);
-            SkXfermode* xfer1 = SkArithmeticMode::Create(0, -one / 2, 0, 1, enforcePMColor);
             SkPaint paint1;
-            paint1.setXfermode(xfer1)->unref();
+            paint1.setXfermode(SkArithmeticMode::Make(0, -one / 2, 0, 1, enforcePMColor));
             canvas->drawBitmap(dst, x, y, &paint1);
-            SkXfermode* xfer2 = SkArithmeticMode::Create(0, one / 2, -one, 1);
             SkPaint paint2;
-            paint2.setXfermode(xfer2)->unref();
+            paint2.setXfermode(SkArithmeticMode::Make(0, one / 2, -one, 1));
             canvas->drawBitmap(dst, x, y, &paint2);
             canvas->restore();
             x += gap;
diff --git a/gm/avoidxfermode.cpp b/gm/avoidxfermode.cpp
index d224b4e..8e8dc28 100644
--- a/gm/avoidxfermode.cpp
+++ b/gm/avoidxfermode.cpp
@@ -37,9 +37,7 @@
         // UL corner: replace white with black with a tight tolerance
         SkPaint p1;
         p1.setColor(SK_ColorBLACK);
-        p1.setXfermode(SkAvoidXfermode::Create(SK_ColorWHITE,
-                                               5,
-                                               SkAvoidXfermode::kTargetColor_Mode))->unref();
+        p1.setXfermode(SkAvoidXfermode::Make(SK_ColorWHITE, 5, SkAvoidXfermode::kTargetColor_Mode));
 
         canvas->drawRect(r, p1);
 
@@ -48,9 +46,8 @@
         // UR corner: draw black everywhere except white with a tight tolerance
         SkPaint p2;
         p2.setColor(SK_ColorBLACK);
-        p2.setXfermode(SkAvoidXfermode::Create(SK_ColorWHITE,
-                                               250,
-                                               SkAvoidXfermode::kAvoidColor_Mode))->unref();
+        p2.setXfermode(SkAvoidXfermode::Make(SK_ColorWHITE, 250,
+                                             SkAvoidXfermode::kAvoidColor_Mode));
 
         canvas->drawRect(r, p2);
 
@@ -59,9 +56,7 @@
         // LL corner: replace red with transparent blue with a loose tolerance
         SkPaint p3;
         p3.setColor(0x7F0000FF);
-        p3.setXfermode(SkAvoidXfermode::Create(SK_ColorRED,
-                                               250,
-                                               SkAvoidXfermode::kTargetColor_Mode))->unref();
+        p3.setXfermode(SkAvoidXfermode::Make(SK_ColorRED, 250, SkAvoidXfermode::kTargetColor_Mode));
 
         canvas->drawRect(r, p3);
 
@@ -70,9 +65,7 @@
         // LR corner: draw black everywhere except red with a loose tolerance
         SkPaint p4;
         p4.setColor(SK_ColorBLACK);
-        p4.setXfermode(SkAvoidXfermode::Create(SK_ColorRED,
-                                               5,
-                                               SkAvoidXfermode::kAvoidColor_Mode))->unref();
+        p4.setXfermode(SkAvoidXfermode::Make(SK_ColorRED, 5, SkAvoidXfermode::kAvoidColor_Mode));
 
         canvas->drawRect(r, p4);
     }
diff --git a/gm/avoidxfermode2.cpp b/gm/avoidxfermode2.cpp
index 039ed40..9fe7d33 100644
--- a/gm/avoidxfermode2.cpp
+++ b/gm/avoidxfermode2.cpp
@@ -35,9 +35,8 @@
         // UL corner: replace the green with a tight tolerance
         SkPaint p1;
         p1.setColor(SK_ColorRED);
-        p1.setXfermode(SkAvoidXfermode::Create(SK_ColorGREEN,
-                                               55,
-                                               SkAvoidXfermode::kTargetColor_Mode))->unref();
+        p1.setXfermode(SkAvoidXfermode::Make(SK_ColorGREEN, 55,
+                                             SkAvoidXfermode::kTargetColor_Mode));
 
         canvas->drawRect(r, p1);
 
@@ -46,9 +45,8 @@
         // UR corner: avoid the green with a tight tolerance
         SkPaint p2;
         p2.setColor(SK_ColorRED);
-        p2.setXfermode(SkAvoidXfermode::Create(SK_ColorGREEN,
-                                               200,
-                                               SkAvoidXfermode::kAvoidColor_Mode))->unref();
+        p2.setXfermode(SkAvoidXfermode::Make(SK_ColorGREEN, 200,
+                                             SkAvoidXfermode::kAvoidColor_Mode));
 
         canvas->drawRect(r, p2);
 
@@ -57,9 +55,8 @@
         // LL corner: replace the green with a loose tolerance
         SkPaint p3;
         p3.setColor(SK_ColorRED);
-        p3.setXfermode(SkAvoidXfermode::Create(SK_ColorGREEN,
-                                               200,
-                                               SkAvoidXfermode::kTargetColor_Mode))->unref();
+        p3.setXfermode(SkAvoidXfermode::Make(SK_ColorGREEN, 200,
+                                             SkAvoidXfermode::kTargetColor_Mode));
 
         canvas->drawRect(r, p3);
 
@@ -68,9 +65,7 @@
         // LR corner: avoid the green with a loose tolerance
         SkPaint p4;
         p4.setColor(SK_ColorRED);
-        p4.setXfermode(SkAvoidXfermode::Create(SK_ColorGREEN,
-                                               55,
-                                               SkAvoidXfermode::kAvoidColor_Mode))->unref();
+        p4.setXfermode(SkAvoidXfermode::Make(SK_ColorGREEN, 55, SkAvoidXfermode::kAvoidColor_Mode));
 
         canvas->drawRect(r, p4);
     }
diff --git a/gm/avoidxfermode3.cpp b/gm/avoidxfermode3.cpp
index c88b2a2..a635ae4 100644
--- a/gm/avoidxfermode3.cpp
+++ b/gm/avoidxfermode3.cpp
@@ -38,9 +38,7 @@
         SkPaint p1;
         p1.setColor(SK_ColorGREEN);
         p1.setAntiAlias(true);
-        p1.setXfermode(SkAvoidXfermode::Create(SK_ColorWHITE,
-                                               5,
-                                               SkAvoidXfermode::kTargetColor_Mode))->unref();
+        p1.setXfermode(SkAvoidXfermode::Make(SK_ColorWHITE, 5, SkAvoidXfermode::kTargetColor_Mode));
 
         canvas->drawRect(r, p1);
 
@@ -50,9 +48,8 @@
         SkPaint p2;
         p2.setColor(SK_ColorRED);
         p2.setAntiAlias(true);
-        p2.setXfermode(SkAvoidXfermode::Create(SK_ColorWHITE,
-                                               250,
-                                               SkAvoidXfermode::kAvoidColor_Mode))->unref();
+        p2.setXfermode(SkAvoidXfermode::Make(SK_ColorWHITE, 250,
+                                             SkAvoidXfermode::kAvoidColor_Mode));
 
         canvas->drawRect(r, p2);
 
@@ -62,9 +59,8 @@
         SkPaint p3;
         p3.setColor(SK_ColorBLUE);
         p3.setAntiAlias(true);
-        p3.setXfermode(SkAvoidXfermode::Create(SK_ColorWHITE,
-                                               250,
-                                               SkAvoidXfermode::kTargetColor_Mode))->unref();
+        p3.setXfermode(SkAvoidXfermode::Make(SK_ColorWHITE, 250,
+                                             SkAvoidXfermode::kTargetColor_Mode));
 
         canvas->drawRect(r, p3);
 
@@ -74,9 +70,7 @@
         SkPaint p4;
         p4.setColor(SK_ColorYELLOW);
         p4.setAntiAlias(true);
-        p4.setXfermode(SkAvoidXfermode::Create(SK_ColorWHITE,
-                                               5,
-                                               SkAvoidXfermode::kAvoidColor_Mode))->unref();
+        p4.setXfermode(SkAvoidXfermode::Make(SK_ColorWHITE, 5, SkAvoidXfermode::kAvoidColor_Mode));
 
         canvas->drawRect(r, p4);
     }
diff --git a/gm/bitmaprect.cpp b/gm/bitmaprect.cpp
index 4853d03..4db6e2f 100644
--- a/gm/bitmaprect.cpp
+++ b/gm/bitmaprect.cpp
@@ -199,12 +199,9 @@
     }
 
     void onDraw(SkCanvas* canvas) override {
-
-        SkXfermode* mode = SkXfermode::Create(SkXfermode::kXor_Mode);
-
         SkPaint paint;
         paint.setAlpha(128);
-        paint.setXfermode(mode)->unref();
+        paint.setXfermode(SkXfermode::Make(SkXfermode::kXor_Mode));
 
         SkRect srcR1 = { 0.0f, 0.0f, 4096.0f, 2040.0f };
         SkRect dstR1 = { 10.1f, 10.1f, 629.9f, 400.9f };
diff --git a/gm/blurredclippedcircle.cpp b/gm/blurredclippedcircle.cpp
index 3bbff75..d162ac1 100644
--- a/gm/blurredclippedcircle.cpp
+++ b/gm/blurredclippedcircle.cpp
@@ -34,7 +34,7 @@
     void onDraw(SkCanvas* canvas) override {
         SkPaint whitePaint;
         whitePaint.setColor(SK_ColorWHITE);
-        whitePaint.setXfermode(SkXfermode::Create(SkXfermode::kSrc_Mode))->unref();
+        whitePaint.setXfermode(SkXfermode::Make(SkXfermode::kSrc_Mode));
         whitePaint.setAntiAlias(true);
 
         // This scale exercises precision limits in the circle blur effect (crbug.com/560651)
diff --git a/gm/colortypexfermode.cpp b/gm/colortypexfermode.cpp
index 3489f36..36db2aa 100644
--- a/gm/colortypexfermode.cpp
+++ b/gm/colortypexfermode.cpp
@@ -121,8 +121,6 @@
         SkScalar y0 = 0;
         SkScalar x = x0, y = y0;
         for (size_t i = 0; i < SK_ARRAY_COUNT(gModes); i++) {
-            SkXfermode* mode = SkXfermode::Create(gModes[i].fMode);
-            SkAutoUnref aur(mode);
             SkRect r;
             r.set(x, y, x+w, y+h);
 
@@ -136,7 +134,7 @@
             p.setShader(nullptr);
             canvas->drawRect(r, p);
 
-            textP.setXfermode(mode);
+            textP.setXfermode(SkXfermode::Make(gModes[i].fMode));
             canvas->drawText("H", 1, x+ w/10.f, y + 7.f*h/8.f, textP);
 #if 1
             canvas->drawText(gModes[i].fLabel, strlen(gModes[i].fLabel),
diff --git a/gm/composeshader.cpp b/gm/composeshader.cpp
index 421641c..efcfe79 100644
--- a/gm/composeshader.cpp
+++ b/gm/composeshader.cpp
@@ -30,9 +30,8 @@
     colors[1] = SkColorSetARGB(0x80, 0, 0, 0);
     auto shaderB = SkGradientShader::MakeLinear(pts, colors, nullptr, 2, SkShader::kClamp_TileMode);
 
-    SkAutoTUnref<SkXfermode> xfer(SkXfermode::Create(mode));
-
-    return SkShader::MakeComposeShader(std::move(shaderA), std::move(shaderB), xfer);
+    return SkShader::MakeComposeShader(std::move(shaderA), std::move(shaderB),
+                                       SkXfermode::Make(mode));
 }
 
 class ComposeShaderGM : public skiagm::GM {
@@ -176,7 +175,7 @@
     }
 
     void onDraw(SkCanvas* canvas) override {
-        SkAutoTUnref<SkXfermode> xfer(SkXfermode::Create(SkXfermode::kDstOver_Mode));
+        auto xfer(SkXfermode::Make(SkXfermode::kDstOver_Mode));
 
         sk_sp<SkShader> shaders[] = {
             // gradient should appear over color bitmap
diff --git a/gm/drawatlascolor.cpp b/gm/drawatlascolor.cpp
index 0e85055..3331482 100644
--- a/gm/drawatlascolor.cpp
+++ b/gm/drawatlascolor.cpp
@@ -26,7 +26,7 @@
     SkCanvas* canvas = surface->getCanvas();
 
     SkPaint paint;
-    paint.setXfermode(SkXfermode::Create(SkXfermode::kSrc_Mode));
+    paint.setXfermode(SkXfermode::Make(SkXfermode::kSrc_Mode));
 
     paint.setColor(SK_ColorWHITE);
     SkRect r = SkRect::MakeXYWH(0, 0,
diff --git a/gm/hairmodes.cpp b/gm/hairmodes.cpp
index 15e75fe..2651d04 100644
--- a/gm/hairmodes.cpp
+++ b/gm/hairmodes.cpp
@@ -33,7 +33,7 @@
 const SkScalar W = SkIntToScalar(gWidth);
 const SkScalar H = SkIntToScalar(gHeight);
 
-static SkScalar drawCell(SkCanvas* canvas, SkXfermode* mode, SkAlpha a0, SkAlpha a1) {
+static SkScalar drawCell(SkCanvas* canvas, sk_sp<SkXfermode> mode, SkAlpha a0, SkAlpha a1) {
 
     SkPaint paint;
     paint.setAntiAlias(true);
@@ -47,7 +47,7 @@
 
     paint.setColor(SK_ColorRED);
     paint.setAlpha(a1);
-    paint.setXfermode(mode);
+    paint.setXfermode(std::move(mode));
     for (int angle = 0; angle < 24; ++angle) {
         SkScalar x = SkScalarCos(SkIntToScalar(angle) * (SK_ScalarPI * 2) / 24) * gWidth;
         SkScalar y = SkScalarSin(SkIntToScalar(angle) * (SK_ScalarPI * 2) / 24) * gHeight;
@@ -101,17 +101,15 @@
                         canvas->translate(W * 5, 0);
                         canvas->save();
                     }
-                    SkXfermode* mode = SkXfermode::Create(gModes[i].fMode);
 
                     canvas->drawRect(bounds, fBGPaint);
                     canvas->saveLayer(&bounds, nullptr);
-                    SkScalar dy = drawCell(canvas, mode,
+                    SkScalar dy = drawCell(canvas, SkXfermode::Make(gModes[i].fMode),
                                            gAlphaValue[alpha & 1],
                                            gAlphaValue[alpha & 2]);
                     canvas->restore();
 
                     canvas->translate(0, dy * 5 / 4);
-                    SkSafeUnref(mode);
                 }
                 canvas->restore();
                 canvas->restore();
diff --git a/gm/imagefiltersgraph.cpp b/gm/imagefiltersgraph.cpp
index 547a3bb..53343bc 100644
--- a/gm/imagefiltersgraph.cpp
+++ b/gm/imagefiltersgraph.cpp
@@ -140,11 +140,10 @@
 
             auto matrixFilter(SkColorFilter::MakeMatrixFilterRowMajor255(matrix));
             SkAutoTUnref<SkImageFilter> colorMorph(SkColorFilterImageFilter::Create(matrixFilter.get(), morph));
-            SkAutoTUnref<SkXfermode> mode(SkXfermode::Create(SkXfermode::kSrcOver_Mode));
-            SkAutoTUnref<SkImageFilter> blendColor(SkXfermodeImageFilter::Create(mode, colorMorph));
-
             SkPaint paint;
-            paint.setImageFilter(blendColor);
+            paint.setImageFilter(SkXfermodeImageFilter::Make(
+                                        SkXfermode::Make(SkXfermode::kSrcOver_Mode), colorMorph));
+
             DrawClippedImage(canvas, fImage.get(), paint);
             canvas->translate(SkIntToScalar(100), 0);
         }
@@ -158,12 +157,11 @@
             SkAutoTUnref<SkImageFilter> offsetFilter(
                 SimpleOffsetFilter::Create(10.0f, 10.f, matrixFilter));
 
-            SkAutoTUnref<SkXfermode> arith(SkArithmeticMode::Create(0, SK_Scalar1, SK_Scalar1, 0));
-            SkAutoTUnref<SkImageFilter> arithFilter(
-                SkXfermodeImageFilter::Create(arith, matrixFilter, offsetFilter));
-
             SkPaint paint;
-            paint.setImageFilter(arithFilter);
+            paint.setImageFilter(
+                SkXfermodeImageFilter::Make(SkArithmeticMode::Make(0, SK_Scalar1, SK_Scalar1, 0),
+                                            matrixFilter, offsetFilter, nullptr));
+
             DrawClippedImage(canvas, fImage.get(), paint);
             canvas->translate(SkIntToScalar(100), 0);
         }
@@ -171,13 +169,11 @@
             SkAutoTUnref<SkImageFilter> blur(SkBlurImageFilter::Create(
               SkIntToScalar(10), SkIntToScalar(10)));
 
-            SkAutoTUnref<SkXfermode> mode(SkXfermode::Create(SkXfermode::kSrcIn_Mode));
             SkImageFilter::CropRect cropRect(SkRect::MakeWH(SkIntToScalar(95), SkIntToScalar(100)));
-            SkAutoTUnref<SkImageFilter> blend(
-                SkXfermodeImageFilter::Create(mode, blur, nullptr, &cropRect));
-
             SkPaint paint;
-            paint.setImageFilter(blend);
+            paint.setImageFilter(
+                SkXfermodeImageFilter::Make(SkXfermode::Make(SkXfermode::kSrcIn_Mode), blur,
+                                            nullptr, &cropRect));
             DrawClippedImage(canvas, fImage.get(), paint);
             canvas->translate(SkIntToScalar(100), 0);
         }
@@ -188,8 +184,6 @@
             // (supplied by the dilate).
             SkAutoTUnref<SkImageFilter> dilate(SkDilateImageFilter::Create(5, 5));
 
-            SkAutoTUnref<SkXfermode> mode(SkXfermode::Create(SkXfermode::kSrcIn_Mode));
-
             SkScalar kernel[9] = {
                 SkIntToScalar(-1), SkIntToScalar( -1 ), SkIntToScalar(-1),
                 SkIntToScalar(-1), SkIntToScalar(  7 ), SkIntToScalar(-1),
diff --git a/gm/lcdblendmodes.cpp b/gm/lcdblendmodes.cpp
index 8ac9449..42359e3 100644
--- a/gm/lcdblendmodes.cpp
+++ b/gm/lcdblendmodes.cpp
@@ -76,8 +76,7 @@
         this->drawColumn(surfCanvas, SK_ColorCYAN, SK_ColorMAGENTA, true);
 
         SkPaint surfPaint;
-        SkAutoTUnref<SkXfermode> xfermode(SkXfermode::Create(SkXfermode::kSrcOver_Mode));
-        surfPaint.setXfermode(xfermode);
+        surfPaint.setXfermode(SkXfermode::Make(SkXfermode::kSrcOver_Mode));
         surface->draw(canvas, 0, 0, &surfPaint);
     }
 
@@ -123,14 +122,13 @@
                                backgroundPaint);
         SkScalar y = fTextHeight;
         for (size_t m = 0; m < SK_ARRAY_COUNT(gModes); m++) {
-            SkAutoTUnref<SkXfermode> xfermode(SkXfermode::Create(gModes[m].fMode));
             SkPaint paint;
             paint.setColor(textColor);
             paint.setAntiAlias(true);
             paint.setSubpixelText(true);
             paint.setLCDRenderText(true);
             paint.setTextSize(fTextHeight);
-            paint.setXfermode(xfermode);
+            paint.setXfermode(SkXfermode::Make(gModes[m].fMode));
             sk_tool_utils::set_portable_typeface(&paint);
             if (useGrad) {
                 SkRect r;
diff --git a/gm/lcdoverlap.cpp b/gm/lcdoverlap.cpp
index 1777564..aae27d8 100644
--- a/gm/lcdoverlap.cpp
+++ b/gm/lcdoverlap.cpp
@@ -60,8 +60,8 @@
                 SK_ColorMAGENTA,
         };
 
-        SkAutoTUnref<SkXfermode> xfermode(SkXfermode::Create(mode));
-        SkAutoTUnref<SkXfermode> xfermode2(SkXfermode::Create(mode2));
+        sk_sp<SkXfermode> xfermode(SkXfermode::Make(mode));
+        sk_sp<SkXfermode> xfermode2(SkXfermode::Make(mode2));
         for (size_t i = 0; i < SK_ARRAY_COUNT(colors); i++) {
             canvas->save();
             canvas->translate(x, y);
diff --git a/gm/patch.cpp b/gm/patch.cpp
index d27c4e1..40eb46f 100644
--- a/gm/patch.cpp
+++ b/gm/patch.cpp
@@ -95,7 +95,7 @@
 
         canvas->save();
         for (int y = 0; y < 3; y++) {
-            SkAutoTUnref<SkXfermode> xfer(SkXfermode::Create(modes[y]));
+            sk_sp<SkXfermode> xfer(SkXfermode::Make(modes[y]));
 
             for (int x = 0; x < 4; x++) {
                 canvas->save();
diff --git a/gm/pixelxorxfermode.cpp b/gm/pixelxorxfermode.cpp
index daccca8..6a490e1 100644
--- a/gm/pixelxorxfermode.cpp
+++ b/gm/pixelxorxfermode.cpp
@@ -38,7 +38,7 @@
         // the green & blue channels alone
         SkPaint p1;
         p1.setColor(SK_ColorBLACK); // noop
-        p1.setXfermode(SkPixelXorXfermode::Create(0x7FFF0000))->unref();
+        p1.setXfermode(SkPixelXorXfermode::Make(0x7FFF0000));
 
         canvas->drawRect(r, p1);
 
@@ -47,7 +47,7 @@
         // Negate the dst color via the src color
         SkPaint p2;
         p2.setColor(SK_ColorWHITE);
-        p2.setXfermode(SkPixelXorXfermode::Create(SK_ColorBLACK))->unref(); // noop
+        p2.setXfermode(SkPixelXorXfermode::Make(SK_ColorBLACK)); // noop
 
         canvas->drawRect(r, p2);
 
@@ -56,7 +56,7 @@
         // Just return the original color
         SkPaint p3;
         p3.setColor(SK_ColorBLACK); // noop
-        p3.setXfermode(SkPixelXorXfermode::Create(SK_ColorBLACK))->unref(); // noop
+        p3.setXfermode(SkPixelXorXfermode::Make(SK_ColorBLACK)); // noop
 
         canvas->drawRect(r, p3);
 
@@ -66,7 +66,7 @@
         // the blue channel alone
         SkPaint p4;
         p4.setColor(SK_ColorBLACK); // noop
-        p4.setXfermode(SkPixelXorXfermode::Create(SK_ColorYELLOW))->unref();
+        p4.setXfermode(SkPixelXorXfermode::Make(SK_ColorYELLOW));
 
         canvas->drawRect(r, p4);
     }
diff --git a/gm/vertices.cpp b/gm/vertices.cpp
index 9c4ccc1..978d9e6 100644
--- a/gm/vertices.cpp
+++ b/gm/vertices.cpp
@@ -154,7 +154,7 @@
         canvas->translate(4, 4);
         int x = 0;
         for (size_t j = 0; j < SK_ARRAY_COUNT(modes); ++j) {
-            SkXfermode* xfer = SkXfermode::Create(modes[j]);
+            auto xfer = SkXfermode::Make(modes[j]);
             canvas->save();
             for (size_t i = 0; i < SK_ARRAY_COUNT(rec); ++i) {
                 paint.setShader(rec[i].fShader);
@@ -170,7 +170,6 @@
             }
             canvas->restore();
             canvas->translate(0, 40);
-            SkSafeUnref(xfer);
         }
     }
 
diff --git a/gm/xfermodeimagefilter.cpp b/gm/xfermodeimagefilter.cpp
index 805e220..90e2dd0 100644
--- a/gm/xfermodeimagefilter.cpp
+++ b/gm/xfermodeimagefilter.cpp
@@ -87,9 +87,8 @@
         int x = 0, y = 0;
         SkAutoTUnref<SkImageFilter> background(SkImageSource::Create(fCheckerboard.get()));
         for (size_t i = 0; i < SK_ARRAY_COUNT(gModes); i++) {
-            SkAutoTUnref<SkXfermode> mode(SkXfermode::Create(gModes[i].fMode));
-            SkAutoTUnref<SkImageFilter> filter(SkXfermodeImageFilter::Create(mode, background));
-            paint.setImageFilter(filter);
+            paint.setImageFilter(SkXfermodeImageFilter::Make(SkXfermode::Make(gModes[i].fMode),
+                                                             background));
             DrawClippedBitmap(canvas, fBitmap, paint, x, y);
             x += fBitmap.width() + MARGIN;
             if (x + fBitmap.width() > WIDTH) {
@@ -98,9 +97,8 @@
             }
         }
         // Test arithmetic mode as image filter
-        SkAutoTUnref<SkXfermode> mode(SkArithmeticMode::Create(0, SK_Scalar1, SK_Scalar1, 0));
-        SkAutoTUnref<SkImageFilter> filter(SkXfermodeImageFilter::Create(mode, background));
-        paint.setImageFilter(filter);
+        paint.setImageFilter(SkXfermodeImageFilter::Make(
+                         SkArithmeticMode::Make(0, SK_Scalar1, SK_Scalar1, 0), background));
         DrawClippedBitmap(canvas, fBitmap, paint, x, y);
         x += fBitmap.width() + MARGIN;
         if (x + fBitmap.width() > WIDTH) {
@@ -108,8 +106,7 @@
             y += fBitmap.height() + MARGIN;
         }
         // Test nullptr mode
-        filter.reset(SkXfermodeImageFilter::Create(nullptr, background));
-        paint.setImageFilter(filter);
+        paint.setImageFilter(SkXfermodeImageFilter::Make(nullptr, background));
         DrawClippedBitmap(canvas, fBitmap, paint, x, y);
         x += fBitmap.width() + MARGIN;
         if (x + fBitmap.width() > WIDTH) {
@@ -125,9 +122,9 @@
             SkIntToScalar(4), SkIntToScalar(-4), foreground));
         SkAutoTUnref<SkImageFilter> offsetBackground(SkOffsetImageFilter::Create(
             SkIntToScalar(4), SkIntToScalar(4), background));
-        mode.reset(SkXfermode::Create(SkXfermode::kSrcOver_Mode));
-        filter.reset(SkXfermodeImageFilter::Create(mode, offsetBackground, offsetForeground));
-        paint.setImageFilter(filter);
+        paint.setImageFilter(SkXfermodeImageFilter::Make(
+                 SkXfermode::Make(SkXfermode::kSrcOver_Mode), offsetBackground,
+                 offsetForeground, nullptr));
         DrawClippedPaint(canvas, clipRect, paint, x, y);
         x += fBitmap.width() + MARGIN;
         if (x + fBitmap.width() > WIDTH) {
@@ -135,9 +132,8 @@
             y += fBitmap.height() + MARGIN;
         }
         // Test offsets on Darken (uses shader blend)
-        mode.reset(SkXfermode::Create(SkXfermode::kDarken_Mode));
-        filter.reset(SkXfermodeImageFilter::Create(mode, offsetBackground, offsetForeground));
-        paint.setImageFilter(filter);
+        paint.setImageFilter(SkXfermodeImageFilter::Make(SkXfermode::Make(SkXfermode::kDarken_Mode),
+                                                     offsetBackground, offsetForeground, nullptr));
         DrawClippedPaint(canvas, clipRect, paint, x, y);
         x += fBitmap.width() + MARGIN;
         if (x + fBitmap.width() > WIDTH) {
@@ -158,10 +154,8 @@
                                                  fBitmap.width()  + offsets[i][2],
                                                  fBitmap.height() + offsets[i][3]);
             SkImageFilter::CropRect rect(SkRect::Make(cropRect));
-            mode.reset(SkXfermode::Create(sampledModes[i]));
-            filter.reset(SkXfermodeImageFilter::Create(
-                                    mode, offsetBackground, offsetForeground, &rect));
-            paint.setImageFilter(filter);
+            paint.setImageFilter(SkXfermodeImageFilter::Make(
+                    SkXfermode::Make(sampledModes[i]), offsetBackground, offsetForeground, &rect));
             DrawClippedPaint(canvas, clipRect, paint, x, y);
             x += fBitmap.width() + MARGIN;
             if (x + fBitmap.width() > WIDTH) {
@@ -170,12 +164,11 @@
             }
         }
         // Test small bg, large fg with Screen (uses shader blend)
-        mode.reset(SkXfermode::Create(SkXfermode::kScreen_Mode));
+        auto mode = SkXfermode::Make(SkXfermode::kScreen_Mode);
         SkImageFilter::CropRect cropRect(SkRect::MakeXYWH(10, 10, 60, 60));
         SkAutoTUnref<SkImageFilter> cropped(
             SkOffsetImageFilter::Create(0, 0, foreground, &cropRect));
-        filter.reset(SkXfermodeImageFilter::Create(mode, cropped, background));
-        paint.setImageFilter(filter);
+        paint.setImageFilter(SkXfermodeImageFilter::Make(mode, cropped, background, nullptr));
         DrawClippedPaint(canvas, clipRect, paint, x, y);
         x += fBitmap.width() + MARGIN;
         if (x + fBitmap.width() > WIDTH) {
@@ -183,8 +176,7 @@
             y += fBitmap.height() + MARGIN;
         }
         // Test small fg, large bg with Screen (uses shader blend)
-        filter.reset(SkXfermodeImageFilter::Create(mode, background, cropped));
-        paint.setImageFilter(filter);
+        paint.setImageFilter(SkXfermodeImageFilter::Make(mode, background, cropped, nullptr));
         DrawClippedPaint(canvas, clipRect, paint, x, y);
         x += fBitmap.width() + MARGIN;
         if (x + fBitmap.width() > WIDTH) {
diff --git a/gm/xfermodes.cpp b/gm/xfermodes.cpp
index 821bb8c..331c3d1 100644
--- a/gm/xfermodes.cpp
+++ b/gm/xfermodes.cpp
@@ -24,19 +24,19 @@
     kAvoid_CustomMode       = 3 << kCustomShift,
 };
 
-static SkXfermode* make_custom(int customMode) {
+static sk_sp<SkXfermode> make_custom(int customMode) {
     switch (customMode) {
         case kArithmetic_CustomMode: {
             const SkScalar k1 = 0.25;
             const SkScalar k2 = 0.75;
             const SkScalar k3 = 0.75;
             const SkScalar k4 = -0.25;
-            return SkArithmeticMode::Create(k1, k2, k3, k4);
+            return SkArithmeticMode::Make(k1, k2, k3, k4);
         }
         case kPixelXor_CustomMode:
-            return SkPixelXorXfermode::Create(0xFF88CC44);
+            return SkPixelXorXfermode::Make(0xFF88CC44);
         case kAvoid_CustomMode:
-            return SkAvoidXfermode::Create(0xFFFF0000, 0x44, SkAvoidXfermode::kAvoidColor_Mode);
+            return SkAvoidXfermode::Make(0xFFFF0000, 0x44, SkAvoidXfermode::kAvoidColor_Mode);
         default:
             break;
     }
@@ -155,7 +155,7 @@
      * uses the implied shape of the drawing command and these modes
      * demonstrate that.
      */
-    void draw_mode(SkCanvas* canvas, SkXfermode* mode, SrcType srcType,
+    void draw_mode(SkCanvas* canvas, sk_sp<SkXfermode> mode, SrcType srcType,
                    SkScalar x, SkScalar y) {
         SkPaint p;
         SkMatrix m;
@@ -163,7 +163,7 @@
         m.setTranslate(x, y);
 
         canvas->drawBitmap(fSrcB, x, y, &p);
-        p.setXfermode(mode);
+        p.setXfermode(std::move(mode));
         switch (srcType) {
             case kSmallTransparentImage_SrcType: {
                 m.postScale(SK_ScalarHalf, SK_ScalarHalf, x, y);
@@ -279,11 +279,11 @@
                 if ((gModes[i].fSourceTypeMask & sourceType) == 0) {
                     continue;
                 }
-                SkAutoTUnref<SkXfermode> mode;
+                sk_sp<SkXfermode> mode;
                 if (gModes[i].fSourceTypeMask & kCustomMask) {
-                    mode.reset(make_custom(gModes[i].fSourceTypeMask & kCustomMask));
+                    mode = make_custom(gModes[i].fSourceTypeMask & kCustomMask);
                 } else {
-                    mode.reset(SkXfermode::Create(gModes[i].fMode));
+                    mode = SkXfermode::Make(gModes[i].fMode);
                 }
                 SkRect r;
                 r.set(x, y, x+w, y+h);
@@ -294,7 +294,7 @@
                 canvas->drawRect(r, p);
 
                 canvas->saveLayer(&r, nullptr);
-                draw_mode(canvas, mode, static_cast<SrcType>(sourceType),
+                draw_mode(canvas, std::move(mode), static_cast<SrcType>(sourceType),
                           r.fLeft, r.fTop);
                 canvas->restore();
 
diff --git a/gm/xfermodes2.cpp b/gm/xfermodes2.cpp
index 0956af6..b0d6ca3 100644
--- a/gm/xfermodes2.cpp
+++ b/gm/xfermodes2.cpp
@@ -41,8 +41,6 @@
         SkScalar x = 0, y = 0;
         for (size_t m = 0; m <= SkXfermode::kLastMode; m++) {
             SkXfermode::Mode mode = static_cast<SkXfermode::Mode>(m);
-            SkXfermode* xm = SkXfermode::Create(mode);
-            SkAutoUnref aur(xm);
 
             canvas->save();
 
@@ -59,7 +57,7 @@
             p.setShader(fDst);
             canvas->drawRect(r, p);
             p.setShader(fSrc);
-            p.setXfermode(xm);
+            p.setXfermode(SkXfermode::Make(mode));
             canvas->drawRect(r, p);
 
             canvas->restore();
diff --git a/gyp/skia_for_android_framework_defines.gypi b/gyp/skia_for_android_framework_defines.gypi
index aab2ea7..a06931c 100644
--- a/gyp/skia_for_android_framework_defines.gypi
+++ b/gyp/skia_for_android_framework_defines.gypi
@@ -25,6 +25,7 @@
       'SK_SUPPORT_LEGACY_PATHEFFECT_PTR',
       'SK_SUPPORT_LEGACY_NEW_SURFACE_API',
       'SK_SUPPORT_LEGACY_PICTURE_PTR',
+      'SK_SUPPORT_LEGACY_XFERMODE_PTR',
     ],
   },
 }
diff --git a/include/client/android/SkAvoidXfermode.h b/include/client/android/SkAvoidXfermode.h
index 34deb8f..b752d07 100644
--- a/include/client/android/SkAvoidXfermode.h
+++ b/include/client/android/SkAvoidXfermode.h
@@ -39,9 +39,14 @@
                 Tolerance near 0: draw only on colors that are nearly identical to the op-color
                 Tolerance near 255: draw on any colors even remotely similar to the op-color
      */
-    static SkAvoidXfermode* Create(SkColor opColor, U8CPU tolerance, Mode mode) {
-        return new SkAvoidXfermode(opColor, tolerance, mode);
+    static sk_sp<SkXfermode> Make(SkColor opColor, U8CPU tolerance, Mode mode) {
+        return sk_sp<SkXfermode>(new SkAvoidXfermode(opColor, tolerance, mode));
     }
+#ifdef SK_SUPPORT_LEGACY_XFERMODE_PTR
+    static SkAvoidXfermode* Create(SkColor opColor, U8CPU tolerance, Mode mode) {
+        return (SkAvoidXfermode*)(Make(opColor, tolerance, mode).release());
+    }
+#endif
 
     // overrides from SkXfermode
     void xfer32(SkPMColor dst[], const SkPMColor src[], int count,
diff --git a/include/client/android/SkPixelXorXfermode.h b/include/client/android/SkPixelXorXfermode.h
index 447bd81..b6fd979 100644
--- a/include/client/android/SkPixelXorXfermode.h
+++ b/include/client/android/SkPixelXorXfermode.h
@@ -17,9 +17,14 @@
 */
 class SK_API SkPixelXorXfermode : public SkXfermode {
 public:
-    static SkXfermode* Create(SkColor opColor) {
-        return new SkPixelXorXfermode(opColor);
+    static sk_sp<SkXfermode> Make(SkColor opColor) {
+        return sk_sp<SkXfermode>(new SkPixelXorXfermode(opColor));
     }
+#ifdef SK_SUPPORT_LEGACY_XFERMODE_PTR
+    static SkXfermode* Create(SkColor opColor) {
+        return Make(opColor).release();
+    }
+#endif
 
 #if SK_SUPPORT_GPU
     const GrFragmentProcessor* getFragmentProcessorForImageFilter(
diff --git a/include/core/SkCanvas.h b/include/core/SkCanvas.h
index b77e8a7..59f97e9 100644
--- a/include/core/SkCanvas.h
+++ b/include/core/SkCanvas.h
@@ -1053,6 +1053,14 @@
                       const SkColor colors[], SkXfermode* xmode,
                       const uint16_t indices[], int indexCount,
                       const SkPaint& paint);
+    void drawVertices(VertexMode vmode, int vertexCount,
+                      const SkPoint vertices[], const SkPoint texs[],
+                      const SkColor colors[], sk_sp<SkXfermode>& xmode,
+                      const uint16_t indices[], int indexCount,
+                      const SkPaint& paint) {
+        this->drawVertices(vmode, vertexCount, vertices, texs, colors, xmode.get(),
+                           indices, indexCount, paint);
+    }
 
     /**
      Draw a cubic coons patch
@@ -1069,6 +1077,10 @@
      */
     void drawPatch(const SkPoint cubics[12], const SkColor colors[4],
                    const SkPoint texCoords[4], SkXfermode* xmode, const SkPaint& paint);
+    void drawPatch(const SkPoint cubics[12], const SkColor colors[4], const SkPoint texCoords[4],
+                   const sk_sp<SkXfermode>& xmode, const SkPaint& paint) {
+        this->drawPatch(cubics, colors, texCoords, xmode.get(), paint);
+    }
 
     /**
      *  Draw a set of sprites from the atlas. Each is specified by a tex rectangle in the
diff --git a/include/core/SkPaint.h b/include/core/SkPaint.h
index cb9f810..1a80ce3 100644
--- a/include/core/SkPaint.h
+++ b/include/core/SkPaint.h
@@ -539,8 +539,10 @@
                         paint
         @return         xfermode
     */
-    SkXfermode* setXfermode(SkXfermode* xfermode);
     void setXfermode(sk_sp<SkXfermode>);
+#ifdef SK_SUPPORT_LEGACY_XFERMODE_PTR
+    SkXfermode* setXfermode(SkXfermode* xfermode);
+#endif
 
     /** Create an xfermode based on the specified Mode, and assign it into the
         paint, returning the mode that was set. If the Mode is SrcOver, then
diff --git a/include/core/SkShader.h b/include/core/SkShader.h
index e2ebda5..0de53ad 100644
--- a/include/core/SkShader.h
+++ b/include/core/SkShader.h
@@ -404,7 +404,11 @@
      *  The caller is responsible for managing its reference-count for the xfer (if not null).
      */
     static sk_sp<SkShader> MakeComposeShader(sk_sp<SkShader> dst, sk_sp<SkShader> src,
+                                             sk_sp<SkXfermode> xfer);
+#ifdef SK_SUPPORT_LEGACY_XFERMODE_PTR
+    static sk_sp<SkShader> MakeComposeShader(sk_sp<SkShader> dst, sk_sp<SkShader> src,
                                              SkXfermode* xfer);
+#endif
 
     /** Call this to create a new shader that will draw with the specified bitmap.
      *
diff --git a/include/core/SkXfermode.h b/include/core/SkXfermode.h
index 2c4da5f..db8d570 100644
--- a/include/core/SkXfermode.h
+++ b/include/core/SkXfermode.h
@@ -126,6 +126,9 @@
      *  if the xfermode is NULL, and if so, treats it as kSrcOver_Mode.
      */
     static bool AsMode(const SkXfermode*, Mode* mode);
+    static bool AsMode(const sk_sp<SkXfermode>& xfer, Mode* mode) {
+        return AsMode(xfer.get(), mode);
+    }
 
     /**
      *  Returns true if the xfermode claims to be the specified Mode. This works
@@ -138,10 +141,22 @@
      *  }
      */
     static bool IsMode(const SkXfermode* xfer, Mode mode);
+    static bool IsMode(const sk_sp<SkXfermode>& xfer, Mode mode) {
+        return IsMode(xfer.get(), mode);
+    }
 
     /** Return an SkXfermode object for the specified mode.
      */
-    static SkXfermode* Create(Mode mode);
+    static sk_sp<SkXfermode> Make(Mode);
+#ifdef SK_SUPPORT_LEGACY_XFERMODE_PTR
+    static SkXfermode* Create(Mode mode) {
+        return Make(mode).release();
+    }
+    SK_ATTR_DEPRECATED("use AsMode(...)")
+    static bool IsMode(const SkXfermode* xfer, Mode* mode) {
+        return AsMode(xfer, mode);
+    }
+#endif
 
     /** Return a function pointer to a routine that applies the specified
         porter-duff transfer mode.
@@ -159,11 +174,6 @@
      */
     static bool ModeAsCoeff(Mode mode, Coeff* src, Coeff* dst);
 
-    SK_ATTR_DEPRECATED("use AsMode(...)")
-    static bool IsMode(const SkXfermode* xfer, Mode* mode) {
-        return AsMode(xfer, mode);
-    }
-
     /**
      * Returns whether or not the xfer mode can support treating coverage as alpha
      */
@@ -174,6 +184,9 @@
      *  the xfermode is NULL, and if so, treats it as kSrcOver_Mode.
      */
     static bool SupportsCoverageAsAlpha(const SkXfermode* xfer);
+    static bool SupportsCoverageAsAlpha(const sk_sp<SkXfermode>& xfer) {
+        return SupportsCoverageAsAlpha(xfer.get());
+    }
 
     enum SrcColorOpacity {
         // The src color is known to be opaque (alpha == 255)
@@ -198,6 +211,9 @@
      *  the xfermode is NULL, and if so, treats it as kSrcOver_Mode.
      */
     static bool IsOpaque(const SkXfermode* xfer, SrcColorOpacity opacityType);
+    static bool IsOpaque(const sk_sp<SkXfermode>& xfer, SrcColorOpacity opacityType) {
+        return IsOpaque(xfer.get(), opacityType);
+    }
 
 #if SK_SUPPORT_GPU
     /** Used by the SkXfermodeImageFilter to blend two colors via a GrFragmentProcessor.
@@ -228,6 +244,9 @@
     typedef void (*D32Proc)(const SkXfermode*, uint32_t dst[], const SkPM4f src[],
                             int count, const SkAlpha coverage[]);
     static D32Proc GetD32Proc(SkXfermode*, uint32_t flags);
+    static D32Proc GetD32Proc(const sk_sp<SkXfermode>& xfer, uint32_t flags) {
+        return GetD32Proc(xfer.get(), flags);
+    }
 
     enum D64Flags {
         kSrcIsOpaque_D64Flag  = 1 << 0,
@@ -237,6 +256,9 @@
     typedef void (*D64Proc)(const SkXfermode*, uint64_t dst[], const SkPM4f src[], int count,
                             const SkAlpha coverage[]);
     static D64Proc GetD64Proc(SkXfermode*, uint32_t flags);
+    static D64Proc GetD64Proc(const sk_sp<SkXfermode>& xfer, uint32_t flags) {
+        return GetD64Proc(xfer.get(), flags);
+    }
 
     enum LCDFlags {
         kSrcIsOpaque_LCDFlag    = 1 << 0,   // else src(s) may have alpha < 1
diff --git a/include/effects/SkArithmeticMode.h b/include/effects/SkArithmeticMode.h
index 9e8df2e..b160dc7 100644
--- a/include/effects/SkArithmeticMode.h
+++ b/include/effects/SkArithmeticMode.h
@@ -10,8 +10,7 @@
 
 #include "SkFlattenable.h"
 #include "SkScalar.h"
-
-class SkXfermode;
+#include "SkXfermode.h"
 
 class SK_API SkArithmeticMode {
 public:
@@ -22,9 +21,15 @@
      *  k1=k3=k4=0, k2=1.0 results in returning the src
      *  k1=k2=k4=0, k3=1.0 results in returning the dst
      */
+    static sk_sp<SkXfermode> Make(SkScalar k1, SkScalar k2, SkScalar k3, SkScalar k4,
+                                  bool enforcePMColor = true);
+#ifdef SK_SUPPORT_LEGACY_XFERMODE_PTR
     static SkXfermode* Create(SkScalar k1, SkScalar k2,
                               SkScalar k3, SkScalar k4,
-                              bool enforcePMColor = true);
+                              bool enforcePMColor = true) {
+        return Make(k1, k2, k3, k4, enforcePMColor).release();
+    }
+#endif
 
     SK_DECLARE_FLATTENABLE_REGISTRAR_GROUP();
 
diff --git a/include/effects/SkXfermodeImageFilter.h b/include/effects/SkXfermodeImageFilter.h
index 6df7903..f1e5d71 100644
--- a/include/effects/SkXfermodeImageFilter.h
+++ b/include/effects/SkXfermodeImageFilter.h
@@ -21,13 +21,19 @@
       */
 
 public:
+    static sk_sp<SkImageFilter> Make(sk_sp<SkXfermode> mode, SkImageFilter* background,
+                                     SkImageFilter* foreground, const CropRect* cropRect);
+    static sk_sp<SkImageFilter> Make(sk_sp<SkXfermode> mode, SkImageFilter* background) {
+        return Make(std::move(mode), background, nullptr, nullptr);
+    }
+#ifdef SK_SUPPORT_LEGACY_XFERMODE_PTR
     static SkImageFilter* Create(SkXfermode* mode, SkImageFilter* background,
                                  SkImageFilter* foreground = NULL,
                                  const CropRect* cropRect = NULL) {
-        SkImageFilter* inputs[2] = { background, foreground };
-        return new SkXfermodeImageFilter(mode, inputs, cropRect);
+        return Make(sk_ref_sp(mode), background, foreground, cropRect).release();
     }
-
+#endif
+    
     SK_TO_STRING_OVERRIDE()
     SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkXfermodeImageFilter)
 
@@ -43,12 +49,12 @@
 #endif
 
 protected:
-    SkXfermodeImageFilter(SkXfermode* mode, SkImageFilter* inputs[2],
+    SkXfermodeImageFilter(sk_sp<SkXfermode> mode, SkImageFilter* inputs[2],
                           const CropRect* cropRect);
     void flatten(SkWriteBuffer&) const override;
 
 private:
-    SkAutoTUnref<SkXfermode> fMode;
+    sk_sp<SkXfermode> fMode;
     typedef SkImageFilter INHERITED;
 };
 
diff --git a/public.bzl b/public.bzl
index 31aba98..be43304 100644
--- a/public.bzl
+++ b/public.bzl
@@ -524,6 +524,7 @@
     "SK_SUPPORT_LEGACY_COLORFILTER_PTR",
     "SK_SUPPORT_LEGACY_CREATESHADER_PTR",
     "SK_SUPPORT_LEGACY_PICTURE_PTR",
+    "SK_SUPPORT_LEGACY_XFERMODE_PTR",
 ]
 
 ################################################################################
diff --git a/samplecode/PerlinPatch.cpp b/samplecode/PerlinPatch.cpp
index c5a0db8..8f7e28d 100644
--- a/samplecode/PerlinPatch.cpp
+++ b/samplecode/PerlinPatch.cpp
@@ -138,8 +138,8 @@
             { fTexX + texWidth, fTexY + texHeight},
             { fTexX - texWidth, fTexY + texHeight}}
         ;
-
-        SkAutoTUnref<SkXfermode> xfer(SkXfermode::Create(SkXfermode::kSrc_Mode));
+        
+        sk_sp<SkXfermode> xfer(SkXfermode::Make(SkXfermode::kSrc_Mode));
 
         SkScalar scaleFreq = 2.0;
         fShader1 = SkPerlinNoiseShader2::MakeImprovedNoise(fXFreq/scaleFreq, fYFreq/scaleFreq, 4,
diff --git a/samplecode/SampleAARectModes.cpp b/samplecode/SampleAARectModes.cpp
index 4339223..8066e68 100644
--- a/samplecode/SampleAARectModes.cpp
+++ b/samplecode/SampleAARectModes.cpp
@@ -35,9 +35,7 @@
 const SkScalar W = SkIntToScalar(gWidth);
 const SkScalar H = SkIntToScalar(gHeight);
 
-static SkScalar drawCell(SkCanvas* canvas, SkXfermode* mode,
-                         SkAlpha a0, SkAlpha a1) {
-
+static SkScalar drawCell(SkCanvas* canvas, const sk_sp<SkXfermode>& mode, SkAlpha a0, SkAlpha a1) {
     SkPaint paint;
     paint.setAntiAlias(true);
 
@@ -109,17 +107,15 @@
                     canvas->translate(W * 5, 0);
                     canvas->save();
                 }
-                SkXfermode* mode = SkXfermode::Create(gModes[i].fMode);
+                sk_sp<SkXfermode> mode = SkXfermode::Make(gModes[i].fMode);
 
                 canvas->drawRect(bounds, fBGPaint);
                 canvas->saveLayer(&bounds, nullptr);
-                SkScalar dy = drawCell(canvas, mode,
-                                       gAlphaValue[alpha & 1],
+                SkScalar dy = drawCell(canvas, mode, gAlphaValue[alpha & 1],
                                        gAlphaValue[alpha & 2]);
                 canvas->restore();
 
                 canvas->translate(0, dy * 5 / 4);
-                SkSafeUnref(mode);
             }
             canvas->restore();
             canvas->restore();
diff --git a/samplecode/SampleAll.cpp b/samplecode/SampleAll.cpp
index d3be968..aa08261 100644
--- a/samplecode/SampleAll.cpp
+++ b/samplecode/SampleAll.cpp
@@ -382,7 +382,6 @@
         SkScalar sigma = SkBlurMask::ConvertRadiusToSigma(SkIntToScalar(12)/5);
         SkMaskFilter* embossFilter = SkEmbossMaskFilter::Create(sigma, light);
 
-        SkXfermode* xfermode = SkXfermode::Create(SkXfermode::kXor_Mode);
         auto lightingFilter = SkColorMatrixFilter::MakeLightingFilter(
             0xff89bc45, 0xff112233);
 
@@ -404,7 +403,7 @@
         paint.setColor(SK_ColorGREEN);
         paint.setStrokeWidth(SkIntToScalar(10));
         paint.setStyle(SkPaint::kStroke_Style);
-        paint.setXfermode(xfermode)->unref();
+        paint.setXfermode(SkXfermode::Make(SkXfermode::kXor_Mode));
         paint.setColorFilter(lightingFilter);
         canvas->drawLine(start.fX, start.fY, stop.fX, stop.fY, paint); // should not be green
         paint.setXfermode(nullptr);
@@ -505,8 +504,8 @@
         SkColor colors2[] = {SK_ColorBLACK,  SkColorSetARGB(0x80, 0, 0, 0)};
         auto shaderB = SkGradientShader::MakeLinear(pts, colors2, nullptr,
             2, SkShader::kClamp_TileMode);
-        SkAutoTUnref<SkXfermode> mode(SkXfermode::Create(SkXfermode::kDstIn_Mode));
-        return SkShader::MakeComposeShader(shaderA, shaderB, mode);
+        return SkShader::MakeComposeShader(std::move(shaderA), std::move(shaderB),
+                                           SkXfermode::Make(SkXfermode::kDstIn_Mode));
     }
 
     virtual void startTest() {
diff --git a/samplecode/SampleFilterFuzz.cpp b/samplecode/SampleFilterFuzz.cpp
index 18806c9..d5fbc97 100644
--- a/samplecode/SampleFilterFuzz.cpp
+++ b/samplecode/SampleFilterFuzz.cpp
@@ -582,10 +582,9 @@
         filter = SkDownSampleImageFilter::Create(make_scalar());
         break;
     case XFERMODE:
-    {
-        SkAutoTUnref<SkXfermode> mode(SkXfermode::Create(make_xfermode()));
-        filter = SkXfermodeImageFilter::Create(mode, make_image_filter(), make_image_filter());
-    }
+        filter = SkXfermodeImageFilter::Make(SkXfermode::Make(make_xfermode()),
+                                             make_image_filter(), make_image_filter(),
+                                             nullptr).release();
         break;
     case OFFSET:
         filter = SkOffsetImageFilter::Create(make_scalar(), make_scalar(), make_image_filter());
diff --git a/samplecode/SampleHairModes.cpp b/samplecode/SampleHairModes.cpp
index 085581c..fd937e2 100644
--- a/samplecode/SampleHairModes.cpp
+++ b/samplecode/SampleHairModes.cpp
@@ -35,8 +35,7 @@
 const SkScalar W = SkIntToScalar(gWidth);
 const SkScalar H = SkIntToScalar(gHeight);
 
-static SkScalar drawCell(SkCanvas* canvas, SkXfermode* mode, SkAlpha a0, SkAlpha a1) {
-
+static SkScalar drawCell(SkCanvas* canvas, sk_sp<SkXfermode> mode, SkAlpha a0, SkAlpha a1) {
     SkPaint paint;
     paint.setAntiAlias(true);
 
@@ -105,17 +104,14 @@
                     canvas->translate(W * 5, 0);
                     canvas->save();
                 }
-                SkXfermode* mode = SkXfermode::Create(gModes[i].fMode);
-
                 canvas->drawRect(bounds, fBGPaint);
                 canvas->saveLayer(&bounds, nullptr);
-                SkScalar dy = drawCell(canvas, mode,
+                SkScalar dy = drawCell(canvas, SkXfermode::Make(gModes[i].fMode),
                                        gAlphaValue[alpha & 1],
                                        gAlphaValue[alpha & 2]);
                 canvas->restore();
 
                 canvas->translate(0, dy * 5 / 4);
-                SkSafeUnref(mode);
             }
             canvas->restore();
             canvas->restore();
diff --git a/samplecode/SampleShaders.cpp b/samplecode/SampleShaders.cpp
index 2ea6f0a..608199d 100644
--- a/samplecode/SampleShaders.cpp
+++ b/samplecode/SampleShaders.cpp
@@ -32,11 +32,10 @@
     auto shaderA = SkGradientShader::MakeLinear(pts, colors, nullptr, 2, SkShader::kClamp_TileMode);
 
     auto shaderB = SkShader::MakeBitmapShader(bm,
-                        SkShader::kClamp_TileMode, SkShader::kClamp_TileMode);
+                                              SkShader::kClamp_TileMode, SkShader::kClamp_TileMode);
 
-    SkAutoTUnref<SkXfermode> mode(SkXfermode::Create(SkXfermode::kDstIn_Mode));
-
-    return SkShader::MakeComposeShader(std::move(shaderB), std::move(shaderA), mode);
+    return SkShader::MakeComposeShader(std::move(shaderB), std::move(shaderA),
+                                       SkXfermode::Make(SkXfermode::kDstIn_Mode));
 }
 
 class ShaderView : public SampleView {
@@ -62,9 +61,8 @@
         colors[1] = SkColorSetARGB(0x80, 0, 0, 0);
         auto shaderB = SkGradientShader::MakeLinear(pts, colors, nullptr, 2, SkShader::kClamp_TileMode);
 
-        SkAutoTUnref<SkXfermode> mode(SkXfermode::Create(SkXfermode::kDstIn_Mode));
-
-        fShader = SkShader::MakeComposeShader(std::move(shaderA), std::move(shaderB), mode);
+        fShader = SkShader::MakeComposeShader(std::move(shaderA), std::move(shaderB),
+                                              SkXfermode::Make(SkXfermode::kDstIn_Mode));
     }
 
 protected:
diff --git a/samplecode/SampleXfermodesBlur.cpp b/samplecode/SampleXfermodesBlur.cpp
index 52419a0..cab1339 100644
--- a/samplecode/SampleXfermodesBlur.cpp
+++ b/samplecode/SampleXfermodesBlur.cpp
@@ -39,7 +39,7 @@
     SkBitmap    fBG;
     SkBitmap    fSrcB, fDstB;
 
-    void draw_mode(SkCanvas* canvas, SkXfermode* mode, int alpha,
+    void draw_mode(SkCanvas* canvas, sk_sp<SkXfermode> mode, int alpha,
                    SkScalar x, SkScalar y) {
         SkPaint p;
         SkMaskFilter* mf = SkBlurMaskFilter::Create(kNormal_SkBlurStyle,
@@ -58,7 +58,7 @@
         r.offset(x, y);
         canvas->drawOval(r, p);
 
-        p.setXfermode(mode);
+        p.setXfermode(std::move(mode));
 
         // draw a square overlapping the circle
         // in the lower right of the canvas
@@ -163,8 +163,6 @@
         for (int twice = 0; twice < 2; twice++) {
             SkScalar x = x0, y = 0;
             for (size_t i = 0; i < SK_ARRAY_COUNT(gModes); i++) {
-                SkXfermode* mode = SkXfermode::Create(gModes[i].fMode);
-                SkAutoUnref aur(mode);
                 SkRect r;
                 r.set(x, y, x+w, y+h);
 
@@ -174,7 +172,8 @@
                 canvas->drawRect(r, p);
 
                 canvas->saveLayer(&r, nullptr);
-                draw_mode(canvas, mode, twice ? 0x88 : 0xFF, r.fLeft, r.fTop);
+                draw_mode(canvas, SkXfermode::Make(gModes[i].fMode),
+                          twice ? 0x88 : 0xFF, r.fLeft, r.fTop);
                 canvas->restore();
 
                 r.inset(-SK_ScalarHalf, -SK_ScalarHalf);
diff --git a/src/core/SkBitmapProcShader.cpp b/src/core/SkBitmapProcShader.cpp
index 0a3c0ea..14114c0 100644
--- a/src/core/SkBitmapProcShader.cpp
+++ b/src/core/SkBitmapProcShader.cpp
@@ -132,7 +132,7 @@
         // To implement the old shadeSpan entry-point, we need to efficiently convert our native
         // floats into SkPMColor. The SkXfermode::D32Procs do exactly that.
         //
-        sk_sp<SkXfermode> xfer(SkXfermode::Create(SkXfermode::kSrc_Mode));
+        sk_sp<SkXfermode> xfer(SkXfermode::Make(SkXfermode::kSrc_Mode));
         fXferProc = SkXfermode::GetD32Proc(xfer.get(), 0);
     }
 
diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp
index 258343a..f177744 100644
--- a/src/core/SkCanvas.cpp
+++ b/src/core/SkCanvas.cpp
@@ -481,7 +481,7 @@
              */
             SkPaint tmp;
             tmp.setImageFilter(fPaint->getImageFilter());
-            tmp.setXfermode(fPaint->getXfermode());
+            tmp.setXfermode(sk_ref_sp(fPaint->getXfermode()));
             SkRect storage;
             if (rawBounds) {
                 // Make rawBounds include all paint outsets except for those due to image filters.
diff --git a/src/core/SkComposeShader.cpp b/src/core/SkComposeShader.cpp
index 4d3e4e5..f39f20c 100644
--- a/src/core/SkComposeShader.cpp
+++ b/src/core/SkComposeShader.cpp
@@ -16,19 +16,6 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 
-SkComposeShader::SkComposeShader(sk_sp<SkShader> sA, sk_sp<SkShader> sB, SkXfermode* mode)
-    : fShaderA(std::move(sA))
-    , fShaderB(std::move(sB))
-{
-    // mode may be null
-    fMode = mode;
-    SkSafeRef(mode);
-}
-
-SkComposeShader::~SkComposeShader() {
-    SkSafeUnref(fMode);
-}
-
 size_t SkComposeShader::onContextSize(const ContextRec& rec) const {
     return sizeof(ComposeShaderContext)
         + fShaderA->contextSize(rec)
@@ -55,17 +42,17 @@
 SkFlattenable* SkComposeShader::CreateProc(SkReadBuffer& buffer) {
     sk_sp<SkShader> shaderA(buffer.readShader());
     sk_sp<SkShader> shaderB(buffer.readShader());
-    SkAutoTUnref<SkXfermode> mode(buffer.readXfermode());
+    sk_sp<SkXfermode> mode(buffer.readXfermode());
     if (!shaderA || !shaderB) {
         return nullptr;
     }
-    return new SkComposeShader(std::move(shaderA), std::move(shaderB), mode);
+    return new SkComposeShader(std::move(shaderA), std::move(shaderB), std::move(mode));
 }
 
 void SkComposeShader::flatten(SkWriteBuffer& buffer) const {
     buffer.writeFlattenable(fShaderA.get());
     buffer.writeFlattenable(fShaderB.get());
-    buffer.writeFlattenable(fMode);
+    buffer.writeFlattenable(fMode.get());
 }
 
 template <typename T> void safe_call_destructor(T* obj) {
@@ -120,7 +107,7 @@
     if (rec) {
         rec->fShaderA = fShaderA.get();
         rec->fShaderB = fShaderB.get();
-        rec->fMode = fMode;
+        rec->fMode = fMode.get();
     }
     return true;
 }
@@ -133,7 +120,7 @@
 void SkComposeShader::ComposeShaderContext::shadeSpan(int x, int y, SkPMColor result[], int count) {
     SkShader::Context* shaderContextA = fShaderContextA;
     SkShader::Context* shaderContextB = fShaderContextB;
-    SkXfermode*        mode = static_cast<const SkComposeShader&>(fShader).fMode;
+    SkXfermode*        mode = static_cast<const SkComposeShader&>(fShader).fMode.get();
     unsigned           scale = SkAlpha255To256(this->getPaintAlpha());
 
     SkPMColor   tmp[TMP_COLOR_COUNT];
@@ -255,15 +242,14 @@
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
 sk_sp<SkShader> SkShader::MakeComposeShader(sk_sp<SkShader> dst, sk_sp<SkShader> src,
-                                            SkXfermode* xfer) {
+                                            sk_sp<SkXfermode> xfer) {
     if (!dst || !src) {
         return nullptr;
     }
-    return sk_make_sp<SkComposeShader>(std::move(dst), std::move(src), xfer);
+    return sk_make_sp<SkComposeShader>(std::move(dst), std::move(src), std::move(xfer));
 }
 
 sk_sp<SkShader> SkShader::MakeComposeShader(sk_sp<SkShader> dst, sk_sp<SkShader> src,
                                             SkXfermode::Mode mode) {
-    SkAutoTUnref<SkXfermode> xfer(SkXfermode::Create(mode));
-    return MakeComposeShader(std::move(dst), std::move(src), xfer);
+    return MakeComposeShader(std::move(dst), std::move(src), SkXfermode::Make(mode));
 }
diff --git a/src/core/SkComposeShader.h b/src/core/SkComposeShader.h
index 8ea7c67..4d561fa 100644
--- a/src/core/SkComposeShader.h
+++ b/src/core/SkComposeShader.h
@@ -5,13 +5,11 @@
  * found in the LICENSE file.
  */
 
-
 #ifndef SkComposeShader_DEFINED
 #define SkComposeShader_DEFINED
 
 #include "SkShader.h"
-
-class SkXfermode;
+#include "SkXfermode.h"
 
 ///////////////////////////////////////////////////////////////////////////////////////////
 
@@ -30,8 +28,11 @@
         @param mode     The xfermode that combines the colors from the two shaders. If mode
                         is null, then SRC_OVER is assumed.
     */
-    SkComposeShader(sk_sp<SkShader> sA, sk_sp<SkShader> sB, SkXfermode* mode = NULL);
-    virtual ~SkComposeShader();
+    SkComposeShader(sk_sp<SkShader> sA, sk_sp<SkShader> sB, sk_sp<SkXfermode> mode)
+        : fShaderA(std::move(sA))
+        , fShaderB(std::move(sB))
+        , fMode(std::move(mode))
+    {}
 
 #if SK_SUPPORT_GPU
     const GrFragmentProcessor*  asFragmentProcessor(GrContext*,
@@ -72,15 +73,15 @@
     SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkComposeShader)
 
 protected:
-    SkComposeShader(SkReadBuffer& );
+    SkComposeShader(SkReadBuffer&);
     void flatten(SkWriteBuffer&) const override;
     size_t onContextSize(const ContextRec&) const override;
     Context* onCreateContext(const ContextRec&, void*) const override;
 
 private:
-    sk_sp<SkShader> fShaderA;
-    sk_sp<SkShader> fShaderB;
-    SkXfermode*     fMode;
+    sk_sp<SkShader>     fShaderA;
+    sk_sp<SkShader>     fShaderB;
+    sk_sp<SkXfermode>   fMode;
 
     typedef SkShader INHERITED;
 };
diff --git a/src/core/SkDraw.cpp b/src/core/SkDraw.cpp
index b4bcc2e..c63c90f 100644
--- a/src/core/SkDraw.cpp
+++ b/src/core/SkDraw.cpp
@@ -32,6 +32,7 @@
 #include "SkTLazy.h"
 #include "SkUtils.h"
 #include "SkVertState.h"
+#include "SkXfermode.h"
 
 #include "SkBitmapProcShader.h"
 #include "SkDrawProcs.h"
@@ -1900,15 +1901,9 @@
         } else {
             // colors * texture
             SkASSERT(shader);
-            bool releaseMode = false;
-            if (nullptr == xmode) {
-                xmode = SkXfermode::Create(SkXfermode::kModulate_Mode);
-                releaseMode = true;
-            }
-            p.setShader(sk_make_sp<SkComposeShader>(triShader, sk_ref_sp(shader), xmode));
-            if (releaseMode) {
-                xmode->unref();
-            }
+            sk_sp<SkXfermode> xfer = xmode ? sk_ref_sp(xmode)
+                                           : SkXfermode::Make(SkXfermode::kModulate_Mode);
+            p.setShader(SkShader::MakeComposeShader(triShader, sk_ref_sp(shader), std::move(xfer)));
         }
     }
 
diff --git a/src/core/SkPaint.cpp b/src/core/SkPaint.cpp
index 8d62a6a..e4eca0c 100644
--- a/src/core/SkPaint.cpp
+++ b/src/core/SkPaint.cpp
@@ -380,7 +380,9 @@
 #ifdef SK_SUPPORT_LEGACY_COLORFILTER_PTR
 SET_PTR(ColorFilter)
 #endif
+#ifdef SK_SUPPORT_LEGACY_XFERMODE_PTR
 SET_PTR(Xfermode)
+#endif
 #ifdef SK_SUPPORT_LEGACY_PATHEFFECT_PTR
 SET_PTR(PathEffect)
 #endif
@@ -395,8 +397,8 @@
 #endif
 
 SkXfermode* SkPaint::setXfermodeMode(SkXfermode::Mode mode) {
-    fXfermode.reset(SkXfermode::Create(mode));
-    return fXfermode.get();
+    fXfermode = SkXfermode::Make(mode);
+    return fXfermode.get(); // can/should we change this API to be void, like the other setters?
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -1927,7 +1929,7 @@
     if (flatFlags & kHasEffects_FlatFlag) {
         this->setPathEffect(buffer.readPathEffect());
         this->setShader(buffer.readShader());
-        SkSafeUnref(this->setXfermode(buffer.readXfermode()));
+        this->setXfermode(buffer.readXfermode());
         SkSafeUnref(this->setMaskFilter(buffer.readMaskFilter()));
         this->setColorFilter(buffer.readColorFilter());
         this->setRasterizer(buffer.readRasterizer());
diff --git a/src/core/SkPicturePlayback.cpp b/src/core/SkPicturePlayback.cpp
index f21ac32..774c2c0 100644
--- a/src/core/SkPicturePlayback.cpp
+++ b/src/core/SkPicturePlayback.cpp
@@ -307,15 +307,15 @@
                 texCoords = (const SkPoint*)reader->skip(SkPatchUtils::kNumCorners *
                                                          sizeof(SkPoint));
             }
-            SkAutoTUnref<SkXfermode> xfer;
+            sk_sp<SkXfermode> xfer;
             if (flag & DRAW_VERTICES_HAS_XFER) {
                 int mode = reader->readInt();
                 if (mode < 0 || mode > SkXfermode::kLastMode) {
                     mode = SkXfermode::kModulate_Mode;
                 }
-                xfer.reset(SkXfermode::Create((SkXfermode::Mode)mode));
+                xfer = SkXfermode::Make((SkXfermode::Mode)mode);
             }
-            canvas->drawPatch(cubics, colors, texCoords, xfer, paint);
+            canvas->drawPatch(cubics, colors, texCoords, std::move(xfer), paint);
         } break;
         case DRAW_PATH: {
             const SkPaint& paint = *fPictureData->getPaint(reader);
@@ -435,7 +435,7 @@
             canvas->drawTextOnPath(text.text(), text.length(), path, &matrix, paint);
         } break;
         case DRAW_VERTICES: {
-            SkAutoTUnref<SkXfermode> xfer;
+            sk_sp<SkXfermode> xfer;
             const SkPaint& paint = *fPictureData->getPaint(reader);
             DrawVertexFlags flags = (DrawVertexFlags)reader->readInt();
             SkCanvas::VertexMode vmode = (SkCanvas::VertexMode)reader->readInt();
@@ -460,7 +460,7 @@
                 if (mode < 0 || mode > SkXfermode::kLastMode) {
                     mode = SkXfermode::kModulate_Mode;
                 }
-                xfer.reset(SkXfermode::Create((SkXfermode::Mode)mode));
+                xfer = SkXfermode::Make((SkXfermode::Mode)mode);
             }
             canvas->drawVertices(vmode, vCount, verts, texs, colors, xfer, indices, iCount, paint);
         } break;
diff --git a/src/core/SkReadBuffer.h b/src/core/SkReadBuffer.h
index 46f6b81..960f2a3 100644
--- a/src/core/SkReadBuffer.h
+++ b/src/core/SkReadBuffer.h
@@ -145,7 +145,9 @@
         return sk_sp<SkRasterizer>(this->readFlattenable<SkRasterizer>());
     }
     sk_sp<SkShader> readShader()     { return sk_sp<SkShader>(this->readFlattenable<SkShader>()); }
-    SkXfermode*    readXfermode()    { return this->readFlattenable<SkXfermode>(); }
+    sk_sp<SkXfermode> readXfermode() {
+        return sk_sp<SkXfermode>(this->readFlattenable<SkXfermode>());
+    }
 
     /**
      *  Like readFlattenable() but explicitly just skips the data that was written for the
diff --git a/src/core/SkShader.cpp b/src/core/SkShader.cpp
index 75fa6fc6..e4cbc7b 100644
--- a/src/core/SkShader.cpp
+++ b/src/core/SkShader.cpp
@@ -453,3 +453,11 @@
     return this->makeWithColorFilter(sk_ref_sp(filter)).release();
 }
 #endif
+
+#ifdef SK_SUPPORT_LEGACY_XFERMODE_PTR
+#include "SkXfermode.h"
+sk_sp<SkShader> SkShader::MakeComposeShader(sk_sp<SkShader> dst, sk_sp<SkShader> src,
+                                            SkXfermode* xfer) {
+    return MakeComposeShader(std::move(dst), std::move(src), sk_ref_sp(xfer));
+}
+#endif
diff --git a/src/core/SkXfermode.cpp b/src/core/SkXfermode.cpp
index 98eb796..01d6dc5 100644
--- a/src/core/SkXfermode.cpp
+++ b/src/core/SkXfermode.cpp
@@ -1097,7 +1097,7 @@
     if (!buffer.validate(mode32 < SK_ARRAY_COUNT(gProcCoeffs))) {
         return nullptr;
     }
-    return SkXfermode::Create((SkXfermode::Mode)mode32);
+    return SkXfermode::Make((SkXfermode::Mode)mode32).release();
 }
 
 void SkProcCoeffXfermode::flatten(SkWriteBuffer& buffer) const {
@@ -1305,7 +1305,7 @@
 
 SK_DECLARE_STATIC_ONCE_PTR(SkXfermode, cached[SkXfermode::kLastMode + 1]);
 
-SkXfermode* SkXfermode::Create(Mode mode) {
+sk_sp<SkXfermode> SkXfermode::Make(Mode mode) {
     SkASSERT(SK_ARRAY_COUNT(gProcCoeffs) == kModeCount);
 
     if ((unsigned)mode >= kModeCount) {
@@ -1319,7 +1319,7 @@
         return nullptr;
     }
 
-    return SkSafeRef(cached[mode].get([=]{
+    return sk_ref_sp(cached[mode].get([=]{
         ProcCoeff rec = gProcCoeffs[mode];
         if (auto xfermode = SkOpts::create_xfermode(rec, mode)) {
             return xfermode;
diff --git a/src/effects/SkArithmeticMode.cpp b/src/effects/SkArithmeticMode.cpp
index 32238f1..b225e6d 100644
--- a/src/effects/SkArithmeticMode.cpp
+++ b/src/effects/SkArithmeticMode.cpp
@@ -60,7 +60,7 @@
     const SkScalar k3 = buffer.readScalar();
     const SkScalar k4 = buffer.readScalar();
     const bool enforcePMColor = buffer.readBool();
-    return SkArithmeticMode::Create(k1, k2, k3, k4, enforcePMColor);
+    return SkArithmeticMode::Make(k1, k2, k3, k4, enforcePMColor).release();
 }
 
 static int pinToByte(int value) {
@@ -137,18 +137,16 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 
-SkXfermode* SkArithmeticMode::Create(SkScalar k1, SkScalar k2,
-                                     SkScalar k3, SkScalar k4,
-                                     bool enforcePMColor) {
+sk_sp<SkXfermode> SkArithmeticMode::Make(SkScalar k1, SkScalar k2, SkScalar k3, SkScalar k4,
+                                         bool enforcePMColor) {
     if (SkScalarNearlyZero(k1) && SkScalarNearlyEqual(k2, SK_Scalar1) &&
         SkScalarNearlyZero(k3) && SkScalarNearlyZero(k4)) {
-        return SkXfermode::Create(SkXfermode::kSrc_Mode);
+        return SkXfermode::Make(SkXfermode::kSrc_Mode);
     } else if (SkScalarNearlyZero(k1) && SkScalarNearlyZero(k2) &&
                SkScalarNearlyEqual(k3, SK_Scalar1) && SkScalarNearlyZero(k4)) {
-        return SkXfermode::Create(SkXfermode::kDst_Mode);
+        return SkXfermode::Make(SkXfermode::kDst_Mode);
     }
-
-    return new SkArithmeticMode_scalar(k1, k2, k3, k4, enforcePMColor);
+    return sk_make_sp<SkArithmeticMode_scalar>(k1, k2, k3, k4, enforcePMColor);
 }
 
 
diff --git a/src/effects/SkAvoidXfermode.cpp b/src/effects/SkAvoidXfermode.cpp
index d9678f5..4b7e636 100644
--- a/src/effects/SkAvoidXfermode.cpp
+++ b/src/effects/SkAvoidXfermode.cpp
@@ -25,7 +25,7 @@
     const SkColor color = buffer.readColor();
     const unsigned tolerance = buffer.readUInt();
     const unsigned mode = buffer.readUInt();
-    return Create(color, tolerance, (Mode)mode);
+    return Make(color, tolerance, (Mode)mode).release();
 }
 
 void SkAvoidXfermode::flatten(SkWriteBuffer& buffer) const {
diff --git a/src/effects/SkLayerDrawLooper.cpp b/src/effects/SkLayerDrawLooper.cpp
index 0a5c4f9..b3430bb 100644
--- a/src/effects/SkLayerDrawLooper.cpp
+++ b/src/effects/SkLayerDrawLooper.cpp
@@ -104,7 +104,7 @@
         dst->setColorFilter(sk_ref_sp(src.getColorFilter()));
     }
     if (bits & kXfermode_Bit) {
-        dst->setXfermode(src.getXfermode());
+        dst->setXfermode(sk_ref_sp(src.getXfermode()));
     }
 
     // we don't override these
diff --git a/src/effects/SkPixelXorXfermode.cpp b/src/effects/SkPixelXorXfermode.cpp
index c69fe09..4ad3f1b 100644
--- a/src/effects/SkPixelXorXfermode.cpp
+++ b/src/effects/SkPixelXorXfermode.cpp
@@ -27,7 +27,7 @@
 }
 
 SkFlattenable* SkPixelXorXfermode::CreateProc(SkReadBuffer& buffer) {
-    return Create(buffer.readColor());
+    return Make(buffer.readColor()).release();
 }
 
 #ifndef SK_IGNORE_TO_STRING
diff --git a/src/effects/SkXfermodeImageFilter.cpp b/src/effects/SkXfermodeImageFilter.cpp
index 8f7fdc7..8cd7512 100644
--- a/src/effects/SkXfermodeImageFilter.cpp
+++ b/src/effects/SkXfermodeImageFilter.cpp
@@ -23,22 +23,30 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 
-SkXfermodeImageFilter::SkXfermodeImageFilter(SkXfermode* mode,
+sk_sp<SkImageFilter> SkXfermodeImageFilter::Make(sk_sp<SkXfermode> mode, SkImageFilter* background,
+                                                 SkImageFilter* foreground,
+                                                 const CropRect* cropRect) {
+    SkImageFilter* inputs[2] = { background, foreground };
+    return sk_sp<SkImageFilter>(new SkXfermodeImageFilter(mode, inputs, cropRect));
+}
+
+SkXfermodeImageFilter::SkXfermodeImageFilter(sk_sp<SkXfermode> mode,
                                              SkImageFilter* inputs[2],
                                              const CropRect* cropRect)
     : INHERITED(2, inputs, cropRect)
-    , fMode(SkSafeRef(mode)) {
-}
+    , fMode(std::move(mode))
+{}
 
 SkFlattenable* SkXfermodeImageFilter::CreateProc(SkReadBuffer& buffer) {
     SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 2);
-    SkAutoTUnref<SkXfermode> mode(buffer.readXfermode());
-    return Create(mode, common.getInput(0), common.getInput(1), &common.cropRect());
+    sk_sp<SkXfermode> mode(buffer.readXfermode());
+    return Make(std::move(mode), common.getInput(0),
+                common.getInput(1), &common.cropRect()).release();
 }
 
 void SkXfermodeImageFilter::flatten(SkWriteBuffer& buffer) const {
     this->INHERITED::flatten(buffer);
-    buffer.writeFlattenable(fMode);
+    buffer.writeFlattenable(fMode.get());
 }
 
 bool SkXfermodeImageFilter::onFilterImageDeprecated(Proxy* proxy,
diff --git a/src/gpu/GrSWMaskHelper.cpp b/src/gpu/GrSWMaskHelper.cpp
index 396d2be..0e1fd3e 100644
--- a/src/gpu/GrSWMaskHelper.cpp
+++ b/src/gpu/GrSWMaskHelper.cpp
@@ -105,17 +105,13 @@
                           bool antiAlias, uint8_t alpha) {
     SkPaint paint;
 
-    SkXfermode* mode = SkXfermode::Create(op_to_mode(op));
-
     SkASSERT(kNone_CompressionMode == fCompressionMode);
 
-    paint.setXfermode(mode);
+    paint.setXfermode(SkXfermode::Make(op_to_mode(op)));
     paint.setAntiAlias(antiAlias);
     paint.setColor(SkColorSetARGB(alpha, alpha, alpha, alpha));
 
     fDraw.drawRect(rect, paint);
-
-    SkSafeUnref(mode);
 }
 
 /**
diff --git a/src/utils/SkLua.cpp b/src/utils/SkLua.cpp
index 01bf507..9af5bfd 100644
--- a/src/utils/SkLua.cpp
+++ b/src/utils/SkLua.cpp
@@ -1098,7 +1098,7 @@
 
 static int lpaint_setXfermode(lua_State* L) {
     SkPaint* paint = get_obj<SkPaint>(L, 1);
-    paint->setXfermode(get_ref<SkXfermode>(L, 2));
+    paint->setXfermode(sk_ref_sp(get_ref<SkXfermode>(L, 2)));
     return 0;
 }
 
diff --git a/tests/BlendTest.cpp b/tests/BlendTest.cpp
index 612492d..ca9e46e 100644
--- a/tests/BlendTest.cpp
+++ b/tests/BlendTest.cpp
@@ -80,7 +80,7 @@
         if (mode == SkXfermode::kSrcOver_Mode) {
             return;  // TODO: can't create a SrcOver xfermode.
         }
-        SkAutoTUnref<SkXfermode> xfermode(SkXfermode::Create(mode));
+        auto xfermode(SkXfermode::Make(mode));
         SkASSERT(xfermode);
         // We'll test all alphas and legal color values, assuming all colors work the same.
         // This is not true for non-separable blend modes, but this test still can't hurt.
diff --git a/tests/GrGetCoeffBlendKnownComponentsTest.cpp b/tests/GrGetCoeffBlendKnownComponentsTest.cpp
index c55b02b..38dfb30 100644
--- a/tests/GrGetCoeffBlendKnownComponentsTest.cpp
+++ b/tests/GrGetCoeffBlendKnownComponentsTest.cpp
@@ -31,7 +31,7 @@
     SkRandom random;
     for (int i = 0; i < SkXfermode::kLastCoeffMode; ++i) {
         SkXfermode::Mode mode = (SkXfermode::Mode)i;
-        SkAutoTUnref<SkXfermode> xm(SkXfermode::Create(mode));
+        auto xm(SkXfermode::Make(mode));
         SkXfermode::Coeff srcCoeff, dstCoeff;
         SkAssertResult(SkXfermode::ModeAsCoeff(mode, &srcCoeff, &dstCoeff));
         for (int j = 0; j < 1000; ++j) {
@@ -44,7 +44,7 @@
                                            src, kRGBA_GrColorComponentFlags,
                                            dst, kRGBA_GrColorComponentFlags,
                                            &outColor, &outFlags);
-            GrColor baselineColor = make_baseline_color(src, dst, xm);
+            GrColor baselineColor = make_baseline_color(src, dst, xm.get());
             if (SkAbs32(GrColorUnpackA(baselineColor) - GrColorUnpackA(outColor)) > 1 ||
                 SkAbs32(GrColorUnpackR(baselineColor) - GrColorUnpackR(outColor)) > 1 ||
                 SkAbs32(GrColorUnpackG(baselineColor) - GrColorUnpackG(outColor)) > 1 ||
diff --git a/tests/ImageFilterTest.cpp b/tests/ImageFilterTest.cpp
index e4ab1ac..9d20396 100644
--- a/tests/ImageFilterTest.cpp
+++ b/tests/ImageFilterTest.cpp
@@ -191,8 +191,8 @@
             five, five, pictureFilter.get(), cropRect));
         this->addFilter("paint and blur", SkBlurImageFilter::Create(
             five, five, paintFilter.get(), cropRect));
-        this->addFilter("xfermode", SkXfermodeImageFilter::Create(
-            SkXfermode::Create(SkXfermode::kSrc_Mode), input, input, cropRect));
+        this->addFilter("xfermode", SkXfermodeImageFilter::Make(
+            SkXfermode::Make(SkXfermode::kSrc_Mode), input, input, cropRect).release());
     }
     int count() const { return fFilters.count(); }
     SkImageFilter* getFilter(int index) const { return fFilters[index].fFilter.get(); }
@@ -799,16 +799,15 @@
     // Regardless of which order they appear in, the image filter bounds should
     // be combined correctly.
     {
-        SkAutoTUnref<SkImageFilter> composite(SkXfermodeImageFilter::Create(
-            nullptr, offset.get(), nullptr));
+        sk_sp<SkImageFilter> composite(SkXfermodeImageFilter::Make(nullptr, offset.get()));
         SkRect bounds = SkRect::MakeWH(100, 100);
         // Intentionally aliasing here, as that's what the real callers do.
         bounds = composite->computeFastBounds(bounds);
         REPORTER_ASSERT(reporter, bounds == SkRect::MakeWH(150, 100));
     }
     {
-        SkAutoTUnref<SkImageFilter> composite(SkXfermodeImageFilter::Create(
-            nullptr, nullptr, offset.get()));
+        sk_sp<SkImageFilter> composite(SkXfermodeImageFilter::Make(nullptr, nullptr,
+                                                                   offset.get(), nullptr));
         SkRect bounds = SkRect::MakeWH(100, 100);
         // Intentionally aliasing here, as that's what the real callers do.
         bounds = composite->computeFastBounds(bounds);
@@ -1249,13 +1248,10 @@
 
     // Check that an xfermode image filter whose input has been cropped out still draws the other
     // input. Also check that drawing with both inputs cropped out doesn't cause a GPU warning.
-    SkXfermode* mode = SkXfermode::Create(SkXfermode::kSrcOver_Mode);
-    SkAutoTUnref<SkImageFilter> xfermodeNoFg(
-        SkXfermodeImageFilter::Create(mode, greenFilter, croppedOut));
-    SkAutoTUnref<SkImageFilter> xfermodeNoBg(
-        SkXfermodeImageFilter::Create(mode, croppedOut, greenFilter));
-    SkAutoTUnref<SkImageFilter> xfermodeNoFgNoBg(
-        SkXfermodeImageFilter::Create(mode, croppedOut, croppedOut));
+    auto mode = SkXfermode::Make(SkXfermode::kSrcOver_Mode);
+    auto xfermodeNoFg(SkXfermodeImageFilter::Make(mode, greenFilter, croppedOut, nullptr));
+    auto xfermodeNoBg(SkXfermodeImageFilter::Make(mode, croppedOut, greenFilter, nullptr));
+    auto xfermodeNoFgNoBg(SkXfermodeImageFilter::Make(mode, croppedOut, croppedOut, nullptr));
 
     SkPaint paint;
     paint.setImageFilter(xfermodeNoFg);
diff --git a/tests/PaintTest.cpp b/tests/PaintTest.cpp
index 945c8a1..b07c0e4 100644
--- a/tests/PaintTest.cpp
+++ b/tests/PaintTest.cpp
@@ -292,7 +292,7 @@
     paint.setColor(0x00AABBCC);
     paint.setTextScaleX(1.0f);  // Default value, ignored.
     paint.setTextSize(19);
-    paint.setXfermode(SkXfermode::Create(SkXfermode::kModulate_Mode))->unref();
+    paint.setXfermode(SkXfermode::Make(SkXfermode::kModulate_Mode));
     paint.setLooper(nullptr);  // Default value, ignored.
 
     SkWriteBuffer writer;
diff --git a/tests/SerializationTest.cpp b/tests/SerializationTest.cpp
index f6b1275..6914a49 100644
--- a/tests/SerializationTest.cpp
+++ b/tests/SerializationTest.cpp
@@ -246,13 +246,13 @@
     SkAutoTUnref<SkImageFilter> validBitmapSource(SkImageSource::Create(validImage.get()));
     sk_sp<SkImage> invalidImage(SkImage::MakeFromBitmap(invalidBitmap));
     SkAutoTUnref<SkImageFilter> invalidBitmapSource(SkImageSource::Create(invalidImage.get()));
-    SkAutoTUnref<SkXfermode> mode(SkXfermode::Create(SkXfermode::kSrcOver_Mode));
-    SkAutoTUnref<SkImageFilter> xfermodeImageFilter(
-        SkXfermodeImageFilter::Create(mode, invalidBitmapSource, validBitmapSource));
+    sk_sp<SkImageFilter> xfermodeImageFilter(
+        SkXfermodeImageFilter::Make(SkXfermode::Make(SkXfermode::kSrcOver_Mode),
+                                    invalidBitmapSource, validBitmapSource, nullptr));
 
     SkAutoTUnref<SkImageFilter> deserializedFilter(
         TestFlattenableSerialization<SkImageFilter>(
-            xfermodeImageFilter, shouldSucceed, reporter));
+            xfermodeImageFilter.get(), shouldSucceed, reporter));
 
     // Try to render a small bitmap using the invalid deserialized filter
     // to make sure we don't crash while trying to render it
@@ -274,8 +274,8 @@
             // skip SrcOver, as it is allowed to return nullptr from Create()
             continue;
         }
-        SkAutoTUnref<SkXfermode> mode(SkXfermode::Create(static_cast<SkXfermode::Mode>(i)));
-        REPORTER_ASSERT(reporter, mode.get());
+        auto mode(SkXfermode::Make(static_cast<SkXfermode::Mode>(i)));
+        REPORTER_ASSERT(reporter, mode);
         SkAutoTUnref<SkXfermode> copy(
             TestFlattenableSerialization<SkXfermode>(mode.get(), true, reporter));
     }
diff --git a/tests/XfermodeTest.cpp b/tests/XfermodeTest.cpp
index 294d63d..c3a4d96 100644
--- a/tests/XfermodeTest.cpp
+++ b/tests/XfermodeTest.cpp
@@ -13,7 +13,7 @@
 
 static void test_asMode(skiatest::Reporter* reporter) {
     for (int mode = 0; mode <= SkXfermode::kLastMode; mode++) {
-        SkXfermode* xfer = SkXfermode::Create((SkXfermode::Mode) mode);
+        auto xfer = SkXfermode::Make((SkXfermode::Mode) mode);
 
         SkXfermode::Mode reportedMode = ILLEGAL_MODE;
         REPORTER_ASSERT(reporter, reportedMode != mode);
@@ -27,7 +27,6 @@
             reportedMode = (SkXfermode::Mode) -1;
             REPORTER_ASSERT(reporter, xfer->asMode(&reportedMode));
             REPORTER_ASSERT(reporter, reportedMode == mode);
-            xfer->unref();
         } else {
             REPORTER_ASSERT(reporter, SkXfermode::kSrcOver_Mode == mode);
         }
@@ -41,9 +40,8 @@
     for (int i = 0; i <= SkXfermode::kLastMode; ++i) {
         SkXfermode::Mode mode = (SkXfermode::Mode)i;
 
-        SkXfermode* xfer = SkXfermode::Create(mode);
+        auto xfer = SkXfermode::Make(mode);
         REPORTER_ASSERT(reporter, SkXfermode::IsMode(xfer, mode));
-        SkSafeUnref(xfer);
 
         if (SkXfermode::kSrcOver_Mode != mode) {
             REPORTER_ASSERT(reporter, !SkXfermode::IsMode(nullptr, mode));
diff --git a/tools/debugger/SkDebugCanvas.cpp b/tools/debugger/SkDebugCanvas.cpp
index cf3da5d..123b9b4 100644
--- a/tools/debugger/SkDebugCanvas.cpp
+++ b/tools/debugger/SkDebugCanvas.cpp
@@ -33,7 +33,7 @@
                            bool overrideFilterQuality,
                            SkFilterQuality quality)
         : INHERITED(width, height)
-        , fOverdrawXfermode(overdrawViz ? SkOverdrawMode::Create() : nullptr)
+        , fOverdrawXfermode(overdrawViz ? SkOverdrawMode::Make() : nullptr)
         , fOverrideFilterQuality(overrideFilterQuality)
         , fFilterQuality(quality) {}
 
@@ -42,7 +42,7 @@
         if (*paint) {
             if (nullptr != fOverdrawXfermode.get()) {
                 paint->writable()->setAntiAlias(false);
-                paint->writable()->setXfermode(fOverdrawXfermode.get());
+                paint->writable()->setXfermode(fOverdrawXfermode);
             }
 
             if (fOverrideFilterQuality) {
@@ -60,7 +60,7 @@
     }
 
 private:
-    SkAutoTUnref<SkXfermode> fOverdrawXfermode;
+    sk_sp<SkXfermode> fOverdrawXfermode;
 
     bool fOverrideFilterQuality;
     SkFilterQuality fFilterQuality;
diff --git a/tools/debugger/SkDrawCommand.cpp b/tools/debugger/SkDrawCommand.cpp
index fcd2885..a32e0b6 100644
--- a/tools/debugger/SkDrawCommand.cpp
+++ b/tools/debugger/SkDrawCommand.cpp
@@ -1169,10 +1169,9 @@
                                         SkPaint* target) {
     if (jsonPaint.isMember(SKDEBUGCANVAS_ATTRIBUTE_XFERMODE)) {
         Json::Value jsonXfermode = jsonPaint[SKDEBUGCANVAS_ATTRIBUTE_XFERMODE];
-        SkXfermode* xfermode = (SkXfermode*) load_flattenable(jsonXfermode, urlDataManager);
+        sk_sp<SkXfermode> xfermode((SkXfermode*) load_flattenable(jsonXfermode, urlDataManager));
         if (xfermode != nullptr) {
             target->setXfermode(xfermode);
-            xfermode->unref();
         }
     }
 }
diff --git a/tools/debugger/SkOverdrawMode.cpp b/tools/debugger/SkOverdrawMode.cpp
index 3b695ec..7eee387 100644
--- a/tools/debugger/SkOverdrawMode.cpp
+++ b/tools/debugger/SkOverdrawMode.cpp
@@ -317,7 +317,7 @@
     return Create();
 }
 
-SkXfermode* SkOverdrawMode::Create() { return new SkOverdrawXfermode; }
+sk_sp<SkXfermode> SkOverdrawMode::Make() { return sk_make_sp<SkOverdrawXfermode>(); }
 
 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkOverdrawMode)
     SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkOverdrawXfermode)
diff --git a/tools/debugger/SkOverdrawMode.h b/tools/debugger/SkOverdrawMode.h
index dba7635..9e69293 100644
--- a/tools/debugger/SkOverdrawMode.h
+++ b/tools/debugger/SkOverdrawMode.h
@@ -14,7 +14,7 @@
 
 class SkOverdrawMode {
 public:
-    static SkXfermode* Create();
+    static sk_sp<SkXfermode> Make();
 
     SK_DECLARE_FLATTENABLE_REGISTRAR_GROUP();