replace SkXfermode obj with SkBlendMode enum in paints

BUG=skia:5814

GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2714

Change-Id: I4fb489ba6b3f77b458f7e4a99f79c7ad10859135
Reviewed-on: https://skia-review.googlesource.com/2714
Reviewed-by: Florin Malita <fmalita@chromium.org>
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Mike Reed <reed@google.com>
diff --git a/bench/RectBench.cpp b/bench/RectBench.cpp
index 46a515d..48764ca 100644
--- a/bench/RectBench.cpp
+++ b/bench/RectBench.cpp
@@ -85,7 +85,7 @@
 class SrcModeRectBench : public RectBench {
 public:
     SrcModeRectBench() : INHERITED(1, 0) {
-        fMode = SkXfermode::Make(SkXfermode::kSrc_Mode);
+        fMode = SkBlendMode::kSrc;
     }
 
 protected:
@@ -93,7 +93,7 @@
         this->INHERITED::setupPaint(paint);
         // srcmode is most interesting when we're not opaque
         paint->setAlpha(0x80);
-        paint->setXfermode(fMode);
+        paint->setBlendMode(fMode);
     }
 
     const char* onGetName() override {
@@ -103,8 +103,8 @@
     }
 
 private:
-    SkString fName;
-    sk_sp<SkXfermode> fMode;
+    SkString    fName;
+    SkBlendMode fMode;
 
     typedef RectBench INHERITED;
 };
diff --git a/bench/RotatedRectBench.cpp b/bench/RotatedRectBench.cpp
index 23e0443..f81bfb1 100644
--- a/bench/RotatedRectBench.cpp
+++ b/bench/RotatedRectBench.cpp
@@ -67,7 +67,7 @@
 
 class RotRectBench: public Benchmark {
 public:
-    RotRectBench(bool aa, ColorType ct, SkXfermode::Mode mode)
+    RotRectBench(bool aa, ColorType ct, SkBlendMode mode)
         : fAA(aa)
         , fColorType(ct)
         , fMode(mode) {
@@ -80,7 +80,7 @@
     void onDraw(int loops, SkCanvas* canvas) override {
         SkPaint paint;
         paint.setAntiAlias(fAA);
-        paint.setXfermodeMode(fMode);
+        paint.setBlendMode(fMode);
         SkColor color = start_color(fColorType);
 
         int w = this->getSize().x();
@@ -147,48 +147,48 @@
         fName.appendf("_%s", to_lower(SkXfermode::ModeName(fMode)).c_str());
     }
 
-    bool             fAA;
-    ColorType        fColorType;
-    SkXfermode::Mode fMode;
-    SkString         fName;
+    bool        fAA;
+    ColorType   fColorType;
+    SkBlendMode fMode;
+    SkString    fName;
 
     typedef Benchmark INHERITED;
 };
 
 // Choose kSrcOver because it always allows coverage and alpha to be conflated. kSrc only allows
 // conflation when opaque, and kDarken because it isn't possilbe with standard GL blending.
-DEF_BENCH(return new RotRectBench(true,  kConstantOpaque_ColorType,                  SkXfermode::kSrcOver_Mode);)
-DEF_BENCH(return new RotRectBench(true,  kConstantTransparent_ColorType,             SkXfermode::kSrcOver_Mode);)
-DEF_BENCH(return new RotRectBench(true,  kChangingOpaque_ColorType,                  SkXfermode::kSrcOver_Mode);)
-DEF_BENCH(return new RotRectBench(true,  kChangingTransparent_ColorType,             SkXfermode::kSrcOver_Mode);)
-DEF_BENCH(return new RotRectBench(true,  kAlternatingOpaqueAndTransparent_ColorType, SkXfermode::kSrcOver_Mode);)
+DEF_BENCH(return new RotRectBench(true,  kConstantOpaque_ColorType,                  SkBlendMode::kSrcOver);)
+DEF_BENCH(return new RotRectBench(true,  kConstantTransparent_ColorType,             SkBlendMode::kSrcOver);)
+DEF_BENCH(return new RotRectBench(true,  kChangingOpaque_ColorType,                  SkBlendMode::kSrcOver);)
+DEF_BENCH(return new RotRectBench(true,  kChangingTransparent_ColorType,             SkBlendMode::kSrcOver);)
+DEF_BENCH(return new RotRectBench(true,  kAlternatingOpaqueAndTransparent_ColorType, SkBlendMode::kSrcOver);)
 
-DEF_BENCH(return new RotRectBench(false, kConstantOpaque_ColorType,                  SkXfermode::kSrcOver_Mode);)
-DEF_BENCH(return new RotRectBench(false, kConstantTransparent_ColorType,             SkXfermode::kSrcOver_Mode);)
-DEF_BENCH(return new RotRectBench(false, kChangingOpaque_ColorType,                  SkXfermode::kSrcOver_Mode);)
-DEF_BENCH(return new RotRectBench(false, kChangingTransparent_ColorType,             SkXfermode::kSrcOver_Mode);)
-DEF_BENCH(return new RotRectBench(false, kAlternatingOpaqueAndTransparent_ColorType, SkXfermode::kSrcOver_Mode);)
+DEF_BENCH(return new RotRectBench(false, kConstantOpaque_ColorType,                  SkBlendMode::kSrcOver);)
+DEF_BENCH(return new RotRectBench(false, kConstantTransparent_ColorType,             SkBlendMode::kSrcOver);)
+DEF_BENCH(return new RotRectBench(false, kChangingOpaque_ColorType,                  SkBlendMode::kSrcOver);)
+DEF_BENCH(return new RotRectBench(false, kChangingTransparent_ColorType,             SkBlendMode::kSrcOver);)
+DEF_BENCH(return new RotRectBench(false, kAlternatingOpaqueAndTransparent_ColorType, SkBlendMode::kSrcOver);)
 
-DEF_BENCH(return new RotRectBench(true,  kConstantOpaque_ColorType,                  SkXfermode::kSrc_Mode);)
-DEF_BENCH(return new RotRectBench(true,  kConstantTransparent_ColorType,             SkXfermode::kSrc_Mode);)
-DEF_BENCH(return new RotRectBench(true,  kChangingOpaque_ColorType,                  SkXfermode::kSrc_Mode);)
-DEF_BENCH(return new RotRectBench(true,  kChangingTransparent_ColorType,             SkXfermode::kSrc_Mode);)
-DEF_BENCH(return new RotRectBench(true,  kAlternatingOpaqueAndTransparent_ColorType, SkXfermode::kSrc_Mode);)
+DEF_BENCH(return new RotRectBench(true,  kConstantOpaque_ColorType,                  SkBlendMode::kSrc);)
+DEF_BENCH(return new RotRectBench(true,  kConstantTransparent_ColorType,             SkBlendMode::kSrc);)
+DEF_BENCH(return new RotRectBench(true,  kChangingOpaque_ColorType,                  SkBlendMode::kSrc);)
+DEF_BENCH(return new RotRectBench(true,  kChangingTransparent_ColorType,             SkBlendMode::kSrc);)
+DEF_BENCH(return new RotRectBench(true,  kAlternatingOpaqueAndTransparent_ColorType, SkBlendMode::kSrc);)
 
-DEF_BENCH(return new RotRectBench(false, kConstantOpaque_ColorType,                  SkXfermode::kSrc_Mode);)
-DEF_BENCH(return new RotRectBench(false, kConstantTransparent_ColorType,             SkXfermode::kSrc_Mode);)
-DEF_BENCH(return new RotRectBench(false, kChangingOpaque_ColorType,                  SkXfermode::kSrc_Mode);)
-DEF_BENCH(return new RotRectBench(false, kChangingTransparent_ColorType,             SkXfermode::kSrc_Mode);)
-DEF_BENCH(return new RotRectBench(false, kAlternatingOpaqueAndTransparent_ColorType, SkXfermode::kSrc_Mode);)
+DEF_BENCH(return new RotRectBench(false, kConstantOpaque_ColorType,                  SkBlendMode::kSrc);)
+DEF_BENCH(return new RotRectBench(false, kConstantTransparent_ColorType,             SkBlendMode::kSrc);)
+DEF_BENCH(return new RotRectBench(false, kChangingOpaque_ColorType,                  SkBlendMode::kSrc);)
+DEF_BENCH(return new RotRectBench(false, kChangingTransparent_ColorType,             SkBlendMode::kSrc);)
+DEF_BENCH(return new RotRectBench(false, kAlternatingOpaqueAndTransparent_ColorType, SkBlendMode::kSrc);)
 
-DEF_BENCH(return new RotRectBench(true,  kConstantOpaque_ColorType,                  SkXfermode::kDarken_Mode);)
-DEF_BENCH(return new RotRectBench(true,  kConstantTransparent_ColorType,             SkXfermode::kDarken_Mode);)
-DEF_BENCH(return new RotRectBench(true,  kChangingOpaque_ColorType,                  SkXfermode::kDarken_Mode);)
-DEF_BENCH(return new RotRectBench(true,  kChangingTransparent_ColorType,             SkXfermode::kDarken_Mode);)
-DEF_BENCH(return new RotRectBench(true,  kAlternatingOpaqueAndTransparent_ColorType, SkXfermode::kDarken_Mode);)
+DEF_BENCH(return new RotRectBench(true,  kConstantOpaque_ColorType,                  SkBlendMode::kDarken);)
+DEF_BENCH(return new RotRectBench(true,  kConstantTransparent_ColorType,             SkBlendMode::kDarken);)
+DEF_BENCH(return new RotRectBench(true,  kChangingOpaque_ColorType,                  SkBlendMode::kDarken);)
+DEF_BENCH(return new RotRectBench(true,  kChangingTransparent_ColorType,             SkBlendMode::kDarken);)
+DEF_BENCH(return new RotRectBench(true,  kAlternatingOpaqueAndTransparent_ColorType, SkBlendMode::kDarken);)
 
-DEF_BENCH(return new RotRectBench(false, kConstantOpaque_ColorType,                  SkXfermode::kDarken_Mode);)
-DEF_BENCH(return new RotRectBench(false, kConstantTransparent_ColorType,             SkXfermode::kDarken_Mode);)
-DEF_BENCH(return new RotRectBench(false, kChangingOpaque_ColorType,                  SkXfermode::kDarken_Mode);)
-DEF_BENCH(return new RotRectBench(false, kChangingTransparent_ColorType,             SkXfermode::kDarken_Mode);)
-DEF_BENCH(return new RotRectBench(false, kAlternatingOpaqueAndTransparent_ColorType, SkXfermode::kDarken_Mode);)
+DEF_BENCH(return new RotRectBench(false, kConstantOpaque_ColorType,                  SkBlendMode::kDarken);)
+DEF_BENCH(return new RotRectBench(false, kConstantTransparent_ColorType,             SkBlendMode::kDarken);)
+DEF_BENCH(return new RotRectBench(false, kChangingOpaque_ColorType,                  SkBlendMode::kDarken);)
+DEF_BENCH(return new RotRectBench(false, kChangingTransparent_ColorType,             SkBlendMode::kDarken);)
+DEF_BENCH(return new RotRectBench(false, kAlternatingOpaqueAndTransparent_ColorType, SkBlendMode::kDarken);)
diff --git a/bench/XfermodeBench.cpp b/bench/XfermodeBench.cpp
index 60879d6..9e148d4 100644
--- a/bench/XfermodeBench.cpp
+++ b/bench/XfermodeBench.cpp
@@ -15,10 +15,8 @@
 // Benchmark that draws non-AA rects or AA text with an SkXfermode::Mode.
 class XfermodeBench : public Benchmark {
 public:
-    XfermodeBench(SkXfermode::Mode mode, bool aa) {
-        fXfermode = SkXfermode::Make(mode);
+    XfermodeBench(SkBlendMode mode, bool aa) : fBlendMode(mode) {
         fAA = aa;
-        SkASSERT(fXfermode.get() || SkXfermode::kSrcOver_Mode == mode);
         fName.printf("Xfermode_%s%s", SkXfermode::ModeName(mode), aa ? "_aa" : "");
     }
 
@@ -32,7 +30,7 @@
         SkRandom random;
         for (int i = 0; i < loops; ++i) {
             SkPaint paint;
-            paint.setXfermode(fXfermode);
+            paint.setBlendMode(fBlendMode);
             paint.setColor(random.nextU());
             if (fAA) {
                 // Draw text to exercise AA code paths.
@@ -61,71 +59,48 @@
     }
 
 private:
-    sk_sp<SkXfermode>   fXfermode;
-    SkString            fName;
-    bool                fAA;
+    SkBlendMode fBlendMode;
+    SkString    fName;
+    bool        fAA;
 
     typedef Benchmark INHERITED;
 };
 
-class XferCreateBench : public Benchmark {
-public:
-    bool isSuitableFor(Backend backend) override {
-        return backend == kNonRendering_Backend;
-    }
-
-protected:
-    const char* onGetName() override { return "xfermode_create"; }
-
-    void onDraw(int loops, SkCanvas* canvas) override {
-        for (int outer = 0; outer < loops * 10; ++outer) {
-            for (int i = 0; i <= SkXfermode::kLastMode; ++i) {
-                (void)SkXfermode::Make(SkXfermode::Mode(i));
-            }
-        }
-    }
-
-private:
-    typedef Benchmark INHERITED;
-};
-
 //////////////////////////////////////////////////////////////////////////////
 
 #define BENCH(...)                                             \
     DEF_BENCH( return new XfermodeBench(__VA_ARGS__, true); )  \
     DEF_BENCH( return new XfermodeBench(__VA_ARGS__, false); )
 
-BENCH(SkXfermode::kClear_Mode)
-BENCH(SkXfermode::kSrc_Mode)
-BENCH(SkXfermode::kDst_Mode)
-BENCH(SkXfermode::kSrcOver_Mode)
-BENCH(SkXfermode::kDstOver_Mode)
-BENCH(SkXfermode::kSrcIn_Mode)
-BENCH(SkXfermode::kDstIn_Mode)
-BENCH(SkXfermode::kSrcOut_Mode)
-BENCH(SkXfermode::kDstOut_Mode)
-BENCH(SkXfermode::kSrcATop_Mode)
-BENCH(SkXfermode::kDstATop_Mode)
-BENCH(SkXfermode::kXor_Mode)
+BENCH(SkBlendMode::kClear)
+BENCH(SkBlendMode::kSrc)
+BENCH(SkBlendMode::kDst)
+BENCH(SkBlendMode::kSrcOver)
+BENCH(SkBlendMode::kDstOver)
+BENCH(SkBlendMode::kSrcIn)
+BENCH(SkBlendMode::kDstIn)
+BENCH(SkBlendMode::kSrcOut)
+BENCH(SkBlendMode::kDstOut)
+BENCH(SkBlendMode::kSrcATop)
+BENCH(SkBlendMode::kDstATop)
+BENCH(SkBlendMode::kXor)
 
-BENCH(SkXfermode::kPlus_Mode)
-BENCH(SkXfermode::kModulate_Mode)
-BENCH(SkXfermode::kScreen_Mode)
+BENCH(SkBlendMode::kPlus)
+BENCH(SkBlendMode::kModulate)
+BENCH(SkBlendMode::kScreen)
 
-BENCH(SkXfermode::kOverlay_Mode)
-BENCH(SkXfermode::kDarken_Mode)
-BENCH(SkXfermode::kLighten_Mode)
-BENCH(SkXfermode::kColorDodge_Mode)
-BENCH(SkXfermode::kColorBurn_Mode)
-BENCH(SkXfermode::kHardLight_Mode)
-BENCH(SkXfermode::kSoftLight_Mode)
-BENCH(SkXfermode::kDifference_Mode)
-BENCH(SkXfermode::kExclusion_Mode)
-BENCH(SkXfermode::kMultiply_Mode)
+BENCH(SkBlendMode::kOverlay)
+BENCH(SkBlendMode::kDarken)
+BENCH(SkBlendMode::kLighten)
+BENCH(SkBlendMode::kColorDodge)
+BENCH(SkBlendMode::kColorBurn)
+BENCH(SkBlendMode::kHardLight)
+BENCH(SkBlendMode::kSoftLight)
+BENCH(SkBlendMode::kDifference)
+BENCH(SkBlendMode::kExclusion)
+BENCH(SkBlendMode::kMultiply)
 
-BENCH(SkXfermode::kHue_Mode)
-BENCH(SkXfermode::kSaturation_Mode)
-BENCH(SkXfermode::kColor_Mode)
-BENCH(SkXfermode::kLuminosity_Mode)
-
-DEF_BENCH(return new XferCreateBench;)
+BENCH(SkBlendMode::kHue)
+BENCH(SkBlendMode::kSaturation)
+BENCH(SkBlendMode::kColor)
+BENCH(SkBlendMode::kLuminosity)
diff --git a/dm/DMSrcSink.cpp b/dm/DMSrcSink.cpp
index 0565ee9..585a51d 100644
--- a/dm/DMSrcSink.cpp
+++ b/dm/DMSrcSink.cpp
@@ -1454,7 +1454,7 @@
     SkCanvas canvas(uprighted);
     canvas.concat(upright);
     SkPaint paint;
-    paint.setXfermodeMode(SkXfermode::kSrc_Mode);
+    paint.setBlendMode(SkBlendMode::kSrc);
     canvas.drawBitmap(*bitmap, 0, 0, &paint);
 
     *bitmap = uprighted;
diff --git a/fuzz/FilterFuzz.cpp b/fuzz/FilterFuzz.cpp
index 6b766a2..e6f9cb3 100644
--- a/fuzz/FilterFuzz.cpp
+++ b/fuzz/FilterFuzz.cpp
@@ -154,8 +154,8 @@
     return m;
 }
 
-static SkXfermode::Mode make_xfermode() {
-    return static_cast<SkXfermode::Mode>(R(SkXfermode::kLastMode+1));
+static SkBlendMode make_blendmode() {
+    return static_cast<SkBlendMode>(R((int)SkBlendMode::kLastMode+1));
 }
 
 static SkPaint::Align make_paint_align() {
@@ -369,7 +369,7 @@
             return SkTableColorFilter::MakeARGB(tableA, tableR, tableG, tableB);
         }
         case 3:
-            return SkColorFilter::MakeModeFilter(make_color(), make_xfermode());
+            return SkColorFilter::MakeModeFilter(make_color(), (SkXfermode::Mode)make_blendmode());
         case 4:
             return SkColorMatrixFilter::MakeLightingFilter(make_color(), make_color());
         case 5:
@@ -505,7 +505,7 @@
     paint.setStrokeCap(make_paint_cap());
     paint.setStrokeJoin(make_paint_join());
     paint.setColorFilter(make_color_filter());
-    paint.setXfermodeMode(make_xfermode());
+    paint.setBlendMode(make_blendmode());
     paint.setPathEffect(make_path_effect());
     paint.setMaskFilter(make_mask_filter());
 
@@ -540,7 +540,7 @@
     }
 
     enum { ALPHA_THRESHOLD, MERGE, COLOR, LUT3D, BLUR, MAGNIFIER,
-           XFERMODE, OFFSET, MATRIX, MATRIX_CONVOLUTION, COMPOSE,
+           BLENDMODE, OFFSET, MATRIX, MATRIX_CONVOLUTION, COMPOSE,
            DISTANT_LIGHT, POINT_LIGHT, SPOT_LIGHT, NOISE, DROP_SHADOW,
            MORPHOLOGY, BITMAP, DISPLACE, TILE, PICTURE, PAINT, NUM_FILTERS };
 
@@ -554,7 +554,7 @@
     case MERGE:
         filter = SkMergeImageFilter::Make(make_image_filter(),
                                           make_image_filter(),
-                                          make_xfermode());
+                                          (SkXfermode::Mode)make_blendmode());
         break;
     case COLOR: {
         sk_sp<SkColorFilter> cf(make_color_filter());
@@ -580,8 +580,8 @@
                                               make_scalar(true),
                                               make_image_filter());
         break;
-    case XFERMODE:
-        filter = SkXfermodeImageFilter::Make(SkXfermode::Make(make_xfermode()),
+    case BLENDMODE:
+        filter = SkXfermodeImageFilter::Make(make_blendmode(),
                                              make_image_filter(),
                                              make_image_filter(),
                                              nullptr);
diff --git a/gm/aaclip.cpp b/gm/aaclip.cpp
index 26a25c1..f00a4cd 100644
--- a/gm/aaclip.cpp
+++ b/gm/aaclip.cpp
@@ -11,7 +11,7 @@
 
 static void do_draw(SkCanvas* canvas, const SkRect& r) {
     SkPaint paint;
-    paint.setXfermodeMode(SkXfermode::kSrc_Mode);
+    paint.setBlendMode(SkBlendMode::kSrc);
     paint.setColor(0x800000FF);
     canvas->drawRect(r, paint);
 }
diff --git a/gm/aarectmodes.cpp b/gm/aarectmodes.cpp
index 6e9f4bf..ebc47c2 100644
--- a/gm/aarectmodes.cpp
+++ b/gm/aarectmodes.cpp
@@ -59,21 +59,21 @@
 }
 
 constexpr struct {
-    SkXfermode::Mode  fMode;
-    const char*         fLabel;
+    SkBlendMode fMode;
+    const char* fLabel;
 } gModes[] = {
-    { SkXfermode::kClear_Mode,    "Clear"     },
-    { SkXfermode::kSrc_Mode,      "Src"       },
-    { SkXfermode::kDst_Mode,      "Dst"       },
-    { SkXfermode::kSrcOver_Mode,  "SrcOver"   },
-    { SkXfermode::kDstOver_Mode,  "DstOver"   },
-    { SkXfermode::kSrcIn_Mode,    "SrcIn"     },
-    { SkXfermode::kDstIn_Mode,    "DstIn"     },
-    { SkXfermode::kSrcOut_Mode,   "SrcOut"    },
-    { SkXfermode::kDstOut_Mode,   "DstOut"    },
-    { SkXfermode::kSrcATop_Mode,  "SrcATop"   },
-    { SkXfermode::kDstATop_Mode,  "DstATop"   },
-    { SkXfermode::kXor_Mode,      "Xor"       },
+    { SkBlendMode::kClear,    "Clear"     },
+    { SkBlendMode::kSrc,      "Src"       },
+    { SkBlendMode::kDst,      "Dst"       },
+    { SkBlendMode::kSrcOver,  "SrcOver"   },
+    { SkBlendMode::kDstOver,  "DstOver"   },
+    { SkBlendMode::kSrcIn,    "SrcIn"     },
+    { SkBlendMode::kDstIn,    "DstIn"     },
+    { SkBlendMode::kSrcOut,   "SrcOut"    },
+    { SkBlendMode::kDstOut,   "DstOut"    },
+    { SkBlendMode::kSrcATop,  "SrcATop"   },
+    { SkBlendMode::kDstATop,  "DstATop"   },
+    { SkBlendMode::kXor,      "Xor"       },
 };
 
 const int gWidth = 64;
@@ -81,7 +81,7 @@
 const SkScalar W = SkIntToScalar(gWidth);
 const SkScalar H = SkIntToScalar(gHeight);
 
-static SkScalar drawCell(SkCanvas* canvas, sk_sp<SkXfermode> mode, SkAlpha a0, SkAlpha a1) {
+static SkScalar drawCell(SkCanvas* canvas, SkBlendMode mode, SkAlpha a0, SkAlpha a1) {
 
     SkPaint paint;
     paint.setAntiAlias(true);
@@ -95,7 +95,7 @@
 
     paint.setColor(SK_ColorRED);
     paint.setAlpha(a1);
-    paint.setXfermode(std::move(mode));
+    paint.setBlendMode(mode);
 
     SkScalar offset = SK_Scalar1 / 3;
     SkRect rect = SkRect::MakeXYWH(W / 4 + offset,
@@ -155,7 +155,7 @@
                     }
                     canvas->drawRect(bounds, fBGPaint);
                     canvas->saveLayer(&bounds, nullptr);
-                    SkScalar dy = drawCell(canvas, SkXfermode::Make(gModes[i].fMode),
+                    SkScalar dy = drawCell(canvas, gModes[i].fMode,
                                            gAlphaValue[alpha & 1],
                                            gAlphaValue[alpha & 2]);
                     canvas->restore();
diff --git a/gm/aaxfermodes.cpp b/gm/aaxfermodes.cpp
index 678a837..7106ce8 100644
--- a/gm/aaxfermodes.cpp
+++ b/gm/aaxfermodes.cpp
@@ -121,7 +121,7 @@
                 if (firstMode + m > SkXfermode::kLastMode) {
                     break;
                 }
-                SkXfermode::Mode mode = static_cast<SkXfermode::Mode>(firstMode + m);
+                SkBlendMode mode = static_cast<SkBlendMode>(firstMode + m);
                 canvas->save();
 
                 if (kShape_Pass == drawingPass) {
@@ -144,7 +144,7 @@
                                         10);
                             } else {
                                 SkASSERT(kBackground_Pass == drawingPass);
-                                canvas->drawColor(kBGColor, SkXfermode::kSrc_Mode);
+                                canvas->drawColor(kBGColor, SkBlendMode::kSrc);
                             }
                             canvas->restore();
                         } else {
@@ -190,18 +190,17 @@
         canvas->restore();
     }
 
-    void drawModeName(SkCanvas* canvas, SkXfermode::Mode mode) {
-        const char* modeName = mode <= SkXfermode::kLastMode ? SkXfermode::ModeName(mode)
-                                                             : "Arithmetic";
+    void drawModeName(SkCanvas* canvas, SkBlendMode mode) {
+        const char* modeName = SkXfermode::ModeName(mode);
         fLabelPaint.setTextAlign(SkPaint::kRight_Align);
         canvas->drawText(modeName, strlen(modeName), kLabelSpacing - kShapeSize / 4,
                          fLabelPaint.getTextSize() / 4, fLabelPaint);
     }
 
-    void setupShapePaint(SkCanvas* canvas, GrColor color, SkXfermode::Mode mode, SkPaint* paint) {
+    void setupShapePaint(SkCanvas* canvas, GrColor color, SkBlendMode mode, SkPaint* paint) {
         paint->setColor(color);
 
-        if (mode == SkXfermode::kPlus_Mode) {
+        if (mode == SkBlendMode::kPlus) {
             // Check for overflow, otherwise we might get confusing AA artifacts.
             int maxSum = SkTMax(SkTMax(SkColorGetA(kBGColor) + SkColorGetA(color),
                                        SkColorGetR(kBGColor) + SkColorGetR(color)),
@@ -211,7 +210,7 @@
             if (maxSum > 255) {
                 SkPaint dimPaint;
                 dimPaint.setAntiAlias(false);
-                dimPaint.setXfermodeMode(SkXfermode::kDstIn_Mode);
+                dimPaint.setBlendMode(SkBlendMode::kDstIn);
                 if (255 != paint->getAlpha()) {
                     // Dim the src and dst colors.
                     dimPaint.setARGB(255 * 255 / maxSum, 0, 0, 0);
@@ -227,11 +226,11 @@
         }
     }
 
-    void drawShape(SkCanvas* canvas, Shape shape, const SkPaint& paint, SkXfermode::Mode mode) {
-        SkASSERT(mode <= SkXfermode::kLastMode);
+    void drawShape(SkCanvas* canvas, Shape shape, const SkPaint& paint, SkBlendMode mode) {
+        SkASSERT(mode <= SkBlendMode::kLastMode);
         SkPaint shapePaint(paint);
         shapePaint.setAntiAlias(kSquare_Shape != shape);
-        shapePaint.setXfermodeMode(mode);
+        shapePaint.setBlendMode(mode);
 
         switch (shape) {
             case kSquare_Shape:
@@ -249,7 +248,7 @@
 
             case kOval_Shape:
                 canvas->save();
-                canvas->rotate(static_cast<SkScalar>((511 * mode + 257) % 360));
+                canvas->rotate(static_cast<SkScalar>((511 * (int)mode + 257) % 360));
                 canvas->drawPath(fOval, shapePaint);
                 canvas->restore();
                 break;
diff --git a/gm/bitmaprect.cpp b/gm/bitmaprect.cpp
index 2a81300..06bf36a 100644
--- a/gm/bitmaprect.cpp
+++ b/gm/bitmaprect.cpp
@@ -201,7 +201,7 @@
     void onDraw(SkCanvas* canvas) override {
         SkPaint paint;
         paint.setAlpha(128);
-        paint.setXfermode(SkXfermode::Make(SkXfermode::kXor_Mode));
+        paint.setBlendMode(SkBlendMode::kXor);
 
         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 a087064..a0359c3 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::Make(SkXfermode::kSrc_Mode));
+        whitePaint.setBlendMode(SkBlendMode::kSrc);
         whitePaint.setAntiAlias(true);
 
         // This scale exercises precision limits in the circle blur effect (crbug.com/560651)
diff --git a/gm/colormatrix.cpp b/gm/colormatrix.cpp
index 202f72a..f6d51fc 100644
--- a/gm/colormatrix.cpp
+++ b/gm/colormatrix.cpp
@@ -77,7 +77,7 @@
         SkPaint paint;
         SkColorMatrix matrix;
 
-        paint.setXfermodeMode(SkXfermode::kSrc_Mode);
+        paint.setBlendMode(SkBlendMode::kSrc);
         const SkImage* bmps[] = { fSolidImg.get(), fTransparentImg.get() };
 
         for (size_t i = 0; i < SK_ARRAY_COUNT(bmps); ++i) {
diff --git a/gm/colortypexfermode.cpp b/gm/colortypexfermode.cpp
index 554282f..9b715ef 100644
--- a/gm/colortypexfermode.cpp
+++ b/gm/colortypexfermode.cpp
@@ -57,39 +57,39 @@
         canvas->translate(SkIntToScalar(10), SkIntToScalar(20));
 
         const struct {
-            SkXfermode::Mode  fMode;
-            const char*       fLabel;
+            SkBlendMode fMode;
+            const char* fLabel;
         } gModes[] = {
-            { SkXfermode::kClear_Mode,        "Clear"       },
-            { SkXfermode::kSrc_Mode,          "Src"         },
-            { SkXfermode::kDst_Mode,          "Dst"         },
-            { SkXfermode::kSrcOver_Mode,      "SrcOver"     },
-            { SkXfermode::kDstOver_Mode,      "DstOver"     },
-            { SkXfermode::kSrcIn_Mode,        "SrcIn"       },
-            { SkXfermode::kDstIn_Mode,        "DstIn"       },
-            { SkXfermode::kSrcOut_Mode,       "SrcOut"      },
-            { SkXfermode::kDstOut_Mode,       "DstOut"      },
-            { SkXfermode::kSrcATop_Mode,      "SrcATop"     },
-            { SkXfermode::kDstATop_Mode,      "DstATop"     },
+            { SkBlendMode::kClear,        "Clear"       },
+            { SkBlendMode::kSrc,          "Src"         },
+            { SkBlendMode::kDst,          "Dst"         },
+            { SkBlendMode::kSrcOver,      "SrcOver"     },
+            { SkBlendMode::kDstOver,      "DstOver"     },
+            { SkBlendMode::kSrcIn,        "SrcIn"       },
+            { SkBlendMode::kDstIn,        "DstIn"       },
+            { SkBlendMode::kSrcOut,       "SrcOut"      },
+            { SkBlendMode::kDstOut,       "DstOut"      },
+            { SkBlendMode::kSrcATop,      "SrcATop"     },
+            { SkBlendMode::kDstATop,      "DstATop"     },
 
-            { SkXfermode::kXor_Mode,          "Xor"         },
-            { SkXfermode::kPlus_Mode,         "Plus"        },
-            { SkXfermode::kModulate_Mode,     "Modulate"    },
-            { SkXfermode::kScreen_Mode,       "Screen"      },
-            { SkXfermode::kOverlay_Mode,      "Overlay"     },
-            { SkXfermode::kDarken_Mode,       "Darken"      },
-            { SkXfermode::kLighten_Mode,      "Lighten"     },
-            { SkXfermode::kColorDodge_Mode,   "ColorDodge"  },
-            { SkXfermode::kColorBurn_Mode,    "ColorBurn"   },
-            { SkXfermode::kHardLight_Mode,    "HardLight"   },
-            { SkXfermode::kSoftLight_Mode,    "SoftLight"   },
-            { SkXfermode::kDifference_Mode,   "Difference"  },
-            { SkXfermode::kExclusion_Mode,    "Exclusion"   },
-            { SkXfermode::kMultiply_Mode,     "Multiply"    },
-            { SkXfermode::kHue_Mode,          "Hue"         },
-            { SkXfermode::kSaturation_Mode,   "Saturation"  },
-            { SkXfermode::kColor_Mode,        "Color"       },
-            { SkXfermode::kLuminosity_Mode,   "Luminosity"  },
+            { SkBlendMode::kXor,          "Xor"         },
+            { SkBlendMode::kPlus,         "Plus"        },
+            { SkBlendMode::kModulate,     "Modulate"    },
+            { SkBlendMode::kScreen,       "Screen"      },
+            { SkBlendMode::kOverlay,      "Overlay"     },
+            { SkBlendMode::kDarken,       "Darken"      },
+            { SkBlendMode::kLighten,      "Lighten"     },
+            { SkBlendMode::kColorDodge,   "ColorDodge"  },
+            { SkBlendMode::kColorBurn,    "ColorBurn"   },
+            { SkBlendMode::kHardLight,    "HardLight"   },
+            { SkBlendMode::kSoftLight,    "SoftLight"   },
+            { SkBlendMode::kDifference,   "Difference"  },
+            { SkBlendMode::kExclusion,    "Exclusion"   },
+            { SkBlendMode::kMultiply,     "Multiply"    },
+            { SkBlendMode::kHue,          "Hue"         },
+            { SkBlendMode::kSaturation,   "Saturation"  },
+            { SkBlendMode::kColor,        "Color"       },
+            { SkBlendMode::kLuminosity,   "Luminosity"  },
         };
 
         const SkScalar w = SkIntToScalar(W);
@@ -128,7 +128,7 @@
             p.setShader(nullptr);
             canvas->drawRect(r, p);
 
-            textP.setXfermode(SkXfermode::Make(gModes[i].fMode));
+            textP.setBlendMode(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/drawatlas.cpp b/gm/drawatlas.cpp
index dd81628..43b103c 100644
--- a/gm/drawatlas.cpp
+++ b/gm/drawatlas.cpp
@@ -23,12 +23,12 @@
         canvas->clear(SK_ColorRED);
 
         SkPaint paint;
-        paint.setXfermodeMode(SkXfermode::kClear_Mode);
+        paint.setBlendMode(SkBlendMode::kClear);
         SkRect r(target);
         r.inset(-1, -1);
         // zero out a place (with a 1-pixel border) to land our drawing.
         canvas->drawRect(r, paint);
-        paint.setXfermode(nullptr);
+        paint.setBlendMode(SkBlendMode::kSrcOver);
         paint.setColor(SK_ColorBLUE);
         paint.setAntiAlias(true);
         canvas->drawOval(target, paint);
diff --git a/gm/drawatlascolor.cpp b/gm/drawatlascolor.cpp
index d7b973c..bf76c48 100644
--- a/gm/drawatlascolor.cpp
+++ b/gm/drawatlascolor.cpp
@@ -26,7 +26,7 @@
     SkCanvas* canvas = surface->getCanvas();
 
     SkPaint paint;
-    paint.setXfermode(SkXfermode::Make(SkXfermode::kSrc_Mode));
+    paint.setBlendMode(SkBlendMode::kSrc);
 
     paint.setColor(SK_ColorWHITE);
     SkRect r = SkRect::MakeXYWH(0, 0,
diff --git a/gm/dstreadshuffle.cpp b/gm/dstreadshuffle.cpp
index 47c7056..72a68b1 100644
--- a/gm/dstreadshuffle.cpp
+++ b/gm/dstreadshuffle.cpp
@@ -159,8 +159,8 @@
                             p.setColor(color);
                             // In order to get some batching on the GPU backend we do 2 src over for
                             // each xfer mode which requires a dst read
-                            p.setXfermodeMode(r % 3 == 0 ? SkXfermode::kLighten_Mode :
-                                                           SkXfermode::kSrcOver_Mode);
+                            p.setBlendMode(r % 3 == 0 ? SkBlendMode::kLighten :
+                                                        SkBlendMode::kSrcOver);
                             SetStyle(&p, style, width);
                             canvas->save();
                             canvas->translate(x, y);
diff --git a/gm/gamma.cpp b/gm/gamma.cpp
index f6b4a9c..80209e5 100644
--- a/gm/gamma.cpp
+++ b/gm/gamma.cpp
@@ -75,11 +75,11 @@
         advance();
     };
 
-    auto nextXferRect = [&](SkColor srcColor, SkXfermode::Mode mode, SkColor dstColor) {
+    auto nextXferRect = [&](SkColor srcColor, SkBlendMode mode, SkColor dstColor) {
         p.setColor(dstColor);
         canvas->drawRect(r, p);
         p.setColor(srcColor);
-        p.setXfermodeMode(mode);
+        p.setBlendMode(mode);
         canvas->drawRect(r, p);
 
         SkString srcText = SkStringPrintf("%08X", srcColor);
@@ -207,18 +207,18 @@
 
     canvas->saveLayer(nullptr, nullptr);
 
-    nextXferRect(0x7fffffff, SkXfermode::kSrcOver_Mode, SK_ColorBLACK);
-    nextXferRect(0x7f000000, SkXfermode::kSrcOver_Mode, SK_ColorWHITE);
+    nextXferRect(0x7fffffff, SkBlendMode::kSrcOver, SK_ColorBLACK);
+    nextXferRect(0x7f000000, SkBlendMode::kSrcOver, SK_ColorWHITE);
 
-    nextXferRect(SK_ColorBLACK, SkXfermode::kDstOver_Mode, 0x7fffffff);
-    nextXferRect(SK_ColorWHITE, SkXfermode::kSrcIn_Mode, 0x7fff00ff);
-    nextXferRect(0x7fff00ff, SkXfermode::kDstIn_Mode, SK_ColorWHITE);
+    nextXferRect(SK_ColorBLACK, SkBlendMode::kDstOver, 0x7fffffff);
+    nextXferRect(SK_ColorWHITE, SkBlendMode::kSrcIn, 0x7fff00ff);
+    nextXferRect(0x7fff00ff, SkBlendMode::kDstIn, SK_ColorWHITE);
 
     // 0x89 = 255 * linear_to_srgb(0.25)
-    nextXferRect(0xff898989, SkXfermode::kPlus_Mode, 0xff898989);
+    nextXferRect(0xff898989, SkBlendMode::kPlus, 0xff898989);
 
     // 0xDB = 255 * linear_to_srgb(sqrt(0.5))
-    nextXferRect(0xffdbdbdb, SkXfermode::kModulate_Mode, 0xffdbdbdb);
+    nextXferRect(0xffdbdbdb, SkBlendMode::kModulate, 0xffdbdbdb);
 
     canvas->restore();
 }
diff --git a/gm/gm.cpp b/gm/gm.cpp
index b6cac0c..1b0598f 100644
--- a/gm/gm.cpp
+++ b/gm/gm.cpp
@@ -58,7 +58,7 @@
 /////////////////////////////////////////////////////////////////////////////////////////////
 
 void GM::onDrawBackground(SkCanvas* canvas) {
-    canvas->drawColor(fBGColor, SkXfermode::kSrc_Mode);
+    canvas->drawColor(fBGColor, SkBlendMode::kSrc);
 }
 
 void GM::drawSizeBounds(SkCanvas* canvas, SkColor color) {
diff --git a/gm/hairmodes.cpp b/gm/hairmodes.cpp
index de937c4..a628f4a 100644
--- a/gm/hairmodes.cpp
+++ b/gm/hairmodes.cpp
@@ -11,21 +11,21 @@
 #include "SkShader.h"
 
 constexpr struct {
-    SkXfermode::Mode  fMode;
-    const char*         fLabel;
+    SkBlendMode fMode;
+    const char* fLabel;
 } gModes[] = {
-    { SkXfermode::kClear_Mode,    "Clear"     },
-    { SkXfermode::kSrc_Mode,      "Src"       },
-    { SkXfermode::kDst_Mode,      "Dst"       },
-    { SkXfermode::kSrcOver_Mode,  "SrcOver"   },
-    { SkXfermode::kDstOver_Mode,  "DstOver"   },
-    { SkXfermode::kSrcIn_Mode,    "SrcIn"     },
-    { SkXfermode::kDstIn_Mode,    "DstIn"     },
-    { SkXfermode::kSrcOut_Mode,   "SrcOut"    },
-    { SkXfermode::kDstOut_Mode,   "DstOut"    },
-    { SkXfermode::kSrcATop_Mode,  "SrcATop"   },
-    { SkXfermode::kDstATop_Mode,  "DstATop"   },
-    { SkXfermode::kXor_Mode,      "Xor"       },
+    { SkBlendMode::kClear,    "Clear"     },
+    { SkBlendMode::kSrc,      "Src"       },
+    { SkBlendMode::kDst,      "Dst"       },
+    { SkBlendMode::kSrcOver,  "SrcOver"   },
+    { SkBlendMode::kDstOver,  "DstOver"   },
+    { SkBlendMode::kSrcIn,    "SrcIn"     },
+    { SkBlendMode::kDstIn,    "DstIn"     },
+    { SkBlendMode::kSrcOut,   "SrcOut"    },
+    { SkBlendMode::kDstOut,   "DstOut"    },
+    { SkBlendMode::kSrcATop,  "SrcATop"   },
+    { SkBlendMode::kDstATop,  "DstATop"   },
+    { SkBlendMode::kXor,      "Xor"       },
 };
 
 const int gWidth = 64;
@@ -33,7 +33,7 @@
 const SkScalar W = SkIntToScalar(gWidth);
 const SkScalar H = SkIntToScalar(gHeight);
 
-static SkScalar drawCell(SkCanvas* canvas, sk_sp<SkXfermode> mode, SkAlpha a0, SkAlpha a1) {
+static SkScalar drawCell(SkCanvas* canvas, SkBlendMode mode, SkAlpha a0, SkAlpha a1) {
 
     SkPaint paint;
     paint.setAntiAlias(true);
@@ -47,7 +47,7 @@
 
     paint.setColor(SK_ColorRED);
     paint.setAlpha(a1);
-    paint.setXfermode(std::move(mode));
+    paint.setBlendMode(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;
@@ -104,7 +104,7 @@
 
                     canvas->drawRect(bounds, fBGPaint);
                     canvas->saveLayer(&bounds, nullptr);
-                    SkScalar dy = drawCell(canvas, SkXfermode::Make(gModes[i].fMode),
+                    SkScalar dy = drawCell(canvas, gModes[i].fMode,
                                            gAlphaValue[alpha & 1],
                                            gAlphaValue[alpha & 2]);
                     canvas->restore();
diff --git a/gm/imagefilters.cpp b/gm/imagefilters.cpp
index e9f54a3..27422b5 100644
--- a/gm/imagefilters.cpp
+++ b/gm/imagefilters.cpp
@@ -19,7 +19,7 @@
  *
  *  see https://bug.skia.org/3741
  */
-static void do_draw(SkCanvas* canvas, SkXfermode::Mode mode, sk_sp<SkImageFilter> imf) {
+static void do_draw(SkCanvas* canvas, SkBlendMode mode, sk_sp<SkImageFilter> imf) {
         SkAutoCanvasRestore acr(canvas, true);
         canvas->clipRect(SkRect::MakeWH(220, 220));
 
@@ -40,7 +40,7 @@
 
         paint.setColor(0x660000FF);
         paint.setImageFilter(std::move(imf));
-        paint.setXfermodeMode(mode);
+        paint.setBlendMode(mode);
         canvas->drawOval(r1, paint);
 }
 
@@ -52,8 +52,8 @@
                                                                  kNone_SkFilterQuality,
                                                                  nullptr));
 
-        const SkXfermode::Mode modes[] = {
-            SkXfermode::kSrcATop_Mode, SkXfermode::kDstIn_Mode
+        const SkBlendMode modes[] = {
+            SkBlendMode::kSrcATop, SkBlendMode::kDstIn
         };
 
         for (size_t i = 0; i < SK_ARRAY_COUNT(modes); ++i) {
diff --git a/gm/imagefiltersgraph.cpp b/gm/imagefiltersgraph.cpp
index 9803989..2d27728 100644
--- a/gm/imagefiltersgraph.cpp
+++ b/gm/imagefiltersgraph.cpp
@@ -69,9 +69,8 @@
             sk_sp<SkImageFilter> colorMorph(SkColorFilterImageFilter::Make(std::move(matrixFilter),
                                                                            std::move(morph)));
             SkPaint paint;
-            paint.setImageFilter(SkXfermodeImageFilter::Make(
-                                        SkXfermode::Make(SkXfermode::kSrcOver_Mode),
-                                        std::move(colorMorph)));
+            paint.setImageFilter(SkXfermodeImageFilter::Make(SkBlendMode::kSrcOver,
+                                                             std::move(colorMorph)));
 
             DrawClippedImage(canvas, fImage.get(), paint);
             canvas->translate(SkIntToScalar(100), 0);
@@ -105,9 +104,8 @@
             SkImageFilter::CropRect cropRect(SkRect::MakeWH(SkIntToScalar(95), SkIntToScalar(100)));
             SkPaint paint;
             paint.setImageFilter(
-                SkXfermodeImageFilter::Make(SkXfermode::Make(SkXfermode::kSrcIn_Mode),
-                                            std::move(blur),
-                                            nullptr, &cropRect));
+                SkXfermodeImageFilter::Make(SkBlendMode::kSrcIn, std::move(blur), nullptr,
+                                            &cropRect));
             DrawClippedImage(canvas, fImage.get(), paint);
             canvas->translate(SkIntToScalar(100), 0);
         }
diff --git a/gm/imagefilterstransformed.cpp b/gm/imagefilterstransformed.cpp
index 0906eb3..dc8257c 100644
--- a/gm/imagefilterstransformed.cpp
+++ b/gm/imagefilterstransformed.cpp
@@ -127,7 +127,7 @@
     sk_sp<SkImageFilter> filters[] = {
         nullptr,
         SkBlurImageFilter::Make(6, 0, nullptr),
-        SkXfermodeImageFilter::Make(SkXfermode::Make(SkXfermode::kSrcOver_Mode), nullptr),
+        SkXfermodeImageFilter::Make(SkBlendMode::kSrcOver, nullptr),
     };
 
     for (auto& filter : filters) {
diff --git a/gm/lcdblendmodes.cpp b/gm/lcdblendmodes.cpp
index 537c4cb..a16e219 100644
--- a/gm/lcdblendmodes.cpp
+++ b/gm/lcdblendmodes.cpp
@@ -76,44 +76,44 @@
         this->drawColumn(surfCanvas, SK_ColorCYAN, SK_ColorMAGENTA, true);
 
         SkPaint surfPaint;
-        surfPaint.setXfermode(SkXfermode::Make(SkXfermode::kSrcOver_Mode));
+        surfPaint.setBlendMode(SkBlendMode::kSrcOver);
         surface->draw(canvas, 0, 0, &surfPaint);
     }
 
     void drawColumn(SkCanvas* canvas, SkColor backgroundColor, SkColor textColor, bool useGrad) {
         const struct {
-            SkXfermode::Mode  fMode;
-            const char*       fLabel;
+            SkBlendMode fMode;
+            const char* fLabel;
         } gModes[] = {
-            { SkXfermode::kClear_Mode,        "Clear"       },
-            { SkXfermode::kSrc_Mode,          "Src"         },
-            { SkXfermode::kDst_Mode,          "Dst"         },
-            { SkXfermode::kSrcOver_Mode,      "SrcOver"     },
-            { SkXfermode::kDstOver_Mode,      "DstOver"     },
-            { SkXfermode::kSrcIn_Mode,        "SrcIn"       },
-            { SkXfermode::kDstIn_Mode,        "DstIn"       },
-            { SkXfermode::kSrcOut_Mode,       "SrcOut"      },
-            { SkXfermode::kDstOut_Mode,       "DstOut"      },
-            { SkXfermode::kSrcATop_Mode,      "SrcATop"     },
-            { SkXfermode::kDstATop_Mode,      "DstATop"     },
-            { SkXfermode::kXor_Mode,          "Xor"         },
-            { SkXfermode::kPlus_Mode,         "Plus"        },
-            { SkXfermode::kModulate_Mode,     "Modulate"    },
-            { SkXfermode::kScreen_Mode,       "Screen"      },
-            { SkXfermode::kOverlay_Mode,      "Overlay"     },
-            { SkXfermode::kDarken_Mode,       "Darken"      },
-            { SkXfermode::kLighten_Mode,      "Lighten"     },
-            { SkXfermode::kColorDodge_Mode,   "ColorDodge"  },
-            { SkXfermode::kColorBurn_Mode,    "ColorBurn"   },
-            { SkXfermode::kHardLight_Mode,    "HardLight"   },
-            { SkXfermode::kSoftLight_Mode,    "SoftLight"   },
-            { SkXfermode::kDifference_Mode,   "Difference"  },
-            { SkXfermode::kExclusion_Mode,    "Exclusion"   },
-            { SkXfermode::kMultiply_Mode,     "Multiply"    },
-            { SkXfermode::kHue_Mode,          "Hue"         },
-            { SkXfermode::kSaturation_Mode,   "Saturation"  },
-            { SkXfermode::kColor_Mode,        "Color"       },
-            { SkXfermode::kLuminosity_Mode,   "Luminosity"  },
+            { SkBlendMode::kClear,        "Clear"       },
+            { SkBlendMode::kSrc,          "Src"         },
+            { SkBlendMode::kDst,          "Dst"         },
+            { SkBlendMode::kSrcOver,      "SrcOver"     },
+            { SkBlendMode::kDstOver,      "DstOver"     },
+            { SkBlendMode::kSrcIn,        "SrcIn"       },
+            { SkBlendMode::kDstIn,        "DstIn"       },
+            { SkBlendMode::kSrcOut,       "SrcOut"      },
+            { SkBlendMode::kDstOut,       "DstOut"      },
+            { SkBlendMode::kSrcATop,      "SrcATop"     },
+            { SkBlendMode::kDstATop,      "DstATop"     },
+            { SkBlendMode::kXor,          "Xor"         },
+            { SkBlendMode::kPlus,         "Plus"        },
+            { SkBlendMode::kModulate,     "Modulate"    },
+            { SkBlendMode::kScreen,       "Screen"      },
+            { SkBlendMode::kOverlay,      "Overlay"     },
+            { SkBlendMode::kDarken,       "Darken"      },
+            { SkBlendMode::kLighten,      "Lighten"     },
+            { SkBlendMode::kColorDodge,   "ColorDodge"  },
+            { SkBlendMode::kColorBurn,    "ColorBurn"   },
+            { SkBlendMode::kHardLight,    "HardLight"   },
+            { SkBlendMode::kSoftLight,    "SoftLight"   },
+            { SkBlendMode::kDifference,   "Difference"  },
+            { SkBlendMode::kExclusion,    "Exclusion"   },
+            { SkBlendMode::kMultiply,     "Multiply"    },
+            { SkBlendMode::kHue,          "Hue"         },
+            { SkBlendMode::kSaturation,   "Saturation"  },
+            { SkBlendMode::kColor,        "Color"       },
+            { SkBlendMode::kLuminosity,   "Luminosity"  },
         };
         // Draw background rect
         SkPaint backgroundPaint;
@@ -128,7 +128,7 @@
             paint.setSubpixelText(true);
             paint.setLCDRenderText(true);
             paint.setTextSize(fTextHeight);
-            paint.setXfermode(SkXfermode::Make(gModes[m].fMode));
+            paint.setBlendMode(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 623d746..3808785 100644
--- a/gm/lcdoverlap.cpp
+++ b/gm/lcdoverlap.cpp
@@ -49,8 +49,8 @@
 
     SkISize onISize() override { return SkISize::Make(kWidth, kHeight); }
 
-    void drawTestCase(SkCanvas* canvas, SkScalar x, SkScalar y, SkXfermode::Mode mode,
-                      SkXfermode::Mode mode2) {
+    void drawTestCase(SkCanvas* canvas, SkScalar x, SkScalar y, SkBlendMode mode,
+                      SkBlendMode mode2) {
         const SkColor colors[] {
                 SK_ColorRED,
                 SK_ColorGREEN,
@@ -60,8 +60,6 @@
                 SK_ColorMAGENTA,
         };
 
-        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);
@@ -70,7 +68,7 @@
 
             SkPaint textPaint;
             textPaint.setColor(colors[i]);
-            textPaint.setXfermode(i % 2 == 0 ? xfermode : xfermode2);
+            textPaint.setBlendMode(i % 2 == 0 ? mode : mode2);
             canvas->drawTextBlob(fBlob, 0, 0, textPaint);
             canvas->restore();
         }
@@ -79,13 +77,11 @@
     void onDraw(SkCanvas* canvas) override {
         SkScalar offsetX = kWidth / 4.0f;
         SkScalar offsetY = kHeight / 4.0f;
-        drawTestCase(canvas, offsetX, offsetY,  SkXfermode::kSrc_Mode, SkXfermode::kSrc_Mode);
-        drawTestCase(canvas, 3 * offsetX, offsetY,  SkXfermode::kSrcOver_Mode,
-                     SkXfermode::kSrcOver_Mode);
-        drawTestCase(canvas, offsetX, 3 * offsetY,  SkXfermode::kHardLight_Mode,
-                     SkXfermode::kLuminosity_Mode);
-        drawTestCase(canvas, 3 * offsetX, 3 * offsetY,  SkXfermode::kSrcOver_Mode,
-                     SkXfermode::kSrc_Mode);
+        drawTestCase(canvas, offsetX, offsetY,  SkBlendMode::kSrc, SkBlendMode::kSrc);
+        drawTestCase(canvas, 3 * offsetX, offsetY,  SkBlendMode::kSrcOver, SkBlendMode::kSrcOver);
+        drawTestCase(canvas, offsetX, 3 * offsetY,  SkBlendMode::kHardLight,
+                     SkBlendMode::kLuminosity);
+        drawTestCase(canvas, 3 * offsetX, 3 * offsetY,  SkBlendMode::kSrcOver, SkBlendMode::kSrc);
     }
 
 private:
diff --git a/gm/lumafilter.cpp b/gm/lumafilter.cpp
index 10eefab..3852d93 100644
--- a/gm/lumafilter.cpp
+++ b/gm/lumafilter.cpp
@@ -26,7 +26,7 @@
                      paint);
 }
 
-static void draw_scene(SkCanvas* canvas, const sk_sp<SkColorFilter>& filter, SkXfermode::Mode mode,
+static void draw_scene(SkCanvas* canvas, const sk_sp<SkColorFilter>& filter, SkBlendMode mode,
                        const sk_sp<SkShader>& s1, const sk_sp<SkShader>& s2) {
     SkPaint paint;
     paint.setAntiAlias(true);
@@ -53,7 +53,7 @@
     }
 
     SkPaint xferPaint;
-    xferPaint.setXfermodeMode(mode);
+    xferPaint.setBlendMode(mode);
     canvas->saveLayer(&bounds, &xferPaint);
 
     r = bounds;
@@ -101,13 +101,14 @@
     }
 
     void onDraw(SkCanvas* canvas) override {
-        SkXfermode::Mode modes[] = { SkXfermode::kSrcOver_Mode,
-                                     SkXfermode::kDstOver_Mode,
-                                     SkXfermode::kSrcATop_Mode,
-                                     SkXfermode::kDstATop_Mode,
-                                     SkXfermode::kSrcIn_Mode,
-                                     SkXfermode::kDstIn_Mode,
-                                   };
+        SkBlendMode modes[] = {
+            SkBlendMode::kSrcOver,
+            SkBlendMode::kDstOver,
+            SkBlendMode::kSrcATop,
+            SkBlendMode::kDstATop,
+            SkBlendMode::kSrcIn,
+            SkBlendMode::kDstIn,
+        };
         struct {
             const sk_sp<SkShader>& fShader1;
             const sk_sp<SkShader>& fShader2;
diff --git a/gm/modecolorfilters.cpp b/gm/modecolorfilters.cpp
index 50bb27f..ae926ef 100644
--- a/gm/modecolorfilters.cpp
+++ b/gm/modecolorfilters.cpp
@@ -78,7 +78,7 @@
         }
         SkPaint bgPaint;
         bgPaint.setShader(fBmpShader);
-        bgPaint.setXfermodeMode(SkXfermode::kSrc_Mode);
+        bgPaint.setBlendMode(SkBlendMode::kSrc);
 
         sk_sp<SkShader> shaders[] = {
             nullptr,                                   // use a paint color instead of a shader
diff --git a/gm/picture.cpp b/gm/picture.cpp
index 1ea8ada..72d4159 100644
--- a/gm/picture.cpp
+++ b/gm/picture.cpp
@@ -29,7 +29,7 @@
     canvas->drawPath(path, paint);
 
     paint.setColor(0x80FFFFFF);
-    paint.setXfermodeMode(SkXfermode::kPlus_Mode);
+    paint.setBlendMode(SkBlendMode::kPlus);
     canvas->drawRect(SkRect::MakeXYWH(25, 25, 50, 50), paint);
 
     return rec.finishRecordingAsPicture();
diff --git a/gm/plus.cpp b/gm/plus.cpp
index 6a5af61..51ac2cb 100644
--- a/gm/plus.cpp
+++ b/gm/plus.cpp
@@ -37,7 +37,7 @@
 
     // Using Plus on the right should merge the AA of seam together completely covering the red.
     canvas->saveLayer(nullptr, nullptr);
-      p.setXfermodeMode(SkXfermode::kPlus_Mode);
+      p.setBlendMode(SkBlendMode::kPlus);
       canvas->translate(150, 0);
       canvas->drawPath(upperLeft, p);
       canvas->drawPath(bottomRight, p);
diff --git a/gm/srcmode.cpp b/gm/srcmode.cpp
index 0d02cdc..d57b77c 100644
--- a/gm/srcmode.cpp
+++ b/gm/srcmode.cpp
@@ -82,8 +82,8 @@
             draw_hair, draw_thick, draw_rect, draw_oval, draw_text
         };
 
-        const SkXfermode::Mode modes[] = {
-            SkXfermode::kSrcOver_Mode, SkXfermode::kSrc_Mode, SkXfermode::kClear_Mode
+        const SkBlendMode modes[] = {
+            SkBlendMode::kSrcOver, SkBlendMode::kSrc, SkBlendMode::kClear
         };
 
         const PaintProc paintProcs[] = {
@@ -96,7 +96,7 @@
             for (size_t i = 0; i < SK_ARRAY_COUNT(paintProcs); ++i) {
                 paintProcs[i](&paint);
                 for (size_t x = 0; x < SK_ARRAY_COUNT(modes); ++x) {
-                    paint.setXfermodeMode(modes[x]);
+                    paint.setBlendMode(modes[x]);
                     canvas->save();
                     for (size_t y = 0; y < SK_ARRAY_COUNT(procs); ++y) {
                         procs[y](canvas, paint);
diff --git a/gm/textblobblockreordering.cpp b/gm/textblobblockreordering.cpp
index 3974aca..c581e13 100644
--- a/gm/textblobblockreordering.cpp
+++ b/gm/textblobblockreordering.cpp
@@ -69,7 +69,7 @@
         redPaint.setColor(SK_ColorRED);
         canvas->drawRect(bounds, redPaint);
         SkPaint srcInPaint(paint);
-        srcInPaint.setXfermodeMode(SkXfermode::kSrcIn_Mode);
+        srcInPaint.setBlendMode(SkBlendMode::kSrcIn);
         canvas->drawTextBlob(fBlob, 0, 0, srcInPaint);
 
         canvas->translate(SkIntToScalar(xDelta), SkIntToScalar(yDelta));
diff --git a/gm/textbloblooper.cpp b/gm/textbloblooper.cpp
index 3adf349..37eae66 100644
--- a/gm/textbloblooper.cpp
+++ b/gm/textbloblooper.cpp
@@ -51,7 +51,7 @@
 typedef void (*LooperProc)(SkPaint*);
 
 struct LooperSettings {
-    SkXfermode::Mode fMode;
+    SkBlendMode      fMode;
     SkColor          fColor;
     SkPaint::Style   fStyle;
     SkScalar         fWidth;
@@ -120,7 +120,7 @@
     for (size_t i = 0; i < size; i++) {
         info.fOffset.set(settings[i].fOffset, settings[i].fOffset);
         SkPaint* paint = looperBuilder.addLayer(info);
-        paint->setXfermodeMode(settings[i].fMode);
+        paint->setBlendMode(settings[i].fMode);
         paint->setColor(settings[i].fColor);
         paint->setStyle(settings[i].fStyle);
         paint->setStrokeWidth(settings[i].fWidth);
@@ -152,37 +152,37 @@
 
         // create a looper which sandwhiches an effect in two normal draws
         LooperSettings looperSandwhich[] = {
-           { SkXfermode::kSrc_Mode, SK_ColorMAGENTA, SkPaint::kFill_Style, 0, 0, 0, false },
-           { SkXfermode::kSrcOver_Mode, 0x88000000, SkPaint::kFill_Style, 0, 10.f, 0, true },
-           { SkXfermode::kSrcOver_Mode, 0x50FF00FF, SkPaint::kFill_Style, 0, 20.f, 0, false },
+           { SkBlendMode::kSrc, SK_ColorMAGENTA, SkPaint::kFill_Style, 0, 0, 0, false },
+           { SkBlendMode::kSrcOver, 0x88000000, SkPaint::kFill_Style, 0, 10.f, 0, true },
+           { SkBlendMode::kSrcOver, 0x50FF00FF, SkPaint::kFill_Style, 0, 20.f, 0, false },
         };
 
         LooperSettings compound[] = {
-            { SkXfermode::kSrc_Mode, SK_ColorWHITE, SkPaint::kStroke_Style, 1.f * 3/4, 0, 0, false },
-            { SkXfermode::kSrc_Mode, SK_ColorRED, SkPaint::kStroke_Style, 4.f, 0, 0, false },
-            { SkXfermode::kSrc_Mode, SK_ColorBLUE, SkPaint::kFill_Style, 0, 0, 0, false },
-            { SkXfermode::kSrcOver_Mode, 0x88000000, SkPaint::kFill_Style, 0, 10.f, 0, true }
+            { SkBlendMode::kSrc, SK_ColorWHITE, SkPaint::kStroke_Style, 1.f * 3/4, 0, 0, false },
+            { SkBlendMode::kSrc, SK_ColorRED, SkPaint::kStroke_Style, 4.f, 0, 0, false },
+            { SkBlendMode::kSrc, SK_ColorBLUE, SkPaint::kFill_Style, 0, 0, 0, false },
+            { SkBlendMode::kSrcOver, 0x88000000, SkPaint::kFill_Style, 0, 10.f, 0, true }
         };
 
         LooperSettings xfermode[] = {
-            { SkXfermode::kDifference_Mode, SK_ColorWHITE, SkPaint::kFill_Style, 0, 0, 0, false },
-            { SkXfermode::kSrcOver_Mode, 0xFF000000, SkPaint::kFill_Style, 0, 1.f, 0, true },
-            { SkXfermode::kSrcOver_Mode, 0x50FF00FF, SkPaint::kFill_Style, 0, 2.f, 0, false },
+            { SkBlendMode::kDifference, SK_ColorWHITE, SkPaint::kFill_Style, 0, 0, 0, false },
+            { SkBlendMode::kSrcOver, 0xFF000000, SkPaint::kFill_Style, 0, 1.f, 0, true },
+            { SkBlendMode::kSrcOver, 0x50FF00FF, SkPaint::kFill_Style, 0, 2.f, 0, false },
         };
 
         // NOTE, this should be ignored by textblobs
         LooperSettings skew[] = {
-            { SkXfermode::kSrc_Mode, SK_ColorRED, SkPaint::kFill_Style, 0, 0, -1.f, false },
-            { SkXfermode::kSrc_Mode, SK_ColorGREEN, SkPaint::kFill_Style, 0, 10.f, -1.f, false },
-            { SkXfermode::kSrc_Mode, SK_ColorBLUE, SkPaint::kFill_Style, 0, 20.f, -1.f, false },
+            { SkBlendMode::kSrc, SK_ColorRED, SkPaint::kFill_Style, 0, 0, -1.f, false },
+            { SkBlendMode::kSrc, SK_ColorGREEN, SkPaint::kFill_Style, 0, 10.f, -1.f, false },
+            { SkBlendMode::kSrc, SK_ColorBLUE, SkPaint::kFill_Style, 0, 20.f, -1.f, false },
         };
 
         LooperSettings kitchenSink[] = {
-            { SkXfermode::kSrc_Mode, SK_ColorWHITE, SkPaint::kStroke_Style, 1.f * 3/4, 0, 0, false },
-            { SkXfermode::kSrc_Mode, SK_ColorBLACK, SkPaint::kFill_Style, 0, 0, 0, false },
-            { SkXfermode::kDifference_Mode, SK_ColorWHITE, SkPaint::kFill_Style, 1.f, 10.f, 0, false },
-            { SkXfermode::kSrc_Mode, SK_ColorWHITE, SkPaint::kFill_Style, 0, 10.f, 0, true },
-            { SkXfermode::kSrcOver_Mode, 0x50FF00FF, SkPaint::kFill_Style, 0, 20.f, 0, false },
+            { SkBlendMode::kSrc, SK_ColorWHITE, SkPaint::kStroke_Style, 1.f * 3/4, 0, 0, false },
+            { SkBlendMode::kSrc, SK_ColorBLACK, SkPaint::kFill_Style, 0, 0, 0, false },
+            { SkBlendMode::kDifference, SK_ColorWHITE, SkPaint::kFill_Style, 1.f, 10.f, 0, false },
+            { SkBlendMode::kSrc, SK_ColorWHITE, SkPaint::kFill_Style, 0, 10.f, 0, true },
+            { SkBlendMode::kSrcOver, 0x50FF00FF, SkPaint::kFill_Style, 0, 20.f, 0, false },
         };
 
         fLoopers.push_back(setupLooper(SkLayerDrawLooper::kMaskFilter_Bit |
diff --git a/gm/texteffects.cpp b/gm/texteffects.cpp
index 6a5a9c1..453a555 100644
--- a/gm/texteffects.cpp
+++ b/gm/texteffects.cpp
@@ -25,7 +25,7 @@
 
     p.setAlpha(0x11);
     p.setStyle(SkPaint::kFill_Style);
-    p.setXfermodeMode(SkXfermode::kSrc_Mode);
+    p.setBlendMode(SkBlendMode::kSrc);
     rastBuilder->addLayer(p);
 }
 
@@ -33,7 +33,7 @@
     rastBuilder->addLayer(p);
 
     p.setAlpha(0x40);
-    p.setXfermodeMode(SkXfermode::kSrc_Mode);
+    p.setBlendMode(SkBlendMode::kSrc);
     p.setStyle(SkPaint::kStroke_Style);
     p.setStrokeWidth(SK_Scalar1*2);
     rastBuilder->addLayer(p);
@@ -46,7 +46,7 @@
 
     p.setStyle(SkPaint::kStroke_Style);
     p.setStrokeWidth(SK_Scalar1*3/2);
-    p.setXfermodeMode(SkXfermode::kClear_Mode);
+    p.setBlendMode(SkBlendMode::kClear);
     rastBuilder->addLayer(p);
 }
 
@@ -57,7 +57,7 @@
 
     p.setAlpha(0x20);
     p.setStyle(SkPaint::kFill_Style);
-    p.setXfermodeMode(SkXfermode::kSrc_Mode);
+    p.setBlendMode(SkBlendMode::kSrc);
     rastBuilder->addLayer(p);
 }
 
@@ -66,10 +66,10 @@
     rastBuilder->addLayer(p, SkIntToScalar(3), SkIntToScalar(3));
 
     p.setAlpha(0xFF);
-    p.setXfermodeMode(SkXfermode::kClear_Mode);
+    p.setBlendMode(SkBlendMode::kClear);
     rastBuilder->addLayer(p, SK_Scalar1*3/2, SK_Scalar1*3/2);
 
-    p.setXfermode(nullptr);
+    p.setBlendMode(SkBlendMode::kSrcOver);
     rastBuilder->addLayer(p);
 }
 
@@ -79,7 +79,7 @@
     rastBuilder->addLayer(p);
 
     p.setPathEffect(SkDiscretePathEffect::Make(SK_Scalar1*4, SK_Scalar1*3));
-    p.setXfermodeMode(SkXfermode::kSrcOut_Mode);
+    p.setBlendMode(SkBlendMode::kSrcOut);
     rastBuilder->addLayer(p);
 }
 
@@ -90,7 +90,7 @@
     SkLayerRasterizer::Builder rastBuilder2;
     r5(&rastBuilder2, p);
     p.setRasterizer(rastBuilder2.detach());
-    p.setXfermodeMode(SkXfermode::kClear_Mode);
+    p.setBlendMode(SkBlendMode::kClear);
     rastBuilder->addLayer(p);
 }
 
@@ -117,11 +117,11 @@
     lattice.setScale(SK_Scalar1*6, SK_Scalar1*6, 0, 0);
     lattice.postSkew(SK_Scalar1/3, 0, 0, 0);
     p.setPathEffect(MakeDotEffect(SK_Scalar1*2, lattice));
-    p.setXfermodeMode(SkXfermode::kClear_Mode);
+    p.setBlendMode(SkBlendMode::kClear);
     rastBuilder->addLayer(p);
 
     p.setPathEffect(nullptr);
-    p.setXfermode(nullptr);
+    p.setBlendMode(SkBlendMode::kSrcOver);
     p.setStyle(SkPaint::kStroke_Style);
     p.setStrokeWidth(SK_Scalar1);
     rastBuilder->addLayer(p);
@@ -134,11 +134,11 @@
     lattice.setScale(SK_Scalar1, SK_Scalar1*6, 0, 0);
     lattice.postRotate(SkIntToScalar(30), 0, 0);
     p.setPathEffect(SkLine2DPathEffect::Make(SK_Scalar1*2, lattice));
-    p.setXfermodeMode(SkXfermode::kClear_Mode);
+    p.setBlendMode(SkBlendMode::kClear);
     rastBuilder->addLayer(p);
 
     p.setPathEffect(nullptr);
-    p.setXfermode(nullptr);
+    p.setBlendMode(SkBlendMode::kSrcOver);
     p.setStyle(SkPaint::kStroke_Style);
     p.setStrokeWidth(SK_Scalar1);
     rastBuilder->addLayer(p);
diff --git a/gm/texturedomaineffect.cpp b/gm/texturedomaineffect.cpp
index 2dd340e..b0d2ece 100644
--- a/gm/texturedomaineffect.cpp
+++ b/gm/texturedomaineffect.cpp
@@ -57,14 +57,14 @@
         SkColor colors2[] = { SK_ColorMAGENTA, SK_ColorLTGRAY, SK_ColorYELLOW };
         paint.setShader(SkGradientShader::MakeSweep(45.f, 55.f, colors2, nullptr,
                                                     SK_ARRAY_COUNT(colors2)));
-        paint.setXfermodeMode(SkXfermode::kDarken_Mode);
+        paint.setBlendMode(SkBlendMode::kDarken);
         canvas.drawOval(SkRect::MakeXYWH(-5.f, -5.f, fBmp.width() + 10.f, fBmp.height() + 10.f),
                         paint);
 
         SkColor colors3[] = { SK_ColorBLUE, SK_ColorLTGRAY, SK_ColorGREEN };
         paint.setShader(SkGradientShader::MakeSweep(25.f, 35.f, colors3, nullptr,
                                                     SK_ARRAY_COUNT(colors3)));
-        paint.setXfermodeMode(SkXfermode::kLighten_Mode);
+        paint.setBlendMode(SkBlendMode::kLighten);
         canvas.drawOval(SkRect::MakeXYWH(-5.f, -5.f, fBmp.width() + 10.f, fBmp.height() + 10.f),
                         paint);
     }
diff --git a/gm/verylargebitmap.cpp b/gm/verylargebitmap.cpp
index f257bf9..9f1c05f 100644
--- a/gm/verylargebitmap.cpp
+++ b/gm/verylargebitmap.cpp
@@ -18,7 +18,7 @@
     SkPaint paint;
     paint.setShader(SkGradientShader::MakeRadial(center, radius, colors, nullptr, 2,
                                                  SkShader::kMirror_TileMode));
-    paint.setXfermodeMode(SkXfermode::kSrc_Mode);
+    paint.setBlendMode(SkBlendMode::kSrc);
     canvas->drawPaint(paint);
 }
 
diff --git a/gm/xfermodeimagefilter.cpp b/gm/xfermodeimagefilter.cpp
index a0677c7..9190859 100644
--- a/gm/xfermodeimagefilter.cpp
+++ b/gm/xfermodeimagefilter.cpp
@@ -48,46 +48,45 @@
         SkPaint paint;
 
         const struct {
-            SkXfermode::Mode  fMode;
-            const char*         fLabel;
+            SkBlendMode fMode;
+            const char* fLabel;
         } gModes[] = {
-            { SkXfermode::kClear_Mode,    "Clear"     },
-            { SkXfermode::kSrc_Mode,      "Src"       },
-            { SkXfermode::kDst_Mode,      "Dst"       },
-            { SkXfermode::kSrcOver_Mode,  "SrcOver"   },
-            { SkXfermode::kDstOver_Mode,  "DstOver"   },
-            { SkXfermode::kSrcIn_Mode,    "SrcIn"     },
-            { SkXfermode::kDstIn_Mode,    "DstIn"     },
-            { SkXfermode::kSrcOut_Mode,   "SrcOut"    },
-            { SkXfermode::kDstOut_Mode,   "DstOut"    },
-            { SkXfermode::kSrcATop_Mode,  "SrcATop"   },
-            { SkXfermode::kDstATop_Mode,  "DstATop"   },
-            { SkXfermode::kXor_Mode,      "Xor"       },
+            { SkBlendMode::kClear,    "Clear"     },
+            { SkBlendMode::kSrc,      "Src"       },
+            { SkBlendMode::kDst,      "Dst"       },
+            { SkBlendMode::kSrcOver,  "SrcOver"   },
+            { SkBlendMode::kDstOver,  "DstOver"   },
+            { SkBlendMode::kSrcIn,    "SrcIn"     },
+            { SkBlendMode::kDstIn,    "DstIn"     },
+            { SkBlendMode::kSrcOut,   "SrcOut"    },
+            { SkBlendMode::kDstOut,   "DstOut"    },
+            { SkBlendMode::kSrcATop,  "SrcATop"   },
+            { SkBlendMode::kDstATop,  "DstATop"   },
+            { SkBlendMode::kXor,      "Xor"       },
 
-            { SkXfermode::kPlus_Mode,         "Plus"          },
-            { SkXfermode::kModulate_Mode,     "Modulate"      },
-            { SkXfermode::kScreen_Mode,       "Screen"        },
-            { SkXfermode::kOverlay_Mode,      "Overlay"       },
-            { SkXfermode::kDarken_Mode,       "Darken"        },
-            { SkXfermode::kLighten_Mode,      "Lighten"       },
-            { SkXfermode::kColorDodge_Mode,   "ColorDodge"    },
-            { SkXfermode::kColorBurn_Mode,    "ColorBurn"     },
-            { SkXfermode::kHardLight_Mode,    "HardLight"     },
-            { SkXfermode::kSoftLight_Mode,    "SoftLight"     },
-            { SkXfermode::kDifference_Mode,   "Difference"    },
-            { SkXfermode::kExclusion_Mode,    "Exclusion"     },
-            { SkXfermode::kMultiply_Mode,     "Multiply"      },
-            { SkXfermode::kHue_Mode,          "Hue"           },
-            { SkXfermode::kSaturation_Mode,   "Saturation"    },
-            { SkXfermode::kColor_Mode,        "Color"         },
-            { SkXfermode::kLuminosity_Mode,   "Luminosity"    },
+            { SkBlendMode::kPlus,         "Plus"          },
+            { SkBlendMode::kModulate,     "Modulate"      },
+            { SkBlendMode::kScreen,       "Screen"        },
+            { SkBlendMode::kOverlay,      "Overlay"       },
+            { SkBlendMode::kDarken,       "Darken"        },
+            { SkBlendMode::kLighten,      "Lighten"       },
+            { SkBlendMode::kColorDodge,   "ColorDodge"    },
+            { SkBlendMode::kColorBurn,    "ColorBurn"     },
+            { SkBlendMode::kHardLight,    "HardLight"     },
+            { SkBlendMode::kSoftLight,    "SoftLight"     },
+            { SkBlendMode::kDifference,   "Difference"    },
+            { SkBlendMode::kExclusion,    "Exclusion"     },
+            { SkBlendMode::kMultiply,     "Multiply"      },
+            { SkBlendMode::kHue,          "Hue"           },
+            { SkBlendMode::kSaturation,   "Saturation"    },
+            { SkBlendMode::kColor,        "Color"         },
+            { SkBlendMode::kLuminosity,   "Luminosity"    },
         };
 
         int x = 0, y = 0;
         sk_sp<SkImageFilter> background(SkImageSource::Make(fCheckerboard));
         for (size_t i = 0; i < SK_ARRAY_COUNT(gModes); i++) {
-            paint.setImageFilter(SkXfermodeImageFilter::Make(SkXfermode::Make(gModes[i].fMode),
-                                                             background));
+            paint.setImageFilter(SkXfermodeImageFilter::Make(gModes[i].fMode, background));
             DrawClippedBitmap(canvas, fBitmap, paint, x, y);
             x += fBitmap.width() + MARGIN;
             if (x + fBitmap.width() > WIDTH) {
@@ -104,7 +103,7 @@
             y += fBitmap.height() + MARGIN;
         }
         // Test nullptr mode
-        paint.setImageFilter(SkXfermodeImageFilter::Make(nullptr, background));
+        paint.setImageFilter(SkXfermodeImageFilter::Make(SkBlendMode::kSrcOver, background));
         DrawClippedBitmap(canvas, fBitmap, paint, x, y);
         x += fBitmap.width() + MARGIN;
         if (x + fBitmap.width() > WIDTH) {
@@ -122,11 +121,10 @@
         sk_sp<SkImageFilter> offsetBackground(SkOffsetImageFilter::Make(SkIntToScalar(4),
                                                                         SkIntToScalar(4),
                                                                         background));
-        paint.setImageFilter(SkXfermodeImageFilter::Make(
-                                                     SkXfermode::Make(SkXfermode::kSrcOver_Mode),
-                                                     offsetBackground,
-                                                     offsetForeground,
-                                                     nullptr));
+        paint.setImageFilter(SkXfermodeImageFilter::Make(SkBlendMode::kSrcOver,
+                                                         offsetBackground,
+                                                         offsetForeground,
+                                                         nullptr));
         DrawClippedPaint(canvas, clipRect, paint, x, y);
         x += fBitmap.width() + MARGIN;
         if (x + fBitmap.width() > WIDTH) {
@@ -134,7 +132,7 @@
             y += fBitmap.height() + MARGIN;
         }
         // Test offsets on Darken (uses shader blend)
-        paint.setImageFilter(SkXfermodeImageFilter::Make(SkXfermode::Make(SkXfermode::kDarken_Mode),
+        paint.setImageFilter(SkXfermodeImageFilter::Make(SkBlendMode::kDarken,
                                                          offsetBackground,
                                                          offsetForeground,
                                                          nullptr));
@@ -146,9 +144,9 @@
         }
         // Test cropping
         constexpr size_t nbSamples = 3;
-        SkXfermode::Mode sampledModes[nbSamples] = {SkXfermode::kOverlay_Mode,
-                                                    SkXfermode::kSrcOver_Mode,
-                                                    SkXfermode::kPlus_Mode};
+        const SkBlendMode sampledModes[nbSamples] = {
+            SkBlendMode::kOverlay, SkBlendMode::kSrcOver, SkBlendMode::kPlus
+        };
         int offsets[nbSamples][4] = {{ 10,  10, -16, -16},
                                      { 10,  10,  10,  10},
                                      {-10, -10,  -6,  -6}};
@@ -158,7 +156,7 @@
                                                  fBitmap.width()  + offsets[i][2],
                                                  fBitmap.height() + offsets[i][3]);
             SkImageFilter::CropRect rect(SkRect::Make(cropRect));
-            paint.setImageFilter(SkXfermodeImageFilter::Make(SkXfermode::Make(sampledModes[i]),
+            paint.setImageFilter(SkXfermodeImageFilter::Make(sampledModes[i],
                                                              offsetBackground,
                                                              offsetForeground,
                                                              &rect));
@@ -170,7 +168,7 @@
             }
         }
         // Test small bg, large fg with Screen (uses shader blend)
-        auto mode = SkXfermode::Make(SkXfermode::kScreen_Mode);
+        SkBlendMode mode = SkBlendMode::kScreen;
         SkImageFilter::CropRect cropRect(SkRect::MakeXYWH(10, 10, 60, 60));
         sk_sp<SkImageFilter> cropped(SkOffsetImageFilter::Make(0, 0, foreground, &cropRect));
         paint.setImageFilter(SkXfermodeImageFilter::Make(mode, cropped, background, nullptr));
@@ -191,7 +189,7 @@
         // Test small fg, large bg with SrcIn with a crop that forces it to full size.
         // This tests that SkXfermodeImageFilter correctly applies the compositing mode to
         // the region outside the foreground.
-        mode = SkXfermode::Make(SkXfermode::kSrcIn_Mode);
+        mode = SkBlendMode::kSrcIn;
         SkImageFilter::CropRect cropRectFull(SkRect::MakeXYWH(0, 0, 80, 80));
         paint.setImageFilter(SkXfermodeImageFilter::Make(mode, background,
                                                          cropped, &cropRectFull));
diff --git a/gm/xfermodes.cpp b/gm/xfermodes.cpp
index 8fbbdbe..604a767 100644
--- a/gm/xfermodes.cpp
+++ b/gm/xfermodes.cpp
@@ -34,45 +34,45 @@
 };
 
 const struct {
-    SkXfermode::Mode  fMode;
-    const char*       fLabel;
-    int               fSourceTypeMask;  // The source types to use this
+    SkBlendMode fMode;
+    const char* fLabel;
+    int         fSourceTypeMask;  // The source types to use this
     // mode with. See draw_mode for
     // an explanation of each type.
     // PDF has to play some tricks
     // to support the base modes,
     // test those more extensively.
 } gModes[] = {
-    { SkXfermode::kClear_Mode,        "Clear",        kAll_SrcType   },
-    { SkXfermode::kSrc_Mode,          "Src",          kAll_SrcType   },
-    { SkXfermode::kDst_Mode,          "Dst",          kAll_SrcType   },
-    { SkXfermode::kSrcOver_Mode,      "SrcOver",      kAll_SrcType   },
-    { SkXfermode::kDstOver_Mode,      "DstOver",      kAll_SrcType   },
-    { SkXfermode::kSrcIn_Mode,        "SrcIn",        kAll_SrcType   },
-    { SkXfermode::kDstIn_Mode,        "DstIn",        kAll_SrcType   },
-    { SkXfermode::kSrcOut_Mode,       "SrcOut",       kAll_SrcType   },
-    { SkXfermode::kDstOut_Mode,       "DstOut",       kAll_SrcType   },
-    { SkXfermode::kSrcATop_Mode,      "SrcATop",      kAll_SrcType   },
-    { SkXfermode::kDstATop_Mode,      "DstATop",      kAll_SrcType   },
+    { SkBlendMode::kClear,        "Clear",        kAll_SrcType   },
+    { SkBlendMode::kSrc,          "Src",          kAll_SrcType   },
+    { SkBlendMode::kDst,          "Dst",          kAll_SrcType   },
+    { SkBlendMode::kSrcOver,      "SrcOver",      kAll_SrcType   },
+    { SkBlendMode::kDstOver,      "DstOver",      kAll_SrcType   },
+    { SkBlendMode::kSrcIn,        "SrcIn",        kAll_SrcType   },
+    { SkBlendMode::kDstIn,        "DstIn",        kAll_SrcType   },
+    { SkBlendMode::kSrcOut,       "SrcOut",       kAll_SrcType   },
+    { SkBlendMode::kDstOut,       "DstOut",       kAll_SrcType   },
+    { SkBlendMode::kSrcATop,      "SrcATop",      kAll_SrcType   },
+    { SkBlendMode::kDstATop,      "DstATop",      kAll_SrcType   },
 
-    { SkXfermode::kXor_Mode,          "Xor",          kBasic_SrcType },
-    { SkXfermode::kPlus_Mode,         "Plus",         kBasic_SrcType },
-    { SkXfermode::kModulate_Mode,     "Modulate",     kAll_SrcType   },
-    { SkXfermode::kScreen_Mode,       "Screen",       kBasic_SrcType },
-    { SkXfermode::kOverlay_Mode,      "Overlay",      kBasic_SrcType },
-    { SkXfermode::kDarken_Mode,       "Darken",       kBasic_SrcType },
-    { SkXfermode::kLighten_Mode,      "Lighten",      kBasic_SrcType },
-    { SkXfermode::kColorDodge_Mode,   "ColorDodge",   kBasic_SrcType },
-    { SkXfermode::kColorBurn_Mode,    "ColorBurn",    kBasic_SrcType },
-    { SkXfermode::kHardLight_Mode,    "HardLight",    kBasic_SrcType },
-    { SkXfermode::kSoftLight_Mode,    "SoftLight",    kBasic_SrcType },
-    { SkXfermode::kDifference_Mode,   "Difference",   kBasic_SrcType },
-    { SkXfermode::kExclusion_Mode,    "Exclusion",    kBasic_SrcType },
-    { SkXfermode::kMultiply_Mode,     "Multiply",     kAll_SrcType   },
-    { SkXfermode::kHue_Mode,          "Hue",          kBasic_SrcType },
-    { SkXfermode::kSaturation_Mode,   "Saturation",   kBasic_SrcType },
-    { SkXfermode::kColor_Mode,        "Color",        kBasic_SrcType },
-    { SkXfermode::kLuminosity_Mode,   "Luminosity",   kBasic_SrcType },
+    { SkBlendMode::kXor,          "Xor",          kBasic_SrcType },
+    { SkBlendMode::kPlus,         "Plus",         kBasic_SrcType },
+    { SkBlendMode::kModulate,     "Modulate",     kAll_SrcType   },
+    { SkBlendMode::kScreen,       "Screen",       kBasic_SrcType },
+    { SkBlendMode::kOverlay,      "Overlay",      kBasic_SrcType },
+    { SkBlendMode::kDarken,       "Darken",       kBasic_SrcType },
+    { SkBlendMode::kLighten,      "Lighten",      kBasic_SrcType },
+    { SkBlendMode::kColorDodge,   "ColorDodge",   kBasic_SrcType },
+    { SkBlendMode::kColorBurn,    "ColorBurn",    kBasic_SrcType },
+    { SkBlendMode::kHardLight,    "HardLight",    kBasic_SrcType },
+    { SkBlendMode::kSoftLight,    "SoftLight",    kBasic_SrcType },
+    { SkBlendMode::kDifference,   "Difference",   kBasic_SrcType },
+    { SkBlendMode::kExclusion,    "Exclusion",    kBasic_SrcType },
+    { SkBlendMode::kMultiply,     "Multiply",     kAll_SrcType   },
+    { SkBlendMode::kHue,          "Hue",          kBasic_SrcType },
+    { SkBlendMode::kSaturation,   "Saturation",   kBasic_SrcType },
+    { SkBlendMode::kColor,        "Color",        kBasic_SrcType },
+    { SkBlendMode::kLuminosity,   "Luminosity",   kBasic_SrcType },
 };
 
 static void make_bitmaps(int w, int h, SkBitmap* src, SkBitmap* dst,
@@ -118,15 +118,14 @@
      * uses the implied shape of the drawing command and these modes
      * demonstrate that.
      */
-    void draw_mode(SkCanvas* canvas, SkXfermode::Mode mode, SrcType srcType,
-                   SkScalar x, SkScalar y) {
+    void draw_mode(SkCanvas* canvas, SkBlendMode mode, SrcType srcType, SkScalar x, SkScalar y) {
         SkPaint p;
         SkMatrix m;
         bool restoreNeeded = false;
         m.setTranslate(x, y);
 
         canvas->drawBitmap(fSrcB, x, y, &p);
-        p.setXfermodeMode(mode);
+        p.setBlendMode(mode);
         switch (srcType) {
             case kSmallTransparentImage_SrcType: {
                 m.postScale(SK_ScalarHalf, SK_ScalarHalf, x, y);
@@ -141,7 +140,7 @@
                                                  SkIntToScalar(H));
                 canvas->saveLayer(&bounds, &p);
                 restoreNeeded = true;
-                p.setXfermodeMode(SkXfermode::kSrcOver_Mode);
+                p.setBlendMode(SkBlendMode::kSrcOver);
                 // Fall through.
             }
             case kQuarterClear_SrcType: {
diff --git a/gm/xfermodes2.cpp b/gm/xfermodes2.cpp
index 6f7d054..03da0d3 100644
--- a/gm/xfermodes2.cpp
+++ b/gm/xfermodes2.cpp
@@ -40,7 +40,7 @@
 
         SkScalar x = 0, y = 0;
         for (size_t m = 0; m <= SkXfermode::kLastMode; m++) {
-            SkXfermode::Mode mode = static_cast<SkXfermode::Mode>(m);
+            SkBlendMode mode = static_cast<SkBlendMode>(m);
 
             canvas->save();
 
@@ -57,7 +57,7 @@
             p.setShader(fDst);
             canvas->drawRect(r, p);
             p.setShader(fSrc);
-            p.setXfermode(SkXfermode::Make(mode));
+            p.setBlendMode(mode);
             canvas->drawRect(r, p);
 
             canvas->restore();
@@ -65,7 +65,7 @@
             r.inset(-SK_ScalarHalf, -SK_ScalarHalf);
             p.setStyle(SkPaint::kStroke_Style);
             p.setShader(nullptr);
-            p.setXfermode(nullptr);
+            p.setBlendMode(SkBlendMode::kSrcOver);
             canvas->drawRect(r, p);
 
             canvas->restore();
diff --git a/gm/xfermodes3.cpp b/gm/xfermodes3.cpp
index 300b78f..36702bf 100644
--- a/gm/xfermodes3.cpp
+++ b/gm/xfermodes3.cpp
@@ -69,7 +69,7 @@
         };
         for (size_t s = 0; s < SK_ARRAY_COUNT(kStrokes); ++s) {
             for (size_t m = 0; m <= SkXfermode::kLastMode; ++m) {
-                SkXfermode::Mode mode = static_cast<SkXfermode::Mode>(m);
+                SkBlendMode mode = static_cast<SkBlendMode>(m);
                 canvas->drawText(SkXfermode::ModeName(mode),
                                  strlen(SkXfermode::ModeName(mode)),
                                  SkIntToScalar(x),
@@ -77,7 +77,7 @@
                                  labelP);
                 for (size_t c = 0; c < SK_ARRAY_COUNT(kSolidColors); ++c) {
                     SkPaint modePaint;
-                    modePaint.setXfermodeMode(mode);
+                    modePaint.setBlendMode(mode);
                     modePaint.setColor(kSolidColors[c]);
                     modePaint.setStyle(kStrokes[s].fStyle);
                     modePaint.setStrokeWidth(kStrokes[s].fWidth);
@@ -93,7 +93,7 @@
                 }
                 for (size_t a = 0; a < SK_ARRAY_COUNT(kBmpAlphas); ++a) {
                     SkPaint modePaint;
-                    modePaint.setXfermodeMode(mode);
+                    modePaint.setBlendMode(mode);
                     modePaint.setAlpha(kBmpAlphas[a]);
                     modePaint.setShader(fBmpShader);
                     modePaint.setStyle(kStrokes[s].fStyle);
diff --git a/gyp/skia_for_android_framework_defines.gypi b/gyp/skia_for_android_framework_defines.gypi
index de2f541..2c24e75 100644
--- a/gyp/skia_for_android_framework_defines.gypi
+++ b/gyp/skia_for_android_framework_defines.gypi
@@ -33,6 +33,7 @@
       'SK_SUPPORT_LEGACY_STREAM_DATA',
       'SK_SUPPORT_LEGACY_CLIP_REGIONOPS',
       'SK_SUPPORT_LEGACY_SHADER_ISABITMAP',
+      'SK_SUPPORT_LEGACY_XFERMODE_OBJECT',
     ],
   },
 }
diff --git a/include/core/SkBlendMode.h b/include/core/SkBlendMode.h
new file mode 100644
index 0000000..eb3469f
--- /dev/null
+++ b/include/core/SkBlendMode.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkBlendMode_DEFINED
+#define SkBlendMode_DEFINED
+
+enum class SkBlendMode {
+    kClear,    //!< [0, 0]
+    kSrc,      //!< [Sa, Sc]
+    kDst,      //!< [Da, Dc]
+    kSrcOver,  //!< [Sa + Da * (1 - Sa), Sc + Dc * (1 - Sa)]
+    kDstOver,  //!< [Da + Sa * (1 - Da), Dc + Sc * (1 - Da)]
+    kSrcIn,    //!< [Sa * Da, Sc * Da]
+    kDstIn,    //!< [Da * Sa, Dc * Sa]
+    kSrcOut,   //!< [Sa * (1 - Da), Sc * (1 - Da)]
+    kDstOut,   //!< [Da * (1 - Sa), Dc * (1 - Sa)]
+    kSrcATop,  //!< [Da, Sc * Da + Dc * (1 - Sa)]
+    kDstATop,  //!< [Sa, Dc * Sa + Sc * (1 - Da)]
+    kXor,      //!< [Sa + Da - 2 * Sa * Da, Sc * (1 - Da) + Dc * (1 - Sa)]
+    kPlus,     //!< [Sa + Da, Sc + Dc]
+    kModulate, // multiplies all components (= alpha and color)
+
+    // Following blend modes are defined in the CSS Compositing standard:
+    // https://dvcs.w3.org/hg/FXTF/rawfile/tip/compositing/index.html#blending
+    kScreen,
+    kLastCoeffMode = kScreen,
+
+    kOverlay,
+    kDarken,
+    kLighten,
+    kColorDodge,
+    kColorBurn,
+    kHardLight,
+    kSoftLight,
+    kDifference,
+    kExclusion,
+    kMultiply,
+    kLastSeparableMode = kMultiply,
+
+    kHue,
+    kSaturation,
+    kColor,
+    kLuminosity,
+    kLastMode = kLuminosity
+};
+
+#endif
diff --git a/include/core/SkCanvas.h b/include/core/SkCanvas.h
index 8d98e50..5078f42 100644
--- a/include/core/SkCanvas.h
+++ b/include/core/SkCanvas.h
@@ -9,6 +9,7 @@
 #define SkCanvas_DEFINED
 
 #include "SkTypes.h"
+#include "SkBlendMode.h"
 #include "SkBitmap.h"
 #include "SkClipOp.h"
 #include "SkDeque.h"
@@ -595,22 +596,31 @@
         @param b    the blue component (0..255) of the color to fill the canvas
         @param mode the mode to apply the color in (defaults to SrcOver)
     */
-    void drawARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b,
-                  SkXfermode::Mode mode = SkXfermode::kSrcOver_Mode);
+    void drawARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b, SkBlendMode mode = SkBlendMode::kSrcOver);
+#ifdef SK_SUPPORT_LEGACY_XFERMODE_OBJECT
+    void drawARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b, SkXfermode::Mode mode) {
+        this->drawARGB(a, r, g, b, (SkBlendMode)mode);
+    }
+#endif
 
     /** Fill the entire canvas' bitmap (restricted to the current clip) with the
         specified color and mode.
         @param color    the color to draw with
         @param mode the mode to apply the color in (defaults to SrcOver)
     */
-    void drawColor(SkColor color, SkXfermode::Mode mode = SkXfermode::kSrcOver_Mode);
+    void drawColor(SkColor color, SkBlendMode mode = SkBlendMode::kSrcOver);
+#ifdef SK_SUPPORT_LEGACY_XFERMODE_OBJECT
+    void drawColor(SkColor color, SkXfermode::Mode mode) {
+        this->drawColor(color, (SkBlendMode)mode);
+    }
+#endif
 
     /**
      *  Helper method for drawing a color in SRC mode, completely replacing all the pixels
      *  in the current clip with this color.
      */
     void clear(SkColor color) {
-        this->drawColor(color, SkXfermode::kSrc_Mode);
+        this->drawColor(color, SkBlendMode::kSrc);
     }
 
     /**
diff --git a/include/core/SkColorFilter.h b/include/core/SkColorFilter.h
index 609550f..5a23a34 100644
--- a/include/core/SkColorFilter.h
+++ b/include/core/SkColorFilter.h
@@ -115,6 +115,9 @@
                     or NULL if the mode will have no effect.
     */
     static sk_sp<SkColorFilter> MakeModeFilter(SkColor c, SkXfermode::Mode mode);
+    static sk_sp<SkColorFilter> MakeModeFilter(SkColor c, SkBlendMode mode) {
+        return MakeModeFilter(c, (SkXfermode::Mode)mode);
+    }
 
     /** Construct a colorfilter whose effect is to first apply the inner filter and then apply
      *  the outer filter to the result of the inner's.
diff --git a/include/core/SkPaint.h b/include/core/SkPaint.h
index e28d2fc..ddc90ae 100644
--- a/include/core/SkPaint.h
+++ b/include/core/SkPaint.h
@@ -8,11 +8,14 @@
 #ifndef SkPaint_DEFINED
 #define SkPaint_DEFINED
 
+#include "SkBlendMode.h"
 #include "SkColor.h"
 #include "SkFilterQuality.h"
 #include "SkMatrix.h"
 #include "SkXfermode.h"
 
+//#define SK_SUPPORT_LEGACY_XFERMODE_OBJECT
+
 class SkAutoDescriptor;
 class SkAutoGlyphCache;
 class SkColorFilter;
@@ -525,12 +528,13 @@
 #endif
     void setColorFilter(sk_sp<SkColorFilter>);
 
+#ifdef SK_SUPPORT_LEGACY_XFERMODE_OBJECT
     /** Get the paint's xfermode object.
         <p />
       The xfermode's reference count is not affected.
         @return the paint's xfermode (or NULL)
     */
-    SkXfermode* getXfermode() const { return fXfermode.get(); }
+    SkXfermode* getXfermode() const;
 
     /** Set or clear the xfermode object.
         <p />
@@ -552,6 +556,11 @@
         the paint's xfermode is set to null.
      */
     SkXfermode* setXfermodeMode(SkXfermode::Mode);
+#endif
+
+    SkBlendMode getBlendMode() const { return (SkBlendMode)fBlendMode; }
+    bool isSrcOver() const { return (SkBlendMode)fBlendMode == SkBlendMode::kSrcOver; }
+    void setBlendMode(SkBlendMode mode) { fBlendMode = (unsigned)mode; }
 
     /** Get the paint's patheffect object.
         <p />
@@ -1090,7 +1099,6 @@
     sk_sp<SkTypeface>     fTypeface;
     sk_sp<SkPathEffect>   fPathEffect;
     sk_sp<SkShader>       fShader;
-    sk_sp<SkXfermode>     fXfermode;
     sk_sp<SkMaskFilter>   fMaskFilter;
     sk_sp<SkColorFilter>  fColorFilter;
     sk_sp<SkRasterizer>   fRasterizer;
@@ -1103,6 +1111,7 @@
     SkColor         fColor;
     SkScalar        fWidth;
     SkScalar        fMiterLimit;
+    uint32_t        fBlendMode; // just need 5-6 bits for SkXfermode::Mode
     union {
         struct {
             // all of these bitfields should add up to 32
diff --git a/include/core/SkPicture.h b/include/core/SkPicture.h
index c398d3a..c2d05f9 100644
--- a/include/core/SkPicture.h
+++ b/include/core/SkPicture.h
@@ -224,10 +224,11 @@
     // V47: Add occluder rect to SkBlurMaskFilter
     // V48: Read and write extended SkTextBlobs.
     // V49: Gradients serialized as SkColor4f + SkColorSpace
+    // V50: SkXfermode -> SkBlendMode
 
     // Only SKPs within the min/current picture version range (inclusive) can be read.
     static const uint32_t     MIN_PICTURE_VERSION = 35;     // Produced by Chrome M39.
-    static const uint32_t CURRENT_PICTURE_VERSION = 49;
+    static const uint32_t CURRENT_PICTURE_VERSION = 50;
 
     static_assert(MIN_PICTURE_VERSION <= 41,
                   "Remove kFontFileName and related code from SkFontDescriptor.cpp.");
diff --git a/include/core/SkXfermode.h b/include/core/SkXfermode.h
index 2d12b3c..8319ad6 100644
--- a/include/core/SkXfermode.h
+++ b/include/core/SkXfermode.h
@@ -8,8 +8,9 @@
 #ifndef SkXfermode_DEFINED
 #define SkXfermode_DEFINED
 
-#include "SkFlattenable.h"
+#include "SkBlendMode.h"
 #include "SkColor.h"
+#include "SkFlattenable.h"
 
 class GrFragmentProcessor;
 class GrTexture;
@@ -112,6 +113,9 @@
      * Gets the name of the Mode as a string.
      */
     static const char* ModeName(Mode);
+    static const char* ModeName(SkBlendMode mode) {
+        return ModeName(Mode(mode));
+    }
 
     /**
      *  If the xfermode is one of the modes in the Mode enum, then asMode()
@@ -157,6 +161,31 @@
     }
 #endif
 
+    /**
+     *  Skia maintains global xfermode objects corresponding to each BlendMode. This returns a
+     *  ptr to that global xfermode (or null if the mode is srcover). Thus the caller may use
+     *  the returned ptr, but it should leave its refcnt untouched.
+     */
+    static SkXfermode* Peek(SkBlendMode mode) {
+        sk_sp<SkXfermode> xfer = Make(mode);
+        if (!xfer) {
+            SkASSERT(SkBlendMode::kSrcOver == mode);
+            return nullptr;
+        }
+        SkASSERT(!xfer->unique());
+        return xfer.get();
+    }
+
+    static sk_sp<SkXfermode> Make(SkBlendMode bm) {
+        return Make((Mode)bm);
+    }
+
+    SkBlendMode blend() const {
+        Mode mode;
+        SkAssertResult(this->asMode(&mode));
+        return (SkBlendMode)mode;
+    }
+
     /** Return a function pointer to a routine that applies the specified
         porter-duff transfer mode.
      */
@@ -215,6 +244,7 @@
     static bool IsOpaque(const sk_sp<SkXfermode>& xfer, SrcColorOpacity opacityType) {
         return IsOpaque(xfer.get(), opacityType);
     }
+    static bool IsOpaque(SkBlendMode, SrcColorOpacity);
 
 #if SK_SUPPORT_GPU
     /** Used by the SkXfermodeImageFilter to blend two colors via a GrFragmentProcessor.
diff --git a/include/effects/SkXfermodeImageFilter.h b/include/effects/SkXfermodeImageFilter.h
index 6066b8d..fa9c857 100644
--- a/include/effects/SkXfermodeImageFilter.h
+++ b/include/effects/SkXfermodeImageFilter.h
@@ -8,6 +8,7 @@
 #ifndef SkXfermodeImageFilter_DEFINED
 #define SkXfermodeImageFilter_DEFINED
 
+#include "SkBlendMode.h"
 #include "SkImageFilter.h"
 
 class SkXfermode;
@@ -19,11 +20,11 @@
  */
 class SK_API SkXfermodeImageFilter {
 public:
-    static sk_sp<SkImageFilter> Make(sk_sp<SkXfermode> mode, sk_sp<SkImageFilter> background,
+    static sk_sp<SkImageFilter> Make(SkBlendMode, sk_sp<SkImageFilter> background,
                                      sk_sp<SkImageFilter> foreground,
                                      const SkImageFilter::CropRect* cropRect);
-    static sk_sp<SkImageFilter> Make(sk_sp<SkXfermode> mode, sk_sp<SkImageFilter> background) {
-        return Make(std::move(mode), std::move(background), nullptr, nullptr);
+    static sk_sp<SkImageFilter> Make(SkBlendMode mode, sk_sp<SkImageFilter> background) {
+        return Make(mode, std::move(background), nullptr, nullptr);
     }
 
     static sk_sp<SkImageFilter> MakeArithmetic(float k1, float k2, float k3, float k4,
@@ -38,6 +39,16 @@
                               nullptr, nullptr);
     }
 
+#ifdef SK_SUPPORT_LEGACY_XFERMODE_OBJECT
+    static sk_sp<SkImageFilter> Make(sk_sp<SkXfermode> mode, sk_sp<SkImageFilter> background,
+                                     sk_sp<SkImageFilter> foreground,
+                                     const SkImageFilter::CropRect* cropRect);
+    static sk_sp<SkImageFilter> Make(sk_sp<SkXfermode> mode, sk_sp<SkImageFilter> background) {
+        return Make(std::move(mode), std::move(background), nullptr, nullptr);
+    }
+
+#endif
+
 #ifdef SK_SUPPORT_LEGACY_XFERMODE_PTR
     static SkImageFilter* Create(SkXfermode* mode, SkImageFilter* background,
                                  SkImageFilter* foreground = NULL,
diff --git a/include/gpu/GrPaint.h b/include/gpu/GrPaint.h
index 6120348..a8af3c2 100644
--- a/include/gpu/GrPaint.h
+++ b/include/gpu/GrPaint.h
@@ -16,9 +16,9 @@
 #include "effects/GrPorterDuffXferProcessor.h"
 #include "GrFragmentProcessor.h"
 
+#include "SkBlendMode.h"
 #include "SkRefCnt.h"
 #include "SkRegion.h"
-#include "SkXfermode.h"
 
 /**
  * The paint describes how color and coverage are computed at each pixel by GrContext draw
@@ -95,6 +95,10 @@
         fXPFactory = std::move(xpFactory);
     }
 
+    void setPorterDuffXPFactory(SkBlendMode mode) {
+        fXPFactory = GrPorterDuffXPFactory::Make((SkXfermode::Mode)mode);
+    }
+
     void setPorterDuffXPFactory(SkXfermode::Mode mode) {
         fXPFactory = GrPorterDuffXPFactory::Make(mode);
     }
diff --git a/include/gpu/effects/GrPorterDuffXferProcessor.h b/include/gpu/effects/GrPorterDuffXferProcessor.h
index 8399d58..6777d76 100644
--- a/include/gpu/effects/GrPorterDuffXferProcessor.h
+++ b/include/gpu/effects/GrPorterDuffXferProcessor.h
@@ -17,6 +17,9 @@
 class GrPorterDuffXPFactory : public GrXPFactory {
 public:
     static sk_sp<GrXPFactory> Make(SkXfermode::Mode mode);
+    static sk_sp<GrXPFactory> Make(SkBlendMode mode) {
+        return Make((SkXfermode::Mode)mode);
+    }
 
     void getInvariantBlendedColor(const GrProcOptInfo& colorPOI,
                                   GrXPFactory::InvariantBlendedColor*) const override;
diff --git a/public.bzl b/public.bzl
index a34f76e..0e7a065 100644
--- a/public.bzl
+++ b/public.bzl
@@ -618,6 +618,7 @@
     "SK_SUPPORT_LEGACY_TEXTBLOB_BUILDER",
     "SK_SUPPORT_LEGACY_CLIP_REGIONOPS",
     "SK_SUPPORT_LEGACY_SHADER_ISABITMAP",
+    "SK_SUPPORT_LEGACY_XFERMODE_OBJECT",
 ]
 
 ################################################################################
diff --git a/samplecode/SampleAARectModes.cpp b/samplecode/SampleAARectModes.cpp
index 65b1da1..0a50303 100644
--- a/samplecode/SampleAARectModes.cpp
+++ b/samplecode/SampleAARectModes.cpp
@@ -12,21 +12,21 @@
 #include "SkShader.h"
 
 static const struct {
-    SkXfermode::Mode  fMode;
-    const char*         fLabel;
+    SkBlendMode fMode;
+    const char* fLabel;
 } gModes[] = {
-    { SkXfermode::kClear_Mode,    "Clear"     },
-    { SkXfermode::kSrc_Mode,      "Src"       },
-    { SkXfermode::kDst_Mode,      "Dst"       },
-    { SkXfermode::kSrcOver_Mode,  "SrcOver"   },
-    { SkXfermode::kDstOver_Mode,  "DstOver"   },
-    { SkXfermode::kSrcIn_Mode,    "SrcIn"     },
-    { SkXfermode::kDstIn_Mode,    "DstIn"     },
-    { SkXfermode::kSrcOut_Mode,   "SrcOut"    },
-    { SkXfermode::kDstOut_Mode,   "DstOut"    },
-    { SkXfermode::kSrcATop_Mode,  "SrcATop"   },
-    { SkXfermode::kDstATop_Mode,  "DstATop"   },
-    { SkXfermode::kXor_Mode,      "Xor"       },
+    { SkBlendMode::kClear,    "Clear"     },
+    { SkBlendMode::kSrc,      "Src"       },
+    { SkBlendMode::kDst,      "Dst"       },
+    { SkBlendMode::kSrcOver,  "SrcOver"   },
+    { SkBlendMode::kDstOver,  "DstOver"   },
+    { SkBlendMode::kSrcIn,    "SrcIn"     },
+    { SkBlendMode::kDstIn,    "DstIn"     },
+    { SkBlendMode::kSrcOut,   "SrcOut"    },
+    { SkBlendMode::kDstOut,   "DstOut"    },
+    { SkBlendMode::kSrcATop,  "SrcATop"   },
+    { SkBlendMode::kDstATop,  "DstATop"   },
+    { SkBlendMode::kXor,      "Xor"       },
 };
 
 const int gWidth = 64;
@@ -34,7 +34,7 @@
 const SkScalar W = SkIntToScalar(gWidth);
 const SkScalar H = SkIntToScalar(gHeight);
 
-static SkScalar drawCell(SkCanvas* canvas, const sk_sp<SkXfermode>& mode, SkAlpha a0, SkAlpha a1) {
+static SkScalar drawCell(SkCanvas* canvas, SkBlendMode 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.setBlendMode(mode);
 
     SkScalar offset = SK_Scalar1 / 3;
     SkRect rect = SkRect::MakeXYWH(W / 4 + offset,
@@ -106,11 +106,10 @@
                     canvas->translate(W * 5, 0);
                     canvas->save();
                 }
-                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, gModes[i].fMode, gAlphaValue[alpha & 1],
                                        gAlphaValue[alpha & 2]);
                 canvas->restore();
 
diff --git a/samplecode/SampleAll.cpp b/samplecode/SampleAll.cpp
index 29b5c66..8c1ace5 100644
--- a/samplecode/SampleAll.cpp
+++ b/samplecode/SampleAll.cpp
@@ -89,7 +89,7 @@
 
     p.setAlpha(0x11);
     p.setStyle(SkPaint::kFill_Style);
-    p.setXfermodeMode(SkXfermode::kSrc_Mode);
+    p.setBlendMode(SkBlendMode::kSrc);
     rastBuilder->addLayer(p);
 }
 
@@ -97,7 +97,7 @@
     rastBuilder->addLayer(p);
 
     p.setAlpha(0x40);
-    p.setXfermodeMode(SkXfermode::kSrc_Mode);
+    p.setBlendMode(SkBlendMode::kSrc);
     p.setStyle(SkPaint::kStroke_Style);
     p.setStrokeWidth(SK_Scalar1*2);
     rastBuilder->addLayer(p);
@@ -110,7 +110,7 @@
 
     p.setStyle(SkPaint::kStroke_Style);
     p.setStrokeWidth(SK_Scalar1*3/2);
-    p.setXfermodeMode(SkXfermode::kClear_Mode);
+    p.setBlendMode(SkBlendMode::kClear);
     rastBuilder->addLayer(p);
 }
 
@@ -121,7 +121,7 @@
 
     p.setAlpha(0x20);
     p.setStyle(SkPaint::kFill_Style);
-    p.setXfermodeMode(SkXfermode::kSrc_Mode);
+    p.setBlendMode(SkBlendMode::kSrc);
     rastBuilder->addLayer(p);
 }
 
@@ -130,10 +130,10 @@
     rastBuilder->addLayer(p, SkIntToScalar(3), SkIntToScalar(3));
 
     p.setAlpha(0xFF);
-    p.setXfermodeMode(SkXfermode::kClear_Mode);
+    p.setBlendMode(SkBlendMode::kClear);
     rastBuilder->addLayer(p, SK_Scalar1*3/2, SK_Scalar1*3/2);
 
-    p.setXfermode(nullptr);
+    p.setBlendMode(SkBlendMode::kSrcOver);
     rastBuilder->addLayer(p);
 }
 
@@ -141,7 +141,7 @@
     rastBuilder->addLayer(p);
 
     p.setPathEffect(SkDiscretePathEffect::Make(SK_Scalar1*4, SK_Scalar1*3));
-    p.setXfermodeMode(SkXfermode::kSrcOut_Mode);
+    p.setBlendMode(SkBlendMode::kSrcOut);
     rastBuilder->addLayer(p);
 }
 
@@ -152,7 +152,7 @@
     SkLayerRasterizer::Builder rastBuilder2;
     r5(&rastBuilder2, p);
     p.setRasterizer(rastBuilder2.detach());
-    p.setXfermodeMode(SkXfermode::kClear_Mode);
+    p.setBlendMode(SkBlendMode::kClear);
     rastBuilder->addLayer(p);
 }
 
@@ -194,11 +194,11 @@
     lattice.setScale(SK_Scalar1*6, SK_Scalar1*6, 0, 0);
     lattice.postSkew(SK_Scalar1/3, 0, 0, 0);
     p.setPathEffect(sk_make_sp<Dot2DPathEffect>(SK_Scalar1*2, lattice));
-    p.setXfermodeMode(SkXfermode::kClear_Mode);
+    p.setBlendMode(SkBlendMode::kClear);
     rastBuilder->addLayer(p);
 
     p.setPathEffect(nullptr);
-    p.setXfermode(nullptr);
+    p.setBlendMode(SkBlendMode::kSrcOver);
     p.setStyle(SkPaint::kStroke_Style);
     p.setStrokeWidth(SK_Scalar1);
     rastBuilder->addLayer(p);
@@ -211,11 +211,11 @@
     lattice.setScale(SK_Scalar1, SK_Scalar1*6, 0, 0);
     lattice.postRotate(SkIntToScalar(30), 0, 0);
     p.setPathEffect(SkLine2DPathEffect::Make(SK_Scalar1*2, lattice));
-    p.setXfermodeMode(SkXfermode::kClear_Mode);
+    p.setBlendMode(SkBlendMode::kClear);
     rastBuilder->addLayer(p);
 
     p.setPathEffect(nullptr);
-    p.setXfermode(nullptr);
+    p.setBlendMode(SkBlendMode::kSrcOver);
     p.setStyle(SkPaint::kStroke_Style);
     p.setStrokeWidth(SK_Scalar1);
     rastBuilder->addLayer(p);
@@ -401,10 +401,10 @@
         paint.setColor(SK_ColorGREEN);
         paint.setStrokeWidth(SkIntToScalar(10));
         paint.setStyle(SkPaint::kStroke_Style);
-        paint.setXfermode(SkXfermode::Make(SkXfermode::kXor_Mode));
+        paint.setBlendMode(SkBlendMode::kXor);
         paint.setColorFilter(lightingFilter);
         canvas->drawLine(start.fX, start.fY, stop.fX, stop.fY, paint); // should not be green
-        paint.setXfermode(nullptr);
+        paint.setBlendMode(SkBlendMode::kSrcOver);
         paint.setColorFilter(nullptr);
 
         // rectangle
diff --git a/samplecode/SampleApp.cpp b/samplecode/SampleApp.cpp
index 233306c..d2374f5 100644
--- a/samplecode/SampleApp.cpp
+++ b/samplecode/SampleApp.cpp
@@ -351,7 +351,7 @@
             bool doGamma = (fActualColorBits == 30) && SkImageInfoIsGammaCorrect(win->info());
 
             SkPaint gammaPaint;
-            gammaPaint.setXfermodeMode(SkXfermode::kSrc_Mode);
+            gammaPaint.setBlendMode(SkBlendMode::kSrc);
             if (doGamma) {
                 gammaPaint.setColorFilter(SkGammaColorFilter::Make(1.0f / 2.2f));
             }
diff --git a/samplecode/SampleColorFilter.cpp b/samplecode/SampleColorFilter.cpp
index 3da77a4..67c7b2e 100644
--- a/samplecode/SampleColorFilter.cpp
+++ b/samplecode/SampleColorFilter.cpp
@@ -100,7 +100,7 @@
     canvas.drawOval(r, paint);
 
     r.inset(SK_Scalar1*n/4, SK_Scalar1*n/4);
-    paint.setXfermodeMode(SkXfermode::kSrc_Mode);
+    paint.setBlendMode(SkBlendMode::kSrc);
     paint.setColor(0x800000FF);
     canvas.drawOval(r, paint);
 
diff --git a/samplecode/SampleFatBits.cpp b/samplecode/SampleFatBits.cpp
index 8da6058..82eb25f 100644
--- a/samplecode/SampleFatBits.cpp
+++ b/samplecode/SampleFatBits.cpp
@@ -163,7 +163,7 @@
         canvas->restore();
 
         SkPaint paint;
-        paint.setXfermodeMode(SkXfermode::kClear_Mode);
+        paint.setBlendMode(SkBlendMode::kClear);
         for (int iy = 1; iy < fH; ++iy) {
             SkScalar y = SkIntToScalar(iy * fZoom);
             canvas->drawLine(0, y - SK_ScalarHalf, 999, y - SK_ScalarHalf, paint);
diff --git a/samplecode/SampleFilterFuzz.cpp b/samplecode/SampleFilterFuzz.cpp
index 755e8fb..28aa5f4 100644
--- a/samplecode/SampleFilterFuzz.cpp
+++ b/samplecode/SampleFilterFuzz.cpp
@@ -157,8 +157,8 @@
     return m;
 }
 
-static SkXfermode::Mode make_xfermode() {
-    return static_cast<SkXfermode::Mode>(R(SkXfermode::kLastMode+1));
+static SkBlendMode make_xfermode() {
+    return static_cast<SkBlendMode>(R(SkXfermode::kLastMode+1));
 }
 
 static SkPaint::Align make_paint_align() {
@@ -508,7 +508,7 @@
     paint.setStrokeCap(make_paint_cap());
     paint.setStrokeJoin(make_paint_join());
     paint.setColorFilter(make_color_filter());
-    paint.setXfermodeMode(make_xfermode());
+    paint.setBlendMode(make_xfermode());
     paint.setPathEffect(make_path_effect());
     paint.setMaskFilter(make_mask_filter());
 
@@ -558,7 +558,7 @@
     case MERGE:
         filter = SkMergeImageFilter::Make(make_image_filter(),
                                           make_image_filter(),
-                                          make_xfermode());
+                                          (SkXfermode::Mode)make_xfermode());
         break;
     case COLOR: {
         sk_sp<SkColorFilter> cf(make_color_filter());
@@ -585,7 +585,7 @@
                                               make_image_filter());
         break;
     case XFERMODE:
-        filter = SkXfermodeImageFilter::Make(SkXfermode::Make(make_xfermode()),
+        filter = SkXfermodeImageFilter::Make(make_xfermode(),
                                              make_image_filter(),
                                              make_image_filter(),
                                              nullptr);
diff --git a/samplecode/SampleFuzz.cpp b/samplecode/SampleFuzz.cpp
index 76420f0..c7d0578 100644
--- a/samplecode/SampleFuzz.cpp
+++ b/samplecode/SampleFuzz.cpp
@@ -153,15 +153,15 @@
       break;
 
       case 2: {
-          SkXfermode::Mode mode;
+          SkBlendMode mode;
           switch (R(3)) {
-            case 0: mode = SkXfermode::kSrc_Mode; break;
-            case 1: mode = SkXfermode::kXor_Mode; break;
+            case 0: mode = SkBlendMode::kSrc; break;
+            case 1: mode = SkBlendMode::kXor; break;
             case 2:
             default:  // silence warning
-              mode = SkXfermode::kSrcOver_Mode; break;
+              mode = SkBlendMode::kSrcOver; break;
           }
-          paint.setXfermodeMode(mode);
+          paint.setBlendMode(mode);
       }
       break;
 
diff --git a/samplecode/SampleHairModes.cpp b/samplecode/SampleHairModes.cpp
index 26037d7..5eeb6cb 100644
--- a/samplecode/SampleHairModes.cpp
+++ b/samplecode/SampleHairModes.cpp
@@ -12,21 +12,21 @@
 #include "SkShader.h"
 
 static const struct {
-    SkXfermode::Mode  fMode;
-    const char*         fLabel;
+    SkBlendMode fMode;
+    const char* fLabel;
 } gModes[] = {
-    { SkXfermode::kClear_Mode,    "Clear"     },
-    { SkXfermode::kSrc_Mode,      "Src"       },
-    { SkXfermode::kDst_Mode,      "Dst"       },
-    { SkXfermode::kSrcOver_Mode,  "SrcOver"   },
-    { SkXfermode::kDstOver_Mode,  "DstOver"   },
-    { SkXfermode::kSrcIn_Mode,    "SrcIn"     },
-    { SkXfermode::kDstIn_Mode,    "DstIn"     },
-    { SkXfermode::kSrcOut_Mode,   "SrcOut"    },
-    { SkXfermode::kDstOut_Mode,   "DstOut"    },
-    { SkXfermode::kSrcATop_Mode,  "SrcATop"   },
-    { SkXfermode::kDstATop_Mode,  "DstATop"   },
-    { SkXfermode::kXor_Mode,      "Xor"       },
+    { SkBlendMode::kClear,    "Clear"     },
+    { SkBlendMode::kSrc,      "Src"       },
+    { SkBlendMode::kDst,      "Dst"       },
+    { SkBlendMode::kSrcOver,  "SrcOver"   },
+    { SkBlendMode::kDstOver,  "DstOver"   },
+    { SkBlendMode::kSrcIn,    "SrcIn"     },
+    { SkBlendMode::kDstIn,    "DstIn"     },
+    { SkBlendMode::kSrcOut,   "SrcOut"    },
+    { SkBlendMode::kDstOut,   "DstOut"    },
+    { SkBlendMode::kSrcATop,  "SrcATop"   },
+    { SkBlendMode::kDstATop,  "DstATop"   },
+    { SkBlendMode::kXor,      "Xor"       },
 };
 
 const int gWidth = 64;
@@ -34,7 +34,7 @@
 const SkScalar W = SkIntToScalar(gWidth);
 const SkScalar H = SkIntToScalar(gHeight);
 
-static SkScalar drawCell(SkCanvas* canvas, sk_sp<SkXfermode> mode, SkAlpha a0, SkAlpha a1) {
+static SkScalar drawCell(SkCanvas* canvas, SkBlendMode 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.setBlendMode(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;
@@ -105,7 +105,7 @@
                 }
                 canvas->drawRect(bounds, fBGPaint);
                 canvas->saveLayer(&bounds, nullptr);
-                SkScalar dy = drawCell(canvas, SkXfermode::Make(gModes[i].fMode),
+                SkScalar dy = drawCell(canvas, gModes[i].fMode,
                                        gAlphaValue[alpha & 1],
                                        gAlphaValue[alpha & 2]);
                 canvas->restore();
diff --git a/samplecode/SampleLayerMask.cpp b/samplecode/SampleLayerMask.cpp
index 5fce85c..f0c6a40 100644
--- a/samplecode/SampleLayerMask.cpp
+++ b/samplecode/SampleLayerMask.cpp
@@ -44,13 +44,13 @@
             bounds.offset(-bounds.fLeft, -bounds.fTop);
             c.drawOval(bounds, paint);
 
-            paint.setXfermodeMode(SkXfermode::kDstIn_Mode);
+            paint.setBlendMode(SkBlendMode::kDstIn);
             canvas->drawBitmap(mask, r.fLeft, r.fTop, &paint);
         } else {
             SkPath p;
             p.addOval(r);
             p.setFillType(SkPath::kInverseWinding_FillType);
-            paint.setXfermodeMode(SkXfermode::kDstOut_Mode);
+            paint.setBlendMode(SkBlendMode::kDstOut);
             canvas->drawPath(p, paint);
         }
     }
diff --git a/samplecode/SampleLayers.cpp b/samplecode/SampleLayers.cpp
index 52e6593..71b2e8b 100644
--- a/samplecode/SampleLayers.cpp
+++ b/samplecode/SampleLayers.cpp
@@ -31,7 +31,7 @@
     SkPoint pts[] = { { 0, 0 }, { 0, SK_Scalar1*20 } };
     paint->setShader(SkGradientShader::MakeLinear(pts, colors, nullptr, 2,
                                                   SkShader::kClamp_TileMode, 0, &localMatrix));
-    paint->setXfermodeMode(SkXfermode::kDstIn_Mode);
+    paint->setBlendMode(SkBlendMode::kDstIn);
 }
 
 // test drawing with strips of fading gradient above and below
@@ -141,7 +141,7 @@
             canvas->saveLayer(&r, &p);
             canvas->drawColor(0xFFFF0000);
             p.setAlpha(0);  // or 0
-            p.setXfermodeMode(SkXfermode::kSrc_Mode);
+            p.setBlendMode(SkBlendMode::kSrc);
             canvas->drawOval(r, p);
             canvas->restore();
             return;
diff --git a/samplecode/SamplePathClip.cpp b/samplecode/SamplePathClip.cpp
index a53fe71..af9608f 100644
--- a/samplecode/SamplePathClip.cpp
+++ b/samplecode/SamplePathClip.cpp
@@ -225,7 +225,7 @@
         // We use a layer, so we can PLUS the different edge-colors, showing where two edges
         // canceled each other out.
         canvas->saveLayer(nullptr, nullptr);
-        p.setXfermodeMode(SkXfermode::kPlus_Mode);
+        p.setBlendMode(SkBlendMode::kPlus);
         for (int i = 0; i < N; ++i) {
             const int j = (i + 1) % N;
             p.setColor(fEdgeColor[i]);
diff --git a/samplecode/SampleQuadStroker.cpp b/samplecode/SampleQuadStroker.cpp
index ab65ff6..30b8603 100644
--- a/samplecode/SampleQuadStroker.cpp
+++ b/samplecode/SampleQuadStroker.cpp
@@ -248,7 +248,7 @@
         canvas->restore();
 
         SkPaint paint;
-        paint.setXfermodeMode(SkXfermode::kClear_Mode);
+        paint.setBlendMode(SkBlendMode::kClear);
         for (int iy = 1; iy < fH; ++iy) {
             SkScalar y = SkIntToScalar(iy * fZoom);
             canvas->drawLine(0, y - SK_ScalarHalf, 999, y - SK_ScalarHalf, paint);
diff --git a/samplecode/SampleRegion.cpp b/samplecode/SampleRegion.cpp
index 1934dc7..082ff22 100644
--- a/samplecode/SampleRegion.cpp
+++ b/samplecode/SampleRegion.cpp
@@ -80,7 +80,7 @@
 
     SkPaint p;
     p.setShader(SkGradientShader::MakeLinear(pts, colors, pos, 3, SkShader::kClamp_TileMode));
-    p.setXfermodeMode(SkXfermode::kDstIn_Mode);
+    p.setBlendMode(SkBlendMode::kDstIn);
     canvas->drawRect(bounds, p);
 
     canvas->restore();
diff --git a/samplecode/SampleSlides.cpp b/samplecode/SampleSlides.cpp
index 5858d26..521e9f6 100644
--- a/samplecode/SampleSlides.cpp
+++ b/samplecode/SampleSlides.cpp
@@ -472,7 +472,7 @@
 
     p.setAlpha(0x11);
     p.setStyle(SkPaint::kFill_Style);
-    p.setXfermodeMode(SkXfermode::kSrc_Mode);
+    p.setBlendMode(SkBlendMode::kSrc);
     rastBuilder->addLayer(p);
 }
 
@@ -481,7 +481,7 @@
     rastBuilder->addLayer(p);
 
     p.setAlpha(0x40);
-    p.setXfermodeMode(SkXfermode::kSrc_Mode);
+    p.setBlendMode(SkBlendMode::kSrc);
     p.setStyle(SkPaint::kStroke_Style);
     p.setStrokeWidth(SK_Scalar1*2);
     rastBuilder->addLayer(p);
@@ -495,7 +495,7 @@
 
     p.setStyle(SkPaint::kStroke_Style);
     p.setStrokeWidth(SK_Scalar1*3/2);
-    p.setXfermodeMode(SkXfermode::kClear_Mode);
+    p.setBlendMode(SkBlendMode::kClear);
     rastBuilder->addLayer(p);
 }
 
@@ -507,7 +507,7 @@
 
     p.setAlpha(0x20);
     p.setStyle(SkPaint::kFill_Style);
-    p.setXfermodeMode(SkXfermode::kSrc_Mode);
+    p.setBlendMode(SkBlendMode::kSrc);
     rastBuilder->addLayer(p);
 }
 
@@ -517,10 +517,10 @@
     rastBuilder->addLayer(p, SkIntToScalar(3), SkIntToScalar(3));
 
     p.setAlpha(0xFF);
-    p.setXfermodeMode(SkXfermode::kClear_Mode);
+    p.setBlendMode(SkBlendMode::kClear);
     rastBuilder->addLayer(p, SK_Scalar1*3/2, SK_Scalar1*3/2);
 
-    p.setXfermode(nullptr);
+    p.setBlendMode(SkBlendMode::kSrcOver);
     rastBuilder->addLayer(p);
 }
 
@@ -531,7 +531,7 @@
     rastBuilder->addLayer(p);
 
     p.setPathEffect(SkDiscretePathEffect::Make(SK_Scalar1*4, SK_Scalar1*3));
-    p.setXfermodeMode(SkXfermode::kSrcOut_Mode);
+    p.setBlendMode(SkBlendMode::kSrcOut);
     rastBuilder->addLayer(p);
 }
 
@@ -543,7 +543,7 @@
     SkLayerRasterizer::Builder rastBuilder2;
     r5(&rastBuilder2, p);
     p.setRasterizer(rastBuilder2.detach());
-    p.setXfermodeMode(SkXfermode::kClear_Mode);
+    p.setBlendMode(SkBlendMode::kClear);
     rastBuilder->addLayer(p);
 }
 
@@ -572,11 +572,11 @@
     lattice.setScale(SK_Scalar1*6, SK_Scalar1*6, 0, 0);
     lattice.postSkew(SK_Scalar1/3, 0, 0, 0);
     p.setPathEffect(MakeDotEffect(SK_Scalar1*2, lattice));
-    p.setXfermodeMode(SkXfermode::kClear_Mode);
+    p.setBlendMode(SkBlendMode::kClear);
     rastBuilder->addLayer(p);
 
     p.setPathEffect(nullptr);
-    p.setXfermode(nullptr);
+    p.setBlendMode(SkBlendMode::kSrcOver);
     p.setStyle(SkPaint::kStroke_Style);
     p.setStrokeWidth(SK_Scalar1);
     rastBuilder->addLayer(p);
@@ -590,11 +590,11 @@
     lattice.setScale(SK_Scalar1, SK_Scalar1*6, 0, 0);
     lattice.postRotate(SkIntToScalar(30), 0, 0);
     p.setPathEffect(SkLine2DPathEffect::Make(SK_Scalar1*2, lattice));
-    p.setXfermodeMode(SkXfermode::kClear_Mode);
+    p.setBlendMode(SkBlendMode::kClear);
     rastBuilder->addLayer(p);
 
     p.setPathEffect(nullptr);
-    p.setXfermode(nullptr);
+    p.setBlendMode(SkBlendMode::kSrcOver);
     p.setStyle(SkPaint::kStroke_Style);
     p.setStrokeWidth(SK_Scalar1);
     rastBuilder->addLayer(p);
diff --git a/samplecode/SampleXfer.cpp b/samplecode/SampleXfer.cpp
index 6aaffe5..c0ad000 100644
--- a/samplecode/SampleXfer.cpp
+++ b/samplecode/SampleXfer.cpp
@@ -18,18 +18,18 @@
 #include "SkGradientShader.h"
 
 const struct {
-    SkXfermode::Mode fMode;
-    const char*      fName;
+    SkBlendMode fMode;
+    const char* fName;
 } gModes[] = {
-    { SkXfermode::kSrcOver_Mode, "src-over" },
-    { SkXfermode::kSrc_Mode,     "src" },
-    { SkXfermode::kSrcIn_Mode,   "src-in" },
-    { SkXfermode::kSrcOut_Mode,  "src-out" },
-    { SkXfermode::kSrcATop_Mode, "src-atop" },
-    { SkXfermode::kDstOver_Mode, "dst-over" },
-    { SkXfermode::kDstIn_Mode,   "dst-in" },
-    { SkXfermode::kDstOut_Mode,  "dst-out" },
-    { SkXfermode::kDstATop_Mode, "dst-atop" },
+    { SkBlendMode::kSrcOver, "src-over" },
+    { SkBlendMode::kSrc,     "src" },
+    { SkBlendMode::kSrcIn,   "src-in" },
+    { SkBlendMode::kSrcOut,  "src-out" },
+    { SkBlendMode::kSrcATop, "src-atop" },
+    { SkBlendMode::kDstOver, "dst-over" },
+    { SkBlendMode::kDstIn,   "dst-in" },
+    { SkBlendMode::kDstOut,  "dst-out" },
+    { SkBlendMode::kDstATop, "dst-atop" },
 };
 const int N_Modes = SK_ARRAY_COUNT(gModes);
 
@@ -109,10 +109,10 @@
 
 class ModeDrawable : public SkDrawable {
 public:
-    ModeDrawable() : fMode(SkXfermode::kSrcOver_Mode), fLoc(SkPoint::Make(0, 0)) {}
+    ModeDrawable() : fMode(SkBlendMode::kSrcOver), fLoc(SkPoint::Make(0, 0)) {}
 
-    SkXfermode::Mode fMode;
-    SkPoint          fLoc;
+    SkBlendMode fMode;
+    SkPoint     fLoc;
 
     bool hitTest(SkScalar x, SkScalar y) {
         SkRect target = SkRect::MakeXYWH(x - fLoc.x() - 1, y - fLoc.y() - 1, 3, 3);
@@ -139,7 +139,7 @@
     }
 
     void onDraw(SkCanvas* canvas) override {
-        fPaint.setXfermodeMode(fMode);
+        fPaint.setBlendMode(fMode);
         canvas->save();
         canvas->translate(fLoc.x(), fLoc.y());
         canvas->drawOval(fBounds, fPaint);
@@ -160,7 +160,7 @@
         SkScalar x = 10;
         SkScalar y = 10;
         for (int i = 0; i < N_Modes; ++i) {
-            SkAutoTUnref<SkView> v(new PushButtonWig(gModes[i].fName, gModes[i].fMode));
+            SkAutoTUnref<SkView> v(new PushButtonWig(gModes[i].fName, (int)gModes[i].fMode));
             v->setSize(70, 25);
             v->setLoc(x, y);
             v->setVisibleP(true);
@@ -178,7 +178,7 @@
         for (int i = 0; i < N; ++i) {
             fDrs[i].reset(new CircDrawable(200, colors[i]));
             fDrs[i]->fLoc.set(100.f + i * 100, 100.f + i * 100);
-            fDrs[i]->fMode = SkXfermode::kSrcOver_Mode;
+            fDrs[i]->fMode = SkBlendMode::kSrcOver;
         }
         fSelected = nullptr;
 
@@ -189,7 +189,7 @@
     bool onEvent(const SkEvent& evt) override {
         if (evt.isType("push-button")) {
             if (fSelected) {
-                fSelected->fMode = (SkXfermode::Mode)evt.getFast32();
+                fSelected->fMode = (SkBlendMode)evt.getFast32();
                 this->inval(nullptr);
             }
             return true;
diff --git a/samplecode/SampleXfermodesBlur.cpp b/samplecode/SampleXfermodesBlur.cpp
index ef25114..fe07c9b 100644
--- a/samplecode/SampleXfermodesBlur.cpp
+++ b/samplecode/SampleXfermodesBlur.cpp
@@ -37,8 +37,7 @@
     SkBitmap    fBG;
     SkBitmap    fSrcB, fDstB;
 
-    void draw_mode(SkCanvas* canvas, sk_sp<SkXfermode> mode, int alpha,
-                   SkScalar x, SkScalar y) {
+    void draw_mode(SkCanvas* canvas, SkBlendMode mode, int alpha, SkScalar x, SkScalar y) {
         SkPaint p;
         p.setMaskFilter(SkBlurMaskFilter::Make(kNormal_SkBlurStyle,
                                                SkBlurMask::ConvertRadiusToSigma(5),
@@ -55,7 +54,7 @@
         r.offset(x, y);
         canvas->drawOval(r, p);
 
-        p.setXfermode(std::move(mode));
+        p.setBlendMode(mode);
 
         // draw a square overlapping the circle
         // in the lower right of the canvas
@@ -110,34 +109,23 @@
         }
 
         const struct {
-            SkXfermode::Mode  fMode;
-            const char*         fLabel;
+            SkBlendMode fMode;
+            const char* fLabel;
         } gModes[] = {
-            { SkXfermode::kClear_Mode,    "Clear"     },
-            { SkXfermode::kSrc_Mode,      "Src"       },
-            { SkXfermode::kDst_Mode,      "Dst"       },
-            { SkXfermode::kSrcOver_Mode,  "SrcOver"   },
-            { SkXfermode::kDstOver_Mode,  "DstOver"   },
-            { SkXfermode::kSrcIn_Mode,    "SrcIn"     },
-            { SkXfermode::kDstIn_Mode,    "DstIn"     },
-            { SkXfermode::kSrcOut_Mode,   "SrcOut"    },
-            { SkXfermode::kDstOut_Mode,   "DstOut"    },
-            { SkXfermode::kSrcATop_Mode,  "SrcATop"   },
-            { SkXfermode::kDstATop_Mode,  "DstATop"   },
-            { SkXfermode::kXor_Mode,      "Xor"       },
+            { SkBlendMode::kClear,    "Clear"     },
+            { SkBlendMode::kSrc,      "Src"       },
+            { SkBlendMode::kDst,      "Dst"       },
+            { SkBlendMode::kSrcOver,  "SrcOver"   },
+            { SkBlendMode::kDstOver,  "DstOver"   },
+            { SkBlendMode::kSrcIn,    "SrcIn"     },
+            { SkBlendMode::kDstIn,    "DstIn"     },
+            { SkBlendMode::kSrcOut,   "SrcOut"    },
+            { SkBlendMode::kDstOut,   "DstOut"    },
+            { SkBlendMode::kSrcATop,  "SrcATop"   },
+            { SkBlendMode::kDstATop,  "DstATop"   },
+            { SkBlendMode::kXor,      "Xor"       },
 
-            { SkXfermode::kPlus_Mode,         "Plus"          },
-            /*{ SkXfermode::kModulate_Mode,     "Modulate"      },
-            { SkXfermode::kScreen_Mode,       "Screen"        },
-            { SkXfermode::kOverlay_Mode,      "Overlay"       },
-            { SkXfermode::kDarken_Mode,       "Darken"        },
-            { SkXfermode::kLighten_Mode,      "Lighten"       },
-            { SkXfermode::kColorDodge_Mode,   "ColorDodge"    },
-            { SkXfermode::kColorBurn_Mode,    "ColorBurn"     },
-            { SkXfermode::kHardLight_Mode,    "HardLight"     },
-            { SkXfermode::kSoftLight_Mode,    "SoftLight"     },
-            { SkXfermode::kDifference_Mode,   "Difference"    },
-            { SkXfermode::kExclusion_Mode,    "Exclusion"     },*/
+            { SkBlendMode::kPlus,     "Plus"          },
         };
 
         const SkScalar w = SkIntToScalar(W);
@@ -168,8 +156,7 @@
                 canvas->drawRect(r, p);
 
                 canvas->saveLayer(&r, nullptr);
-                draw_mode(canvas, SkXfermode::Make(gModes[i].fMode),
-                          twice ? 0x88 : 0xFF, r.fLeft, r.fTop);
+                draw_mode(canvas, gModes[i].fMode, twice ? 0x88 : 0xFF, r.fLeft, r.fTop);
                 canvas->restore();
 
                 r.inset(-SK_ScalarHalf, -SK_ScalarHalf);
diff --git a/src/c/sk_paint.cpp b/src/c/sk_paint.cpp
index f82cd81..126170c 100644
--- a/src/c/sk_paint.cpp
+++ b/src/c/sk_paint.cpp
@@ -5,6 +5,7 @@
  * found in the LICENSE file.
  */
 
+#include "SkBlendMode.h"
 #include "SkMaskFilter.h"
 #include "SkPaint.h"
 #include "SkShader.h"
@@ -132,41 +133,41 @@
 
 void sk_paint_set_xfermode_mode(sk_paint_t* paint, sk_xfermode_mode_t mode) {
     SkASSERT(paint);
-    SkXfermode::Mode skmode;
+    SkBlendMode skmode;
     switch (mode) {
         #define MAP(X, Y) case (X): skmode = (Y); break
-        MAP( CLEAR_SK_XFERMODE_MODE,      SkXfermode::kClear_Mode      );
-        MAP( SRC_SK_XFERMODE_MODE,        SkXfermode::kSrc_Mode        );
-        MAP( DST_SK_XFERMODE_MODE,        SkXfermode::kDst_Mode        );
-        MAP( SRCOVER_SK_XFERMODE_MODE,    SkXfermode::kSrcOver_Mode    );
-        MAP( DSTOVER_SK_XFERMODE_MODE,    SkXfermode::kDstOver_Mode    );
-        MAP( SRCIN_SK_XFERMODE_MODE,      SkXfermode::kSrcIn_Mode      );
-        MAP( DSTIN_SK_XFERMODE_MODE,      SkXfermode::kDstIn_Mode      );
-        MAP( SRCOUT_SK_XFERMODE_MODE,     SkXfermode::kSrcOut_Mode     );
-        MAP( DSTOUT_SK_XFERMODE_MODE,     SkXfermode::kDstOut_Mode     );
-        MAP( SRCATOP_SK_XFERMODE_MODE,    SkXfermode::kSrcATop_Mode    );
-        MAP( DSTATOP_SK_XFERMODE_MODE,    SkXfermode::kDstATop_Mode    );
-        MAP( XOR_SK_XFERMODE_MODE,        SkXfermode::kXor_Mode        );
-        MAP( PLUS_SK_XFERMODE_MODE,       SkXfermode::kPlus_Mode       );
-        MAP( MODULATE_SK_XFERMODE_MODE,   SkXfermode::kModulate_Mode   );
-        MAP( SCREEN_SK_XFERMODE_MODE,     SkXfermode::kScreen_Mode     );
-        MAP( OVERLAY_SK_XFERMODE_MODE,    SkXfermode::kOverlay_Mode    );
-        MAP( DARKEN_SK_XFERMODE_MODE,     SkXfermode::kDarken_Mode     );
-        MAP( LIGHTEN_SK_XFERMODE_MODE,    SkXfermode::kLighten_Mode    );
-        MAP( COLORDODGE_SK_XFERMODE_MODE, SkXfermode::kColorDodge_Mode );
-        MAP( COLORBURN_SK_XFERMODE_MODE,  SkXfermode::kColorBurn_Mode  );
-        MAP( HARDLIGHT_SK_XFERMODE_MODE,  SkXfermode::kHardLight_Mode  );
-        MAP( SOFTLIGHT_SK_XFERMODE_MODE,  SkXfermode::kSoftLight_Mode  );
-        MAP( DIFFERENCE_SK_XFERMODE_MODE, SkXfermode::kDifference_Mode );
-        MAP( EXCLUSION_SK_XFERMODE_MODE,  SkXfermode::kExclusion_Mode  );
-        MAP( MULTIPLY_SK_XFERMODE_MODE,   SkXfermode::kMultiply_Mode   );
-        MAP( HUE_SK_XFERMODE_MODE,        SkXfermode::kHue_Mode        );
-        MAP( SATURATION_SK_XFERMODE_MODE, SkXfermode::kSaturation_Mode );
-        MAP( COLOR_SK_XFERMODE_MODE,      SkXfermode::kColor_Mode      );
-        MAP( LUMINOSITY_SK_XFERMODE_MODE, SkXfermode::kLuminosity_Mode );
+        MAP( CLEAR_SK_XFERMODE_MODE,      SkBlendMode::kClear      );
+        MAP( SRC_SK_XFERMODE_MODE,        SkBlendMode::kSrc        );
+        MAP( DST_SK_XFERMODE_MODE,        SkBlendMode::kDst        );
+        MAP( SRCOVER_SK_XFERMODE_MODE,    SkBlendMode::kSrcOver    );
+        MAP( DSTOVER_SK_XFERMODE_MODE,    SkBlendMode::kDstOver    );
+        MAP( SRCIN_SK_XFERMODE_MODE,      SkBlendMode::kSrcIn      );
+        MAP( DSTIN_SK_XFERMODE_MODE,      SkBlendMode::kDstIn      );
+        MAP( SRCOUT_SK_XFERMODE_MODE,     SkBlendMode::kSrcOut     );
+        MAP( DSTOUT_SK_XFERMODE_MODE,     SkBlendMode::kDstOut     );
+        MAP( SRCATOP_SK_XFERMODE_MODE,    SkBlendMode::kSrcATop    );
+        MAP( DSTATOP_SK_XFERMODE_MODE,    SkBlendMode::kDstATop    );
+        MAP( XOR_SK_XFERMODE_MODE,        SkBlendMode::kXor        );
+        MAP( PLUS_SK_XFERMODE_MODE,       SkBlendMode::kPlus       );
+        MAP( MODULATE_SK_XFERMODE_MODE,   SkBlendMode::kModulate   );
+        MAP( SCREEN_SK_XFERMODE_MODE,     SkBlendMode::kScreen     );
+        MAP( OVERLAY_SK_XFERMODE_MODE,    SkBlendMode::kOverlay    );
+        MAP( DARKEN_SK_XFERMODE_MODE,     SkBlendMode::kDarken     );
+        MAP( LIGHTEN_SK_XFERMODE_MODE,    SkBlendMode::kLighten    );
+        MAP( COLORDODGE_SK_XFERMODE_MODE, SkBlendMode::kColorDodge );
+        MAP( COLORBURN_SK_XFERMODE_MODE,  SkBlendMode::kColorBurn  );
+        MAP( HARDLIGHT_SK_XFERMODE_MODE,  SkBlendMode::kHardLight  );
+        MAP( SOFTLIGHT_SK_XFERMODE_MODE,  SkBlendMode::kSoftLight  );
+        MAP( DIFFERENCE_SK_XFERMODE_MODE, SkBlendMode::kDifference );
+        MAP( EXCLUSION_SK_XFERMODE_MODE,  SkBlendMode::kExclusion  );
+        MAP( MULTIPLY_SK_XFERMODE_MODE,   SkBlendMode::kMultiply   );
+        MAP( HUE_SK_XFERMODE_MODE,        SkBlendMode::kHue        );
+        MAP( SATURATION_SK_XFERMODE_MODE, SkBlendMode::kSaturation );
+        MAP( COLOR_SK_XFERMODE_MODE,      SkBlendMode::kColor      );
+        MAP( LUMINOSITY_SK_XFERMODE_MODE, SkBlendMode::kLuminosity );
         #undef MAP
         default:
             return;
     }
-    AsPaint(paint)->setXfermodeMode(skmode);
+    AsPaint(paint)->setBlendMode(skmode);
 }
diff --git a/src/core/SkBitmapDevice.cpp b/src/core/SkBitmapDevice.cpp
index 440de68..26d253c 100644
--- a/src/core/SkBitmapDevice.cpp
+++ b/src/core/SkBitmapDevice.cpp
@@ -446,7 +446,7 @@
         paint.getPathEffect() ||
         paint.isFakeBoldText() ||
         paint.getStyle() != SkPaint::kFill_Style ||
-        !SkXfermode::IsMode(paint.getXfermode(), SkXfermode::kSrcOver_Mode))
+        !paint.isSrcOver())
     {
         return true;
     }
diff --git a/src/core/SkBlendModePriv.h b/src/core/SkBlendModePriv.h
new file mode 100644
index 0000000..b5d9e75
--- /dev/null
+++ b/src/core/SkBlendModePriv.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkBlendModePriv_DEFINED
+#define SkBlendModePriv_DEFINED
+
+#include "SkBlendMode.h"
+
+bool SkBlendMode_SupportsCoverageAsAlpha(SkBlendMode);
+
+#if SK_SUPPORT_GPU
+sk_sp<GrXPFactory> SkBlendMode_AsXPFactory(SkBlendMode);
+#endif
+
+#endif
diff --git a/src/core/SkBlitter.cpp b/src/core/SkBlitter.cpp
index db9fcda..ce689d7 100644
--- a/src/core/SkBlitter.cpp
+++ b/src/core/SkBlitter.cpp
@@ -810,7 +810,7 @@
 
     SkShader* shader = origPaint.getShader();
     SkColorFilter* cf = origPaint.getColorFilter();
-    SkXfermode* mode = origPaint.getXfermode();
+    SkBlendMode mode = origPaint.getBlendMode();
     sk_sp<Sk3DShader> shader3D;
 
     SkTCopyOnFirstWrite<SkPaint> paint(origPaint);
@@ -823,12 +823,12 @@
         shader = shader3D.get();
     }
 
-    if (mode) {
+    if (mode != SkBlendMode::kSrcOver) {
         bool deviceIsOpaque = kRGB_565_SkColorType == device.colorType();
         switch (SkInterpretXfermode(*paint, deviceIsOpaque)) {
             case kSrcOver_SkXfermodeInterpretation:
-                mode = nullptr;
-                paint.writable()->setXfermode(nullptr);
+                mode = SkBlendMode::kSrcOver;
+                paint.writable()->setBlendMode(mode);
                 break;
             case kSkipDrawing_SkXfermodeInterpretation:{
                 return allocator->createT<SkNullBlitter>();
@@ -843,13 +843,13 @@
      *  color/shader/colorfilter, and just pretend we're SRC + color==0. This
      *  will fall into our optimizations for SRC mode.
      */
-    if (SkXfermode::IsMode(mode, SkXfermode::kClear_Mode)) {
+    if (mode == SkBlendMode::kClear) {
         SkPaint* p = paint.writable();
         p->setShader(nullptr);
         shader = nullptr;
         p->setColorFilter(nullptr);
         cf = nullptr;
-        mode = p->setXfermodeMode(SkXfermode::kSrc_Mode);
+        p->setBlendMode(mode = SkBlendMode::kSrc);
         p->setColor(0);
     }
 
@@ -858,7 +858,7 @@
     }
 
     if (nullptr == shader) {
-        if (mode) {
+        if (mode != SkBlendMode::kSrcOver) {
             // xfermodes (and filters) require shaders for our current blitters
             paint.writable()->setShader(SkShader::MakeColorShader(paint->getColor()));
             paint.writable()->setAlpha(0xFF);
@@ -909,7 +909,7 @@
         case kAlpha_8_SkColorType:
             if (drawCoverage) {
                 SkASSERT(nullptr == shader);
-                SkASSERT(nullptr == paint->getXfermode());
+                SkASSERT(paint->isSrcOver());
                 blitter = allocator->createT<SkA8_Coverage_Blitter>(device, *paint);
             } else if (shader) {
                 blitter = allocator->createT<SkA8_Shader_Blitter>(device, *paint, shaderContext);
diff --git a/src/core/SkBlitter_A8.cpp b/src/core/SkBlitter_A8.cpp
index 6697614..cb7d718 100644
--- a/src/core/SkBlitter_A8.cpp
+++ b/src/core/SkBlitter_A8.cpp
@@ -230,10 +230,8 @@
                                          SkShader::Context* shaderContext)
     : INHERITED(device, paint, shaderContext)
 {
-    if ((fXfermode = paint.getXfermode()) != nullptr) {
-        fXfermode->ref();
-        SkASSERT(fShaderContext);
-    }
+    fXfermode = SkXfermode::Peek(paint.getBlendMode());
+    SkASSERT(!fXfermode || fShaderContext);
 
     int width = device.width();
     fBuffer = (SkPMColor*)sk_malloc_throw(sizeof(SkPMColor) * (width + (SkAlign4(width) >> 2)));
@@ -241,7 +239,6 @@
 }
 
 SkA8_Shader_Blitter::~SkA8_Shader_Blitter() {
-    if (fXfermode) SkSafeUnref(fXfermode);
     sk_free(fBuffer);
 }
 
@@ -355,7 +352,7 @@
 SkA8_Coverage_Blitter::SkA8_Coverage_Blitter(const SkPixmap& device,
                              const SkPaint& paint) : SkRasterBlitter(device) {
     SkASSERT(nullptr == paint.getShader());
-    SkASSERT(nullptr == paint.getXfermode());
+    SkASSERT(paint.isSrcOver());
     SkASSERT(nullptr == paint.getColorFilter());
 }
 
diff --git a/src/core/SkBlitter_ARGB32.cpp b/src/core/SkBlitter_ARGB32.cpp
index aada058..ea0554d 100644
--- a/src/core/SkBlitter_ARGB32.cpp
+++ b/src/core/SkBlitter_ARGB32.cpp
@@ -339,8 +339,7 @@
 {
     fBuffer = (SkPMColor*)sk_malloc_throw(device.width() * (sizeof(SkPMColor)));
 
-    fXfermode = paint.getXfermode();
-    SkSafeRef(fXfermode);
+    fXfermode = SkXfermode::Peek(paint.getBlendMode());
 
     int flags = 0;
     if (!(shaderContext->getFlags() & SkShader::kOpaqueAlpha_Flag)) {
@@ -370,7 +369,6 @@
 }
 
 SkARGB32_Shader_Blitter::~SkARGB32_Shader_Blitter() {
-    SkSafeUnref(fXfermode);
     sk_free(fBuffer);
 }
 
diff --git a/src/core/SkBlitter_PM4f.cpp b/src/core/SkBlitter_PM4f.cpp
index 455a97b..d63e924 100644
--- a/src/core/SkBlitter_PM4f.cpp
+++ b/src/core/SkBlitter_PM4f.cpp
@@ -325,7 +325,7 @@
 
 struct State4f {
     State4f(const SkImageInfo& info, const SkPaint& paint, const SkShader::Context* shaderContext) {
-        fXfer = paint.getXfermode();
+        fXfer = SkXfermode::Peek(paint.getBlendMode());
         if (shaderContext) {
             fBuffer.reset(info.width());
         } else {
@@ -410,7 +410,7 @@
         SkShader::Context::BlitState bstate;
         sk_bzero(&bstate, sizeof(bstate));
         bstate.fCtx = shaderContext;
-        bstate.fXfer = paint.getXfermode();
+        bstate.fXfer = SkXfermode::Peek(paint.getBlendMode());
 
         (void)shaderContext->chooseBlitProcs(device.info(), &bstate);
         return allocator->createT<SkState_Shader_Blitter<State>>(device, paint, bstate);
diff --git a/src/core/SkBlitter_RGB16.cpp b/src/core/SkBlitter_RGB16.cpp
index 066ec61..7860b7c 100644
--- a/src/core/SkBlitter_RGB16.cpp
+++ b/src/core/SkBlitter_RGB16.cpp
@@ -160,7 +160,7 @@
     : INHERITED(device, paint) {
     SkASSERT(paint.getShader() == nullptr);
     SkASSERT(paint.getColorFilter() == nullptr);
-    SkASSERT(paint.getXfermode() == nullptr);
+    SkASSERT(paint.isSrcOver());
     SkASSERT(paint.getColor() == SK_ColorBLACK);
 }
 
@@ -683,7 +683,7 @@
                                                SkShader::Context* shaderContext)
     : INHERITED(device, paint, shaderContext)
 {
-    SkASSERT(paint.getXfermode() == nullptr);
+    SkASSERT(paint.isSrcOver());
 
     fBuffer = (SkPMColor*)sk_malloc_throw(device.width() * sizeof(SkPMColor));
 
@@ -809,9 +809,8 @@
                                 SkShader::Context* shaderContext)
     : INHERITED(device, paint, shaderContext)
 {
-    fXfermode = paint.getXfermode();
+    fXfermode = SkXfermode::Peek(paint.getBlendMode());
     SkASSERT(fXfermode);
-    fXfermode->ref();
 
     int width = device.width();
     fBuffer = (SkPMColor*)sk_malloc_throw((width + (SkAlign4(width) >> 2)) * sizeof(SkPMColor));
@@ -819,7 +818,6 @@
 }
 
 SkRGB16_Shader_Xfermode_Blitter::~SkRGB16_Shader_Xfermode_Blitter() {
-    fXfermode->unref();
     sk_free(fBuffer);
 }
 
@@ -897,14 +895,14 @@
 
     SkBlitter* blitter;
     SkShader* shader = paint.getShader();
-    SkXfermode* mode = paint.getXfermode();
+    bool is_srcover = paint.isSrcOver();
 
     // we require a shader if there is an xfermode, handled by our caller
-    SkASSERT(nullptr == mode || shader);
+    SkASSERT(is_srcover || shader);
 
     if (shader) {
         SkASSERT(shaderContext != nullptr);
-        if (mode) {
+        if (!is_srcover) {
             blitter = allocator->createT<SkRGB16_Shader_Xfermode_Blitter>(device, paint,
                                                                           shaderContext);
         } else {
diff --git a/src/core/SkBlitter_Sprite.cpp b/src/core/SkBlitter_Sprite.cpp
index 950f187..cef4cfa 100644
--- a/src/core/SkBlitter_Sprite.cpp
+++ b/src/core/SkBlitter_Sprite.cpp
@@ -68,14 +68,11 @@
         if (0xFF != paint.getAlpha()) {
             return false;
         }
-        SkXfermode::Mode mode;
-        if (!SkXfermode::AsMode(paint.getXfermode(), &mode)) {
-            return false;
-        }
-        if (SkXfermode::kSrc_Mode == mode) {
+        SkBlendMode mode = paint.getBlendMode();
+        if (SkBlendMode::kSrc == mode) {
             return true;
         }
-        if (SkXfermode::kSrcOver_Mode == mode && src.isOpaque()) {
+        if (SkBlendMode::kSrcOver == mode && src.isOpaque()) {
             return true;
         }
 
@@ -85,7 +82,7 @@
             return false;
         }
 
-        return SkXfermode::kSrcOver_Mode == mode;
+        return SkBlendMode::kSrcOver == mode;
     }
 
     SkSpriteBlitter_Src_SrcOver(const SkPixmap& src)
@@ -94,14 +91,11 @@
     void setup(const SkPixmap& dst, int left, int top, const SkPaint& paint) override {
         SkASSERT(Supports(dst, fSource, paint));
         this->INHERITED::setup(dst, left, top, paint);
-        SkXfermode::Mode mode;
-        if (!SkXfermode::AsMode(paint.getXfermode(), &mode)) {
-            SkFAIL("Should never happen.");
-        }
+        SkBlendMode mode = paint.getBlendMode();
 
-        SkASSERT(mode == SkXfermode::kSrcOver_Mode || mode == SkXfermode::kSrc_Mode);
+        SkASSERT(mode == SkBlendMode::kSrcOver || mode == SkBlendMode::kSrc);
 
-        if (mode == SkXfermode::kSrcOver_Mode && !fSource.isOpaque()) {
+        if (mode == SkBlendMode::kSrcOver && !fSource.isOpaque()) {
             fUseMemcpy = false;
         }
     }
diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp
index 7597c7a..38ec770 100644
--- a/src/core/SkCanvas.cpp
+++ b/src/core/SkCanvas.cpp
@@ -484,7 +484,7 @@
              */
             SkPaint tmp;
             tmp.setImageFilter(fPaint->getImageFilter());
-            tmp.setXfermode(sk_ref_sp(fPaint->getXfermode()));
+            tmp.setBlendMode(fPaint->getBlendMode());
             SkRect storage;
             if (rawBounds) {
                 // Make rawBounds include all paint outsets except for those due to image filters.
@@ -558,7 +558,7 @@
 
     if (fTempLayerForImageFilter) {
         paint->setImageFilter(nullptr);
-        paint->setXfermode(nullptr);
+        paint->setBlendMode(SkBlendMode::kSrcOver);
     }
 
     if (fLooperContext && !fLooperContext->next(fCanvas, paint)) {
@@ -2690,7 +2690,7 @@
     // nothing to draw
     if (text == nullptr || byteLength == 0 ||
         draw.fRC->isEmpty() ||
-        (paint.getAlpha() == 0 && paint.getXfermode() == nullptr)) {
+        (paint.getAlpha() == 0 && paint.isSrcOver())) {
         return;
     }
 
@@ -2999,26 +2999,21 @@
 // methods, rather than actually drawing themselves.
 //////////////////////////////////////////////////////////////////////////////
 
-void SkCanvas::drawARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b,
-                        SkXfermode::Mode mode) {
+void SkCanvas::drawARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b, SkBlendMode mode) {
     TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawARGB()");
     SkPaint paint;
 
     paint.setARGB(a, r, g, b);
-    if (SkXfermode::kSrcOver_Mode != mode) {
-        paint.setXfermodeMode(mode);
-    }
+    paint.setBlendMode(mode);
     this->drawPaint(paint);
 }
 
-void SkCanvas::drawColor(SkColor c, SkXfermode::Mode mode) {
+void SkCanvas::drawColor(SkColor c, SkBlendMode mode) {
     TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawColor()");
     SkPaint paint;
 
     paint.setColor(c);
-    if (SkXfermode::kSrcOver_Mode != mode) {
-        paint.setXfermodeMode(mode);
-    }
+    paint.setBlendMode(mode);
     this->drawPaint(paint);
 }
 
diff --git a/src/core/SkDraw.cpp b/src/core/SkDraw.cpp
index 34c7d73..c6c5cf3 100644
--- a/src/core/SkDraw.cpp
+++ b/src/core/SkDraw.cpp
@@ -7,6 +7,7 @@
 #define __STDC_LIMIT_MACROS
 
 #include "SkDraw.h"
+#include "SkBlendModePriv.h"
 #include "SkBlitter.h"
 #include "SkCanvas.h"
 #include "SkColorPriv.h"
@@ -163,31 +164,27 @@
         return nullptr;
     }
 
-    SkXfermode::Mode mode;
-    if (!SkXfermode::AsMode(paint.getXfermode(), &mode)) {
-        return nullptr;
-    }
-
+    SkBlendMode mode = paint.getBlendMode();
     SkColor color = paint.getColor();
 
     // collaps modes based on color...
-    if (SkXfermode::kSrcOver_Mode == mode) {
+    if (SkBlendMode::kSrcOver == mode) {
         unsigned alpha = SkColorGetA(color);
         if (0 == alpha) {
-            mode = SkXfermode::kDst_Mode;
+            mode = SkBlendMode::kDst;
         } else if (0xFF == alpha) {
-            mode = SkXfermode::kSrc_Mode;
+            mode = SkBlendMode::kSrc;
         }
     }
 
     switch (mode) {
-        case SkXfermode::kClear_Mode:
+        case SkBlendMode::kClear:
 //            SkDebugf("--- D_Clear_BitmapXferProc\n");
             return D_Clear_BitmapXferProc;  // ignore data
-        case SkXfermode::kDst_Mode:
+        case SkBlendMode::kDst:
 //            SkDebugf("--- D_Dst_BitmapXferProc\n");
             return D_Dst_BitmapXferProc;    // ignore data
-        case SkXfermode::kSrc_Mode: {
+        case SkBlendMode::kSrc: {
             /*
                 should I worry about dithering for the lower depths?
             */
@@ -1143,7 +1140,7 @@
         if (SkDrawTreatAsHairline(origPaint, *matrix, &coverage)) {
             if (SK_Scalar1 == coverage) {
                 paint.writable()->setStrokeWidth(0);
-            } else if (SkXfermode::SupportsCoverageAsAlpha(origPaint.getXfermode())) {
+            } else if (SkBlendMode_SupportsCoverageAsAlpha(origPaint.getBlendMode())) {
                 U8CPU newAlpha;
 #if 0
                 newAlpha = SkToU8(SkScalarRoundToInt(coverage *
diff --git a/src/core/SkGpuBlurUtils.cpp b/src/core/SkGpuBlurUtils.cpp
index 5b29884..ec3b0a9 100644
--- a/src/core/SkGpuBlurUtils.cpp
+++ b/src/core/SkGpuBlurUtils.cpp
@@ -80,7 +80,7 @@
     sk_sp<GrFragmentProcessor> conv(GrConvolutionEffect::MakeGaussian(
         texture, direction, radius, sigma, useBounds, bounds));
     paint.addColorFragmentProcessor(std::move(conv));
-    paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode);
+    paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
     SkMatrix localMatrix = SkMatrix::MakeTrans(-SkIntToScalar(srcOffset.x()),
                                                -SkIntToScalar(srcOffset.y()));
     drawContext->fillRectWithLocalMatrix(clip, paint, SkMatrix::I(),
@@ -110,7 +110,7 @@
             srcBounds ? GrTextureDomain::kDecal_Mode : GrTextureDomain::kIgnore_Mode,
             true, sigmaX, sigmaY));
     paint.addColorFragmentProcessor(std::move(conv));
-    paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode);
+    paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
     drawContext->fillRectWithLocalMatrix(clip, paint, SkMatrix::I(), 
                                          SkRect::Make(dstRect), localMatrix);
 }
@@ -285,7 +285,7 @@
             GrTextureParams params(SkShader::kClamp_TileMode, GrTextureParams::kBilerp_FilterMode);
             paint.addColorTextureProcessor(srcTexture.get(), nullptr, matrix, params);
         }
-        paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode);
+        paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
         shrink_irect_by_2(&dstRect, i < scaleFactorX, i < scaleFactorY);
 
         dstDrawContext->fillRectToRect(clip, paint, SkMatrix::I(),
@@ -361,7 +361,7 @@
         GrTextureParams params(SkShader::kClamp_TileMode, GrTextureParams::kBilerp_FilterMode);
         sk_sp<GrTexture> tex(srcDrawContext->asTexture());
         paint.addColorTextureProcessor(tex.get(), nullptr, matrix, params);
-        paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode);
+        paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
 
         SkIRect dstRect(srcRect);
         scale_irect(&dstRect, scaleFactorX, scaleFactorY);
diff --git a/src/core/SkImageFilter.cpp b/src/core/SkImageFilter.cpp
index 63095bc..68183cc 100644
--- a/src/core/SkImageFilter.cpp
+++ b/src/core/SkImageFilter.cpp
@@ -281,7 +281,7 @@
                                                 const OutputProperties& outputProperties) {
     GrPaint paint;
     paint.addColorFragmentProcessor(std::move(fp));
-    paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode);
+    paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
 
     sk_sp<SkColorSpace> colorSpace = sk_ref_sp(outputProperties.colorSpace());
     GrPixelConfig config = GrRenderableConfigForColorSpace(colorSpace.get());
diff --git a/src/core/SkMatrixImageFilter.cpp b/src/core/SkMatrixImageFilter.cpp
index 12efc64..0a33280 100644
--- a/src/core/SkMatrixImageFilter.cpp
+++ b/src/core/SkMatrixImageFilter.cpp
@@ -85,7 +85,7 @@
 
     SkPaint paint;
     paint.setAntiAlias(true);
-    paint.setXfermodeMode(SkXfermode::kSrc_Mode);
+    paint.setBlendMode(SkBlendMode::kSrc);
     paint.setFilterQuality(fFilterQuality);
 
     input->draw(canvas, srcRect.x(), srcRect.y(), &paint);
diff --git a/src/core/SkPaint.cpp b/src/core/SkPaint.cpp
index 9d76a16..83e45c0 100644
--- a/src/core/SkPaint.cpp
+++ b/src/core/SkPaint.cpp
@@ -52,6 +52,7 @@
     fColor      = SK_ColorBLACK;
     fWidth      = 0;
     fMiterLimit = SkPaintDefaults_MiterLimit;
+    fBlendMode  = (unsigned)SkBlendMode::kSrcOver;
 
     // Zero all bitfields, then set some non-zero defaults.
     fBitfieldsUInt           = 0;
@@ -69,7 +70,6 @@
     : COPY(fTypeface)
     , COPY(fPathEffect)
     , COPY(fShader)
-    , COPY(fXfermode)
     , COPY(fMaskFilter)
     , COPY(fColorFilter)
     , COPY(fRasterizer)
@@ -81,6 +81,7 @@
     , COPY(fColor)
     , COPY(fWidth)
     , COPY(fMiterLimit)
+    , COPY(fBlendMode)
     , COPY(fBitfields)
 #undef COPY
 {}
@@ -90,7 +91,6 @@
     MOVE(fTypeface);
     MOVE(fPathEffect);
     MOVE(fShader);
-    MOVE(fXfermode);
     MOVE(fMaskFilter);
     MOVE(fColorFilter);
     MOVE(fRasterizer);
@@ -102,6 +102,7 @@
     MOVE(fColor);
     MOVE(fWidth);
     MOVE(fMiterLimit);
+    MOVE(fBlendMode);
     MOVE(fBitfields);
 #undef MOVE
 }
@@ -117,7 +118,6 @@
     ASSIGN(fTypeface);
     ASSIGN(fPathEffect);
     ASSIGN(fShader);
-    ASSIGN(fXfermode);
     ASSIGN(fMaskFilter);
     ASSIGN(fColorFilter);
     ASSIGN(fRasterizer);
@@ -129,6 +129,7 @@
     ASSIGN(fColor);
     ASSIGN(fWidth);
     ASSIGN(fMiterLimit);
+    ASSIGN(fBlendMode);
     ASSIGN(fBitfields);
 #undef ASSIGN
 
@@ -144,7 +145,6 @@
     MOVE(fTypeface);
     MOVE(fPathEffect);
     MOVE(fShader);
-    MOVE(fXfermode);
     MOVE(fMaskFilter);
     MOVE(fColorFilter);
     MOVE(fRasterizer);
@@ -156,6 +156,7 @@
     MOVE(fColor);
     MOVE(fWidth);
     MOVE(fMiterLimit);
+    MOVE(fBlendMode);
     MOVE(fBitfields);
 #undef MOVE
 
@@ -167,7 +168,6 @@
     return EQUAL(fTypeface)
         && EQUAL(fPathEffect)
         && EQUAL(fShader)
-        && EQUAL(fXfermode)
         && EQUAL(fMaskFilter)
         && EQUAL(fColorFilter)
         && EQUAL(fRasterizer)
@@ -179,6 +179,7 @@
         && EQUAL(fColor)
         && EQUAL(fWidth)
         && EQUAL(fMiterLimit)
+        && EQUAL(fBlendMode)
         && EQUAL(fBitfieldsUInt)
         ;
 #undef EQUAL
@@ -360,7 +361,6 @@
 MOVE_FIELD(ImageFilter)
 MOVE_FIELD(Shader)
 MOVE_FIELD(ColorFilter)
-MOVE_FIELD(Xfermode)
 MOVE_FIELD(PathEffect)
 MOVE_FIELD(MaskFilter)
 MOVE_FIELD(DrawLooper)
@@ -385,9 +385,6 @@
 #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
@@ -403,10 +400,18 @@
 }
 #endif
 
-SkXfermode* SkPaint::setXfermodeMode(SkXfermode::Mode mode) {
-    fXfermode = SkXfermode::Make(mode);
-    return fXfermode.get(); // can/should we change this API to be void, like the other setters?
+#ifdef SK_SUPPORT_LEGACY_XFERMODE_OBJECT
+void SkPaint::setXfermode(sk_sp<SkXfermode> mode) {
+    this->setBlendMode(mode ? mode->blend() : SkBlendMode::kSrcOver);
 }
+SkXfermode* SkPaint::getXfermode() const {
+    return SkXfermode::Peek((SkBlendMode)fBlendMode);
+}
+SkXfermode* SkPaint::setXfermodeMode(SkXfermode::Mode mode) {
+    this->setBlendMode((SkBlendMode)mode);
+    return SkXfermode::Peek((SkBlendMode)mode);
+}
+#endif
 
 ///////////////////////////////////////////////////////////////////////////////
 
@@ -1904,7 +1909,6 @@
     }
     if (asint(this->getPathEffect()) |
         asint(this->getShader()) |
-        asint(this->getXfermode()) |
         asint(this->getMaskFilter()) |
         asint(this->getColorFilter()) |
         asint(this->getRasterizer()) |
@@ -1923,7 +1927,8 @@
     buffer.writeUInt(pack_paint_flags(this->getFlags(), this->getHinting(), this->getTextAlign(),
                                       this->getFilterQuality(), flatFlags));
     buffer.writeUInt(pack_4(this->getStrokeCap(), this->getStrokeJoin(),
-                            this->getStyle(), this->getTextEncoding()));
+                            (this->getStyle() << 4) | this->getTextEncoding(),
+                            fBlendMode));
 
     // now we're done with ptr and the (pre)reserved space. If we need to write
     // additional fields, use the buffer directly
@@ -1933,7 +1938,6 @@
     if (flatFlags & kHasEffects_FlatFlag) {
         buffer.writeFlattenable(this->getPathEffect());
         buffer.writeFlattenable(this->getShader());
-        buffer.writeFlattenable(this->getXfermode());
         buffer.writeFlattenable(this->getMaskFilter());
         buffer.writeFlattenable(this->getColorFilter());
         buffer.writeFlattenable(this->getRasterizer());
@@ -1955,8 +1959,14 @@
     uint32_t tmp = buffer.readUInt();
     this->setStrokeCap(static_cast<Cap>((tmp >> 24) & 0xFF));
     this->setStrokeJoin(static_cast<Join>((tmp >> 16) & 0xFF));
-    this->setStyle(static_cast<Style>((tmp >> 8) & 0xFF));
-    this->setTextEncoding(static_cast<TextEncoding>((tmp >> 0) & 0xFF));
+    if (buffer.isVersionLT(SkReadBuffer::kXfermodeToBlendMode_Version)) {
+        this->setStyle(static_cast<Style>((tmp >> 8) & 0xFF));
+        this->setTextEncoding(static_cast<TextEncoding>((tmp >> 0) & 0xFF));
+    } else {
+        this->setStyle(static_cast<Style>((tmp >> 12) & 0xF));
+        this->setTextEncoding(static_cast<TextEncoding>((tmp >> 8) & 0xF));
+        this->setBlendMode((SkBlendMode)(tmp & 0xFF));
+    }
 
     if (flatFlags & kHasTypeface_FlatFlag) {
         this->setTypeface(buffer.readTypeface());
@@ -1967,7 +1977,16 @@
     if (flatFlags & kHasEffects_FlatFlag) {
         this->setPathEffect(buffer.readPathEffect());
         this->setShader(buffer.readShader());
-        this->setXfermode(buffer.readXfermode());
+        if (buffer.isVersionLT(SkReadBuffer::kXfermodeToBlendMode_Version)) {
+            sk_sp<SkXfermode> xfer = buffer.readXfermode();
+            if (xfer) {
+                SkXfermode::Mode mode;
+                if (!xfer->asMode(&mode)) {
+                    mode = SkXfermode::kSrcOver_Mode;
+                }
+                this->setBlendMode((SkBlendMode)mode);
+            }
+        }
         this->setMaskFilter(buffer.readMaskFilter());
         this->setColorFilter(buffer.readColorFilter());
         this->setRasterizer(buffer.readRasterizer());
@@ -1986,7 +2005,6 @@
     } else {
         this->setPathEffect(nullptr);
         this->setShader(nullptr);
-        this->setXfermode(nullptr);
         this->setMaskFilter(nullptr);
         this->setColorFilter(nullptr);
         this->setRasterizer(nullptr);
@@ -2116,11 +2134,8 @@
         str->append("</dd>");
     }
 
-    SkXfermode* xfer = this->getXfermode();
-    if (xfer) {
-        str->append("<dt>Xfermode:</dt><dd>");
-        xfer->toString(str);
-        str->append("</dd>");
+    if (!this->isSrcOver()) {
+        str->appendf("<dt>Xfermode:</dt><dd>%d</dd>", fBlendMode);
     }
 
     SkMaskFilter* maskFilter = this->getMaskFilter();
@@ -2363,23 +2378,20 @@
     if (fDrawLooper) {
         return false;
     }
-    SkXfermode::Mode mode;
-    if (SkXfermode::AsMode(fXfermode.get(), &mode)) {
-        switch (mode) {
-            case SkXfermode::kSrcOver_Mode:
-            case SkXfermode::kSrcATop_Mode:
-            case SkXfermode::kDstOut_Mode:
-            case SkXfermode::kDstOver_Mode:
-            case SkXfermode::kPlus_Mode:
-                if (0 == this->getAlpha()) {
-                    return !affects_alpha(fColorFilter.get()) && !affects_alpha(fImageFilter.get());
-                }
-                break;
-            case SkXfermode::kDst_Mode:
-                return true;
-            default:
-                break;
-        }
+    switch ((SkBlendMode)fBlendMode) {
+        case SkBlendMode::kSrcOver:
+        case SkBlendMode::kSrcATop:
+        case SkBlendMode::kDstOut:
+        case SkBlendMode::kDstOver:
+        case SkBlendMode::kPlus:
+            if (0 == this->getAlpha()) {
+                return !affects_alpha(fColorFilter.get()) && !affects_alpha(fImageFilter.get());
+            }
+            break;
+        case SkBlendMode::kDst:
+            return true;
+        default:
+            break;
     }
     return false;
 }
@@ -2387,7 +2399,7 @@
 uint32_t SkPaint::getHash() const {
     // We're going to hash 10 pointers and 7 32-bit values, finishing up with fBitfields,
     // so fBitfields should be 10 pointers and 6 32-bit values from the start.
-    static_assert(offsetof(SkPaint, fBitfields) == 9 * sizeof(void*) + 6 * sizeof(uint32_t),
+    static_assert(offsetof(SkPaint, fBitfields) == 8 * sizeof(void*) + 7 * sizeof(uint32_t),
                   "SkPaint_notPackedTightly");
     return SkOpts::hash(reinterpret_cast<const uint32_t*>(this),
                         offsetof(SkPaint, fBitfields) + sizeof(fBitfields));
diff --git a/src/core/SkPaintPriv.cpp b/src/core/SkPaintPriv.cpp
index 6725cb4..cbe2558 100644
--- a/src/core/SkPaintPriv.cpp
+++ b/src/core/SkPaintPriv.cpp
@@ -41,7 +41,7 @@
         }
     }
 
-    return SkXfermode::IsOpaque(paint->getXfermode(), opacityType);
+    return SkXfermode::IsOpaque(paint->getBlendMode(), opacityType);
 }
 
 bool SkPaintPriv::Overwrites(const SkBitmap& bitmap, const SkPaint* paint) {
diff --git a/src/core/SkPixmap.cpp b/src/core/SkPixmap.cpp
index 7749839..108c877 100644
--- a/src/core/SkPixmap.cpp
+++ b/src/core/SkPixmap.cpp
@@ -267,7 +267,7 @@
 
     SkPaint paint;
     paint.setFilterQuality(quality);
-    paint.setXfermodeMode(SkXfermode::kSrc_Mode);
+    paint.setBlendMode(SkBlendMode::kSrc);
     surface->getCanvas()->drawBitmapRect(bitmap, SkRect::MakeIWH(dst.width(), dst.height()),
                                          &paint);
     return true;
diff --git a/src/core/SkRasterPipelineBlitter.cpp b/src/core/SkRasterPipelineBlitter.cpp
index 1e8dcf5..91d60be 100644
--- a/src/core/SkRasterPipelineBlitter.cpp
+++ b/src/core/SkRasterPipelineBlitter.cpp
@@ -82,8 +82,8 @@
     }
 
     SkRasterPipeline shader, colorFilter, xfermode;
-    if (!append_effect_stages(paint.getColorFilter(), &colorFilter) ||
-        !append_effect_stages(paint.getXfermode(),    &xfermode   )) {
+    if (!append_effect_stages(paint.getColorFilter(),                 &colorFilter) ||
+        !append_effect_stages(SkXfermode::Peek(paint.getBlendMode()), &xfermode   )) {
         return nullptr;
     }
 
@@ -104,7 +104,7 @@
     if (!paint.getShader()) {
         blitter->fShader.append(SkRasterPipeline::constant_color, &blitter->fPaintColor);
     }
-    if (!paint.getXfermode()) {
+    if (paint.isSrcOver()) {
         blitter->fXfermode.append(SkRasterPipeline::srcover);
     }
 
diff --git a/src/core/SkReadBuffer.h b/src/core/SkReadBuffer.h
index 3e6742f..4ac7973 100644
--- a/src/core/SkReadBuffer.h
+++ b/src/core/SkReadBuffer.h
@@ -69,6 +69,7 @@
         kLightingShaderWritesInvNormRotation = 45,
         kBlurMaskFilterWritesOccluder      = 47,
         kGradientShaderFloatColor_Version  = 49,
+        kXfermodeToBlendMode_Version       = 50,
     };
 
     /**
diff --git a/src/core/SkRecordDraw.cpp b/src/core/SkRecordDraw.cpp
index ca9c1b6..dca19df 100644
--- a/src/core/SkRecordDraw.cpp
+++ b/src/core/SkRecordDraw.cpp
@@ -341,34 +341,27 @@
                 return true;
             }
 
-            // Unusual Xfermodes require us to process a saved layer
+            // Unusual blendmodes require us to process a saved layer
             // even with operations outisde the clip.
             // For example, DstIn is used by masking layers.
             // https://code.google.com/p/skia/issues/detail?id=1291
             // https://crbug.com/401593
-            SkXfermode* xfermode = paint->getXfermode();
-            SkXfermode::Mode mode;
-            // SrcOver is ok, and is also the common case with a nullptr xfermode.
-            // So we should make that the fast path and bypass the mode extraction
-            // and test.
-            if (xfermode && xfermode->asMode(&mode)) {
-                switch (mode) {
-                    // For each of the following transfer modes, if the source
-                    // alpha is zero (our transparent black), the resulting
-                    // blended alpha is not necessarily equal to the original
-                    // destination alpha.
-                    case SkXfermode::kClear_Mode:
-                    case SkXfermode::kSrc_Mode:
-                    case SkXfermode::kSrcIn_Mode:
-                    case SkXfermode::kDstIn_Mode:
-                    case SkXfermode::kSrcOut_Mode:
-                    case SkXfermode::kDstATop_Mode:
-                    case SkXfermode::kModulate_Mode:
-                        return true;
-                        break;
-                    default:
-                        break;
-                }
+            switch (paint->getBlendMode()) {
+                // For each of the following transfer modes, if the source
+                // alpha is zero (our transparent black), the resulting
+                // blended alpha is not necessarily equal to the original
+                // destination alpha.
+                case SkBlendMode::kClear:
+                case SkBlendMode::kSrc:
+                case SkBlendMode::kSrcIn:
+                case SkBlendMode::kDstIn:
+                case SkBlendMode::kSrcOut:
+                case SkBlendMode::kDstATop:
+                case SkBlendMode::kModulate:
+                    return true;
+                    break;
+                default:
+                    break;
             }
         }
         return false;
diff --git a/src/core/SkRecordOpts.cpp b/src/core/SkRecordOpts.cpp
index d46a657..a7feec1 100644
--- a/src/core/SkRecordOpts.cpp
+++ b/src/core/SkRecordOpts.cpp
@@ -98,7 +98,7 @@
     // looper drawing unmodulated filter layer twice and then modulating the result produces
     // different image to drawing modulated filter layer twice.
     // TODO: most likely the looper and only some xfer modes are the hard constraints
-    if (paint->getXfermode() || paint->getLooper()) {
+    if (!paint->isSrcOver() || paint->getLooper()) {
         return false;
     }
 
@@ -129,9 +129,9 @@
         }
 
         // The layer paint can not have any effects.
-        if (layerPaint->getPathEffect() ||
+        if (layerPaint->getPathEffect()  ||
             layerPaint->getShader()      ||
-            layerPaint->getXfermode()    ||
+            !layerPaint->isSrcOver()     ||
             layerPaint->getMaskFilter()  ||
             layerPaint->getColorFilter() ||
             layerPaint->getRasterizer()  ||
@@ -174,16 +174,12 @@
 }
 
 static bool effectively_srcover(const SkPaint* paint) {
-    if (!paint) {
-        return true;
-    }
-    SkXfermode* mode = paint->getXfermode();
-    if (SkXfermode::IsMode(mode, SkXfermode::kSrcOver_Mode)) {
+    if (!paint || paint->isSrcOver()) {
         return true;
     }
     // src-mode with opaque and no effects (which might change opaqueness) is ok too.
     return !paint->getShader() && !paint->getColorFilter() && !paint->getImageFilter() &&
-           0xFF == paint->getAlpha() && SkXfermode::IsMode(mode, SkXfermode::kSrc_Mode);
+           0xFF == paint->getAlpha() && paint->getBlendMode() == SkBlendMode::kSrc;
 }
 
 // For some SaveLayer-[drawing command]-Restore patterns, merge the SaveLayer's alpha into the
diff --git a/src/core/SkSpriteBlitter4f.cpp b/src/core/SkSpriteBlitter4f.cpp
index a13edd9..38ec739 100644
--- a/src/core/SkSpriteBlitter4f.cpp
+++ b/src/core/SkSpriteBlitter4f.cpp
@@ -13,7 +13,7 @@
 class Sprite_4f : public SkSpriteBlitter {
 public:
     Sprite_4f(const SkPixmap& src, const SkPaint& paint) : INHERITED(src) {
-        fXfer = paint.getXfermode();
+        fXfer = SkXfermode::Peek(paint.getBlendMode());
         fLoader = SkLoadSpanProc_Choose(src.info());
         fFilter = SkFilterSpanProc_Choose(paint);
         fBuffer.reset(src.width());
diff --git a/src/core/SkSpriteBlitter_ARGB32.cpp b/src/core/SkSpriteBlitter_ARGB32.cpp
index 9388599..1a76b1b 100644
--- a/src/core/SkSpriteBlitter_ARGB32.cpp
+++ b/src/core/SkSpriteBlitter_ARGB32.cpp
@@ -63,8 +63,7 @@
         fColorFilter = paint.getColorFilter();
         SkSafeRef(fColorFilter);
 
-        fXfermode = paint.getXfermode();
-        SkSafeRef(fXfermode);
+        fXfermode = SkXfermode::Peek(paint.getBlendMode());
 
         fBufferSize = 0;
         fBuffer = nullptr;
@@ -83,7 +82,6 @@
 
     virtual ~Sprite_D32_XferFilter() {
         delete[] fBuffer;
-        SkSafeUnref(fXfermode);
         SkSafeUnref(fColorFilter);
     }
 
@@ -263,7 +261,7 @@
     }
 
     U8CPU       alpha = paint.getAlpha();
-    SkXfermode* xfermode = paint.getXfermode();
+    bool isSrcOver = paint.isSrcOver();
     SkColorFilter* filter = paint.getColorFilter();
     SkSpriteBlitter* blitter = nullptr;
 
@@ -272,7 +270,7 @@
             if (alpha != 0xFF) {
                 return nullptr;    // we only have opaque sprites
             }
-            if (xfermode || filter) {
+            if (!isSrcOver || filter) {
                 blitter = allocator->createT<Sprite_D32_S4444_XferFilter>(source, paint);
             } else if (source.isOpaque()) {
                 blitter = allocator->createT<Sprite_D32_S4444_Opaque>(source);
@@ -281,7 +279,7 @@
             }
             break;
         case kN32_SkColorType:
-            if (xfermode || filter) {
+            if (!isSrcOver || filter) {
                 if (255 == alpha) {
                     // this can handle xfermode or filter, but not alpha
                     blitter = allocator->createT<Sprite_D32_S32A_XferFilter>(source, paint);
diff --git a/src/core/SkSpriteBlitter_RGB16.cpp b/src/core/SkSpriteBlitter_RGB16.cpp
index 6c5a7cb..9df7dab 100644
--- a/src/core/SkSpriteBlitter_RGB16.cpp
+++ b/src/core/SkSpriteBlitter_RGB16.cpp
@@ -307,7 +307,7 @@
     if (paint.getMaskFilter() != nullptr) { // may add cases for this
         return nullptr;
     }
-    if (paint.getXfermode() != nullptr) { // may add cases for this
+    if (!paint.isSrcOver()) { // may add cases for this
         return nullptr;
     }
     if (paint.getColorFilter() != nullptr) { // may add cases for this
diff --git a/src/core/SkXfermode.cpp b/src/core/SkXfermode.cpp
index 2717fab..226f2b8 100644
--- a/src/core/SkXfermode.cpp
+++ b/src/core/SkXfermode.cpp
@@ -1553,3 +1553,64 @@
     }
     return false;
 }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+bool SkBlendMode_SupportsCoverageAsAlpha(SkBlendMode mode) {
+    switch (mode) {
+        case SkBlendMode::kDst:
+        case SkBlendMode::kSrcOver:
+        case SkBlendMode::kDstOver:
+        case SkBlendMode::kDstOut:
+        case SkBlendMode::kSrcATop:
+        case SkBlendMode::kXor:
+        case SkBlendMode::kPlus:
+            return true;
+        default:
+            break;
+    }
+    return false;
+}
+
+bool SkXfermode::IsOpaque(SkBlendMode mode, SrcColorOpacity opacityType) {
+    const ProcCoeff rec = gProcCoeffs[(int)mode];
+
+    switch (rec.fSC) {
+        case kDA_Coeff:
+        case kDC_Coeff:
+        case kIDA_Coeff:
+        case kIDC_Coeff:
+            return false;
+        default:
+            break;
+    }
+
+    switch (rec.fDC) {
+        case kZero_Coeff:
+            return true;
+        case kISA_Coeff:
+            return kOpaque_SrcColorOpacity == opacityType;
+        case kSA_Coeff:
+            return kTransparentBlack_SrcColorOpacity == opacityType ||
+            kTransparentAlpha_SrcColorOpacity == opacityType;
+        case kSC_Coeff:
+            return kTransparentBlack_SrcColorOpacity == opacityType;
+        default:
+            return false;
+    }
+    return false;
+}
+
+#if SK_SUPPORT_GPU
+sk_sp<GrXPFactory> SkBlendMode_AsXPFactory(SkBlendMode mode) {
+    const ProcCoeff rec = gProcCoeffs[(int)mode];
+    if (CANNOT_USE_COEFF != rec.fSC) {
+        sk_sp<GrXPFactory> result(GrPorterDuffXPFactory::Make(mode));
+        SkASSERT(result);
+        return result;
+    }
+
+    SkASSERT(GrCustomXfermode::IsSupportedMode((SkXfermode::Mode)mode));
+    return GrCustomXfermode::MakeXPFactory((SkXfermode::Mode)mode);
+}
+#endif
diff --git a/src/core/SkXfermodeInterpretation.cpp b/src/core/SkXfermodeInterpretation.cpp
index 1b2c8e3..3a1da36 100644
--- a/src/core/SkXfermodeInterpretation.cpp
+++ b/src/core/SkXfermodeInterpretation.cpp
@@ -9,38 +9,31 @@
 #include "SkPaint.h"
 
 static bool just_solid_color(const SkPaint& p) {
-    return SK_AlphaOPAQUE == p.getAlpha()
-        && !p.getColorFilter() && !p.getShader();
+    return SK_AlphaOPAQUE == p.getAlpha() && !p.getColorFilter() && !p.getShader();
 }
 
-SkXfermodeInterpretation SkInterpretXfermode(const SkPaint& paint,
-                                             bool dstIsOpaque) {
-    const SkXfermode* xfer = paint.getXfermode();
-    SkXfermode::Mode mode;
-    if (!SkXfermode::AsMode(xfer, &mode)) {
-        return kNormal_SkXfermodeInterpretation;
-    }
-    switch (mode) {
-        case SkXfermode::kSrcOver_Mode:
+SkXfermodeInterpretation SkInterpretXfermode(const SkPaint& paint, bool dstIsOpaque) {
+    switch (paint.getBlendMode()) {
+        case SkBlendMode::kSrcOver:
             return kSrcOver_SkXfermodeInterpretation;
-        case SkXfermode::kSrc_Mode:
+        case SkBlendMode::kSrc:
             if (just_solid_color(paint)) {
                 return kSrcOver_SkXfermodeInterpretation;
             }
             return kNormal_SkXfermodeInterpretation;
-        case SkXfermode::kDst_Mode:
+        case SkBlendMode::kDst:
             return kSkipDrawing_SkXfermodeInterpretation;
-        case SkXfermode::kDstOver_Mode:
+        case SkBlendMode::kDstOver:
             if (dstIsOpaque) {
                 return kSkipDrawing_SkXfermodeInterpretation;
             }
             return kNormal_SkXfermodeInterpretation;
-        case SkXfermode::kSrcIn_Mode:
+        case SkBlendMode::kSrcIn:
             if (dstIsOpaque && just_solid_color(paint)) {
                 return kSrcOver_SkXfermodeInterpretation;
             }
             return kNormal_SkXfermodeInterpretation;
-        case SkXfermode::kDstIn_Mode:
+        case SkBlendMode::kDstIn:
             if (just_solid_color(paint)) {
                 return kSkipDrawing_SkXfermodeInterpretation;
             }
diff --git a/src/effects/SkAlphaThresholdFilter.cpp b/src/effects/SkAlphaThresholdFilter.cpp
index 1d92aa5..47a2d3d 100644
--- a/src/effects/SkAlphaThresholdFilter.cpp
+++ b/src/effects/SkAlphaThresholdFilter.cpp
@@ -107,7 +107,7 @@
     }
 
     GrPaint grPaint;
-    grPaint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode);
+    grPaint.setPorterDuffXPFactory(SkBlendMode::kSrc);
     SkRegion::Iterator iter(fRegion);
     drawContext->clear(nullptr, 0x0, true);
 
diff --git a/src/effects/SkColorFilterImageFilter.cpp b/src/effects/SkColorFilterImageFilter.cpp
index d6b23d5..507a805 100644
--- a/src/effects/SkColorFilterImageFilter.cpp
+++ b/src/effects/SkColorFilterImageFilter.cpp
@@ -89,7 +89,7 @@
 
     SkPaint paint;
 
-    paint.setXfermodeMode(SkXfermode::kSrc_Mode);
+    paint.setBlendMode(SkBlendMode::kSrc);
     paint.setColorFilter(fColorFilter);
 
     // TODO: it may not be necessary to clear or drawPaint inside the input bounds
diff --git a/src/effects/SkDisplacementMapEffect.cpp b/src/effects/SkDisplacementMapEffect.cpp
index 4f6386d..6c779b7 100644
--- a/src/effects/SkDisplacementMapEffect.cpp
+++ b/src/effects/SkDisplacementMapEffect.cpp
@@ -343,7 +343,7 @@
                                           offsetMatrix,
                                           colorTexture.get(),
                                           SkISize::Make(color->width(), color->height())));
-        paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode);
+        paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
         SkMatrix matrix;
         matrix.setTranslate(-SkIntToScalar(colorBounds.x()), -SkIntToScalar(colorBounds.y()));
 
diff --git a/src/effects/SkDropShadowImageFilter.cpp b/src/effects/SkDropShadowImageFilter.cpp
index b4b8cac..cc43db7 100644
--- a/src/effects/SkDropShadowImageFilter.cpp
+++ b/src/effects/SkDropShadowImageFilter.cpp
@@ -95,7 +95,6 @@
     SkPaint paint;
     paint.setImageFilter(SkBlurImageFilter::Make(sigma.fX, sigma.fY, nullptr));
     paint.setColorFilter(SkColorFilter::MakeModeFilter(fColor, SkXfermode::kSrcIn_Mode));
-    paint.setXfermodeMode(SkXfermode::kSrcOver_Mode);
 
     SkVector offsetVec = SkVector::Make(fDx, fDy);
     ctx.ctm().mapVectors(&offsetVec, 1);
diff --git a/src/effects/SkImageSource.cpp b/src/effects/SkImageSource.cpp
index f434de4..f96a4a1 100644
--- a/src/effects/SkImageSource.cpp
+++ b/src/effects/SkImageSource.cpp
@@ -108,7 +108,7 @@
 
     // Subtract off the integer component of the translation (will be applied in offset, below).
     dstRect.offset(-SkIntToScalar(dstIRect.fLeft), -SkIntToScalar(dstIRect.fTop));
-    paint.setXfermodeMode(SkXfermode::kSrc_Mode);
+    paint.setBlendMode(SkBlendMode::kSrc);
     // FIXME: this probably shouldn't be necessary, but drawImageRect asserts
     // None filtering when it's translate-only
     paint.setFilterQuality(
diff --git a/src/effects/SkLayerDrawLooper.cpp b/src/effects/SkLayerDrawLooper.cpp
index d8f7744..784228f 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(sk_ref_sp(src.getXfermode()));
+        dst->setBlendMode(src.getBlendMode());
     }
 
     // we don't override these
diff --git a/src/effects/SkLightingImageFilter.cpp b/src/effects/SkLightingImageFilter.cpp
index 5627574..057ef24 100644
--- a/src/effects/SkLightingImageFilter.cpp
+++ b/src/effects/SkLightingImageFilter.cpp
@@ -396,7 +396,7 @@
     sk_sp<GrFragmentProcessor> fp(this->makeFragmentProcessor(src, matrix, srcBounds,
                                                               boundaryMode));
     paint.addColorFragmentProcessor(std::move(fp));
-    paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode);
+    paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
     drawContext->fillRectToRect(clip, paint, SkMatrix::I(), dstRect, srcRect);
 }
 
diff --git a/src/effects/SkMergeImageFilter.cpp b/src/effects/SkMergeImageFilter.cpp
index cc7e336..9830669 100755
--- a/src/effects/SkMergeImageFilter.cpp
+++ b/src/effects/SkMergeImageFilter.cpp
@@ -131,7 +131,7 @@
 
         SkPaint paint;
         if (fModes) {
-            paint.setXfermodeMode((SkXfermode::Mode)fModes[i]);
+            paint.setBlendMode((SkBlendMode)fModes[i]);
         }
 
         inputs[i]->draw(canvas,
diff --git a/src/effects/SkMorphologyImageFilter.cpp b/src/effects/SkMorphologyImageFilter.cpp
index 82e47c5..2bd7928 100644
--- a/src/effects/SkMorphologyImageFilter.cpp
+++ b/src/effects/SkMorphologyImageFilter.cpp
@@ -401,7 +401,7 @@
                                                              radius,
                                                              morphType,
                                                              bounds));
-    paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode);
+    paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
     drawContext->fillRectToRect(clip, paint, SkMatrix::I(), SkRect::Make(dstRect),
                                      SkRect::Make(srcRect));
 }
@@ -418,7 +418,7 @@
     paint.setGammaCorrect(drawContext->isGammaCorrect());
     paint.addColorFragmentProcessor(GrMorphologyEffect::Make(texture, direction, radius,
                                                              morphType));
-    paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode);
+    paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
     drawContext->fillRectToRect(clip, paint, SkMatrix::I(), SkRect::Make(dstRect),
                                 SkRect::Make(srcRect));
 }
diff --git a/src/effects/SkOffsetImageFilter.cpp b/src/effects/SkOffsetImageFilter.cpp
index 1c99154..2e8b0d9 100644
--- a/src/effects/SkOffsetImageFilter.cpp
+++ b/src/effects/SkOffsetImageFilter.cpp
@@ -61,7 +61,7 @@
         canvas->clear(0x0);
 
         SkPaint paint;
-        paint.setXfermodeMode(SkXfermode::kSrc_Mode);
+        paint.setBlendMode(SkBlendMode::kSrc);
         canvas->translate(SkIntToScalar(srcOffset.fX - bounds.fLeft),
                           SkIntToScalar(srcOffset.fY - bounds.fTop));
 
diff --git a/src/effects/SkTileImageFilter.cpp b/src/effects/SkTileImageFilter.cpp
index 46c4d9a..a140db2 100644
--- a/src/effects/SkTileImageFilter.cpp
+++ b/src/effects/SkTileImageFilter.cpp
@@ -87,7 +87,7 @@
         SkASSERT(canvas);
 
         SkPaint paint;
-        paint.setXfermodeMode(SkXfermode::kSrc_Mode);
+        paint.setBlendMode(SkBlendMode::kSrc);
 
         input->draw(canvas, 
                     SkIntToScalar(inputOffset.x()), SkIntToScalar(inputOffset.y()),
@@ -107,7 +107,7 @@
     SkASSERT(canvas);
 
     SkPaint paint;
-    paint.setXfermodeMode(SkXfermode::kSrc_Mode);
+    paint.setBlendMode(SkBlendMode::kSrc);
     paint.setShader(subset->makeShader(SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode));
     canvas->translate(-dstRect.fLeft, -dstRect.fTop);
     canvas->drawRect(dstRect, paint);
diff --git a/src/effects/SkXfermodeImageFilter.cpp b/src/effects/SkXfermodeImageFilter.cpp
index 952ce97..2335a76 100644
--- a/src/effects/SkXfermodeImageFilter.cpp
+++ b/src/effects/SkXfermodeImageFilter.cpp
@@ -27,7 +27,7 @@
 
 class SkXfermodeImageFilter_Base : public SkImageFilter {
 public:
-    SkXfermodeImageFilter_Base(sk_sp<SkXfermode> mode, sk_sp<SkImageFilter> inputs[2],
+    SkXfermodeImageFilter_Base(SkBlendMode mode, sk_sp<SkImageFilter> inputs[2],
                                const CropRect* cropRect);
 
     SK_TO_STRING_OVERRIDE()
@@ -55,7 +55,7 @@
 #endif
 
 private:
-    sk_sp<SkXfermode> fMode;
+    SkBlendMode fMode;
 
     friend class SkXfermodeImageFilter;
 
@@ -64,7 +64,7 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 
-sk_sp<SkImageFilter> SkXfermodeImageFilter::Make(sk_sp<SkXfermode> mode,
+sk_sp<SkImageFilter> SkXfermodeImageFilter::Make(SkBlendMode mode,
                                                  sk_sp<SkImageFilter> background,
                                                  sk_sp<SkImageFilter> foreground,
                                                  const SkImageFilter::CropRect* cropRect) {
@@ -72,23 +72,36 @@
     return sk_sp<SkImageFilter>(new SkXfermodeImageFilter_Base(mode, inputs, cropRect));
 }
 
-SkXfermodeImageFilter_Base::SkXfermodeImageFilter_Base(sk_sp<SkXfermode> mode,
-                                             sk_sp<SkImageFilter> inputs[2],
-                                             const CropRect* cropRect)
-    : INHERITED(inputs, 2, cropRect)
-    , fMode(std::move(mode)) {
+#ifdef SK_SUPPORT_LEGACY_XFERMODE_OBJECT
+sk_sp<SkImageFilter> SkXfermodeImageFilter::Make(sk_sp<SkXfermode> mode,
+                                                 sk_sp<SkImageFilter> background,
+                                                 sk_sp<SkImageFilter> foreground,
+                                                 const SkImageFilter::CropRect* cropRect) {
+    return Make(mode ? mode->blend() : SkBlendMode::kSrcOver,
+                std::move(background), std::move(foreground), cropRect);
 }
+#endif
+
+SkXfermodeImageFilter_Base::SkXfermodeImageFilter_Base(SkBlendMode mode,
+                                                       sk_sp<SkImageFilter> inputs[2],
+                                                       const CropRect* cropRect)
+    : INHERITED(inputs, 2, cropRect)
+    , fMode(mode)
+{}
 
 sk_sp<SkFlattenable> SkXfermodeImageFilter_Base::CreateProc(SkReadBuffer& buffer) {
     SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 2);
-    sk_sp<SkXfermode> mode(buffer.readXfermode());
-    return SkXfermodeImageFilter::Make(std::move(mode), common.getInput(0), common.getInput(1),
+    uint32_t mode = buffer.read32();
+    if (!buffer.validate(mode <= (unsigned)SkBlendMode::kLastMode)) {
+        return nullptr;
+    }
+    return SkXfermodeImageFilter::Make((SkBlendMode)mode, common.getInput(0), common.getInput(1),
                                        &common.cropRect());
 }
 
 void SkXfermodeImageFilter_Base::flatten(SkWriteBuffer& buffer) const {
     this->INHERITED::flatten(buffer);
-    buffer.writeFlattenable(fMode.get());
+    buffer.write32((unsigned)fMode);
 }
 
 sk_sp<SkSpecialImage> SkXfermodeImageFilter_Base::onFilterImage(SkSpecialImage* source,
@@ -147,7 +160,7 @@
 
     if (background) {
         SkPaint paint;
-        paint.setXfermodeMode(SkXfermode::kSrc_Mode);
+        paint.setBlendMode(SkBlendMode::kSrc);
         background->draw(canvas,
                          SkIntToScalar(backgroundOffset.fX), SkIntToScalar(backgroundOffset.fY),
                          &paint);
@@ -161,7 +174,7 @@
 void SkXfermodeImageFilter_Base::drawForeground(SkCanvas* canvas, SkSpecialImage* img,
                                                 const SkIRect& fgBounds) const {
     SkPaint paint;
-    paint.setXfermode(fMode);
+    paint.setBlendMode(fMode);
     if (img) {
         img->draw(canvas, SkIntToScalar(fgBounds.fLeft), SkIntToScalar(fgBounds.fTop), &paint);
     }
@@ -175,11 +188,7 @@
 #ifndef SK_IGNORE_TO_STRING
 void SkXfermodeImageFilter_Base::toString(SkString* str) const {
     str->appendf("SkXfermodeImageFilter: (");
-    str->appendf("xfermode: (");
-    if (fMode) {
-        fMode->toString(str);
-    }
-    str->append(")");
+    str->appendf("blendmode: (%d)", fMode);
     if (this->getInput(0)) {
         str->appendf("foreground: (");
         this->getInput(0)->toString(str);
@@ -266,7 +275,7 @@
         paint.addColorFragmentProcessor(std::move(bgFP));
     }
 
-    paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode);
+    paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
 
     sk_sp<GrDrawContext> drawContext(
         context->makeDrawContext(SkBackingFit::kApprox, bounds.width(), bounds.height(),
@@ -290,8 +299,9 @@
 sk_sp<GrFragmentProcessor>
 SkXfermodeImageFilter_Base::makeFGFrag(sk_sp<GrFragmentProcessor> bgFP) const {
     // A null fMode is interpreted to mean kSrcOver_Mode (to match raster).
-    SkAutoTUnref<SkXfermode> mode(SkSafeRef(fMode.get()));
-    if (!mode) {
+    SkXfermode* xfer = SkXfermode::Peek(fMode);
+    sk_sp<SkXfermode> srcover;
+    if (!xfer) {
         // It would be awesome to use SkXfermode::Create here but it knows better
         // than us and won't return a kSrcOver_Mode SkXfermode. That means we
         // have to get one the hard way.
@@ -299,9 +309,11 @@
         rec.fProc = SkXfermode::GetProc(SkXfermode::kSrcOver_Mode);
         SkXfermode::ModeAsCoeff(SkXfermode::kSrcOver_Mode, &rec.fSC, &rec.fDC);
 
-        mode.reset(new SkProcCoeffXfermode(rec, SkXfermode::kSrcOver_Mode));
+        srcover.reset(new SkProcCoeffXfermode(rec, SkXfermode::kSrcOver_Mode));
+        xfer = srcover.get();
+
     }
-    return mode->makeFragmentProcessorForImageFilter(std::move(bgFP));
+    return xfer->makeFragmentProcessorForImageFilter(std::move(bgFP));
 }
 
 #endif
@@ -312,7 +324,8 @@
 public:
     SkArithmeticImageFilter(float k1, float k2, float k3, float k4, bool enforcePMColor,
                             sk_sp<SkImageFilter> inputs[2], const CropRect* cropRect)
-        : SkXfermodeImageFilter_Base(nullptr, inputs, cropRect)
+        // need to pass a blendmode to our inherited constructor, but we ignore it
+        : SkXfermodeImageFilter_Base(SkBlendMode::kSrcOver, inputs, cropRect)
         , fK{ k1, k2, k3, k4 }
         , fEnforcePMColor(enforcePMColor)
     {}
@@ -347,8 +360,8 @@
     SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 2);
 
     // skip the mode (srcover) our parent-class wrote
-    sk_sp<SkXfermode> mode(buffer.readXfermode());
-    SkASSERT(nullptr == mode);
+    SkDEBUGCODE(uint32_t mode =) buffer.read32();
+    SkASSERT((unsigned)SkBlendMode::kSrcOver == mode);
 
     float k[4];
     for (int i = 0; i < 4; ++i) {
@@ -475,16 +488,16 @@
     int mode = -1;  // illegal mode
     if (SkScalarNearlyZero(k1) && SkScalarNearlyEqual(k2, SK_Scalar1) &&
         SkScalarNearlyZero(k3) && SkScalarNearlyZero(k4)) {
-        mode = SkXfermode::kSrc_Mode;
+        mode = (int)SkBlendMode::kSrc;
     } else if (SkScalarNearlyZero(k1) && SkScalarNearlyZero(k2) &&
                SkScalarNearlyEqual(k3, SK_Scalar1) && SkScalarNearlyZero(k4)) {
-        mode = SkXfermode::kDst_Mode;
+        mode = (int)SkBlendMode::kDst;
     } else if (SkScalarNearlyZero(k1) && SkScalarNearlyZero(k2) &&
                SkScalarNearlyZero(k3) && SkScalarNearlyZero(k4)) {
-        mode = SkXfermode::kClear_Mode;
+        mode = (int)SkBlendMode::kClear;
     }
     if (mode >= 0) {
-        return SkXfermodeImageFilter::Make(SkXfermode::Make((SkXfermode::Mode)mode),
+        return SkXfermodeImageFilter::Make((SkBlendMode)mode,
                                            std::move(background), std::move(foreground), crop);
     }
 
diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp
index 6cec1da..176d5da 100644
--- a/src/gpu/GrContext.cpp
+++ b/src/gpu/GrContext.cpp
@@ -356,7 +356,7 @@
             }
             GrPaint paint;
             paint.addColorFragmentProcessor(std::move(fp));
-            paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode);
+            paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
             paint.setAllowSRGBInputs(true);
             SkRect rect = SkRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height));
             drawContext->drawRect(GrNoClip(), paint, matrix, rect, nullptr);
@@ -471,7 +471,7 @@
             if (fp) {
                 GrPaint paint;
                 paint.addColorFragmentProcessor(std::move(fp));
-                paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode);
+                paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
                 paint.setAllowSRGBInputs(true);
                 SkRect rect = SkRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height));
                 tempDC->drawRect(GrNoClip(), paint, SkMatrix::I(), rect, nullptr);
diff --git a/src/gpu/GrDrawContext.cpp b/src/gpu/GrDrawContext.cpp
index e9a9619..42d6795 100644
--- a/src/gpu/GrDrawContext.cpp
+++ b/src/gpu/GrDrawContext.cpp
@@ -241,7 +241,7 @@
 
         GrPaint paint;
         paint.setColor4f(GrColor4f::FromGrColor(color));
-        paint.setXPFactory(GrPorterDuffXPFactory::Make(SkXfermode::kSrc_Mode));
+        paint.setXPFactory(GrPorterDuffXPFactory::Make(SkXfermode::Mode::kSrc_Mode));
 
         this->drawRect(clip, paint, SkMatrix::I(), clearRect);
     } else if (isFull) {
diff --git a/src/gpu/GrSWMaskHelper.cpp b/src/gpu/GrSWMaskHelper.cpp
index a20eacb..747b757 100644
--- a/src/gpu/GrSWMaskHelper.cpp
+++ b/src/gpu/GrSWMaskHelper.cpp
@@ -21,15 +21,15 @@
 /*
  * Convert a boolean operation into a transfer mode code
  */
-static SkXfermode::Mode op_to_mode(SkRegion::Op op) {
+static SkBlendMode op_to_mode(SkRegion::Op op) {
 
-    static const SkXfermode::Mode modeMap[] = {
-        SkXfermode::kDstOut_Mode,   // kDifference_Op
-        SkXfermode::kModulate_Mode, // kIntersect_Op
-        SkXfermode::kSrcOver_Mode,  // kUnion_Op
-        SkXfermode::kXor_Mode,      // kXOR_Op
-        SkXfermode::kClear_Mode,    // kReverseDifference_Op
-        SkXfermode::kSrc_Mode,      // kReplace_Op
+    static const SkBlendMode modeMap[] = {
+        SkBlendMode::kDstOut,   // kDifference_Op
+        SkBlendMode::kModulate, // kIntersect_Op
+        SkBlendMode::kSrcOver,  // kUnion_Op
+        SkBlendMode::kXor,      // kXOR_Op
+        SkBlendMode::kClear,    // kReverseDifference_Op
+        SkBlendMode::kSrc,      // kReplace_Op
     };
 
     return modeMap[op];
@@ -42,7 +42,7 @@
                               bool antiAlias, uint8_t alpha) {
     SkPaint paint;
 
-    paint.setXfermode(SkXfermode::Make(op_to_mode(op)));
+    paint.setBlendMode(op_to_mode(op));
     paint.setAntiAlias(antiAlias);
     paint.setColor(SkColorSetARGB(alpha, alpha, alpha, alpha));
 
@@ -65,7 +65,7 @@
         SkASSERT(0xFF == paint.getAlpha());
         fDraw.drawPathCoverage(path, paint);
     } else {
-        paint.setXfermodeMode(op_to_mode(op));
+        paint.setBlendMode(op_to_mode(op));
         paint.setColor(SkColorSetARGB(alpha, alpha, alpha, alpha));
         fDraw.drawPath(path, paint);
     }
diff --git a/src/gpu/GrTextureParamsAdjuster.cpp b/src/gpu/GrTextureParamsAdjuster.cpp
index 3ca90f5..f51cc54 100644
--- a/src/gpu/GrTextureParamsAdjuster.cpp
+++ b/src/gpu/GrTextureParamsAdjuster.cpp
@@ -72,7 +72,7 @@
         GrTextureParams params(SkShader::kClamp_TileMode, copyParams.fFilter);
         paint.addColorTextureProcessor(inputTexture, nullptr, SkMatrix::I(), params);
     }
-    paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode);
+    paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
 
     SkRect localRect;
     if (subset) {
diff --git a/src/gpu/GrTextureToYUVPlanes.cpp b/src/gpu/GrTextureToYUVPlanes.cpp
index 5e7dafe..93a62d2 100644
--- a/src/gpu/GrTextureToYUVPlanes.cpp
+++ b/src/gpu/GrTextureToYUVPlanes.cpp
@@ -41,7 +41,7 @@
         return false;
     }
     GrPaint paint;
-    paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode);
+    paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
     paint.addColorFragmentProcessor(std::move(fp));
     dst->drawRect(GrNoClip(), paint, SkMatrix::I(), SkRect::MakeIWH(dstW, dstH));
     return true;
diff --git a/src/gpu/GrYUVProvider.cpp b/src/gpu/GrYUVProvider.cpp
index b187ec3..db58e0a 100644
--- a/src/gpu/GrYUVProvider.cpp
+++ b/src/gpu/GrYUVProvider.cpp
@@ -142,7 +142,7 @@
         }
     }
 
-    paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode);
+    paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
     const SkRect r = SkRect::MakeIWH(yuvInfo.fSizeInfo.fSizes[SkYUVSizeInfo::kY].fWidth,
             yuvInfo.fSizeInfo.fSizes[SkYUVSizeInfo::kY].fHeight);
 
diff --git a/src/gpu/SkGr.cpp b/src/gpu/SkGr.cpp
index d4db461..ee4e40a 100644
--- a/src/gpu/SkGr.cpp
+++ b/src/gpu/SkGr.cpp
@@ -20,6 +20,7 @@
 #include "GrXferProcessor.h"
 #include "GrYUVProvider.h"
 
+#include "SkBlendModePriv.h"
 #include "SkColorFilter.h"
 #include "SkConfig8888.h"
 #include "SkCanvas.h"
@@ -680,9 +681,8 @@
     // When the xfermode is null on the SkPaint (meaning kSrcOver) we need the XPFactory field on
     // the GrPaint to also be null (also kSrcOver).
     SkASSERT(!grPaint->getXPFactory());
-    SkXfermode* xfermode = skPaint.getXfermode();
-    if (xfermode) {
-        grPaint->setXPFactory(xfermode->asXPFactory());
+    if (!skPaint.isSrcOver()) {
+        grPaint->setXPFactory(SkBlendMode_AsXPFactory(skPaint.getBlendMode()));
     }
 
 #ifndef SK_IGNORE_GPU_DITHER
diff --git a/src/gpu/effects/GrConfigConversionEffect.cpp b/src/gpu/effects/GrConfigConversionEffect.cpp
index 4eb7a11..80a0314 100644
--- a/src/gpu/effects/GrConfigConversionEffect.cpp
+++ b/src/gpu/effects/GrConfigConversionEffect.cpp
@@ -229,19 +229,19 @@
                 tempDC->asTexture().get(), GrSwizzle::RGBA(), *pmToUPMRule, SkMatrix::I()));
 
         paint1.addColorFragmentProcessor(std::move(pmToUPM1));
-        paint1.setPorterDuffXPFactory(SkXfermode::kSrc_Mode);
+        paint1.setPorterDuffXPFactory(SkBlendMode::kSrc);
 
         readDC->fillRectToRect(GrNoClip(), paint1, SkMatrix::I(), kDstRect, kSrcRect);
 
         readDC->asTexture()->readPixels(0, 0, kSize, kSize, kConfig, firstRead);
 
         paint2.addColorFragmentProcessor(std::move(upmToPM));
-        paint2.setPorterDuffXPFactory(SkXfermode::kSrc_Mode);
+        paint2.setPorterDuffXPFactory(SkBlendMode::kSrc);
 
         tempDC->fillRectToRect(GrNoClip(), paint2, SkMatrix::I(), kDstRect, kSrcRect);
 
         paint3.addColorFragmentProcessor(std::move(pmToUPM2));
-        paint3.setPorterDuffXPFactory(SkXfermode::kSrc_Mode);
+        paint3.setPorterDuffXPFactory(SkBlendMode::kSrc);
 
         readDC->fillRectToRect(GrNoClip(), paint3, SkMatrix::I(), kDstRect, kSrcRect);
 
diff --git a/src/gpu/text/GrTextUtils.cpp b/src/gpu/text/GrTextUtils.cpp
index 56d4ec1..a5685f0 100644
--- a/src/gpu/text/GrTextUtils.cpp
+++ b/src/gpu/text/GrTextUtils.cpp
@@ -547,8 +547,7 @@
 }
 
 bool GrTextUtils::ShouldDisableLCD(const SkPaint& paint) {
-    return !SkXfermode::AsMode(paint.getXfermode(), nullptr) ||
-           paint.getMaskFilter() ||
+    return paint.getMaskFilter() ||
            paint.getRasterizer() ||
            paint.getPathEffect() ||
            paint.isFakeBoldText() ||
diff --git a/src/image/SkImage.cpp b/src/image/SkImage.cpp
index 2870f31..67779ba 100644
--- a/src/image/SkImage.cpp
+++ b/src/image/SkImage.cpp
@@ -259,7 +259,7 @@
     SkCanvas canvas(bm);
 
     SkPaint paint;
-    paint.setXfermodeMode(SkXfermode::kSrc_Mode);
+    paint.setBlendMode(SkBlendMode::kSrc);
     canvas.drawImage(this, -SkIntToScalar(srcX), -SkIntToScalar(srcY), &paint);
 
     return true;
diff --git a/src/pdf/SkPDFDevice.cpp b/src/pdf/SkPDFDevice.cpp
index a002120..a874284 100644
--- a/src/pdf/SkPDFDevice.cpp
+++ b/src/pdf/SkPDFDevice.cpp
@@ -47,12 +47,11 @@
 
 // Utility functions
 
-// If the paint will definitely draw opaquely, replace kSrc_Mode with
-// kSrcOver_Mode.  http://crbug.com/473572
+// If the paint will definitely draw opaquely, replace kSrc with
+// kSrcOver.  http://crbug.com/473572
 static void replace_srcmode_on_opaque_paint(SkPaint* paint) {
-    if (kSrcOver_SkXfermodeInterpretation
-        == SkInterpretXfermode(*paint, false)) {
-        paint->setXfermode(nullptr);
+    if (kSrcOver_SkXfermodeInterpretation == SkInterpretXfermode(*paint, false)) {
+        paint->setBlendMode(SkBlendMode::kSrcOver);
     }
 }
 
@@ -392,7 +391,7 @@
                        const SkPaint& paint, bool hasText = false)
         : fDevice(device),
           fContentEntry(nullptr),
-          fXfermode(SkXfermode::kSrcOver_Mode),
+          fBlendMode(SkBlendMode::kSrcOver),
           fDstFormXObject(nullptr) {
         init(draw.fClipStack, draw.fRC->bwRgn(), *draw.fMatrix, paint, hasText);
     }
@@ -401,7 +400,7 @@
                        const SkPaint& paint, bool hasText = false)
         : fDevice(device),
           fContentEntry(nullptr),
-          fXfermode(SkXfermode::kSrcOver_Mode),
+          fBlendMode(SkBlendMode::kSrcOver),
           fDstFormXObject(nullptr) {
         init(clipStack, clipRegion, matrix, paint, hasText);
     }
@@ -412,7 +411,7 @@
             if (shape->isEmpty()) {
                 shape = nullptr;
             }
-            fDevice->finishContentEntry(fXfermode, std::move(fDstFormXObject), shape);
+            fDevice->finishContentEntry(fBlendMode, std::move(fDstFormXObject), shape);
         }
     }
 
@@ -420,16 +419,16 @@
 
     /* Returns true when we explicitly need the shape of the drawing. */
     bool needShape() {
-        switch (fXfermode) {
-            case SkXfermode::kClear_Mode:
-            case SkXfermode::kSrc_Mode:
-            case SkXfermode::kSrcIn_Mode:
-            case SkXfermode::kSrcOut_Mode:
-            case SkXfermode::kDstIn_Mode:
-            case SkXfermode::kDstOut_Mode:
-            case SkXfermode::kSrcATop_Mode:
-            case SkXfermode::kDstATop_Mode:
-            case SkXfermode::kModulate_Mode:
+        switch (fBlendMode) {
+            case SkBlendMode::kClear:
+            case SkBlendMode::kSrc:
+            case SkBlendMode::kSrcIn:
+            case SkBlendMode::kSrcOut:
+            case SkBlendMode::kDstIn:
+            case SkBlendMode::kDstOut:
+            case SkBlendMode::kSrcATop:
+            case SkBlendMode::kDstATop:
+            case SkBlendMode::kModulate:
                 return true;
             default:
                 return false;
@@ -438,7 +437,7 @@
 
     /* Returns true unless we only need the shape of the drawing. */
     bool needSource() {
-        if (fXfermode == SkXfermode::kClear_Mode) {
+        if (fBlendMode == SkBlendMode::kClear) {
             return false;
         }
         return true;
@@ -455,7 +454,7 @@
 private:
     SkPDFDevice* fDevice;
     SkPDFDevice::ContentEntry* fContentEntry;
-    SkXfermode::Mode fXfermode;
+    SkBlendMode fBlendMode;
     sk_sp<SkPDFObject> fDstFormXObject;
     SkPath fShape;
 
@@ -466,9 +465,7 @@
             NOT_IMPLEMENTED(!matrix.hasPerspective(), false);
             return;
         }
-        if (paint.getXfermode()) {
-            paint.getXfermode()->asMode(&fXfermode);
-        }
+        fBlendMode = paint.getBlendMode();
         fContentEntry = fDevice->setUpContentEntry(clipStack, clipRegion,
                                                    matrix, paint, hasText,
                                                    &fDstFormXObject);
@@ -1708,7 +1705,7 @@
                                           sk_sp<SkPDFObject> mask,
                                           const SkClipStack* clipStack,
                                           const SkRegion& clipRegion,
-                                          SkXfermode::Mode mode,
+                                          SkBlendMode mode,
                                           bool invertClip) {
     if (clipRegion.isEmpty() && !invertClip) {
         return;
@@ -1721,7 +1718,7 @@
     SkMatrix identity;
     identity.reset();
     SkPaint paint;
-    paint.setXfermodeMode(mode);
+    paint.setBlendMode(mode);
     ScopedContentEntry content(this, clipStack, clipRegion, identity, paint);
     if (!content.entry()) {
         return;
@@ -1767,27 +1764,24 @@
         }
     }
 
-    SkXfermode::Mode xfermode = SkXfermode::kSrcOver_Mode;
-    if (paint.getXfermode()) {
-        paint.getXfermode()->asMode(&xfermode);
-    }
+    SkBlendMode blendMode = paint.getBlendMode();
 
     // For the following modes, we want to handle source and destination
     // separately, so make an object of what's already there.
-    if (xfermode == SkXfermode::kClear_Mode       ||
-            xfermode == SkXfermode::kSrc_Mode     ||
-            xfermode == SkXfermode::kSrcIn_Mode   ||
-            xfermode == SkXfermode::kDstIn_Mode   ||
-            xfermode == SkXfermode::kSrcOut_Mode  ||
-            xfermode == SkXfermode::kDstOut_Mode  ||
-            xfermode == SkXfermode::kSrcATop_Mode ||
-            xfermode == SkXfermode::kDstATop_Mode ||
-            xfermode == SkXfermode::kModulate_Mode) {
+    if (blendMode == SkBlendMode::kClear       ||
+            blendMode == SkBlendMode::kSrc     ||
+            blendMode == SkBlendMode::kSrcIn   ||
+            blendMode == SkBlendMode::kDstIn   ||
+            blendMode == SkBlendMode::kSrcOut  ||
+            blendMode == SkBlendMode::kDstOut  ||
+            blendMode == SkBlendMode::kSrcATop ||
+            blendMode == SkBlendMode::kDstATop ||
+            blendMode == SkBlendMode::kModulate) {
         if (!isContentEmpty()) {
             *dst = this->makeFormXObjectFromDevice();
             SkASSERT(isContentEmpty());
-        } else if (xfermode != SkXfermode::kSrc_Mode &&
-                   xfermode != SkXfermode::kSrcOut_Mode) {
+        } else if (blendMode != SkBlendMode::kSrc &&
+                   blendMode != SkBlendMode::kSrcOut) {
             // Except for Src and SrcOut, if there isn't anything already there,
             // then we're done.
             return nullptr;
@@ -1797,14 +1791,14 @@
     // Xor, Plus.
 
     // Dst xfer mode doesn't draw source at all.
-    if (xfermode == SkXfermode::kDst_Mode) {
+    if (blendMode == SkBlendMode::kDst) {
         return nullptr;
     }
 
     SkPDFDevice::ContentEntry* entry;
     if (fContentEntries.back() && fContentEntries.back()->fContent.getOffset() == 0) {
         entry = fContentEntries.back();
-    } else if (xfermode != SkXfermode::kDstOver_Mode) {
+    } else if (blendMode != SkBlendMode::kDstOver) {
         entry = fContentEntries.emplace_back();
     } else {
         entry = fContentEntries.emplace_front();
@@ -1814,23 +1808,23 @@
     return entry;
 }
 
-void SkPDFDevice::finishContentEntry(SkXfermode::Mode xfermode,
+void SkPDFDevice::finishContentEntry(SkBlendMode blendMode,
                                      sk_sp<SkPDFObject> dst,
                                      SkPath* shape) {
-    if (xfermode != SkXfermode::kClear_Mode       &&
-            xfermode != SkXfermode::kSrc_Mode     &&
-            xfermode != SkXfermode::kDstOver_Mode &&
-            xfermode != SkXfermode::kSrcIn_Mode   &&
-            xfermode != SkXfermode::kDstIn_Mode   &&
-            xfermode != SkXfermode::kSrcOut_Mode  &&
-            xfermode != SkXfermode::kDstOut_Mode  &&
-            xfermode != SkXfermode::kSrcATop_Mode &&
-            xfermode != SkXfermode::kDstATop_Mode &&
-            xfermode != SkXfermode::kModulate_Mode) {
+    if (blendMode != SkBlendMode::kClear       &&
+            blendMode != SkBlendMode::kSrc     &&
+            blendMode != SkBlendMode::kDstOver &&
+            blendMode != SkBlendMode::kSrcIn   &&
+            blendMode != SkBlendMode::kDstIn   &&
+            blendMode != SkBlendMode::kSrcOut  &&
+            blendMode != SkBlendMode::kDstOut  &&
+            blendMode != SkBlendMode::kSrcATop &&
+            blendMode != SkBlendMode::kDstATop &&
+            blendMode != SkBlendMode::kModulate) {
         SkASSERT(!dst);
         return;
     }
-    if (xfermode == SkXfermode::kDstOver_Mode) {
+    if (blendMode == SkBlendMode::kDstOver) {
         SkASSERT(!dst);
         if (fContentEntries.front()->fContent.getOffset() == 0) {
             // For DstOver, an empty content entry was inserted before the rest
@@ -1841,8 +1835,8 @@
         return;
     }
     if (!dst) {
-        SkASSERT(xfermode == SkXfermode::kSrc_Mode ||
-                 xfermode == SkXfermode::kSrcOut_Mode);
+        SkASSERT(blendMode == SkBlendMode::kSrc ||
+                 blendMode == SkBlendMode::kSrcOut);
         return;
     }
 
@@ -1867,8 +1861,8 @@
         // If there is shape, then an empty source with Src, SrcIn, SrcOut,
         // DstIn, DstAtop or Modulate reduces to Clear and DstOut or SrcAtop
         // reduces to Dst.
-        if (shape == nullptr || xfermode == SkXfermode::kDstOut_Mode ||
-                xfermode == SkXfermode::kSrcATop_Mode) {
+        if (shape == nullptr || blendMode == SkBlendMode::kDstOut ||
+                blendMode == SkBlendMode::kSrcATop) {
             ScopedContentEntry content(this, &fExistingClipStack,
                                        fExistingClipRegion, identity,
                                        stockPaint);
@@ -1877,7 +1871,7 @@
                                         &content.entry()->fContent);
             return;
         } else {
-            xfermode = SkXfermode::kClear_Mode;
+            blendMode = SkBlendMode::kClear;
         }
     } else {
         SkASSERT(fContentEntries.count() == 1);
@@ -1886,14 +1880,14 @@
 
     // TODO(vandebo) srcFormXObject may contain alpha, but here we want it
     // without alpha.
-    if (xfermode == SkXfermode::kSrcATop_Mode) {
+    if (blendMode == SkBlendMode::kSrcATop) {
         // TODO(vandebo): In order to properly support SrcATop we have to track
         // the shape of what's been drawn at all times. It's the intersection of
         // the non-transparent parts of the device and the outlines (shape) of
         // all images and devices drawn.
         drawFormXObjectWithMask(addXObjectResource(srcFormXObject.get()), dst,
                                 &fExistingClipStack, fExistingClipRegion,
-                                SkXfermode::kSrcOver_Mode, true);
+                                SkBlendMode::kSrcOver, true);
     } else {
         if (shape != nullptr) {
             // Draw shape into a form-xobject.
@@ -1909,19 +1903,19 @@
             drawFormXObjectWithMask(addXObjectResource(dst.get()),
                                     this->makeFormXObjectFromDevice(),
                                     &fExistingClipStack, fExistingClipRegion,
-                                    SkXfermode::kSrcOver_Mode, true);
+                                    SkBlendMode::kSrcOver, true);
 
         } else {
             drawFormXObjectWithMask(addXObjectResource(dst.get()), srcFormXObject,
                                     &fExistingClipStack, fExistingClipRegion,
-                                    SkXfermode::kSrcOver_Mode, true);
+                                    SkBlendMode::kSrcOver, true);
         }
     }
 
-    if (xfermode == SkXfermode::kClear_Mode) {
+    if (blendMode == SkBlendMode::kClear) {
         return;
-    } else if (xfermode == SkXfermode::kSrc_Mode ||
-            xfermode == SkXfermode::kDstATop_Mode) {
+    } else if (blendMode == SkBlendMode::kSrc ||
+            blendMode == SkBlendMode::kDstATop) {
         ScopedContentEntry content(this, &fExistingClipStack,
                                    fExistingClipRegion, identity, stockPaint);
         if (content.entry()) {
@@ -1929,10 +1923,10 @@
                     this->addXObjectResource(srcFormXObject.get()),
                     &content.entry()->fContent);
         }
-        if (xfermode == SkXfermode::kSrc_Mode) {
+        if (blendMode == SkBlendMode::kSrc) {
             return;
         }
-    } else if (xfermode == SkXfermode::kSrcATop_Mode) {
+    } else if (blendMode == SkBlendMode::kSrcATop) {
         ScopedContentEntry content(this, &fExistingClipStack,
                                    fExistingClipRegion, identity, stockPaint);
         if (content.entry()) {
@@ -1941,36 +1935,36 @@
         }
     }
 
-    SkASSERT(xfermode == SkXfermode::kSrcIn_Mode   ||
-             xfermode == SkXfermode::kDstIn_Mode   ||
-             xfermode == SkXfermode::kSrcOut_Mode  ||
-             xfermode == SkXfermode::kDstOut_Mode  ||
-             xfermode == SkXfermode::kSrcATop_Mode ||
-             xfermode == SkXfermode::kDstATop_Mode ||
-             xfermode == SkXfermode::kModulate_Mode);
+    SkASSERT(blendMode == SkBlendMode::kSrcIn   ||
+             blendMode == SkBlendMode::kDstIn   ||
+             blendMode == SkBlendMode::kSrcOut  ||
+             blendMode == SkBlendMode::kDstOut  ||
+             blendMode == SkBlendMode::kSrcATop ||
+             blendMode == SkBlendMode::kDstATop ||
+             blendMode == SkBlendMode::kModulate);
 
-    if (xfermode == SkXfermode::kSrcIn_Mode ||
-            xfermode == SkXfermode::kSrcOut_Mode ||
-            xfermode == SkXfermode::kSrcATop_Mode) {
+    if (blendMode == SkBlendMode::kSrcIn ||
+            blendMode == SkBlendMode::kSrcOut ||
+            blendMode == SkBlendMode::kSrcATop) {
         drawFormXObjectWithMask(addXObjectResource(srcFormXObject.get()),
                                 std::move(dst),
                                 &fExistingClipStack, fExistingClipRegion,
-                                SkXfermode::kSrcOver_Mode,
-                                xfermode == SkXfermode::kSrcOut_Mode);
+                                SkBlendMode::kSrcOver,
+                                blendMode == SkBlendMode::kSrcOut);
         return;
     } else {
-        SkXfermode::Mode mode = SkXfermode::kSrcOver_Mode;
+        SkBlendMode mode = SkBlendMode::kSrcOver;
         int resourceID = addXObjectResource(dst.get());
-        if (xfermode == SkXfermode::kModulate_Mode) {
+        if (blendMode == SkBlendMode::kModulate) {
             drawFormXObjectWithMask(addXObjectResource(srcFormXObject.get()),
                                     std::move(dst), &fExistingClipStack,
                                     fExistingClipRegion,
-                                    SkXfermode::kSrcOver_Mode, false);
-            mode = SkXfermode::kMultiply_Mode;
+                                    SkBlendMode::kSrcOver, false);
+            mode = SkBlendMode::kMultiply;
         }
         drawFormXObjectWithMask(resourceID, std::move(srcFormXObject),
                                 &fExistingClipStack, fExistingClipRegion, mode,
-                                xfermode == SkXfermode::kDstOut_Mode);
+                                blendMode == SkBlendMode::kDstOut);
         return;
     }
 }
diff --git a/src/pdf/SkPDFDevice.h b/src/pdf/SkPDFDevice.h
index be0a277..7d207e7 100644
--- a/src/pdf/SkPDFDevice.h
+++ b/src/pdf/SkPDFDevice.h
@@ -246,7 +246,7 @@
                                  sk_sp<SkPDFObject> mask,
                                  const SkClipStack* clipStack,
                                  const SkRegion& clipRegion,
-                                 SkXfermode::Mode mode,
+                                 SkBlendMode,
                                  bool invertClip);
 
     // If the paint or clip is such that we shouldn't draw anything, this
@@ -259,9 +259,7 @@
                                     const SkPaint& paint,
                                     bool hasText,
                                     sk_sp<SkPDFObject>* dst);
-    void finishContentEntry(SkXfermode::Mode xfermode,
-                            sk_sp<SkPDFObject> dst,
-                            SkPath* shape);
+    void finishContentEntry(SkBlendMode, sk_sp<SkPDFObject> dst, SkPath* shape);
     bool isContentEmpty();
 
     void populateGraphicStateEntryFromPaint(const SkMatrix& matrix,
diff --git a/src/pdf/SkPDFGraphicState.cpp b/src/pdf/SkPDFGraphicState.cpp
index a78c4c5..d60526c 100644
--- a/src/pdf/SkPDFGraphicState.cpp
+++ b/src/pdf/SkPDFGraphicState.cpp
@@ -12,58 +12,58 @@
 #include "SkPDFGraphicState.h"
 #include "SkPDFUtils.h"
 
-static const char* as_blend_mode(SkXfermode::Mode mode) {
+static const char* as_blend_mode(SkBlendMode mode) {
     switch (mode) {
-        case SkXfermode::kSrcOver_Mode:
+        case SkBlendMode::kSrcOver:
             return "Normal";
-        case SkXfermode::kMultiply_Mode:
+        case SkBlendMode::kMultiply:
             return "Multiply";
-        case SkXfermode::kScreen_Mode:
+        case SkBlendMode::kScreen:
             return "Screen";
-        case SkXfermode::kOverlay_Mode:
+        case SkBlendMode::kOverlay:
             return "Overlay";
-        case SkXfermode::kDarken_Mode:
+        case SkBlendMode::kDarken:
             return "Darken";
-        case SkXfermode::kLighten_Mode:
+        case SkBlendMode::kLighten:
             return "Lighten";
-        case SkXfermode::kColorDodge_Mode:
+        case SkBlendMode::kColorDodge:
             return "ColorDodge";
-        case SkXfermode::kColorBurn_Mode:
+        case SkBlendMode::kColorBurn:
             return "ColorBurn";
-        case SkXfermode::kHardLight_Mode:
+        case SkBlendMode::kHardLight:
             return "HardLight";
-        case SkXfermode::kSoftLight_Mode:
+        case SkBlendMode::kSoftLight:
             return "SoftLight";
-        case SkXfermode::kDifference_Mode:
+        case SkBlendMode::kDifference:
             return "Difference";
-        case SkXfermode::kExclusion_Mode:
+        case SkBlendMode::kExclusion:
             return "Exclusion";
-        case SkXfermode::kHue_Mode:
+        case SkBlendMode::kHue:
             return "Hue";
-        case SkXfermode::kSaturation_Mode:
+        case SkBlendMode::kSaturation:
             return "Saturation";
-        case SkXfermode::kColor_Mode:
+        case SkBlendMode::kColor:
             return "Color";
-        case SkXfermode::kLuminosity_Mode:
+        case SkBlendMode::kLuminosity:
             return "Luminosity";
 
         // These are handled in SkPDFDevice::setUpContentEntry.
-        case SkXfermode::kClear_Mode:
-        case SkXfermode::kSrc_Mode:
-        case SkXfermode::kDst_Mode:
-        case SkXfermode::kDstOver_Mode:
-        case SkXfermode::kSrcIn_Mode:
-        case SkXfermode::kDstIn_Mode:
-        case SkXfermode::kSrcOut_Mode:
-        case SkXfermode::kDstOut_Mode:
-        case SkXfermode::kSrcATop_Mode:
-        case SkXfermode::kDstATop_Mode:
-        case SkXfermode::kModulate_Mode:
+        case SkBlendMode::kClear:
+        case SkBlendMode::kSrc:
+        case SkBlendMode::kDst:
+        case SkBlendMode::kDstOver:
+        case SkBlendMode::kSrcIn:
+        case SkBlendMode::kDstIn:
+        case SkBlendMode::kSrcOut:
+        case SkBlendMode::kDstOut:
+        case SkBlendMode::kSrcATop:
+        case SkBlendMode::kDstATop:
+        case SkBlendMode::kModulate:
             return "Normal";
 
         // TODO(vandebo): Figure out if we can support more of these modes.
-        case SkXfermode::kXor_Mode:
-        case SkXfermode::kPlus_Mode:
+        case SkBlendMode::kXor:
+        case SkBlendMode::kPlus:
             return nullptr;
     }
     return nullptr;
@@ -71,32 +71,28 @@
 
 // If a SkXfermode is unsupported in PDF, this function returns
 // SrcOver, otherwise, it returns that Xfermode as a Mode.
-static SkXfermode::Mode mode_for_pdf(const SkXfermode* xfermode) {
-    SkXfermode::Mode mode = SkXfermode::kSrcOver_Mode;
-    if (xfermode) {
-        xfermode->asMode(&mode);
-    }
+static SkBlendMode mode_for_pdf(SkBlendMode mode) {
     switch (mode) {
-        case SkXfermode::kSrcOver_Mode:
-        case SkXfermode::kMultiply_Mode:
-        case SkXfermode::kScreen_Mode:
-        case SkXfermode::kOverlay_Mode:
-        case SkXfermode::kDarken_Mode:
-        case SkXfermode::kLighten_Mode:
-        case SkXfermode::kColorDodge_Mode:
-        case SkXfermode::kColorBurn_Mode:
-        case SkXfermode::kHardLight_Mode:
-        case SkXfermode::kSoftLight_Mode:
-        case SkXfermode::kDifference_Mode:
-        case SkXfermode::kExclusion_Mode:
-        case SkXfermode::kHue_Mode:
-        case SkXfermode::kSaturation_Mode:
-        case SkXfermode::kColor_Mode:
-        case SkXfermode::kLuminosity_Mode:
+        case SkBlendMode::kSrcOver:
+        case SkBlendMode::kMultiply:
+        case SkBlendMode::kScreen:
+        case SkBlendMode::kOverlay:
+        case SkBlendMode::kDarken:
+        case SkBlendMode::kLighten:
+        case SkBlendMode::kColorDodge:
+        case SkBlendMode::kColorBurn:
+        case SkBlendMode::kHardLight:
+        case SkBlendMode::kSoftLight:
+        case SkBlendMode::kDifference:
+        case SkBlendMode::kExclusion:
+        case SkBlendMode::kHue:
+        case SkBlendMode::kSaturation:
+        case SkBlendMode::kColor:
+        case SkBlendMode::kLuminosity:
             // Mode is suppported and handled by pdf graphics state.
             return mode;
         default:
-            return SkXfermode::kSrcOver_Mode;  // Default mode.
+            return SkBlendMode::kSrcOver;  // Default mode.
     }
 }
 
@@ -106,7 +102,7 @@
     , fAlpha(p.getAlpha())
     , fStrokeCap(SkToU8(p.getStrokeCap()))
     , fStrokeJoin(SkToU8(p.getStrokeJoin()))
-    , fMode(SkToU8(mode_for_pdf(p.getXfermode()))) {}
+    , fMode(SkToU8((unsigned)mode_for_pdf(p.getBlendMode()))) {}
 
 // static
 SkPDFGraphicState* SkPDFGraphicState::GetGraphicStateForPaint(
@@ -186,7 +182,6 @@
 
     SkPaint::Cap strokeCap = (SkPaint::Cap)fStrokeCap;
     SkPaint::Join strokeJoin = (SkPaint::Join)fStrokeJoin;
-    SkXfermode::Mode xferMode = (SkXfermode::Mode)fMode;
 
     static_assert(SkPaint::kButt_Cap == 0, "paint_cap_mismatch");
     static_assert(SkPaint::kRound_Cap == 1, "paint_cap_mismatch");
@@ -205,6 +200,6 @@
     dict->insertScalar("LW", fStrokeWidth);
     dict->insertScalar("ML", fStrokeMiter);
     dict->insertBool("SA", true);  // SA = Auto stroke adjustment.
-    dict->insertName("BM", as_blend_mode(xferMode));
+    dict->insertName("BM", as_blend_mode((SkBlendMode)fMode));
     dict->emitObject(stream, objNumMap);
 }
diff --git a/src/pdf/SkPDFGraphicState.h b/src/pdf/SkPDFGraphicState.h
index 0c2e4a0..8ee6728 100644
--- a/src/pdf/SkPDFGraphicState.h
+++ b/src/pdf/SkPDFGraphicState.h
@@ -70,7 +70,7 @@
     const uint8_t fAlpha;
     const uint8_t fStrokeCap;   // SkPaint::Cap
     const uint8_t fStrokeJoin;  // SkPaint::Join
-    const uint8_t fMode;        // SkXfermode::Mode
+    const uint8_t fMode;        // SkBlendMode
 
     SkPDFGraphicState(const SkPaint&);
 
diff --git a/src/pipe/SkPipeCanvas.cpp b/src/pipe/SkPipeCanvas.cpp
index a01237f..3b636a2 100644
--- a/src/pipe/SkPipeCanvas.cpp
+++ b/src/pipe/SkPipeCanvas.cpp
@@ -81,7 +81,6 @@
         bits |= (paint.getMaskFilter()  ? kMaskFilter_NonDef : 0);
     }
 
-    bits |= (paint.getXfermode()    ? kXfermode_NonDef : 0);
     bits |= (paint.getColorFilter() ? kColorFilter_NonDef : 0);
     bits |= (paint.getImageFilter() ? kImageFilter_NonDef : 0);
     bits |= (paint.getDrawLooper()  ? kDrawLooper_NonDef : 0);
@@ -150,15 +149,8 @@
     writer.write32(packedFlags);
 
     unsigned nondef = compute_nondef(paint, (PaintUsage)usage);
-    SkXfermode::Mode mode;
-    if (SkXfermode::AsMode(paint.getXfermode(), &mode)) {
-        nondef &= ~kXfermode_NonDef;    // don't need to store a pointer since we have an enum
-    } else {
-        SkASSERT(nondef & kXfermode_NonDef);
-        mode = (SkXfermode::Mode)0;
-    }
     const uint8_t pad = 0;
-    writer.write32((nondef << 16) | ((unsigned)mode << 8) | pad);
+    writer.write32((nondef << 16) | ((unsigned)paint.getBlendMode() << 8) | pad);
 
     CHECK_WRITE_SCALAR(writer, nondef, paint, TextSize);
     CHECK_WRITE_SCALAR(writer, nondef, paint, TextScaleX);
@@ -179,7 +171,6 @@
 
     CHECK_WRITE_FLATTENABLE(writer, nondef, paint, PathEffect);
     CHECK_WRITE_FLATTENABLE(writer, nondef, paint, Shader);
-    CHECK_WRITE_FLATTENABLE(writer, nondef, paint, Xfermode);
     CHECK_WRITE_FLATTENABLE(writer, nondef, paint, MaskFilter);
     CHECK_WRITE_FLATTENABLE(writer, nondef, paint, ColorFilter);
     CHECK_WRITE_FLATTENABLE(writer, nondef, paint, Rasterizer);
diff --git a/src/pipe/SkPipeFormat.h b/src/pipe/SkPipeFormat.h
index 8f5c828..9a1d30c 100644
--- a/src/pipe/SkPipeFormat.h
+++ b/src/pipe/SkPipeFormat.h
@@ -94,12 +94,11 @@
     kTypeface_NonDef    = 1 << 6,
     kPathEffect_NonDef  = 1 << 7,
     kShader_NonDef      = 1 << 8,
-    kXfermode_NonDef    = 1 << 9,
-    kMaskFilter_NonDef  = 1 << 10,
-    kColorFilter_NonDef = 1 << 11,
-    kRasterizer_NonDef  = 1 << 12,
-    kImageFilter_NonDef = 1 << 13,
-    kDrawLooper_NonDef  = 1 << 14,
+    kMaskFilter_NonDef  = 1 << 9,
+    kColorFilter_NonDef = 1 << 10,
+    kRasterizer_NonDef  = 1 << 11,
+    kImageFilter_NonDef = 1 << 12,
+    kDrawLooper_NonDef  = 1 << 13,
 };
 
 enum {
diff --git a/src/pipe/SkPipeReader.cpp b/src/pipe/SkPipeReader.cpp
index 8840da1..47d4072 100644
--- a/src/pipe/SkPipeReader.cpp
+++ b/src/pipe/SkPipeReader.cpp
@@ -149,13 +149,13 @@
  *      pad zeros       : 8
  */
 static SkPaint read_paint(SkReadBuffer& reader) {
+    SkPaint paint;
+
     uint32_t packedFlags = reader.read32();
     uint32_t extra = reader.read32();
     unsigned nondef = extra >> 16;
-    SkXfermode::Mode mode = (SkXfermode::Mode)((extra >> 8) & 0xFF);
-    SkASSERT((extra & 0xFF) == 0);
-
-    SkPaint paint;
+    paint.setBlendMode(SkBlendMode((extra >> 8) & 0xFF));
+    SkASSERT((extra & 0xFF) == 0);  // zero pad byte
 
     packedFlags >>= 2;  // currently unused
     paint.setTextEncoding((SkPaint::TextEncoding)(packedFlags & 3));    packedFlags >>= 2;
@@ -180,17 +180,12 @@
     CHECK_SET_FLATTENABLE(Typeface);
     CHECK_SET_FLATTENABLE(PathEffect);
     CHECK_SET_FLATTENABLE(Shader);
-    CHECK_SET_FLATTENABLE(Xfermode);
     CHECK_SET_FLATTENABLE(MaskFilter);
     CHECK_SET_FLATTENABLE(ColorFilter);
     CHECK_SET_FLATTENABLE(Rasterizer);
     CHECK_SET_FLATTENABLE(ImageFilter);
     CHECK_SET_FLATTENABLE(DrawLooper);
 
-    if (!(nondef & kXfermode_NonDef)) {
-        paint.setXfermodeMode(mode);
-    }
-
     return paint;
 }
 
diff --git a/src/utils/SkDumpCanvas.cpp b/src/utils/SkDumpCanvas.cpp
index fcb24d2..68bd13e 100644
--- a/src/utils/SkDumpCanvas.cpp
+++ b/src/utils/SkDumpCanvas.cpp
@@ -209,8 +209,8 @@
         if (paint->getAlpha() != 0xFF) {
             str.appendf(" alpha:0x%02X", paint->getAlpha());
         }
-        if (paint->getXfermode()) {
-            str.appendf(" xfermode:%p", paint->getXfermode());
+        if (!paint->isSrcOver()) {
+            str.appendf(" blendmode:%d", paint->getBlendMode());
         }
     }
     this->dump(kSave_Verb, paint, str.c_str());
@@ -540,8 +540,10 @@
 
     if (p) {
         msg.appendf(" color:0x%08X flags:%X", p->getColor(), p->getFlags());
+        if (!p->isSrcOver()) {
+            msg.appendf(" blendmode:%d", p->getBlendMode());
+        }
         appendFlattenable(&msg, p->getShader(), "shader");
-        appendFlattenable(&msg, p->getXfermode(), "xfermode");
         appendFlattenable(&msg, p->getPathEffect(), "pathEffect");
         appendFlattenable(&msg, p->getMaskFilter(), "maskFilter");
         appendFlattenable(&msg, p->getPathEffect(), "pathEffect");
diff --git a/src/utils/SkLua.cpp b/src/utils/SkLua.cpp
index e80708c..ba311af 100644
--- a/src/utils/SkLua.cpp
+++ b/src/utils/SkLua.cpp
@@ -28,7 +28,6 @@
 #include "SkSurface.h"
 #include "SkTextBlob.h"
 #include "SkTypeface.h"
-#include "SkXfermode.h"
 
 extern "C" {
     #include "lua.h"
@@ -59,7 +58,6 @@
 DEF_MTNAME(SkSurface)
 DEF_MTNAME(SkTextBlob)
 DEF_MTNAME(SkTypeface)
-DEF_MTNAME(SkXfermode)
 
 template <typename T> T* push_new(lua_State* L) {
     T* addr = (T*)lua_newuserdata(L, sizeof(T));
@@ -1073,26 +1071,9 @@
     setfield_bool_if(L, "shader",      !!paint->getShader());
     setfield_bool_if(L, "colorFilter", !!paint->getColorFilter());
     setfield_bool_if(L, "imageFilter", !!paint->getImageFilter());
-    setfield_bool_if(L, "xfermode",    !!paint->getXfermode());
     return 1;
 }
 
-static int lpaint_getXfermode(lua_State* L) {
-    const SkPaint* paint = get_obj<SkPaint>(L, 1);
-    SkXfermode* xfermode = paint->getXfermode();
-    if (xfermode) {
-        push_ref(L, xfermode);
-        return 1;
-    }
-    return 0;
-}
-
-static int lpaint_setXfermode(lua_State* L) {
-    SkPaint* paint = get_obj<SkPaint>(L, 1);
-    paint->setXfermode(sk_ref_sp(get_ref<SkXfermode>(L, 2)));
-    return 0;
-}
-
 static int lpaint_getColorFilter(lua_State* L) {
     const SkPaint* paint = get_obj<SkPaint>(L, 1);
     SkColorFilter* cf = paint->getColorFilter();
@@ -1217,8 +1198,6 @@
     { "setColorFilter", lpaint_setColorFilter },
     { "getImageFilter", lpaint_getImageFilter },
     { "setImageFilter", lpaint_setImageFilter },
-    { "getXfermode", lpaint_getXfermode },
-    { "setXfermode", lpaint_setXfermode },
     { "getShader", lpaint_getShader },
     { "setShader", lpaint_setShader },
     { "getPathEffect", lpaint_getPathEffect },
@@ -1341,24 +1320,6 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 
-static int lpxfermode_getTypeName(lua_State* L) {
-    lua_pushstring(L, get_ref<SkXfermode>(L, 1)->getTypeName());
-    return 1;
-}
-
-static int lpxfermode_gc(lua_State* L) {
-    get_ref<SkXfermode>(L, 1)->unref();
-    return 0;
-}
-
-static const struct luaL_Reg gSkXfermode_Methods[] = {
-    { "getTypeName",    lpxfermode_getTypeName },
-    { "__gc",           lpxfermode_gc },
-    { nullptr, nullptr }
-};
-
-///////////////////////////////////////////////////////////////////////////////
-
 static int lpcolorfilter_gc(lua_State* L) {
     get_ref<SkColorFilter>(L, 1)->unref();
     return 0;
@@ -2178,7 +2139,6 @@
     REG_CLASS(L, SkSurface);
     REG_CLASS(L, SkTextBlob);
     REG_CLASS(L, SkTypeface);
-    REG_CLASS(L, SkXfermode);
 }
 
 extern "C" int luaopen_skia(lua_State* L);
diff --git a/src/utils/SkRGBAToYUV.cpp b/src/utils/SkRGBAToYUV.cpp
index 63d9152..0528b14 100644
--- a/src/utils/SkRGBAToYUV.cpp
+++ b/src/utils/SkRGBAToYUV.cpp
@@ -45,7 +45,7 @@
         }
         SkPaint paint;
         paint.setFilterQuality(kLow_SkFilterQuality);
-        paint.setXfermodeMode(SkXfermode::kSrc_Mode);
+        paint.setBlendMode(SkBlendMode::kSrc);
         int rowStartIdx = 5 * i;
         const SkScalar* row = kYUVColorSpaceInvMatrices[colorSpace] + rowStartIdx;
         paint.setColorFilter(
diff --git a/src/xps/SkXPSDevice.cpp b/src/xps/SkXPSDevice.cpp
index 7757cb8..5db644c 100644
--- a/src/xps/SkXPSDevice.cpp
+++ b/src/xps/SkXPSDevice.cpp
@@ -1220,7 +1220,7 @@
                                    const SkPaint& paint) {
     //Exit early if there is nothing to draw.
     if (d.fRC->isEmpty() ||
-        (paint.getAlpha() == 0 && paint.getXfermode() == nullptr)) {
+        (paint.getAlpha() == 0 && paint.isSrcOver())) {
         return;
     }
 
@@ -1536,7 +1536,7 @@
 
     // nothing to draw
     if (d.fRC->isEmpty() ||
-        (paint->getAlpha() == 0 && paint->getXfermode() == nullptr)) {
+        (paint->getAlpha() == 0 && paint->isSrcOver())) {
         return;
     }
 
diff --git a/tests/ApplyGammaTest.cpp b/tests/ApplyGammaTest.cpp
index 6e6e23a..ec790f5 100644
--- a/tests/ApplyGammaTest.cpp
+++ b/tests/ApplyGammaTest.cpp
@@ -112,7 +112,7 @@
             dstCanvas->flush();
 
             SkPaint gammaPaint;
-            gammaPaint.setXfermodeMode(SkXfermode::kSrc_Mode);
+            gammaPaint.setBlendMode(SkBlendMode::kSrc);
             gammaPaint.setColorFilter(SkGammaColorFilter::Make(gamma));
 
             dstCanvas->drawImage(src, 0, 0, &gammaPaint);
diff --git a/tests/ImageFilterTest.cpp b/tests/ImageFilterTest.cpp
index fd83a6c..668ae5a 100644
--- a/tests/ImageFilterTest.cpp
+++ b/tests/ImageFilterTest.cpp
@@ -261,8 +261,8 @@
                                                                       std::move(paintFilter),
                                                                       cropRect));
         }
-        this->addFilter("xfermode", SkXfermodeImageFilter::Make(
-            SkXfermode::Make(SkXfermode::kSrc_Mode), input, input, cropRect));
+        this->addFilter("xfermode", SkXfermodeImageFilter::Make(SkBlendMode::kSrc, input, input,
+                                                                cropRect));
     }
     int count() const { return fFilters.count(); }
     SkImageFilter* getFilter(int index) const { return fFilters[index].fFilter.get(); }
@@ -938,14 +938,14 @@
     // Regardless of which order they appear in, the image filter bounds should
     // be combined correctly.
     {
-        sk_sp<SkImageFilter> composite(SkXfermodeImageFilter::Make(nullptr, offset));
+        sk_sp<SkImageFilter> composite(SkXfermodeImageFilter::Make(SkBlendMode::kSrcOver, offset));
         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));
     }
     {
-        sk_sp<SkImageFilter> composite(SkXfermodeImageFilter::Make(nullptr, nullptr,
+        sk_sp<SkImageFilter> composite(SkXfermodeImageFilter::Make(SkBlendMode::kSrcOver, nullptr,
                                                                    offset, nullptr));
         SkRect bounds = SkRect::MakeWH(100, 100);
         // Intentionally aliasing here, as that's what the real callers do.
@@ -1432,7 +1432,7 @@
 
     // 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.
-    sk_sp<SkXfermode> mode(SkXfermode::Make(SkXfermode::kSrcOver_Mode));
+    SkBlendMode mode = SkBlendMode::kSrcOver;
     sk_sp<SkImageFilter> xfermodeNoFg(SkXfermodeImageFilter::Make(mode, greenFilter,
                                                                   croppedOut, nullptr));
     sk_sp<SkImageFilter> xfermodeNoBg(SkXfermodeImageFilter::Make(mode, croppedOut,
diff --git a/tests/ImageTest.cpp b/tests/ImageTest.cpp
index 993c3fa..74dd532 100644
--- a/tests/ImageTest.cpp
+++ b/tests/ImageTest.cpp
@@ -351,7 +351,7 @@
     }
 
     SkPaint paint;
-    paint.setXfermodeMode(SkXfermode::kSrc_Mode);
+    paint.setBlendMode(SkBlendMode::kSrc);
     paint.setColor(SK_ColorRED);
 
     surface->getCanvas()->drawRect(SkRect::MakeXYWH(1, 1, 1, 1), paint);
diff --git a/tests/LayerDrawLooperTest.cpp b/tests/LayerDrawLooperTest.cpp
index 8ba290f..4897fd2 100644
--- a/tests/LayerDrawLooperTest.cpp
+++ b/tests/LayerDrawLooperTest.cpp
@@ -53,7 +53,7 @@
     layerInfo.fOffset.set(10.0f, 20.0f);
     layerInfo.fPaintBits |= SkLayerDrawLooper::kXfermode_Bit;
     SkPaint* layerPaint = looperBuilder.addLayer(layerInfo);
-    layerPaint->setXfermodeMode(SkXfermode::kSrc_Mode);
+    layerPaint->setBlendMode(SkBlendMode::kSrc);
 
     FakeDevice device;
     SkCanvas canvas(&device);
@@ -65,7 +65,7 @@
 
     // The back layer should come first.
     REPORTER_ASSERT(reporter, context->next(&canvas, &paint));
-    REPORTER_ASSERT(reporter, SkXfermode::IsMode(paint.getXfermode(), SkXfermode::kSrc_Mode));
+    REPORTER_ASSERT(reporter, paint.getBlendMode() == SkBlendMode::kSrc);
     canvas.drawRect(SkRect::MakeWH(50.0f, 50.0f), paint);
     REPORTER_ASSERT(reporter, 10.0f == device.fLastMatrix.getTranslateX());
     REPORTER_ASSERT(reporter, 20.0f == device.fLastMatrix.getTranslateY());
@@ -73,7 +73,7 @@
 
     // Then the front layer.
     REPORTER_ASSERT(reporter, context->next(&canvas, &paint));
-    REPORTER_ASSERT(reporter, SkXfermode::IsMode(paint.getXfermode(), SkXfermode::kSrcOver_Mode));
+    REPORTER_ASSERT(reporter, paint.getBlendMode() == SkBlendMode::kSrcOver);
     canvas.drawRect(SkRect::MakeWH(50.0f, 50.0f), paint);
     REPORTER_ASSERT(reporter, 0.0f == device.fLastMatrix.getTranslateX());
     REPORTER_ASSERT(reporter, 0.0f == device.fLastMatrix.getTranslateY());
@@ -93,7 +93,7 @@
     layerInfo.fOffset.set(10.0f, 20.0f);
     layerInfo.fPaintBits |= SkLayerDrawLooper::kXfermode_Bit;
     SkPaint* layerPaint = looperBuilder.addLayerOnTop(layerInfo);
-    layerPaint->setXfermodeMode(SkXfermode::kSrc_Mode);
+    layerPaint->setBlendMode(SkBlendMode::kSrc);
 
     FakeDevice device;
     SkCanvas canvas(&device);
@@ -105,7 +105,7 @@
 
     // The back layer should come first.
     REPORTER_ASSERT(reporter, context->next(&canvas, &paint));
-    REPORTER_ASSERT(reporter, SkXfermode::IsMode(paint.getXfermode(), SkXfermode::kSrcOver_Mode));
+    REPORTER_ASSERT(reporter, paint.getBlendMode() == SkBlendMode::kSrcOver);
     canvas.drawRect(SkRect::MakeWH(50.0f, 50.0f), paint);
     REPORTER_ASSERT(reporter, 0.0f == device.fLastMatrix.getTranslateX());
     REPORTER_ASSERT(reporter, 0.0f == device.fLastMatrix.getTranslateY());
@@ -113,7 +113,7 @@
 
     // Then the front layer.
     REPORTER_ASSERT(reporter, context->next(&canvas, &paint));
-    REPORTER_ASSERT(reporter, SkXfermode::IsMode(paint.getXfermode(), SkXfermode::kSrc_Mode));
+    REPORTER_ASSERT(reporter, paint.getBlendMode() == SkBlendMode::kSrc);
     canvas.drawRect(SkRect::MakeWH(50.0f, 50.0f), paint);
     REPORTER_ASSERT(reporter, 10.0f == device.fLastMatrix.getTranslateX());
     REPORTER_ASSERT(reporter, 20.0f == device.fLastMatrix.getTranslateY());
@@ -133,7 +133,7 @@
     layerInfo.fOffset.set(10.0f, 20.0f);
     layerInfo.fPaintBits |= SkLayerDrawLooper::kXfermode_Bit;
     SkPaint* layerPaint = looperBuilder.addLayerOnTop(layerInfo);
-    layerPaint->setXfermodeMode(SkXfermode::kSrc_Mode);
+    layerPaint->setBlendMode(SkBlendMode::kSrc);
 
     FakeDevice device;
     SkCanvas canvas(&device);
@@ -145,7 +145,7 @@
 
     // The back layer should come first.
     REPORTER_ASSERT(reporter, context->next(&canvas, &paint));
-    REPORTER_ASSERT(reporter, SkXfermode::IsMode(paint.getXfermode(), SkXfermode::kSrcOver_Mode));
+    REPORTER_ASSERT(reporter, paint.getBlendMode() == SkBlendMode::kSrcOver);
     canvas.drawRect(SkRect::MakeWH(50.0f, 50.0f), paint);
     REPORTER_ASSERT(reporter, 0.0f == device.fLastMatrix.getTranslateX());
     REPORTER_ASSERT(reporter, 0.0f == device.fLastMatrix.getTranslateY());
@@ -153,7 +153,7 @@
 
     // Then the front layer.
     REPORTER_ASSERT(reporter, context->next(&canvas, &paint));
-    REPORTER_ASSERT(reporter, SkXfermode::IsMode(paint.getXfermode(), SkXfermode::kSrc_Mode));
+    REPORTER_ASSERT(reporter, paint.getBlendMode() == SkBlendMode::kSrc);
     canvas.drawRect(SkRect::MakeWH(50.0f, 50.0f), paint);
     REPORTER_ASSERT(reporter, 10.0f == device.fLastMatrix.getTranslateX());
     REPORTER_ASSERT(reporter, 20.0f == device.fLastMatrix.getTranslateY());
diff --git a/tests/PDFOpaqueSrcModeToSrcOverTest.cpp b/tests/PDFOpaqueSrcModeToSrcOverTest.cpp
index 76796f5..e15234d 100644
--- a/tests/PDFOpaqueSrcModeToSrcOverTest.cpp
+++ b/tests/PDFOpaqueSrcModeToSrcOverTest.cpp
@@ -9,14 +9,14 @@
 #include "SkStream.h"
 #include "Test.h"
 
-static void run_test(SkWStream* out, SkXfermode::Mode mode, U8CPU alpha) {
+static void run_test(SkWStream* out, SkBlendMode mode, U8CPU alpha) {
     sk_sp<SkDocument> pdfDoc(SkDocument::MakePDF(out));
     SkCanvas* c = pdfDoc->beginPage(612.0f, 792.0f);
     SkPaint black;
     SkPaint background;
     background.setColor(SK_ColorWHITE);
     background.setAlpha(alpha);
-    background.setXfermodeMode(mode);
+    background.setBlendMode(mode);
     c->drawRect(SkRect::MakeWH(612.0f, 792.0f), background);
     c->drawRect(SkRect::MakeXYWH(36.0f, 36.0f, 9.0f, 9.0f), black);
     c->drawRect(SkRect::MakeXYWH(72.0f, 72.0f, 468.0f, 648.0f), background);
@@ -31,8 +31,8 @@
     SkDynamicMemoryWStream srcOverMode;
 
     U8CPU alpha = SK_AlphaOPAQUE;
-    run_test(&srcMode, SkXfermode::kSrc_Mode, alpha);
-    run_test(&srcOverMode, SkXfermode::kSrcOver_Mode, alpha);
+    run_test(&srcMode, SkBlendMode::kSrc, alpha);
+    run_test(&srcOverMode, SkBlendMode::kSrcOver, alpha);
     REPORTER_ASSERT(r, srcMode.getOffset() == srcOverMode.getOffset());
     // The two PDFs should be equal because they have an opaque alpha.
 
@@ -40,8 +40,8 @@
     srcOverMode.reset();
 
     alpha = 0x80;
-    run_test(&srcMode, SkXfermode::kSrc_Mode, alpha);
-    run_test(&srcOverMode, SkXfermode::kSrcOver_Mode, alpha);
+    run_test(&srcMode, SkBlendMode::kSrc, alpha);
+    run_test(&srcOverMode, SkBlendMode::kSrcOver, alpha);
     REPORTER_ASSERT(r, srcMode.getOffset() > srcOverMode.getOffset());
     // The two PDFs should not be equal because they have a non-opaque alpha.
 }
diff --git a/tests/PaintTest.cpp b/tests/PaintTest.cpp
index f507467..9cd9cfc 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::Make(SkXfermode::kModulate_Mode));
+    paint.setBlendMode(SkBlendMode::kModulate);
     paint.setLooper(nullptr);  // Default value, ignored.
 
     SkBinaryWriteBuffer writer;
@@ -311,12 +311,7 @@
     ASSERT(other.getTextScaleX() == paint.getTextScaleX());
     ASSERT(other.getTextSize()   == paint.getTextSize());
     ASSERT(other.getLooper()     == paint.getLooper());
-
-    // We have to be a little looser and compare just the modes.  Pointers might not be the same.
-    SkXfermode::Mode otherMode, paintMode;
-    ASSERT(other.getXfermode()->asMode(&otherMode));
-    ASSERT(paint.getXfermode()->asMode(&paintMode));
-    ASSERT(otherMode == paintMode);
+    ASSERT(other.getBlendMode()  == paint.getBlendMode());
 }
 
 DEF_TEST(Paint_getHash, r) {
@@ -355,11 +350,11 @@
     REPORTER_ASSERT(r, paint.nothingToDraw());
 
     paint.setAlpha(0xFF);
-    paint.setXfermodeMode(SkXfermode::kDst_Mode);
+    paint.setBlendMode(SkBlendMode::kDst);
     REPORTER_ASSERT(r, paint.nothingToDraw());
 
     paint.setAlpha(0);
-    paint.setXfermodeMode(SkXfermode::kSrcOver_Mode);
+    paint.setBlendMode(SkBlendMode::kSrcOver);
 
     SkColorMatrix cm;
     cm.setIdentity();   // does not change alpha
diff --git a/tests/ReadPixelsTest.cpp b/tests/ReadPixelsTest.cpp
index 5fbaf9b..008781c 100644
--- a/tests/ReadPixelsTest.cpp
+++ b/tests/ReadPixelsTest.cpp
@@ -113,7 +113,7 @@
     canvas->setMatrix(SkMatrix::I());
     canvas->clipRect(DEV_RECT_S, SkCanvas::kReplace_Op);
     SkPaint paint;
-    paint.setXfermodeMode(SkXfermode::kSrc_Mode);
+    paint.setBlendMode(SkBlendMode::kSrc);
     canvas->drawBitmap(make_src_bitmap(), 0, 0, &paint);
     canvas->restore();
 }
diff --git a/tests/RecordDrawTest.cpp b/tests/RecordDrawTest.cpp
index cf8141a..1dbd945 100644
--- a/tests/RecordDrawTest.cpp
+++ b/tests/RecordDrawTest.cpp
@@ -240,7 +240,7 @@
     SkRecorder recorder(&record, 50, 50);
 
     SkPaint p;
-    p.setXfermodeMode(SkXfermode::kSrc_Mode);
+    p.setBlendMode(SkBlendMode::kSrc);
 
     SkRect layerBounds = SkRect::MakeLTRB(10, 10, 40, 40);
     recorder.saveLayer(&layerBounds, &p);
diff --git a/tests/RecordOptsTest.cpp b/tests/RecordOptsTest.cpp
index 4567a01..b7c9ae9 100644
--- a/tests/RecordOptsTest.cpp
+++ b/tests/RecordOptsTest.cpp
@@ -140,7 +140,7 @@
     SkPaint alphaOnlyLayerPaint, translucentLayerPaint, xfermodeLayerPaint;
     alphaOnlyLayerPaint.setColor(0x03000000);  // Only alpha.
     translucentLayerPaint.setColor(0x03040506);  // Not only alpha.
-    xfermodeLayerPaint.setXfermodeMode(SkXfermode::kDstIn_Mode);  // Any effect will do.
+    xfermodeLayerPaint.setBlendMode(SkBlendMode::kDstIn);  // Any effect will do.
 
     SkPaint opaqueDrawPaint, translucentDrawPaint;
     opaqueDrawPaint.setColor(0xFF020202);  // Opaque.
@@ -222,10 +222,10 @@
     SkPaint translucentLayerPaint;
     translucentLayerPaint.setColor(0x03040506);  // Not only alpha.
     SkPaint xfermodePaint;
-    xfermodePaint.setXfermodeMode(SkXfermode::kDstIn_Mode);
+    xfermodePaint.setBlendMode(SkBlendMode::kDstIn);
     SkPaint colorFilterPaint;
     colorFilterPaint.setColorFilter(
-        SkColorFilter::MakeModeFilter(SK_ColorLTGRAY, SkXfermode::kSrcIn_Mode));
+        SkColorFilter::MakeModeFilter(SK_ColorLTGRAY, SkBlendMode::kSrcIn));
 
     SkPaint opaqueFilterLayerPaint;
     opaqueFilterLayerPaint.setColor(0xFF020202);  // Opaque.
@@ -353,7 +353,7 @@
 
     if (doLayer) {
         canvas->saveLayer(nullptr, nullptr);
-        p.setXfermodeMode(SkXfermode::kSrc_Mode);
+        p.setBlendMode(SkBlendMode::kSrc);
         canvas->drawPaint(p);
         canvas->restore();
     } else {
diff --git a/tests/RecordingXfermodeTest.cpp b/tests/RecordingXfermodeTest.cpp
index 0f91aea..32aec36 100644
--- a/tests/RecordingXfermodeTest.cpp
+++ b/tests/RecordingXfermodeTest.cpp
@@ -34,7 +34,7 @@
 
     const SkImageInfo& imageInfo() const { return fImageInfo; }
 
-    void draw(SkCanvas* canvas, const SkRect& clipRect, SkXfermode::Mode mode) const {
+    void draw(SkCanvas* canvas, const SkRect& clipRect, SkBlendMode mode) const {
         SkPaint greenPaint;
         greenPaint.setColor(0xff008000);
         SkPaint blackPaint;
@@ -43,7 +43,7 @@
         whitePaint.setColor(0xffffffff);
         SkPaint layerPaint;
         layerPaint.setColor(0xff000000);
-        layerPaint.setXfermodeMode(mode);
+        layerPaint.setBlendMode(mode);
         SkRect canvasRect(SkRect::MakeWH(SkIntToScalar(fImageInfo.width()),
                                          SkIntToScalar(fImageInfo.height())));
 
@@ -68,7 +68,7 @@
     virtual ~RecordingStrategy() {}
     virtual const SkBitmap& recordAndReplay(const Drawer& drawer,
                                             const SkRect& intoClip,
-                                            SkXfermode::Mode) = 0;
+                                            SkBlendMode) = 0;
 };
 
 class BitmapBackedCanvasStrategy : public RecordingStrategy {
@@ -78,9 +78,8 @@
         fBitmap.allocPixels(imageInfo);
     }
 
-    virtual const SkBitmap& recordAndReplay(const Drawer& drawer,
-                                            const SkRect& intoClip,
-                                            SkXfermode::Mode mode) {
+    const SkBitmap& recordAndReplay(const Drawer& drawer, const SkRect& intoClip,
+                                    SkBlendMode mode) override {
         SkCanvas canvas(fBitmap);
         canvas.clear(0xffffffff);
         // Note that the scene is drawn just into the clipped region!
@@ -104,9 +103,8 @@
         fHeight = imageInfo.height();
     }
 
-    virtual const SkBitmap& recordAndReplay(const Drawer& drawer,
-                                            const SkRect& intoClip,
-                                            SkXfermode::Mode mode) {
+    const SkBitmap& recordAndReplay(const Drawer& drawer, const SkRect& intoClip,
+                                    SkBlendMode mode) override {
         SkRTreeFactory factory;
         SkPictureRecorder recorder;
         SkRect canvasRect(SkRect::MakeWH(SkIntToScalar(fWidth),SkIntToScalar(fHeight)));
@@ -144,9 +142,9 @@
     SkString errors;
 #endif
 
-    for (int iMode = 0; iMode < int(SkXfermode::kLastMode); iMode++) {
+    for (int iMode = 0; iMode < int(SkBlendMode::kLastMode); iMode++) {
         const SkRect& clip = SkRect::MakeXYWH(100, 0, 100, 100);
-        SkXfermode::Mode mode = SkXfermode::Mode(iMode);
+        SkBlendMode mode = SkBlendMode(iMode);
 
         const SkBitmap& goldenBM = golden.recordAndReplay(drawer, clip, mode);
         const SkBitmap& pictureBM = picture.recordAndReplay(drawer, clip, mode);
diff --git a/tests/SerializationTest.cpp b/tests/SerializationTest.cpp
index 9e40701..26a2da4 100644
--- a/tests/SerializationTest.cpp
+++ b/tests/SerializationTest.cpp
@@ -260,7 +260,7 @@
     sk_sp<SkImage> invalidImage(SkImage::MakeFromBitmap(invalidBitmap));
     sk_sp<SkImageFilter> invalidBitmapSource(SkImageSource::Make(std::move(invalidImage)));
     sk_sp<SkImageFilter> xfermodeImageFilter(
-        SkXfermodeImageFilter::Make(SkXfermode::Make(SkXfermode::kSrcOver_Mode),
+        SkXfermodeImageFilter::Make(SkBlendMode::kSrcOver,
                                     std::move(invalidBitmapSource),
                                     std::move(validBitmapSource), nullptr));
 
diff --git a/tests/WritePixelsTest.cpp b/tests/WritePixelsTest.cpp
index c59aa2d..77038d4 100644
--- a/tests/WritePixelsTest.cpp
+++ b/tests/WritePixelsTest.cpp
@@ -122,7 +122,7 @@
     canvas->setMatrix(SkMatrix::I());
     canvas->clipRect(DEV_RECT_S, SkCanvas::kReplace_Op);
     SkPaint paint;
-    paint.setXfermodeMode(SkXfermode::kSrc_Mode);
+    paint.setBlendMode(SkBlendMode::kSrc);
     canvas->drawBitmap(bmp, 0, 0, &paint);
     canvas->restore();
 }
diff --git a/tools/debugger/SkDebugCanvas.cpp b/tools/debugger/SkDebugCanvas.cpp
index f15c68c..1da995b 100644
--- a/tools/debugger/SkDebugCanvas.cpp
+++ b/tools/debugger/SkDebugCanvas.cpp
@@ -42,7 +42,8 @@
         if (*paint) {
             if (nullptr != fOverdrawXfermode.get()) {
                 paint->writable()->setAntiAlias(false);
-                paint->writable()->setXfermode(fOverdrawXfermode);
+                // TODO: replace overdraw mode with something else
+//                paint->writable()->setXfermode(fOverdrawXfermode);
             }
 
             if (fOverrideFilterQuality) {
diff --git a/tools/debugger/SkDrawCommand.cpp b/tools/debugger/SkDrawCommand.cpp
index ba6302c..156ca4f7 100644
--- a/tools/debugger/SkDrawCommand.cpp
+++ b/tools/debugger/SkDrawCommand.cpp
@@ -1116,16 +1116,6 @@
     }
 }
 
-static void apply_paint_xfermode(const SkPaint& paint, Json::Value* target,
-                                 UrlDataManager& urlDataManager) {
-    SkFlattenable* xfermode = paint.getXfermode();
-    if (xfermode != nullptr) {
-        Json::Value jsonXfermode;
-        SkDrawCommand::flatten(xfermode, &jsonXfermode, urlDataManager);
-        (*target)[SKDEBUGCANVAS_ATTRIBUTE_XFERMODE] = jsonXfermode;
-    }
-}
-
 static void apply_paint_imagefilter(const SkPaint& paint, Json::Value* target,
                                     UrlDataManager& urlDataManager) {
     SkFlattenable* imageFilter = paint.getImageFilter();
@@ -1177,7 +1167,6 @@
     apply_paint_patheffect(paint, &result, urlDataManager);
     apply_paint_maskfilter(paint, &result, urlDataManager);
     apply_paint_shader(paint, &result, urlDataManager);
-    apply_paint_xfermode(paint, &result, urlDataManager);
     apply_paint_looper(paint, &result, urlDataManager);
     apply_paint_imagefilter(paint, &result, urlDataManager);
     apply_paint_colorfilter(paint, &result, urlDataManager);
@@ -1246,17 +1235,6 @@
     }
 }
 
-static void extract_json_paint_xfermode(Json::Value& jsonPaint, UrlDataManager& urlDataManager,
-                                        SkPaint* target) {
-    if (jsonPaint.isMember(SKDEBUGCANVAS_ATTRIBUTE_XFERMODE)) {
-        Json::Value jsonXfermode = jsonPaint[SKDEBUGCANVAS_ATTRIBUTE_XFERMODE];
-        sk_sp<SkXfermode> xfermode((SkXfermode*) load_flattenable(jsonXfermode, urlDataManager));
-        if (xfermode != nullptr) {
-            target->setXfermode(xfermode);
-        }
-    }
-}
-
 static void extract_json_paint_looper(Json::Value& jsonPaint, UrlDataManager& urlDataManager,
                                       SkPaint* target) {
     if (jsonPaint.isMember(SKDEBUGCANVAS_ATTRIBUTE_LOOPER)) {
@@ -1503,7 +1481,6 @@
     extract_json_paint_patheffect(paint, urlDataManager, result);
     extract_json_paint_maskfilter(paint, urlDataManager, result);
     extract_json_paint_colorfilter(paint, urlDataManager, result);
-    extract_json_paint_xfermode(paint, urlDataManager, result);
     extract_json_paint_looper(paint, urlDataManager, result);
     extract_json_paint_imagefilter(paint, urlDataManager, result);
     extract_json_paint_typeface(paint, urlDataManager, result);
diff --git a/tools/sk_tool_utils.cpp b/tools/sk_tool_utils.cpp
index 72d1af5..c84d452 100644
--- a/tools/sk_tool_utils.cpp
+++ b/tools/sk_tool_utils.cpp
@@ -220,7 +220,7 @@
 void draw_checkerboard(SkCanvas* canvas, SkColor c1, SkColor c2, int size) {
     SkPaint paint;
     paint.setShader(create_checkerboard_shader(c1, c2, size));
-    paint.setXfermodeMode(SkXfermode::kSrc_Mode);
+    paint.setBlendMode(SkBlendMode::kSrc);
     canvas->drawPaint(paint);
 }
 
diff --git a/tools/viewer/sk_app/mac/RasterWindowContext_mac.cpp b/tools/viewer/sk_app/mac/RasterWindowContext_mac.cpp
index 47f349b..fd2f2ef 100644
--- a/tools/viewer/sk_app/mac/RasterWindowContext_mac.cpp
+++ b/tools/viewer/sk_app/mac/RasterWindowContext_mac.cpp
@@ -121,7 +121,7 @@
                        (fDisplayParams.fColorSpace != nullptr ||
                         kRGBA_F16_SkColorType == fDisplayParams.fColorType);
         SkPaint gammaPaint;
-        gammaPaint.setXfermodeMode(SkXfermode::kSrc_Mode);
+        gammaPaint.setBlendMode(SkBlendMode::kSrc);
         if (doGamma) {
             gammaPaint.setColorFilter(SkGammaColorFilter::Make(1.0f / 2.2f));
         }