remove xfermode from public api

BUG=skia:

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

CQ_INCLUDE_TRYBOTS=master.client.skia:Test-Ubuntu-GCC-GCE-CPU-AVX2-x86_64-Release-SKNX_NO_SIMD-Trybot

Change-Id: I19cd056f2af778f10e8c6c2b7b2735593b43dbac
Reviewed-on: https://skia-review.googlesource.com/4020
Reviewed-by: Florin Malita <fmalita@chromium.org>
Reviewed-by: Mike Klein <mtklein@chromium.org>
Commit-Queue: Mike Reed <reed@google.com>
diff --git a/src/core/SkBitmapDevice.cpp b/src/core/SkBitmapDevice.cpp
index e663cce..cb177e0 100644
--- a/src/core/SkBitmapDevice.cpp
+++ b/src/core/SkBitmapDevice.cpp
@@ -367,10 +367,16 @@
 void SkBitmapDevice::drawVertices(const SkDraw& draw, SkCanvas::VertexMode vmode,
                                   int vertexCount,
                                   const SkPoint verts[], const SkPoint textures[],
-                                  const SkColor colors[], SkXfermode* xmode,
+                                  const SkColor colors[], SK_XFERMODE_PARAM xmode,
                                   const uint16_t indices[], int indexCount,
                                   const SkPaint& paint) {
-    draw.drawVertices(vmode, vertexCount, verts, textures, colors, xmode,
+    SkBlendMode bmode;
+#ifdef SK_SUPPORT_LEGACY_XFERMODE_PARAM
+    bmode = xmode ? xmode->blend() : SkBlendMode::kModulate;
+#else
+    bmode = xmode;
+#endif
+    draw.drawVertices(vmode, vertexCount, verts, textures, colors, bmode,
                       indices, indexCount, paint);
 }
 
diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp
index 4e74a77..0fdbc58 100644
--- a/src/core/SkCanvas.cpp
+++ b/src/core/SkCanvas.cpp
@@ -1879,8 +1879,13 @@
 }
 
 void SkCanvas::drawVertices(VertexMode vmode, int vertexCount, const SkPoint vertices[],
-                            const SkPoint texs[], const SkColor colors[], SkXfermode* xmode,
+                            const SkPoint texs[], const SkColor colors[], SkBlendMode bmode,
                             const uint16_t indices[], int indexCount, const SkPaint& paint) {
+#ifdef SK_SUPPORT_LEGACY_XFERMODE_PARAM
+    SkXfermode* xmode = SkXfermode::Peek(bmode);
+#else
+    SkBlendMode xmode = bmode;
+#endif
     this->onDrawVertices(vmode, vertexCount, vertices, texs, colors, xmode,
                          indices, indexCount, paint);
 }
@@ -2009,16 +2014,15 @@
 }
 
 void SkCanvas::drawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[],
-                         const SkColor colors[], int count, SkXfermode::Mode mode,
+                         const SkColor colors[], int count, SkBlendMode mode,
                          const SkRect* cull, const SkPaint* paint) {
     RETURN_ON_NULL(atlas);
     if (count <= 0) {
         return;
     }
     SkASSERT(atlas);
-    SkASSERT(xform);
     SkASSERT(tex);
-    this->onDrawAtlas(atlas, xform, tex, colors, count, mode, cull, paint);
+    this->onDrawAtlas(atlas, xform, tex, colors, count, (SK_XFERMODE_MODE_PARAM)mode, cull, paint);
 }
 
 void SkCanvas::drawAnnotation(const SkRect& rect, const char key[], SkData* value) {
@@ -2827,7 +2831,7 @@
 
 void SkCanvas::onDrawVertices(VertexMode vmode, int vertexCount,
                               const SkPoint verts[], const SkPoint texs[],
-                              const SkColor colors[], SkXfermode* xmode,
+                              const SkColor colors[], SK_XFERMODE_PARAM xmode,
                               const uint16_t indices[], int indexCount,
                               const SkPaint& paint) {
     TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawVertices()");
@@ -2843,17 +2847,24 @@
 }
 
 void SkCanvas::drawPatch(const SkPoint cubics[12], const SkColor colors[4],
-                         const SkPoint texCoords[4], SkXfermode* xmode, const SkPaint& paint) {
+                         const SkPoint texCoords[4], SkBlendMode bmode,
+                         const SkPaint& paint) {
     TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPatch()");
     if (nullptr == cubics) {
         return;
     }
 
+#ifdef SK_SUPPORT_LEGACY_XFERMODE_PARAM
+    SkXfermode* xmode = SkXfermode::Peek(bmode);
+#else
+    SkBlendMode xmode = bmode;
+#endif
     this->onDrawPatch(cubics, colors, texCoords, xmode, paint);
 }
 
 void SkCanvas::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
-                           const SkPoint texCoords[4], SkXfermode* xmode, const SkPaint& paint) {
+                           const SkPoint texCoords[4], SK_XFERMODE_PARAM xmode,
+                           const SkPaint& paint) {
     // Since a patch is always within the convex hull of the control points, we discard it when its
     // bounding rectangle is completely outside the current clip.
     SkRect bounds;
@@ -2896,7 +2907,7 @@
 }
 
 void SkCanvas::onDrawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[],
-                           const SkColor colors[], int count, SkXfermode::Mode mode,
+                           const SkColor colors[], int count, SK_XFERMODE_MODE_PARAM mode,
                            const SkRect* cull, const SkPaint* paint) {
     if (cull && this->quickReject(*cull)) {
         return;
diff --git a/src/core/SkColorFilter.cpp b/src/core/SkColorFilter.cpp
index b23b100..23def9f 100644
--- a/src/core/SkColorFilter.cpp
+++ b/src/core/SkColorFilter.cpp
@@ -19,7 +19,7 @@
 #include "GrFragmentProcessor.h"
 #endif
 
-bool SkColorFilter::asColorMode(SkColor* color, SkXfermode::Mode* mode) const {
+bool SkColorFilter::asColorMode(SkColor* color, SK_XFERMODE_MODE_PARAM* mode) const {
     return false;
 }
 
diff --git a/src/core/SkComposeShader.cpp b/src/core/SkComposeShader.cpp
index 51e30ea..8c21453 100644
--- a/src/core/SkComposeShader.cpp
+++ b/src/core/SkComposeShader.cpp
@@ -14,6 +14,20 @@
 #include "SkXfermode.h"
 #include "SkString.h"
 
+sk_sp<SkShader> SkShader::MakeComposeShader(sk_sp<SkShader> dst, sk_sp<SkShader> src,
+                                            SkBlendMode mode) {
+    if (!src || !dst) {
+        return nullptr;
+    }
+    if (SkBlendMode::kSrc == mode) {
+        return src;
+    }
+    if (SkBlendMode::kDst == mode) {
+        return dst;
+    }
+    return sk_sp<SkShader>(new SkComposeShader(std::move(dst), std::move(src), mode));
+}
+
 ///////////////////////////////////////////////////////////////////////////////
 
 size_t SkComposeShader::onContextSize(const ContextRec& rec) const {
@@ -42,17 +56,23 @@
 sk_sp<SkFlattenable> SkComposeShader::CreateProc(SkReadBuffer& buffer) {
     sk_sp<SkShader> shaderA(buffer.readShader());
     sk_sp<SkShader> shaderB(buffer.readShader());
-    sk_sp<SkXfermode> mode(buffer.readXfermode());
+    SkBlendMode mode;
+    if (buffer.isVersionLT(SkReadBuffer::kXfermodeToBlendMode2_Version)) {
+        sk_sp<SkXfermode> xfer = buffer.readXfermode();
+        mode = xfer ? xfer->blend() : SkBlendMode::kSrcOver;
+    } else {
+        mode = (SkBlendMode)buffer.read32();
+    }
     if (!shaderA || !shaderB) {
         return nullptr;
     }
-    return sk_make_sp<SkComposeShader>(std::move(shaderA), std::move(shaderB), std::move(mode));
+    return sk_make_sp<SkComposeShader>(std::move(shaderA), std::move(shaderB), mode);
 }
 
 void SkComposeShader::flatten(SkWriteBuffer& buffer) const {
     buffer.writeFlattenable(fShaderA.get());
     buffer.writeFlattenable(fShaderB.get());
-    buffer.writeFlattenable(fMode.get());
+    buffer.write32((int)fMode);
 }
 
 template <typename T> void safe_call_destructor(T* obj) {
@@ -107,7 +127,10 @@
     if (rec) {
         rec->fShaderA = fShaderA.get();
         rec->fShaderB = fShaderB.get();
-        rec->fMode = fMode.get();
+#ifdef SK_SUPPORT_LEGACY_XFERMODE_PARAM
+        rec->fMode = SkXfermode::Peek(fMode);
+#endif
+        rec->fBlendMode = fMode;
     }
     return true;
 }
@@ -120,12 +143,13 @@
 void SkComposeShader::ComposeShaderContext::shadeSpan(int x, int y, SkPMColor result[], int count) {
     SkShader::Context* shaderContextA = fShaderContextA;
     SkShader::Context* shaderContextB = fShaderContextB;
-    SkXfermode*        mode = static_cast<const SkComposeShader&>(fShader).fMode.get();
+    SkBlendMode        mode = static_cast<const SkComposeShader&>(fShader).fMode;
     unsigned           scale = SkAlpha255To256(this->getPaintAlpha());
 
     SkPMColor   tmp[TMP_COLOR_COUNT];
 
-    if (nullptr == mode) {   // implied SRC_OVER
+    SkXfermode* xfer = SkXfermode::Peek(mode);
+    if (nullptr == xfer) {   // implied SRC_OVER
         // TODO: when we have a good test-case, should use SkBlitRow::Proc32
         // for these loops
         do {
@@ -161,7 +185,7 @@
 
             shaderContextA->shadeSpan(x, y, result, n);
             shaderContextB->shadeSpan(x, y, tmp, n);
-            mode->xfer32(result, tmp, n, nullptr);
+            xfer->xfer32(result, tmp, n, nullptr);
 
             if (256 != scale) {
                 for (int i = 0; i < n; i++) {
@@ -184,21 +208,15 @@
 /////////////////////////////////////////////////////////////////////
 
 sk_sp<GrFragmentProcessor> SkComposeShader::asFragmentProcessor(const AsFPArgs& args) const {
-    // Fragment processor will only support SkXfermode::Mode modes currently.
-    SkXfermode::Mode mode;
-    if (!(SkXfermode::AsMode(fMode, &mode))) {
-        return nullptr;
-    }
-
-    switch (mode) {
-        case SkXfermode::kClear_Mode:
+    switch (fMode) {
+        case SkBlendMode::kClear:
             return GrConstColorProcessor::Make(GrColor4f::TransparentBlack(),
                                                GrConstColorProcessor::kIgnore_InputMode);
             break;
-        case SkXfermode::kSrc_Mode:
+        case SkBlendMode::kSrc:
             return fShaderB->asFragmentProcessor(args);
             break;
-        case SkXfermode::kDst_Mode:
+        case SkBlendMode::kDst:
             return fShaderA->asFragmentProcessor(args);
             break;
         default:
@@ -211,7 +229,7 @@
                 return nullptr;
             }
             return GrXfermodeFragmentProcessor::MakeFromTwoProcessors(std::move(fpB),
-                                                                      std::move(fpA), mode);
+                                                                      std::move(fpA), fMode);
     }
 }
 #endif
@@ -224,9 +242,8 @@
     fShaderA->toString(str);
     str->append(" ShaderB: ");
     fShaderB->toString(str);
-    if (fMode) {
-        str->append(" Xfermode: ");
-        fMode->toString(str);
+    if (SkBlendMode::kSrcOver != fMode) {
+        str->appendf(" Xfermode: %s", SkXfermode::ModeName(fMode));
     }
 
     this->INHERITED::toString(str);
@@ -234,18 +251,3 @@
     str->append(")");
 }
 #endif
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-sk_sp<SkShader> SkShader::MakeComposeShader(sk_sp<SkShader> dst, sk_sp<SkShader> src,
-                                            sk_sp<SkXfermode> xfer) {
-    if (!dst || !src) {
-        return nullptr;
-    }
-    return sk_make_sp<SkComposeShader>(std::move(dst), std::move(src), std::move(xfer));
-}
-
-sk_sp<SkShader> SkShader::MakeComposeShader(sk_sp<SkShader> dst, sk_sp<SkShader> src,
-                                            SkXfermode::Mode mode) {
-    return MakeComposeShader(std::move(dst), std::move(src), SkXfermode::Make(mode));
-}
diff --git a/src/core/SkComposeShader.h b/src/core/SkComposeShader.h
index d1b095e..95da9c8 100644
--- a/src/core/SkComposeShader.h
+++ b/src/core/SkComposeShader.h
@@ -9,7 +9,7 @@
 #define SkComposeShader_DEFINED
 
 #include "SkShader.h"
-#include "SkXfermode.h"
+#include "SkBlendMode.h"
 
 ///////////////////////////////////////////////////////////////////////////////////////////
 
@@ -28,10 +28,10 @@
         @param mode     The xfermode that combines the colors from the two shaders. If mode
                         is null, then SRC_OVER is assumed.
     */
-    SkComposeShader(sk_sp<SkShader> sA, sk_sp<SkShader> sB, sk_sp<SkXfermode> mode)
+    SkComposeShader(sk_sp<SkShader> sA, sk_sp<SkShader> sB, SkBlendMode mode)
         : fShaderA(std::move(sA))
         , fShaderB(std::move(sB))
-        , fMode(std::move(mode))
+        , fMode(mode)
     {}
 
 #if SK_SUPPORT_GPU
@@ -78,7 +78,7 @@
 private:
     sk_sp<SkShader>     fShaderA;
     sk_sp<SkShader>     fShaderB;
-    sk_sp<SkXfermode>   fMode;
+    SkBlendMode         fMode;
 
     typedef SkShader INHERITED;
 };
diff --git a/src/core/SkDevice.cpp b/src/core/SkDevice.cpp
index 70eabab..30da202 100644
--- a/src/core/SkDevice.cpp
+++ b/src/core/SkDevice.cpp
@@ -119,7 +119,7 @@
 }
 
 void SkBaseDevice::drawPatch(const SkDraw& draw, const SkPoint cubics[12], const SkColor colors[4],
-                             const SkPoint texCoords[4], SkXfermode* xmode, const SkPaint& paint) {
+                             const SkPoint texCoords[4], SK_XFERMODE_PARAM xmode, const SkPaint& paint) {
     SkPatchUtils::VertexData data;
 
     SkISize lod = SkPatchUtils::GetLevelOfDetail(cubics, draw.fMatrix);
@@ -240,7 +240,7 @@
 
 void SkBaseDevice::drawAtlas(const SkDraw& draw, const SkImage* atlas, const SkRSXform xform[],
                              const SkRect tex[], const SkColor colors[], int count,
-                             SkXfermode::Mode mode, const SkPaint& paint) {
+                             SK_XFERMODE_MODE_PARAM mode, const SkPaint& paint) {
     SkPath path;
     path.setIsVolatile(true);
 
@@ -262,7 +262,7 @@
         pnt.setShader(std::move(shader));
 
         if (colors) {
-            pnt.setColorFilter(SkColorFilter::MakeModeFilter(colors[i], mode));
+            pnt.setColorFilter(SkColorFilter::MakeModeFilter(colors[i], (SkBlendMode)mode));
         }
 
         path.rewind();
diff --git a/src/core/SkDraw.cpp b/src/core/SkDraw.cpp
index 2a88781..44e31c4 100644
--- a/src/core/SkDraw.cpp
+++ b/src/core/SkDraw.cpp
@@ -1888,7 +1888,7 @@
 
 void SkDraw::drawVertices(SkCanvas::VertexMode vmode, int count,
                           const SkPoint vertices[], const SkPoint textures[],
-                          const SkColor colors[], SkXfermode* xmode,
+                          const SkColor colors[], SkBlendMode bmode,
                           const uint16_t indices[], int indexCount,
                           const SkPaint& paint) const {
     SkASSERT(0 == count || vertices);
@@ -1935,9 +1935,7 @@
         } else {
             // colors * texture
             SkASSERT(shader);
-            sk_sp<SkXfermode> xfer = xmode ? sk_ref_sp(xmode)
-                                           : SkXfermode::Make(SkXfermode::kModulate_Mode);
-            p.setShader(SkShader::MakeComposeShader(triShader, sk_ref_sp(shader), std::move(xfer)));
+            p.setShader(SkShader::MakeComposeShader(triShader, sk_ref_sp(shader), bmode));
         }
     }
 
diff --git a/src/core/SkLiteDL.cpp b/src/core/SkLiteDL.cpp
index ea9180b..fd20885 100644
--- a/src/core/SkLiteDL.cpp
+++ b/src/core/SkLiteDL.cpp
@@ -454,8 +454,13 @@
     struct DrawPatch final : Op {
         static const auto kType = Type::DrawPatch;
         DrawPatch(const SkPoint cubics[12], const SkColor colors[4], const SkPoint texs[4],
-                  SkXfermode* xfermode, const SkPaint& paint)
-            : xfermode(sk_ref_sp(xfermode)), paint(paint) {
+                  SK_XFERMODE_PARAM xfermode, const SkPaint& paint)
+#ifdef SK_SUPPORT_LEGACY_XFERMODE_PARAM
+            : xfermode(sk_ref_sp(xfermode)), paint(paint)
+#else
+            : xfermode(xfermode), paint(paint)
+#endif
+        {
             copy_v(this->cubics, cubics, 12);
             if (colors) { copy_v(this->colors, colors, 4); has_colors = true; }
             if (texs  ) { copy_v(this->texs  , texs  , 4); has_texs   = true; }
@@ -463,13 +468,17 @@
         SkPoint           cubics[12];
         SkColor           colors[4];
         SkPoint           texs[4];
+#ifdef SK_SUPPORT_LEGACY_XFERMODE_PARAM
         sk_sp<SkXfermode> xfermode;
+#else
+        SkBlendMode       xfermode;
+#endif
         SkPaint           paint;
         bool              has_colors = false;
         bool              has_texs   = false;
         void draw(SkCanvas* c, const SkMatrix&) {
             c->drawPatch(cubics, has_colors ? colors : nullptr, has_texs ? texs : nullptr,
-                         xfermode.get(), paint);
+                         xfermode, paint);
         }
     };
     struct DrawPoints final : Op {
@@ -485,13 +494,21 @@
     };
     struct DrawVertices final : Op {
         static const auto kType = Type::DrawVertices;
-        DrawVertices(SkCanvas::VertexMode mode, int count, SkXfermode* xfermode, int nindices,
+        DrawVertices(SkCanvas::VertexMode mode, int count, SK_XFERMODE_PARAM xfermode, int nindices,
                      const SkPaint& paint, bool has_texs, bool has_colors, bool has_indices)
+#ifdef SK_SUPPORT_LEGACY_XFERMODE_PARAM
             : mode(mode), count(count), xfermode(sk_ref_sp(xfermode)), nindices(nindices)
+#else
+            : mode(mode), count(count), xfermode(xfermode), nindices(nindices)
+#endif
             , paint(paint), has_texs(has_texs), has_colors(has_colors), has_indices(has_indices) {}
         SkCanvas::VertexMode mode;
         int                  count;
+#ifdef SK_SUPPORT_LEGACY_XFERMODE_PARAM
         sk_sp<SkXfermode>    xfermode;
+#else
+        SkBlendMode          xfermode;
+#endif
         int                  nindices;
         SkPaint              paint;
         bool                 has_texs;
@@ -517,13 +534,13 @@
             if (has_indices) {
                 indices = pod<uint16_t>(this, offset);
             }
-            c->drawVertices(mode, count, vertices, texs, colors, xfermode.get(),
+            c->drawVertices(mode, count, vertices, texs, colors, xfermode,
                             indices, nindices, paint);
         }
     };
     struct DrawAtlas final : Op {
         static const auto kType = Type::DrawAtlas;
-        DrawAtlas(const SkImage* atlas, int count, SkXfermode::Mode xfermode,
+        DrawAtlas(const SkImage* atlas, int count, SK_XFERMODE_MODE_PARAM xfermode,
                   const SkRect* cull, const SkPaint* paint, bool has_colors)
             : atlas(sk_ref_sp(atlas)), count(count), xfermode(xfermode), has_colors(has_colors) {
             if (cull)  { this->cull  = *cull; }
@@ -531,7 +548,7 @@
         }
         sk_sp<const SkImage> atlas;
         int                  count;
-        SkXfermode::Mode     xfermode;
+        SK_XFERMODE_MODE_PARAM     xfermode;
         SkRect               cull = kUnset;
         SkPaint              paint;
         bool                 has_colors;
@@ -711,7 +728,7 @@
 }
 
 void SkLiteDL::drawPatch(const SkPoint points[12], const SkColor colors[4], const SkPoint texs[4],
-                         SkXfermode* xfermode, const SkPaint& paint) {
+                         SK_XFERMODE_PARAM xfermode, const SkPaint& paint) {
     this->push<DrawPatch>(0, points, colors, texs, xfermode, paint);
 }
 void SkLiteDL::drawPoints(SkCanvas::PointMode mode, size_t count, const SkPoint points[],
@@ -720,7 +737,7 @@
     copy_v(pod, points,count);
 }
 void SkLiteDL::drawVertices(SkCanvas::VertexMode mode, int count, const SkPoint vertices[],
-                            const SkPoint texs[], const SkColor colors[], SkXfermode* xfermode,
+                            const SkPoint texs[], const SkColor colors[], SK_XFERMODE_PARAM xfermode,
                             const uint16_t indices[], int nindices, const SkPaint& paint) {
     size_t bytes = count * sizeof(SkPoint);
     if (texs  )  { bytes += count    * sizeof(SkPoint); }
@@ -734,7 +751,7 @@
                  indices, indices ? nindices : 0);
 }
 void SkLiteDL::drawAtlas(const SkImage* atlas, const SkRSXform xforms[], const SkRect texs[],
-                         const SkColor colors[], int count, SkXfermode::Mode xfermode,
+                         const SkColor colors[], int count, SK_XFERMODE_MODE_PARAM xfermode,
                          const SkRect* cull, const SkPaint* paint) {
     size_t bytes = count*(sizeof(SkRSXform) + sizeof(SkRect));
     if (colors) {
diff --git a/src/core/SkLiteDL.h b/src/core/SkLiteDL.h
index 3e9eb5e..30211a6 100644
--- a/src/core/SkLiteDL.h
+++ b/src/core/SkLiteDL.h
@@ -78,12 +78,12 @@
                           const SkRect&, const SkPaint*);
 
     void drawPatch(const SkPoint[12], const SkColor[4], const SkPoint[4],
-                   SkXfermode*, const SkPaint&);
+                   SK_XFERMODE_PARAM, const SkPaint&);
     void drawPoints(SkCanvas::PointMode, size_t, const SkPoint[], const SkPaint&);
     void drawVertices(SkCanvas::VertexMode, int, const SkPoint[], const SkPoint[], const SkColor[],
-                      SkXfermode*, const uint16_t[], int, const SkPaint&);
+                      SK_XFERMODE_PARAM, const uint16_t[], int, const SkPaint&);
     void drawAtlas(const SkImage*, const SkRSXform[], const SkRect[], const SkColor[], int,
-                   SkXfermode::Mode, const SkRect*, const SkPaint*);
+                   SK_XFERMODE_MODE_PARAM, const SkRect*, const SkPaint*);
 
     void setBounds(const SkRect& bounds);
 
diff --git a/src/core/SkLiteRecorder.cpp b/src/core/SkLiteRecorder.cpp
index 49b1984..4c3de18 100644
--- a/src/core/SkLiteRecorder.cpp
+++ b/src/core/SkLiteRecorder.cpp
@@ -171,7 +171,7 @@
 
 void SkLiteRecorder::onDrawPatch(const SkPoint cubics[12],
                                  const SkColor colors[4], const SkPoint texCoords[4],
-                                 SkXfermode* xfermode, const SkPaint& paint) {
+                                 SK_XFERMODE_PARAM xfermode, const SkPaint& paint) {
     fDL->drawPatch(cubics, colors, texCoords, xfermode, paint);
 }
 void SkLiteRecorder::onDrawPoints(SkCanvas::PointMode mode,
@@ -182,7 +182,7 @@
 void SkLiteRecorder::onDrawVertices(SkCanvas::VertexMode mode,
                                     int count, const SkPoint vertices[],
                                     const SkPoint texs[], const SkColor colors[],
-                                    SkXfermode* xfermode,
+                                    SK_XFERMODE_PARAM xfermode,
                                     const uint16_t indices[], int indexCount,
                                     const SkPaint& paint) {
     fDL->drawVertices(mode, count, vertices, texs, colors, xfermode, indices, indexCount, paint);
@@ -192,7 +192,7 @@
                                  const SkRect texs[],
                                  const SkColor colors[],
                                  int count,
-                                 SkXfermode::Mode xfermode,
+                                 SK_XFERMODE_MODE_PARAM xfermode,
                                  const SkRect* cull,
                                  const SkPaint* paint) {
     fDL->drawAtlas(atlas, xforms, texs, colors, count, xfermode, cull, paint);
diff --git a/src/core/SkLiteRecorder.h b/src/core/SkLiteRecorder.h
index be27854..9010a42 100644
--- a/src/core/SkLiteRecorder.h
+++ b/src/core/SkLiteRecorder.h
@@ -72,12 +72,12 @@
                          SrcRectConstraint) override;
 
     void onDrawPatch(const SkPoint[12], const SkColor[4],
-                     const SkPoint[4], SkXfermode*, const SkPaint&) override;
+                     const SkPoint[4], SK_XFERMODE_PARAM, const SkPaint&) override;
     void onDrawPoints(PointMode, size_t count, const SkPoint pts[], const SkPaint&) override;
     void onDrawVertices(VertexMode, int, const SkPoint[], const SkPoint[], const SkColor[],
-                        SkXfermode*, const uint16_t[], int, const SkPaint&) override;
+                        SK_XFERMODE_PARAM, const uint16_t[], int, const SkPaint&) override;
     void onDrawAtlas(const SkImage*, const SkRSXform[], const SkRect[], const SkColor[],
-                     int, SkXfermode::Mode, const SkRect*, const SkPaint*) override;
+                     int, SK_XFERMODE_MODE_PARAM, const SkRect*, const SkPaint*) override;
 
 #ifdef SK_EXPERIMENTAL_SHADOWING
     void didTranslateZ(SkScalar) override;
diff --git a/src/core/SkModeColorFilter.cpp b/src/core/SkModeColorFilter.cpp
index f000e7c..acfd328 100644
--- a/src/core/SkModeColorFilter.cpp
+++ b/src/core/SkModeColorFilter.cpp
@@ -29,12 +29,12 @@
 }
 #endif
 
-bool SkModeColorFilter::asColorMode(SkColor* color, SkXfermode::Mode* mode) const {
+bool SkModeColorFilter::asColorMode(SkColor* color, SK_XFERMODE_MODE_PARAM* mode) const {
     if (color) {
         *color = fColor;
     }
     if (mode) {
-        *mode = fMode;
+        *mode = (SK_XFERMODE_MODE_PARAM)fMode;
     }
     return true;
 }
@@ -42,8 +42,8 @@
 uint32_t SkModeColorFilter::getFlags() const {
     uint32_t flags = 0;
     switch (fMode) {
-        case SkXfermode::kDst_Mode:      //!< [Da, Dc]
-        case SkXfermode::kSrcATop_Mode:  //!< [Da, Sc * Da + (1 - Sa) * Dc]
+        case SkBlendMode::kDst:      //!< [Da, Dc]
+        case SkBlendMode::kSrcATop:  //!< [Da, Sc * Da + (1 - Sa) * Dc]
             flags |= kAlphaUnchanged_Flag;
         default:
             break;
@@ -61,7 +61,7 @@
 }
 
 void SkModeColorFilter::filterSpan4f(const SkPM4f shader[], int count, SkPM4f result[]) const {
-    SkXfermodeProc4f  proc = SkXfermode::GetProc4f(fMode);
+    SkXfermodeProc4f  proc = SkXfermode::GetProc4f((SkXfermode::Mode)fMode);
 
     for (int i = 0; i < count; i++) {
         result[i] = proc(fPM4f, shader[i]);
@@ -70,18 +70,18 @@
 
 void SkModeColorFilter::flatten(SkWriteBuffer& buffer) const {
     buffer.writeColor(fColor);
-    buffer.writeUInt(fMode);
+    buffer.writeUInt((int)fMode);
 }
 
 void SkModeColorFilter::updateCache() {
     fPMColor = SkPreMultiplyColor(fColor);
-    fProc = SkXfermode::GetProc(fMode);
+    fProc = SkXfermode::GetProc((SkXfermode::Mode)fMode);
     fPM4f = SkColor4f::FromColor(fColor).premul();
 }
 
 sk_sp<SkFlattenable> SkModeColorFilter::CreateProc(SkReadBuffer& buffer) {
     SkColor color = buffer.readColor();
-    SkXfermode::Mode mode = (SkXfermode::Mode)buffer.readUInt();
+    SkBlendMode mode = (SkBlendMode)buffer.readUInt();
     return SkColorFilter::MakeModeFilter(color, mode);
 }
 
@@ -108,7 +108,7 @@
 
 sk_sp<GrFragmentProcessor> SkModeColorFilter::asFragmentProcessor(
                                                     GrContext*, SkColorSpace* dstColorSpace) const {
-    if (SkXfermode::kDst_Mode == fMode) {
+    if (SkBlendMode::kDst == fMode) {
         return nullptr;
     }
 
@@ -123,7 +123,7 @@
 #ifdef SK_DEBUG
     // With a solid color input this should always be able to compute the blended color
     // (at least for coeff modes)
-    if (fMode <= SkXfermode::kLastCoeffMode) {
+    if ((unsigned)fMode <= (unsigned)SkBlendMode::kLastCoeffMode) {
         static SkRandom gRand;
         GrInvariantOutput io(GrPremulColor(gRand.nextU()), kRGBA_GrColorComponentFlags,
                                 false);
@@ -140,7 +140,7 @@
 
 class Src_SkModeColorFilter final : public SkModeColorFilter {
 public:
-    Src_SkModeColorFilter(SkColor color) : INHERITED(color, SkXfermode::kSrc_Mode) {}
+    Src_SkModeColorFilter(SkColor color) : INHERITED(color, SkBlendMode::kSrc) {}
 
     void filterSpan(const SkPMColor shader[], int count, SkPMColor result[]) const override {
         sk_memset32(result, this->getPMColor(), count);
@@ -152,7 +152,7 @@
 
 class SrcOver_SkModeColorFilter final : public SkModeColorFilter {
 public:
-    SrcOver_SkModeColorFilter(SkColor color) : INHERITED(color, SkXfermode::kSrcOver_Mode) { }
+    SrcOver_SkModeColorFilter(SkColor color) : INHERITED(color, SkBlendMode::kSrcOver) { }
 
     void filterSpan(const SkPMColor shader[], int count, SkPMColor result[]) const override {
         SkBlitRow::Color32(result, shader, count, this->getPMColor());
@@ -164,7 +164,7 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 
-sk_sp<SkColorFilter> SkColorFilter::MakeModeFilter(SkColor color, SkXfermode::Mode mode) {
+sk_sp<SkColorFilter> SkColorFilter::MakeModeFilter(SkColor color, SkBlendMode mode) {
     if (!SkIsValidMode(mode)) {
         return nullptr;
     }
@@ -173,34 +173,34 @@
 
     // first collaps some modes if possible
 
-    if (SkXfermode::kClear_Mode == mode) {
+    if (SkBlendMode::kClear == mode) {
         color = 0;
-        mode = SkXfermode::kSrc_Mode;
-    } else if (SkXfermode::kSrcOver_Mode == mode) {
+        mode = SkBlendMode::kSrc;
+    } else if (SkBlendMode::kSrcOver == mode) {
         if (0 == alpha) {
-            mode = SkXfermode::kDst_Mode;
+            mode = SkBlendMode::kDst;
         } else if (255 == alpha) {
-            mode = SkXfermode::kSrc_Mode;
+            mode = SkBlendMode::kSrc;
         }
         // else just stay srcover
     }
 
     // weed out combinations that are noops, and just return null
-    if (SkXfermode::kDst_Mode == mode ||
-        (0 == alpha && (SkXfermode::kSrcOver_Mode == mode ||
-                        SkXfermode::kDstOver_Mode == mode ||
-                        SkXfermode::kDstOut_Mode == mode ||
-                        SkXfermode::kSrcATop_Mode == mode ||
-                        SkXfermode::kXor_Mode == mode ||
-                        SkXfermode::kDarken_Mode == mode)) ||
-            (0xFF == alpha && SkXfermode::kDstIn_Mode == mode)) {
+    if (SkBlendMode::kDst == mode ||
+        (0 == alpha && (SkBlendMode::kSrcOver == mode ||
+                        SkBlendMode::kDstOver == mode ||
+                        SkBlendMode::kDstOut == mode ||
+                        SkBlendMode::kSrcATop == mode ||
+                        SkBlendMode::kXor == mode ||
+                        SkBlendMode::kDarken == mode)) ||
+            (0xFF == alpha && SkBlendMode::kDstIn == mode)) {
         return nullptr;
     }
 
     switch (mode) {
-        case SkXfermode::kSrc_Mode:
+        case SkBlendMode::kSrc:
             return sk_make_sp<Src_SkModeColorFilter>(color);
-        case SkXfermode::kSrcOver_Mode:
+        case SkBlendMode::kSrcOver:
             return sk_make_sp<SrcOver_SkModeColorFilter>(color);
         default:
             return SkModeColorFilter::Make(color, mode);
diff --git a/src/core/SkModeColorFilter.h b/src/core/SkModeColorFilter.h
index cd8fe7c..afb96e2 100644
--- a/src/core/SkModeColorFilter.h
+++ b/src/core/SkModeColorFilter.h
@@ -14,15 +14,15 @@
 
 class SkModeColorFilter : public SkColorFilter {
 public:
-    static sk_sp<SkColorFilter> Make(SkColor color, SkXfermode::Mode mode) {
+    static sk_sp<SkColorFilter> Make(SkColor color, SkBlendMode mode) {
         return sk_sp<SkColorFilter>(new SkModeColorFilter(color, mode));
     }
 
     SkColor getColor() const { return fColor; }
-    SkXfermode::Mode getMode() const { return fMode; }
+    SkBlendMode getMode() const { return fMode; }
     SkPMColor getPMColor() const { return fPMColor; }
 
-    bool asColorMode(SkColor*, SkXfermode::Mode*) const override;
+    bool asColorMode(SkColor*, SK_XFERMODE_MODE_PARAM*) const override;
     uint32_t getFlags() const override;
     void filterSpan(const SkPMColor shader[], int count, SkPMColor result[]) const override;
     void filterSpan4f(const SkPM4f shader[], int count, SkPM4f result[]) const override;
@@ -37,7 +37,7 @@
     SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkModeColorFilter)
 
 protected:
-    SkModeColorFilter(SkColor color, SkXfermode::Mode mode) {
+    SkModeColorFilter(SkColor color, SkBlendMode mode) {
         fColor = color;
         fMode = mode;
         this->updateCache();
@@ -49,7 +49,7 @@
 
 private:
     SkColor             fColor;
-    SkXfermode::Mode    fMode;
+    SkBlendMode         fMode;
     // cache
     SkPMColor           fPMColor;
     SkXfermodeProc      fProc;
diff --git a/src/core/SkOpts.h b/src/core/SkOpts.h
index 8e1b7fe..76ca68a 100644
--- a/src/core/SkOpts.h
+++ b/src/core/SkOpts.h
@@ -25,7 +25,7 @@
     // Declare function pointers here...
 
     // May return nullptr if we haven't specialized the given Mode.
-    extern SkXfermode* (*create_xfermode)(const ProcCoeff&, SkXfermode::Mode);
+    extern SkXfermode* (*create_xfermode)(const ProcCoeff&, SkBlendMode);
 
     typedef void (*BoxBlur)(const SkPMColor*, int, const SkIRect& srcBounds, SkPMColor*, int, int, int, int, int);
     extern BoxBlur box_blur_xx, box_blur_xy, box_blur_yx;
diff --git a/src/core/SkPicturePlayback.cpp b/src/core/SkPicturePlayback.cpp
index bede601..51e1c98 100644
--- a/src/core/SkPicturePlayback.cpp
+++ b/src/core/SkPicturePlayback.cpp
@@ -232,10 +232,10 @@
             const SkRSXform* xform = (const SkRSXform*)reader->skip(count * sizeof(SkRSXform));
             const SkRect* tex = (const SkRect*)reader->skip(count * sizeof(SkRect));
             const SkColor* colors = nullptr;
-            SkXfermode::Mode mode = SkXfermode::kDst_Mode;
+            SkBlendMode mode = SkBlendMode::kDst;
             if (flags & DRAW_ATLAS_HAS_COLORS) {
                 colors = (const SkColor*)reader->skip(count * sizeof(SkColor));
-                mode = (SkXfermode::Mode)reader->readUInt();
+                mode = (SkBlendMode)reader->readUInt();
             }
             const SkRect* cull = nullptr;
             if (flags & DRAW_ATLAS_HAS_CULL) {
@@ -436,18 +436,17 @@
                 texCoords = (const SkPoint*)reader->skip(SkPatchUtils::kNumCorners *
                                                          sizeof(SkPoint));
             }
-            sk_sp<SkXfermode> xfer;
+            SkBlendMode bmode = SkBlendMode::kModulate;
             if (flag & DRAW_VERTICES_HAS_XFER) {
-                int mode = reader->readInt();
-                if (mode < 0 || mode > SkXfermode::kLastMode) {
-                    mode = SkXfermode::kModulate_Mode;
+                unsigned mode = reader->readInt();
+                if (mode <= (unsigned)SkBlendMode::kLastMode) {
+                    bmode = (SkBlendMode)mode;
                 }
-                xfer = SkXfermode::Make((SkXfermode::Mode)mode);
             }
             BREAK_ON_READ_ERROR(reader);
 
             if (paint) {
-                canvas->drawPatch(cubics, colors, texCoords, std::move(xfer), *paint);
+                canvas->drawPatch(cubics, colors, texCoords, bmode, *paint);
             }
         } break;
         case DRAW_PATH: {
@@ -653,7 +652,6 @@
             }
         } break;
         case DRAW_VERTICES: {
-            sk_sp<SkXfermode> xfer;
             const SkPaint* paint = fPictureData->getPaint(reader);
             DrawVertexFlags flags = (DrawVertexFlags)reader->readInt();
             SkCanvas::VertexMode vmode = (SkCanvas::VertexMode)reader->readInt();
@@ -673,18 +671,18 @@
                 iCount = reader->readInt();
                 indices = (const uint16_t*)reader->skip(iCount * sizeof(uint16_t));
             }
+            SkBlendMode bmode = SkBlendMode::kModulate;
             if (flags & DRAW_VERTICES_HAS_XFER) {
-                int mode = reader->readInt();
-                if (mode < 0 || mode > SkXfermode::kLastMode) {
-                    mode = SkXfermode::kModulate_Mode;
+                unsigned mode = reader->readInt();
+                if (mode <= (unsigned)SkBlendMode::kLastMode) {
+                    bmode = (SkBlendMode)mode;
                 }
-                xfer = SkXfermode::Make((SkXfermode::Mode)mode);
             }
             BREAK_ON_READ_ERROR(reader);
 
             if (paint) {
                 canvas->drawVertices(vmode, vCount, verts, texs, colors,
-                                     xfer, indices, iCount, *paint);
+                                     bmode, indices, iCount, *paint);
             }
         } break;
         case RESTORE:
diff --git a/src/core/SkPictureRecord.cpp b/src/core/SkPictureRecord.cpp
index 6325eda..8b8ee23 100644
--- a/src/core/SkPictureRecord.cpp
+++ b/src/core/SkPictureRecord.cpp
@@ -722,7 +722,7 @@
 
 void SkPictureRecord::onDrawVertices(VertexMode vmode, int vertexCount,
                                      const SkPoint vertices[], const SkPoint texs[],
-                                     const SkColor colors[], SkXfermode* xfer,
+                                     const SkColor colors[], SK_XFERMODE_PARAM xmode,
                                      const uint16_t indices[], int indexCount,
                                      const SkPaint& paint) {
     uint32_t flags = 0;
@@ -735,11 +735,16 @@
     if (indexCount > 0) {
         flags |= DRAW_VERTICES_HAS_INDICES;
     }
-    if (xfer) {
-        SkXfermode::Mode mode;
-        if (xfer->asMode(&mode) && SkXfermode::kModulate_Mode != mode) {
-            flags |= DRAW_VERTICES_HAS_XFER;
-        }
+    SkBlendMode bmode = SkBlendMode::kModulate;
+#ifdef SK_SUPPORT_LEGACY_XFERMODE_PARAM
+    if (xmode) {
+        bmode = xmode->blend();
+    }
+#else
+    bmode = xmode;
+#endif
+    if (SkBlendMode::kModulate != bmode) {
+        flags |= DRAW_VERTICES_HAS_XFER;
     }
 
     // op + paint index + flags + vmode + vCount + vertices
@@ -775,15 +780,13 @@
         fWriter.writePad(indices, indexCount * sizeof(uint16_t));
     }
     if (flags & DRAW_VERTICES_HAS_XFER) {
-        SkXfermode::Mode mode = SkXfermode::kModulate_Mode;
-        (void)xfer->asMode(&mode);
-        this->addInt(mode);
+        this->addInt((int)bmode);
     }
     this->validate(initialOffset, size);
 }
 
 void SkPictureRecord::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
-                                  const SkPoint texCoords[4], SkXfermode* xmode,
+                                  const SkPoint texCoords[4], SK_XFERMODE_PARAM xmode,
                                   const SkPaint& paint) {
     // op + paint index + patch 12 control points + flag + patch 4 colors + 4 texture coordinates
     size_t size = 2 * kUInt32Size + SkPatchUtils::kNumCtrlPts * sizeof(SkPoint) + kUInt32Size;
@@ -796,12 +799,17 @@
         flag |= DRAW_VERTICES_HAS_TEXS;
         size += SkPatchUtils::kNumCorners * sizeof(SkPoint);
     }
+    SkBlendMode bmode = SkBlendMode::kModulate;
+#ifdef SK_SUPPORT_LEGACY_XFERMODE_PARAM
     if (xmode) {
-        SkXfermode::Mode mode;
-        if (xmode->asMode(&mode) && SkXfermode::kModulate_Mode != mode) {
-            flag |= DRAW_VERTICES_HAS_XFER;
-            size += kUInt32Size;
-        }
+        bmode = xmode->blend();
+    }
+#else
+    bmode = xmode;
+#endif
+    if (SkBlendMode::kModulate != bmode) {
+        flag |= DRAW_VERTICES_HAS_XFER;
+        size += kUInt32Size;
     }
 
     size_t initialOffset = this->addDraw(DRAW_PATCH, &size);
@@ -817,15 +825,13 @@
         fWriter.write(texCoords, SkPatchUtils::kNumCorners * sizeof(SkPoint));
     }
     if (flag & DRAW_VERTICES_HAS_XFER) {
-        SkXfermode::Mode mode = SkXfermode::kModulate_Mode;
-        xmode->asMode(&mode);
-        this->addInt(mode);
+        this->addInt((int)bmode);
     }
     this->validate(initialOffset, size);
 }
 
 void SkPictureRecord::onDrawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[],
-                                  const SkColor colors[], int count, SkXfermode::Mode mode,
+                                  const SkColor colors[], int count, SK_XFERMODE_MODE_PARAM mode,
                                   const SkRect* cull, const SkPaint* paint) {
     // [op + paint-index + atlas-index + flags + count] + [xform] + [tex] + [*colors + mode] + cull
     size_t size = 5 * kUInt32Size + count * sizeof(SkRSXform) + count * sizeof(SkRect);
@@ -851,7 +857,7 @@
     // write optional parameters
     if (colors) {
         fWriter.write(colors, count * sizeof(SkColor));
-        this->addInt(mode);
+        this->addInt((int)mode);
     }
     if (cull) {
         fWriter.write(cull, sizeof(SkRect));
diff --git a/src/core/SkPictureRecord.h b/src/core/SkPictureRecord.h
index 6d75609..0db9b8b 100644
--- a/src/core/SkPictureRecord.h
+++ b/src/core/SkPictureRecord.h
@@ -178,10 +178,10 @@
                                 const SkPaint& paint) override;
 
     void onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
-                             const SkPoint texCoords[4], SkXfermode* xmode,
+                             const SkPoint texCoords[4], SK_XFERMODE_PARAM xmode,
                              const SkPaint& paint) override;
     void onDrawAtlas(const SkImage*, const SkRSXform[], const SkRect[], const SkColor[], int,
-                     SkXfermode::Mode, const SkRect*, const SkPaint*) override;
+                     SK_XFERMODE_MODE_PARAM, const SkRect*, const SkPaint*) override;
 
     void onDrawPaint(const SkPaint&) override;
     void onDrawPoints(PointMode, size_t count, const SkPoint pts[], const SkPaint&) override;
@@ -201,7 +201,7 @@
 
     void onDrawVertices(VertexMode vmode, int vertexCount,
                         const SkPoint vertices[], const SkPoint texs[],
-                        const SkColor colors[], SkXfermode* xmode,
+                        const SkColor colors[], SK_XFERMODE_PARAM xmode,
                         const uint16_t indices[], int indexCount,
                         const SkPaint&) override;
 
diff --git a/src/core/SkReadBuffer.h b/src/core/SkReadBuffer.h
index 6b0d332..c49b01c 100644
--- a/src/core/SkReadBuffer.h
+++ b/src/core/SkReadBuffer.h
@@ -70,6 +70,7 @@
         kBlurMaskFilterWritesOccluder      = 47,
         kGradientShaderFloatColor_Version  = 49,
         kXfermodeToBlendMode_Version       = 50,
+        kXfermodeToBlendMode2_Version      = 51,
     };
 
     /**
diff --git a/src/core/SkRecordDraw.cpp b/src/core/SkRecordDraw.cpp
index dca19df..05261bb 100644
--- a/src/core/SkRecordDraw.cpp
+++ b/src/core/SkRecordDraw.cpp
@@ -116,7 +116,7 @@
 DRAW(DrawOval, drawOval(r.oval, r.paint));
 DRAW(DrawPaint, drawPaint(r.paint));
 DRAW(DrawPath, drawPath(r.path, r.paint));
-DRAW(DrawPatch, drawPatch(r.cubics, r.colors, r.texCoords, r.xmode, r.paint));
+DRAW(DrawPatch, drawPatch(r.cubics, r.colors, r.texCoords, r.bmode, r.paint));
 DRAW(DrawPicture, drawPicture(r.picture.get(), &r.matrix, r.paint));
 
 #ifdef SK_EXPERIMENTAL_SHADOWING
@@ -138,7 +138,7 @@
 DRAW(DrawAtlas, drawAtlas(r.atlas.get(),
                           r.xforms, r.texs, r.colors, r.count, r.mode, r.cull, r.paint));
 DRAW(DrawVertices, drawVertices(r.vmode, r.vertexCount, r.vertices, r.texs, r.colors,
-                                r.xmode, r.indices, r.indexCount, r.paint));
+                                r.bmode, r.indices, r.indexCount, r.paint));
 DRAW(DrawAnnotation, drawAnnotation(r.rect, r.key.c_str(), r.value.get()));
 #undef DRAW
 
diff --git a/src/core/SkRecorder.cpp b/src/core/SkRecorder.cpp
index 08c7370..5720186 100644
--- a/src/core/SkRecorder.cpp
+++ b/src/core/SkRecorder.cpp
@@ -330,30 +330,41 @@
 void SkRecorder::onDrawVertices(VertexMode vmode,
                                 int vertexCount, const SkPoint vertices[],
                                 const SkPoint texs[], const SkColor colors[],
-                                SkXfermode* xmode,
+                                SK_XFERMODE_PARAM xmode,
                                 const uint16_t indices[], int indexCount, const SkPaint& paint) {
+#ifdef SK_SUPPORT_LEGACY_XFERMODE_PARAM
+    SkBlendMode bmode = xmode ? xmode->blend() : SkBlendMode::kModulate;
+#else
+    SkBlendMode bmode = xmode;
+#endif
     APPEND(DrawVertices, paint,
                          vmode,
                          vertexCount,
                          this->copy(vertices, vertexCount),
                          texs ? this->copy(texs, vertexCount) : nullptr,
                          colors ? this->copy(colors, vertexCount) : nullptr,
-                         sk_ref_sp(xmode),
+                         bmode,
                          this->copy(indices, indexCount),
                          indexCount);
 }
 
 void SkRecorder::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
-                             const SkPoint texCoords[4], SkXfermode* xmode, const SkPaint& paint) {
+                             const SkPoint texCoords[4], SK_XFERMODE_PARAM xmode,
+                             const SkPaint& paint) {
+#ifdef SK_SUPPORT_LEGACY_XFERMODE_PARAM
+    SkBlendMode bmode = xmode ? xmode->blend() : SkBlendMode::kModulate;
+#else
+    SkBlendMode bmode = xmode;
+#endif
     APPEND(DrawPatch, paint,
            cubics ? this->copy(cubics, SkPatchUtils::kNumCtrlPts) : nullptr,
            colors ? this->copy(colors, SkPatchUtils::kNumCorners) : nullptr,
            texCoords ? this->copy(texCoords, SkPatchUtils::kNumCorners) : nullptr,
-           sk_ref_sp(xmode));
+           bmode);
 }
 
 void SkRecorder::onDrawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[],
-                             const SkColor colors[], int count, SkXfermode::Mode mode,
+                             const SkColor colors[], int count, SK_XFERMODE_MODE_PARAM mode,
                              const SkRect* cull, const SkPaint* paint) {
     APPEND(DrawAtlas, this->copy(paint),
            sk_ref_sp(atlas),
@@ -361,7 +372,7 @@
            this->copy(tex, count),
            this->copy(colors, count),
            count,
-           mode,
+           (SkBlendMode)mode,
            this->copy(cull));
 }
 
diff --git a/src/core/SkRecorder.h b/src/core/SkRecorder.h
index 715fc93..7015167 100644
--- a/src/core/SkRecorder.h
+++ b/src/core/SkRecorder.h
@@ -99,7 +99,7 @@
                         SkScalar y,
                         const SkPaint& paint) override;
     void onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
-                     const SkPoint texCoords[4], SkXfermode* xmode,
+                     const SkPoint texCoords[4], SK_XFERMODE_PARAM xmode,
                      const SkPaint& paint) override;
 
     void onDrawPaint(const SkPaint&) override;
@@ -126,11 +126,11 @@
                              const SkPaint*) override;
     void onDrawVertices(VertexMode vmode, int vertexCount,
                         const SkPoint vertices[], const SkPoint texs[],
-                        const SkColor colors[], SkXfermode* xmode,
+                        const SkColor colors[], SK_XFERMODE_PARAM xmode,
                         const uint16_t indices[], int indexCount,
                         const SkPaint&) override;
     void onDrawAtlas(const SkImage*, const SkRSXform[], const SkRect[], const SkColor[],
-                     int count, SkXfermode::Mode, const SkRect* cull, const SkPaint*) override;
+                     int count, SK_XFERMODE_MODE_PARAM, const SkRect* cull, const SkPaint*) override;
 
     void onClipRect(const SkRect& rect, ClipOp, ClipEdgeStyle) override;
     void onClipRRect(const SkRRect& rrect, ClipOp, ClipEdgeStyle) override;
diff --git a/src/core/SkValidationUtils.h b/src/core/SkValidationUtils.h
index e9e5986..d71666c 100644
--- a/src/core/SkValidationUtils.h
+++ b/src/core/SkValidationUtils.h
@@ -9,7 +9,7 @@
 #define SkValidationUtils_DEFINED
 
 #include "SkBitmap.h"
-#include "SkXfermode.h"
+#include "SkBlendMode.h"
 
 /** Returns true if coeff's value is in the SkXfermode::Coeff enum.
   */
@@ -17,10 +17,10 @@
     return coeff >= 0 && coeff < SkXfermode::kCoeffCount;
 }
 
-/** Returns true if mode's value is in the SkXfermode::Mode enum.
+/** Returns true if mode's value is in the SkBlendMode enum.
   */
-static inline bool SkIsValidMode(SkXfermode::Mode mode) {
-    return (mode >= 0) && (mode <= SkXfermode::kLastMode);
+static inline bool SkIsValidMode(SkBlendMode mode) {
+    return (unsigned)mode <= (unsigned)SkBlendMode::kLastMode;
 }
 
 /** Returns true if the rect's dimensions are between 0 and SK_MaxS32
diff --git a/src/core/SkXfermode.cpp b/src/core/SkXfermode.cpp
index 7180824..8632fdf 100644
--- a/src/core/SkXfermode.cpp
+++ b/src/core/SkXfermode.cpp
@@ -1109,12 +1109,12 @@
 }
 
 void SkProcCoeffXfermode::flatten(SkWriteBuffer& buffer) const {
-    buffer.write32(fMode);
+    buffer.write32((int)fMode);
 }
 
 bool SkProcCoeffXfermode::asMode(Mode* mode) const {
     if (mode) {
-        *mode = fMode;
+        *mode = (Mode)fMode;
     }
     return true;
 }
@@ -1307,32 +1307,33 @@
 #endif
 
 
-sk_sp<SkXfermode> SkXfermode::Make(Mode mode) {
-    if ((unsigned)mode >= kModeCount) {
+sk_sp<SkXfermode> SkXfermode::Make(SkBlendMode mode) {
+    if ((unsigned)mode > (unsigned)SkBlendMode::kLastMode) {
         // report error
         return nullptr;
     }
 
     // Skia's "default" mode is srcover. nullptr in SkPaint is interpreted as srcover
     // so we can just return nullptr from the factory.
-    if (kSrcOver_Mode == mode) {
+    if (SkBlendMode::kSrcOver == mode) {
         return nullptr;
     }
 
-    SkASSERT(SK_ARRAY_COUNT(gProcCoeffs) == kModeCount);
+    const int COUNT_BLENDMODES = (int)SkBlendMode::kLastMode + 1;
+    SkASSERT(SK_ARRAY_COUNT(gProcCoeffs) == COUNT_BLENDMODES);
 
-    static SkOnce        once[SkXfermode::kLastMode+1];
-    static SkXfermode* cached[SkXfermode::kLastMode+1];
+    static SkOnce        once[COUNT_BLENDMODES];
+    static SkXfermode* cached[COUNT_BLENDMODES];
 
-    once[mode]([mode] {
-        ProcCoeff rec = gProcCoeffs[mode];
+    once[(int)mode]([mode] {
+        ProcCoeff rec = gProcCoeffs[(int)mode];
         if (auto xfermode = SkOpts::create_xfermode(rec, mode)) {
-            cached[mode] = xfermode;
+            cached[(int)mode] = xfermode;
         } else {
-            cached[mode] = new SkProcCoeffXfermode(rec, mode);
+            cached[(int)mode] = new SkProcCoeffXfermode(rec, mode);
         }
     });
-    return sk_ref_sp(cached[mode]);
+    return sk_ref_sp(cached[(int)mode]);
 }
 
 SkXfermodeProc SkXfermode::GetProc(Mode mode) {
@@ -1481,8 +1482,8 @@
         return result;
     }
 
-    SkASSERT(GrCustomXfermode::IsSupportedMode((SkXfermode::Mode)mode));
-    return GrCustomXfermode::MakeXPFactory((SkXfermode::Mode)mode);
+    SkASSERT(GrCustomXfermode::IsSupportedMode(mode));
+    return GrCustomXfermode::MakeXPFactory(mode);
 }
 #endif
 
diff --git a/src/core/SkXfermode_proccoeff.h b/src/core/SkXfermode_proccoeff.h
index 357de43..8d70957 100644
--- a/src/core/SkXfermode_proccoeff.h
+++ b/src/core/SkXfermode_proccoeff.h
@@ -23,7 +23,7 @@
 
 class SK_API SkProcCoeffXfermode : public SkXfermode {
 public:
-    SkProcCoeffXfermode(const ProcCoeff& rec, Mode mode) {
+    SkProcCoeffXfermode(const ProcCoeff& rec, SkBlendMode mode) {
         fMode = mode;
         fProc = rec.fProc;
         // these may be valid, or may be CANNOT_USE_COEFF
@@ -56,13 +56,13 @@
 protected:
     void flatten(SkWriteBuffer& buffer) const override;
 
-    Mode getMode() const { return fMode; }
+    SkBlendMode getMode() const { return fMode; }
 
     SkXfermodeProc getProc() const { return fProc; }
 
 private:
     SkXfermodeProc  fProc;
-    Mode            fMode;
+    SkBlendMode     fMode;
     Coeff           fSrcCoeff, fDstCoeff;
 
     friend class SkXfermode;
diff --git a/src/effects/SkBlurDrawLooper.cpp b/src/effects/SkBlurDrawLooper.cpp
index 3058374..e554295 100644
--- a/src/effects/SkBlurDrawLooper.cpp
+++ b/src/effects/SkBlurDrawLooper.cpp
@@ -44,7 +44,7 @@
         // be baked into the blurred mask.
         SkColor opaqueColor = SkColorSetA(fBlurColor, 255);
         //The SrcIn xfer mode will multiply 'color' by the incoming alpha
-        fColorFilter = SkColorFilter::MakeModeFilter(opaqueColor, SkXfermode::kSrcIn_Mode);
+        fColorFilter = SkColorFilter::MakeModeFilter(opaqueColor, SkBlendMode::kSrcIn);
     } else {
         fColorFilter = nullptr;
     }
diff --git a/src/effects/SkColorMatrixFilter.cpp b/src/effects/SkColorMatrixFilter.cpp
index 32cb3d9..0a2f08f 100644
--- a/src/effects/SkColorMatrixFilter.cpp
+++ b/src/effects/SkColorMatrixFilter.cpp
@@ -20,8 +20,7 @@
     const SkColor opaqueAlphaMask = SK_ColorBLACK;
     // omit the alpha and compare only the RGB values
     if (0 == (add & ~opaqueAlphaMask)) {
-        return SkColorFilter::MakeModeFilter(mul | opaqueAlphaMask,
-                                             SkXfermode::Mode::kModulate_Mode);
+        return SkColorFilter::MakeModeFilter(mul | opaqueAlphaMask, SkBlendMode::kModulate);
     }
 
     SkColorMatrix matrix;
diff --git a/src/effects/SkDropShadowImageFilter.cpp b/src/effects/SkDropShadowImageFilter.cpp
index cc43db7..f2a41ee 100644
--- a/src/effects/SkDropShadowImageFilter.cpp
+++ b/src/effects/SkDropShadowImageFilter.cpp
@@ -94,7 +94,7 @@
 
     SkPaint paint;
     paint.setImageFilter(SkBlurImageFilter::Make(sigma.fX, sigma.fY, nullptr));
-    paint.setColorFilter(SkColorFilter::MakeModeFilter(fColor, SkXfermode::kSrcIn_Mode));
+    paint.setColorFilter(SkColorFilter::MakeModeFilter(fColor, SkBlendMode::kSrcIn));
 
     SkVector offsetVec = SkVector::Make(fDx, fDy);
     ctx.ctm().mapVectors(&offsetVec, 1);
diff --git a/src/effects/SkLayerDrawLooper.cpp b/src/effects/SkLayerDrawLooper.cpp
index 784228f..51a3f77 100644
--- a/src/effects/SkLayerDrawLooper.cpp
+++ b/src/effects/SkLayerDrawLooper.cpp
@@ -15,7 +15,7 @@
 
 SkLayerDrawLooper::LayerInfo::LayerInfo() {
     fPaintBits = 0;                     // ignore our paint fields
-    fColorMode = SkXfermode::kDst_Mode; // ignore our color
+    fColorMode = (SK_XFERMODE_MODE_PARAM)SkBlendMode::kDst; // ignore our color
     fOffset.set(0, 0);
     fPostTranslate = false;
 }
@@ -39,16 +39,16 @@
     return new (storage) LayerDrawLooperContext(this);
 }
 
-static SkColor xferColor(SkColor src, SkColor dst, SkXfermode::Mode mode) {
+static SkColor xferColor(SkColor src, SkColor dst, SkBlendMode mode) {
     switch (mode) {
-        case SkXfermode::kSrc_Mode:
+        case SkBlendMode::kSrc:
             return src;
-        case SkXfermode::kDst_Mode:
+        case SkBlendMode::kDst:
             return dst;
         default: {
             SkPMColor pmS = SkPreMultiplyColor(src);
             SkPMColor pmD = SkPreMultiplyColor(dst);
-            SkPMColor result = SkXfermode::GetProc(mode)(pmS, pmD);
+            SkPMColor result = SkXfermode::GetProc((SkXfermode::Mode)mode)(pmS, pmD);
             return SkUnPreMultiply::PMColorToColor(result);
         }
     }
@@ -60,7 +60,7 @@
 void SkLayerDrawLooper::LayerDrawLooperContext::ApplyInfo(
         SkPaint* dst, const SkPaint& src, const LayerInfo& info) {
 
-    dst->setColor(xferColor(src.getColor(), dst->getColor(), info.fColorMode));
+    dst->setColor(xferColor(src.getColor(), dst->getColor(), (SkBlendMode)info.fColorMode));
 
     BitFlags bits = info.fPaintBits;
     SkPaint::TextEncoding encoding = dst->getTextEncoding();
@@ -161,7 +161,7 @@
     if ((rec->fInfo.fPaintBits & ~kMaskFilter_Bit)) {
         return false;
     }
-    if (SkXfermode::kSrc_Mode != rec->fInfo.fColorMode) {
+    if (SkBlendMode::kSrc != (SkBlendMode)rec->fInfo.fColorMode) {
         return false;
     }
     const SkMaskFilter* mf = rec->fPaint.getMaskFilter();
@@ -178,7 +178,7 @@
     if (rec->fInfo.fPaintBits) {
         return false;
     }
-    if (SkXfermode::kDst_Mode != rec->fInfo.fColorMode) {
+    if (SkBlendMode::kDst != (SkBlendMode)rec->fInfo.fColorMode) {
         return false;
     }
     if (!rec->fInfo.fOffset.equals(0, 0)) {
@@ -206,7 +206,7 @@
         buffer.writeInt(0);
 
         buffer.writeInt(rec->fInfo.fPaintBits);
-        buffer.writeInt(rec->fInfo.fColorMode);
+        buffer.writeInt((int)rec->fInfo.fColorMode);
         buffer.writePoint(rec->fInfo.fOffset);
         buffer.writeBool(rec->fInfo.fPostTranslate);
         buffer.writePaint(rec->fPaint);
@@ -224,7 +224,7 @@
         (void)buffer.readInt();
 
         info.fPaintBits = buffer.readInt();
-        info.fColorMode = (SkXfermode::Mode)buffer.readInt();
+        info.fColorMode = (SK_XFERMODE_MODE_PARAM)buffer.readInt();
         buffer.readPoint(&info.fOffset);
         info.fPostTranslate = buffer.readBool();
         buffer.readPaint(builder.addLayerOnTop(info));
@@ -262,14 +262,14 @@
         }
         str->append(") ");
 
-        static const char* gModeStrings[SkXfermode::kLastMode+1] = {
+        static const char* gModeStrings[(int)SkBlendMode::kLastMode+1] = {
             "kClear", "kSrc", "kDst", "kSrcOver", "kDstOver", "kSrcIn", "kDstIn",
             "kSrcOut", "kDstOut", "kSrcATop", "kDstATop", "kXor", "kPlus",
             "kMultiply", "kScreen", "kOverlay", "kDarken", "kLighten", "kColorDodge",
             "kColorBurn", "kHardLight", "kSoftLight", "kDifference", "kExclusion"
         };
 
-        str->appendf("mode: %s ", gModeStrings[rec->fInfo.fColorMode]);
+        str->appendf("mode: %s ", gModeStrings[(int)rec->fInfo.fColorMode]);
 
         str->append("offset: (");
         str->appendScalar(rec->fInfo.fOffset.fX);
diff --git a/src/effects/SkMergeImageFilter.cpp b/src/effects/SkMergeImageFilter.cpp
index 9830669..9043620 100644
--- a/src/effects/SkMergeImageFilter.cpp
+++ b/src/effects/SkMergeImageFilter.cpp
@@ -16,17 +16,16 @@
 
 sk_sp<SkImageFilter> SkMergeImageFilter::Make(sk_sp<SkImageFilter> first,
                                               sk_sp<SkImageFilter> second,
-                                              SkXfermode::Mode mode,
+                                              SkBlendMode mode,
                                               const CropRect* cropRect) {
     sk_sp<SkImageFilter> inputs[2] = { first, second };
-    SkXfermode::Mode modes[2] = { mode, mode };
+    SkBlendMode modes[2] = { mode, mode };
     return sk_sp<SkImageFilter>(new SkMergeImageFilter(inputs, 2, modes, cropRect));
 }
 
-sk_sp<SkImageFilter> SkMergeImageFilter::Make(sk_sp<SkImageFilter> filters[],
-                                              int count,
-                                              const SkXfermode::Mode modes[],
-                                              const CropRect* cropRect) {
+sk_sp<SkImageFilter> SkMergeImageFilter::MakeN(sk_sp<SkImageFilter> filters[], int count,
+                                               const SkBlendMode modes[],
+                                               const CropRect* cropRect) {
     return sk_sp<SkImageFilter>(new SkMergeImageFilter(filters, count, modes, cropRect));
 }
 
@@ -46,12 +45,12 @@
     }
 }
 
-void SkMergeImageFilter::initModes(const SkXfermode::Mode modes[]) {
+void SkMergeImageFilter::initModes(const SkBlendMode modes[]) {
     if (modes) {
         this->initAllocModes();
         int inputCount = this->countInputs();
         for (int i = 0; i < inputCount; ++i) {
-            fModes[i] = SkToU8(modes[i]);
+            fModes[i] = SkToU8((unsigned)modes[i]);
         }
     } else {
         fModes = nullptr;
@@ -59,7 +58,7 @@
 }
 
 SkMergeImageFilter::SkMergeImageFilter(sk_sp<SkImageFilter> filters[], int count,
-                                       const SkXfermode::Mode modes[],
+                                       const SkBlendMode modes[],
                                        const CropRect* cropRect)
     : INHERITED(filters, count, cropRect) {
     SkASSERT(count >= 0);
@@ -153,21 +152,21 @@
     const int count = common.inputCount();
     bool hasModes = buffer.readBool();
     if (hasModes) {
-        SkAutoSTArray<4, SkXfermode::Mode> modes(count);
+        SkAutoSTArray<4, SkBlendMode> modes(count);
         SkAutoSTArray<4, uint8_t> modes8(count);
         if (!buffer.readByteArray(modes8.get(), count)) {
             return nullptr;
         }
         for (int i = 0; i < count; ++i) {
-            modes[i] = (SkXfermode::Mode)modes8[i];
+            modes[i] = (SkBlendMode)modes8[i];
             buffer.validate(SkIsValidMode(modes[i]));
         }
         if (!buffer.isValid()) {
             return nullptr;
         }
-        return Make(common.inputs(), count, modes.get(), &common.cropRect());
+        return MakeN(common.inputs(), count, modes.get(), &common.cropRect());
     }
-    return Make(common.inputs(), count, nullptr, &common.cropRect());
+    return MakeN(common.inputs(), count, nullptr, &common.cropRect());
 }
 
 void SkMergeImageFilter::flatten(SkWriteBuffer& buffer) const {
diff --git a/src/effects/SkXfermodeImageFilter.cpp b/src/effects/SkXfermodeImageFilter.cpp
index 6587b74..7484869 100644
--- a/src/effects/SkXfermodeImageFilter.cpp
+++ b/src/effects/SkXfermodeImageFilter.cpp
@@ -333,7 +333,7 @@
         rec.fProc = SkXfermode::GetProc(SkXfermode::kSrcOver_Mode);
         SkXfermode::ModeAsCoeff(SkXfermode::kSrcOver_Mode, &rec.fSC, &rec.fDC);
 
-        srcover.reset(new SkProcCoeffXfermode(rec, SkXfermode::kSrcOver_Mode));
+        srcover.reset(new SkProcCoeffXfermode(rec, SkBlendMode::kSrcOver));
         xfer = srcover.get();
 
     }
diff --git a/src/gpu/GrFragmentProcessor.cpp b/src/gpu/GrFragmentProcessor.cpp
index 1844983..820b428 100644
--- a/src/gpu/GrFragmentProcessor.cpp
+++ b/src/gpu/GrFragmentProcessor.cpp
@@ -104,8 +104,7 @@
     if (!fp) {
         return nullptr;
     }
-    return GrXfermodeFragmentProcessor::MakeFromDstProcessor(std::move(fp),
-                                                             SkXfermode::kDstIn_Mode);
+    return GrXfermodeFragmentProcessor::MakeFromDstProcessor(std::move(fp), SkBlendMode::kDstIn);
 }
 
 sk_sp<GrFragmentProcessor> GrFragmentProcessor::PremulInput(sk_sp<GrFragmentProcessor> fp) {
diff --git a/src/gpu/GrRenderTargetContext.cpp b/src/gpu/GrRenderTargetContext.cpp
index 937910f..ad8adb0 100644
--- a/src/gpu/GrRenderTargetContext.cpp
+++ b/src/gpu/GrRenderTargetContext.cpp
@@ -252,7 +252,7 @@
 
         GrPaint paint;
         paint.setColor4f(GrColor4f::FromGrColor(color));
-        paint.setXPFactory(GrPorterDuffXPFactory::Make(SkXfermode::Mode::kSrc_Mode));
+        paint.setXPFactory(GrPorterDuffXPFactory::Make(SkBlendMode::kSrc));
 
         this->drawRect(clip, paint, SkMatrix::I(), clearRect);
     } else if (isFull) {
diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
index dbb4699..b49687f 100644
--- a/src/gpu/SkGpuDevice.cpp
+++ b/src/gpu/SkGpuDevice.cpp
@@ -1564,7 +1564,7 @@
 void SkGpuDevice::drawVertices(const SkDraw& draw, SkCanvas::VertexMode vmode,
                               int vertexCount, const SkPoint vertices[],
                               const SkPoint texs[], const SkColor colors[],
-                              SkXfermode* xmode,
+                              SK_XFERMODE_PARAM xmode,
                               const uint16_t indices[], int indexCount,
                               const SkPaint& paint) {
     ASSERT_SINGLE_OWNER
@@ -1646,14 +1646,11 @@
         if (colors) {
             // When there are texs and colors the shader and colors are combined using xmode. A null
             // xmode is defined to mean modulate.
-            SkXfermode::Mode colorMode;
-            if (xmode) {
-                if (!xmode->asMode(&colorMode)) {
-                    return;
-                }
-            } else {
-                colorMode = SkXfermode::kModulate_Mode;
-            }
+#ifdef SK_SUPPORT_LEGACY_XFERMODE_PARAM
+            SkBlendMode colorMode = xmode ? xmode->blend() : SkBlendMode::kModulate;
+#else
+            SkBlendMode colorMode = xmode;
+#endif
             if (!SkPaintToGrPaintWithXfermode(this->context(), fRenderTargetContext.get(), paint,
                                               *draw.fMatrix, colorMode, false, &grPaint)) {
                 return;
@@ -1698,7 +1695,7 @@
 
 void SkGpuDevice::drawAtlas(const SkDraw& draw, const SkImage* atlas, const SkRSXform xform[],
                             const SkRect texRect[], const SkColor colors[], int count,
-                            SkXfermode::Mode mode, const SkPaint& paint) {
+                            SK_XFERMODE_MODE_PARAM mode, const SkPaint& paint) {
     ASSERT_SINGLE_OWNER
     if (paint.isAntiAlias()) {
         this->INHERITED::drawAtlas(draw, atlas, xform, texRect, colors, count, mode, paint);
@@ -1714,7 +1711,7 @@
     GrPaint grPaint;
     if (colors) {
         if (!SkPaintToGrPaintWithXfermode(this->context(), fRenderTargetContext.get(), p,
-                                          *draw.fMatrix, mode, true, &grPaint)) {
+                                          *draw.fMatrix, (SkBlendMode)mode, true, &grPaint)) {
             return;
         }
     } else {
diff --git a/src/gpu/SkGpuDevice.h b/src/gpu/SkGpuDevice.h
index 0b50dee..77afda7 100644
--- a/src/gpu/SkGpuDevice.h
+++ b/src/gpu/SkGpuDevice.h
@@ -92,10 +92,10 @@
     void drawTextBlob(const SkDraw&, const SkTextBlob*, SkScalar x, SkScalar y,
                       const SkPaint& paint, SkDrawFilter* drawFilter) override;
     void drawVertices(const SkDraw&, SkCanvas::VertexMode, int vertexCount, const SkPoint verts[],
-                      const SkPoint texs[], const SkColor colors[], SkXfermode* xmode,
+                      const SkPoint texs[], const SkColor colors[], SK_XFERMODE_PARAM,
                       const uint16_t indices[], int indexCount, const SkPaint&) override;
     void drawAtlas(const SkDraw&, const SkImage* atlas, const SkRSXform[], const SkRect[],
-                   const SkColor[], int count, SkXfermode::Mode, const SkPaint&) override;
+                   const SkColor[], int count, SK_XFERMODE_MODE_PARAM, const SkPaint&) override;
     void drawDevice(const SkDraw&, SkBaseDevice*, int x, int y, const SkPaint&) override;
 
     void drawImage(const SkDraw&, const SkImage*, SkScalar x, SkScalar y, const SkPaint&) override;
diff --git a/src/gpu/SkGr.cpp b/src/gpu/SkGr.cpp
index 95bd30c..270be46 100644
--- a/src/gpu/SkGr.cpp
+++ b/src/gpu/SkGr.cpp
@@ -566,11 +566,11 @@
 
 ////////////////////////////////////////////////////////////////////////////////////////////////
 
-static inline bool blend_requires_shader(const SkXfermode::Mode mode, bool primitiveIsSrc) {
+static inline bool blend_requires_shader(const SkBlendMode mode, bool primitiveIsSrc) {
     if (primitiveIsSrc) {
-        return SkXfermode::kSrc_Mode != mode;
+        return SkBlendMode::kSrc != mode;
     } else {
-        return SkXfermode::kDst_Mode != mode;
+        return SkBlendMode::kDst != mode;
     }
 }
 
@@ -579,7 +579,7 @@
                                            const SkPaint& skPaint,
                                            const SkMatrix& viewM,
                                            sk_sp<GrFragmentProcessor>* shaderProcessor,
-                                           SkXfermode::Mode* primColorMode,
+                                           SkBlendMode* primColorMode,
                                            bool primitiveIsSrc,
                                            GrPaint* grPaint) {
     grPaint->setAntiAlias(skPaint.isAntiAlias());
@@ -760,12 +760,12 @@
 }
 
 /** Blends the SkPaint's shader (or color if no shader) with a per-primitive color which must
-be setup as a vertex attribute using the specified SkXfermode::Mode. */
+be setup as a vertex attribute using the specified SkBlendMode. */
 bool SkPaintToGrPaintWithXfermode(GrContext* context,
                                   GrRenderTargetContext* rtc,
                                   const SkPaint& skPaint,
                                   const SkMatrix& viewM,
-                                  SkXfermode::Mode primColorMode,
+                                  SkBlendMode primColorMode,
                                   bool primitiveIsSrc,
                                   GrPaint* grPaint) {
     return skpaint_to_grpaint_impl(context, rtc, skPaint, viewM, nullptr, &primColorMode,
diff --git a/src/gpu/SkGrPriv.h b/src/gpu/SkGrPriv.h
index 1a976f1..3aa8a0c 100644
--- a/src/gpu/SkGrPriv.h
+++ b/src/gpu/SkGrPriv.h
@@ -75,7 +75,7 @@
                                   GrRenderTargetContext* rtc,
                                   const SkPaint& skPaint,
                                   const SkMatrix& viewM,
-                                  SkXfermode::Mode primColorMode,
+                                  SkBlendMode primColorMode,
                                   bool primitiveIsSrc,
                                   GrPaint* grPaint);
 
@@ -85,7 +85,7 @@
     applied to the primitive color after interpolation. */
 inline bool SkPaintToGrPaintWithPrimitiveColor(GrContext* context, GrRenderTargetContext* rtc,
                                                const SkPaint& skPaint, GrPaint* grPaint) {
-    return SkPaintToGrPaintWithXfermode(context, rtc, skPaint, SkMatrix::I(), SkXfermode::kDst_Mode,
+    return SkPaintToGrPaintWithXfermode(context, rtc, skPaint, SkMatrix::I(), SkBlendMode::kDst,
                                         false, grPaint);
 }
 
diff --git a/src/gpu/effects/GrCustomXfermode.cpp b/src/gpu/effects/GrCustomXfermode.cpp
index 1b94a6b..3895f57 100644
--- a/src/gpu/effects/GrCustomXfermode.cpp
+++ b/src/gpu/effects/GrCustomXfermode.cpp
@@ -24,33 +24,34 @@
 #include "glsl/GrGLSLUniformHandler.h"
 #include "glsl/GrGLSLXferProcessor.h"
 
-bool GrCustomXfermode::IsSupportedMode(SkXfermode::Mode mode) {
-    return mode > SkXfermode::kLastCoeffMode && mode <= SkXfermode::kLastMode;
+bool GrCustomXfermode::IsSupportedMode(SkBlendMode mode) {
+    return (int)mode  > (int)SkBlendMode::kLastCoeffMode &&
+           (int)mode <= (int)SkBlendMode::kLastMode;
 }
 
 ///////////////////////////////////////////////////////////////////////////////
 // Static helpers
 ///////////////////////////////////////////////////////////////////////////////
 
-static GrBlendEquation hw_blend_equation(SkXfermode::Mode mode) {
-    enum { kOffset = kOverlay_GrBlendEquation - SkXfermode::kOverlay_Mode };
-    return static_cast<GrBlendEquation>(mode + kOffset);
+static GrBlendEquation hw_blend_equation(SkBlendMode mode) {
+    enum { kOffset = kOverlay_GrBlendEquation - (int)SkBlendMode::kOverlay };
+    return static_cast<GrBlendEquation>((int)mode + kOffset);
 
-    GR_STATIC_ASSERT(kOverlay_GrBlendEquation == SkXfermode::kOverlay_Mode + kOffset);
-    GR_STATIC_ASSERT(kDarken_GrBlendEquation == SkXfermode::kDarken_Mode + kOffset);
-    GR_STATIC_ASSERT(kLighten_GrBlendEquation == SkXfermode::kLighten_Mode + kOffset);
-    GR_STATIC_ASSERT(kColorDodge_GrBlendEquation == SkXfermode::kColorDodge_Mode + kOffset);
-    GR_STATIC_ASSERT(kColorBurn_GrBlendEquation == SkXfermode::kColorBurn_Mode + kOffset);
-    GR_STATIC_ASSERT(kHardLight_GrBlendEquation == SkXfermode::kHardLight_Mode + kOffset);
-    GR_STATIC_ASSERT(kSoftLight_GrBlendEquation == SkXfermode::kSoftLight_Mode + kOffset);
-    GR_STATIC_ASSERT(kDifference_GrBlendEquation == SkXfermode::kDifference_Mode + kOffset);
-    GR_STATIC_ASSERT(kExclusion_GrBlendEquation == SkXfermode::kExclusion_Mode + kOffset);
-    GR_STATIC_ASSERT(kMultiply_GrBlendEquation == SkXfermode::kMultiply_Mode + kOffset);
-    GR_STATIC_ASSERT(kHSLHue_GrBlendEquation == SkXfermode::kHue_Mode + kOffset);
-    GR_STATIC_ASSERT(kHSLSaturation_GrBlendEquation == SkXfermode::kSaturation_Mode + kOffset);
-    GR_STATIC_ASSERT(kHSLColor_GrBlendEquation == SkXfermode::kColor_Mode + kOffset);
-    GR_STATIC_ASSERT(kHSLLuminosity_GrBlendEquation == SkXfermode::kLuminosity_Mode + kOffset);
-    GR_STATIC_ASSERT(kGrBlendEquationCnt == SkXfermode::kLastMode + 1 + kOffset);
+    GR_STATIC_ASSERT(kOverlay_GrBlendEquation == (int)SkBlendMode::kOverlay + kOffset);
+    GR_STATIC_ASSERT(kDarken_GrBlendEquation == (int)SkBlendMode::kDarken + kOffset);
+    GR_STATIC_ASSERT(kLighten_GrBlendEquation == (int)SkBlendMode::kLighten + kOffset);
+    GR_STATIC_ASSERT(kColorDodge_GrBlendEquation == (int)SkBlendMode::kColorDodge + kOffset);
+    GR_STATIC_ASSERT(kColorBurn_GrBlendEquation == (int)SkBlendMode::kColorBurn + kOffset);
+    GR_STATIC_ASSERT(kHardLight_GrBlendEquation == (int)SkBlendMode::kHardLight + kOffset);
+    GR_STATIC_ASSERT(kSoftLight_GrBlendEquation == (int)SkBlendMode::kSoftLight + kOffset);
+    GR_STATIC_ASSERT(kDifference_GrBlendEquation == (int)SkBlendMode::kDifference + kOffset);
+    GR_STATIC_ASSERT(kExclusion_GrBlendEquation == (int)SkBlendMode::kExclusion + kOffset);
+    GR_STATIC_ASSERT(kMultiply_GrBlendEquation == (int)SkBlendMode::kMultiply + kOffset);
+    GR_STATIC_ASSERT(kHSLHue_GrBlendEquation == (int)SkBlendMode::kHue + kOffset);
+    GR_STATIC_ASSERT(kHSLSaturation_GrBlendEquation == (int)SkBlendMode::kSaturation + kOffset);
+    GR_STATIC_ASSERT(kHSLColor_GrBlendEquation == (int)SkBlendMode::kColor + kOffset);
+    GR_STATIC_ASSERT(kHSLLuminosity_GrBlendEquation == (int)SkBlendMode::kLuminosity + kOffset);
+    GR_STATIC_ASSERT(kGrBlendEquationCnt == (int)SkBlendMode::kLastMode + 1 + kOffset);
 }
 
 static bool can_use_hw_blend_equation(GrBlendEquation equation,
@@ -77,13 +78,13 @@
 
 class CustomXP : public GrXferProcessor {
 public:
-    CustomXP(SkXfermode::Mode mode, GrBlendEquation hwBlendEquation)
+    CustomXP(SkBlendMode mode, GrBlendEquation hwBlendEquation)
         : fMode(mode),
           fHWBlendEquation(hwBlendEquation) {
         this->initClassID<CustomXP>();
     }
 
-    CustomXP(const DstTexture* dstTexture, bool hasMixedSamples, SkXfermode::Mode mode)
+    CustomXP(const DstTexture* dstTexture, bool hasMixedSamples, SkBlendMode mode)
         : INHERITED(dstTexture, true, hasMixedSamples),
           fMode(mode),
           fHWBlendEquation(static_cast<GrBlendEquation>(-1)) {
@@ -94,7 +95,7 @@
 
     GrGLSLXferProcessor* createGLSLInstance() const override;
 
-    SkXfermode::Mode mode() const { return fMode; }
+    SkBlendMode mode() const { return fMode; }
     bool hasHWBlendEquation() const { return -1 != static_cast<int>(fHWBlendEquation); }
 
     GrBlendEquation hwBlendEquation() const {
@@ -116,7 +117,7 @@
 
     bool onIsEqual(const GrXferProcessor& xpBase) const override;
 
-    const SkXfermode::Mode fMode;
+    const SkBlendMode      fMode;
     const GrBlendEquation  fHWBlendEquation;
 
     typedef GrXferProcessor INHERITED;
@@ -138,7 +139,7 @@
             GR_STATIC_ASSERT(GrGLSLCaps::kLast_AdvBlendEqInteraction < 4);
         }
         if (!xp.hasHWBlendEquation() || caps.mustEnableSpecificAdvBlendEqs()) {
-            key |= xp.mode() << 3;
+            key |= (int)xp.mode() << 3;
         }
         b->add32(key);
     }
@@ -326,7 +327,7 @@
 ///////////////////////////////////////////////////////////////////////////////
 class CustomXPFactory : public GrXPFactory {
 public:
-    CustomXPFactory(SkXfermode::Mode mode);
+    CustomXPFactory(SkBlendMode mode);
 
     void getInvariantBlendedColor(const GrProcOptInfo& colorPOI,
                                   GrXPFactory::InvariantBlendedColor*) const override;
@@ -346,13 +347,13 @@
 
     GR_DECLARE_XP_FACTORY_TEST;
 
-    SkXfermode::Mode fMode;
-    GrBlendEquation  fHWBlendEquation;
+    SkBlendMode     fMode;
+    GrBlendEquation fHWBlendEquation;
 
     typedef GrXPFactory INHERITED;
 };
 
-CustomXPFactory::CustomXPFactory(SkXfermode::Mode mode)
+CustomXPFactory::CustomXPFactory(SkBlendMode mode)
     : fMode(mode),
       fHWBlendEquation(hw_blend_equation(mode)) {
     SkASSERT(GrCustomXfermode::IsSupportedMode(fMode));
@@ -386,12 +387,12 @@
     int mode = d->fRandom->nextRangeU(SkXfermode::kLastCoeffMode + 1,
                                       SkXfermode::kLastSeparableMode);
 
-    return sk_sp<GrXPFactory>(new CustomXPFactory(static_cast<SkXfermode::Mode>(mode)));
+    return sk_sp<GrXPFactory>(new CustomXPFactory(static_cast<SkBlendMode>(mode)));
 }
 
 ///////////////////////////////////////////////////////////////////////////////
 
-sk_sp<GrXPFactory> GrCustomXfermode::MakeXPFactory(SkXfermode::Mode mode) {
+sk_sp<GrXPFactory> GrCustomXfermode::MakeXPFactory(SkBlendMode mode) {
     if (!GrCustomXfermode::IsSupportedMode(mode)) {
         return nullptr;
     } else {
diff --git a/src/gpu/effects/GrPorterDuffXferProcessor.cpp b/src/gpu/effects/GrPorterDuffXferProcessor.cpp
index f51e94b..d511fae 100644
--- a/src/gpu/effects/GrPorterDuffXferProcessor.cpp
+++ b/src/gpu/effects/GrPorterDuffXferProcessor.cpp
@@ -323,20 +323,20 @@
 static BlendFormula get_blend_formula(const GrProcOptInfo& colorPOI,
                                       const GrProcOptInfo& coveragePOI,
                                       bool hasMixedSamples,
-                                      SkXfermode::Mode xfermode) {
-    SkASSERT(xfermode >= 0 && xfermode <= SkXfermode::kLastCoeffMode);
+                                      SkBlendMode xfermode) {
+    SkASSERT((unsigned)xfermode <= (unsigned)SkBlendMode::kLastCoeffMode);
     SkASSERT(!coveragePOI.isFourChannelOutput());
 
     bool conflatesCoverage = !coveragePOI.isSolidWhite() || hasMixedSamples;
-    return gBlendTable[colorPOI.isOpaque()][conflatesCoverage][xfermode];
+    return gBlendTable[colorPOI.isOpaque()][conflatesCoverage][(int)xfermode];
 }
 
 static BlendFormula get_lcd_blend_formula(const GrProcOptInfo& coveragePOI,
-                                          SkXfermode::Mode xfermode) {
-    SkASSERT(xfermode >= 0 && xfermode <= SkXfermode::kLastCoeffMode);
+                                          SkBlendMode xfermode) {
+    SkASSERT((unsigned)xfermode <= (unsigned)SkBlendMode::kLastCoeffMode);
     SkASSERT(coveragePOI.isFourChannelOutput());
 
-    return gLCDBlendTable[xfermode];
+    return gLCDBlendTable[(int)xfermode];
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -506,7 +506,7 @@
 public:
     ShaderPDXferProcessor(const DstTexture* dstTexture,
                           bool hasMixedSamples,
-                          SkXfermode::Mode xfermode)
+                          SkBlendMode xfermode)
         : INHERITED(dstTexture, true, hasMixedSamples)
         , fXfermode(xfermode) {
         this->initClassID<ShaderPDXferProcessor>();
@@ -516,7 +516,7 @@
 
     GrGLSLXferProcessor* createGLSLInstance() const override;
 
-    SkXfermode::Mode getXfermode() const { return fXfermode; }
+    SkBlendMode getXfermode() const { return fXfermode; }
 
 private:
     GrXferProcessor::OptFlags onGetOptimizations(const GrPipelineOptimizations&, bool, GrColor*,
@@ -531,7 +531,7 @@
         return fXfermode == xp.fXfermode;
     }
 
-    const SkXfermode::Mode fXfermode;
+    const SkBlendMode fXfermode;
 
     typedef GrXferProcessor INHERITED;
 };
@@ -542,7 +542,7 @@
 public:
     static void GenKey(const GrProcessor& processor, GrProcessorKeyBuilder* b) {
         const ShaderPDXferProcessor& xp = processor.cast<ShaderPDXferProcessor>();
-        b->add32(xp.getXfermode());
+        b->add32((int)xp.getXfermode());
     }
 
 private:
@@ -583,7 +583,7 @@
 
 class PDLCDXferProcessor : public GrXferProcessor {
 public:
-    static GrXferProcessor* Create(SkXfermode::Mode xfermode, const GrProcOptInfo& colorPOI);
+    static GrXferProcessor* Create(SkBlendMode xfermode, const GrProcOptInfo& colorPOI);
 
     ~PDLCDXferProcessor() override;
 
@@ -654,9 +654,9 @@
     this->initClassID<PDLCDXferProcessor>();
 }
 
-GrXferProcessor* PDLCDXferProcessor::Create(SkXfermode::Mode xfermode,
+GrXferProcessor* PDLCDXferProcessor::Create(SkBlendMode xfermode,
                                             const GrProcOptInfo& colorPOI) {
-    if (SkXfermode::kSrcOver_Mode != xfermode) {
+    if (SkBlendMode::kSrcOver != xfermode) {
         return nullptr;
     }
 
@@ -698,40 +698,40 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 
-GrPorterDuffXPFactory::GrPorterDuffXPFactory(SkXfermode::Mode xfermode)
+GrPorterDuffXPFactory::GrPorterDuffXPFactory(SkBlendMode xfermode)
     : fXfermode(xfermode) {
-    SkASSERT(fXfermode <= SkXfermode::kLastCoeffMode);
+    SkASSERT((unsigned)fXfermode <= (unsigned)SkBlendMode::kLastCoeffMode);
     this->initClassID<GrPorterDuffXPFactory>();
 }
 
-sk_sp<GrXPFactory> GrPorterDuffXPFactory::Make(SkXfermode::Mode xfermode) {
-    static GrPorterDuffXPFactory gClearPDXPF(SkXfermode::kClear_Mode);
-    static GrPorterDuffXPFactory gSrcPDXPF(SkXfermode::kSrc_Mode);
-    static GrPorterDuffXPFactory gDstPDXPF(SkXfermode::kDst_Mode);
-    static GrPorterDuffXPFactory gSrcOverPDXPF(SkXfermode::kSrcOver_Mode);
-    static GrPorterDuffXPFactory gDstOverPDXPF(SkXfermode::kDstOver_Mode);
-    static GrPorterDuffXPFactory gSrcInPDXPF(SkXfermode::kSrcIn_Mode);
-    static GrPorterDuffXPFactory gDstInPDXPF(SkXfermode::kDstIn_Mode);
-    static GrPorterDuffXPFactory gSrcOutPDXPF(SkXfermode::kSrcOut_Mode);
-    static GrPorterDuffXPFactory gDstOutPDXPF(SkXfermode::kDstOut_Mode);
-    static GrPorterDuffXPFactory gSrcATopPDXPF(SkXfermode::kSrcATop_Mode);
-    static GrPorterDuffXPFactory gDstATopPDXPF(SkXfermode::kDstATop_Mode);
-    static GrPorterDuffXPFactory gXorPDXPF(SkXfermode::kXor_Mode);
-    static GrPorterDuffXPFactory gPlusPDXPF(SkXfermode::kPlus_Mode);
-    static GrPorterDuffXPFactory gModulatePDXPF(SkXfermode::kModulate_Mode);
-    static GrPorterDuffXPFactory gScreenPDXPF(SkXfermode::kScreen_Mode);
+sk_sp<GrXPFactory> GrPorterDuffXPFactory::Make(SkBlendMode xfermode) {
+    static GrPorterDuffXPFactory gClearPDXPF(SkBlendMode::kClear);
+    static GrPorterDuffXPFactory gSrcPDXPF(SkBlendMode::kSrc);
+    static GrPorterDuffXPFactory gDstPDXPF(SkBlendMode::kDst);
+    static GrPorterDuffXPFactory gSrcOverPDXPF(SkBlendMode::kSrcOver);
+    static GrPorterDuffXPFactory gDstOverPDXPF(SkBlendMode::kDstOver);
+    static GrPorterDuffXPFactory gSrcInPDXPF(SkBlendMode::kSrcIn);
+    static GrPorterDuffXPFactory gDstInPDXPF(SkBlendMode::kDstIn);
+    static GrPorterDuffXPFactory gSrcOutPDXPF(SkBlendMode::kSrcOut);
+    static GrPorterDuffXPFactory gDstOutPDXPF(SkBlendMode::kDstOut);
+    static GrPorterDuffXPFactory gSrcATopPDXPF(SkBlendMode::kSrcATop);
+    static GrPorterDuffXPFactory gDstATopPDXPF(SkBlendMode::kDstATop);
+    static GrPorterDuffXPFactory gXorPDXPF(SkBlendMode::kXor);
+    static GrPorterDuffXPFactory gPlusPDXPF(SkBlendMode::kPlus);
+    static GrPorterDuffXPFactory gModulatePDXPF(SkBlendMode::kModulate);
+    static GrPorterDuffXPFactory gScreenPDXPF(SkBlendMode::kScreen);
 
     static GrPorterDuffXPFactory* gFactories[] = {
         &gClearPDXPF, &gSrcPDXPF, &gDstPDXPF, &gSrcOverPDXPF, &gDstOverPDXPF, &gSrcInPDXPF,
         &gDstInPDXPF, &gSrcOutPDXPF, &gDstOutPDXPF, &gSrcATopPDXPF, &gDstATopPDXPF, &gXorPDXPF,
         &gPlusPDXPF, &gModulatePDXPF, &gScreenPDXPF
     };
-    GR_STATIC_ASSERT(SK_ARRAY_COUNT(gFactories) == SkXfermode::kLastCoeffMode + 1);
+    GR_STATIC_ASSERT(SK_ARRAY_COUNT(gFactories) == (int)SkBlendMode::kLastCoeffMode + 1);
 
-    if (xfermode < 0 || xfermode > SkXfermode::kLastCoeffMode) {
+    if ((int)xfermode < 0 || (int)xfermode > (int)SkBlendMode::kLastCoeffMode) {
         return nullptr;
     }
-    return sk_sp<GrXPFactory>(SkRef(gFactories[xfermode]));
+    return sk_sp<GrXPFactory>(SkRef(gFactories[(int)xfermode]));
 }
 
 GrXferProcessor*
@@ -744,7 +744,7 @@
     }
     BlendFormula blendFormula;
     if (optimizations.fCoveragePOI.isFourChannelOutput()) {
-        if (SkXfermode::kSrcOver_Mode == fXfermode &&
+        if (SkBlendMode::kSrcOver == fXfermode &&
             kRGBA_GrColorComponentFlags == optimizations.fColorPOI.validFlags() &&
             !caps.shaderCaps()->dualSourceBlendingSupport() &&
             !caps.shaderCaps()->dstReadInShaderSupport()) {
@@ -770,7 +770,7 @@
 void GrPorterDuffXPFactory::getInvariantBlendedColor(const GrProcOptInfo& colorPOI,
                                                      InvariantBlendedColor* blendedColor) const {
     // Find the blended color info based on the formula that does not have coverage.
-    BlendFormula colorFormula = gBlendTable[colorPOI.isOpaque()][0][fXfermode];
+    BlendFormula colorFormula = gBlendTable[colorPOI.isOpaque()][0][(int)fXfermode];
     if (colorFormula.usesDstColor()) {
         blendedColor->fWillBlendWithDst = true;
         blendedColor->fKnownColorFlags = kNone_GrColorComponentFlags;
@@ -808,7 +808,7 @@
     // blend. The one exception is when we are using srcover mode and we know the input color into
     // the XP.
     if (optimizations.fCoveragePOI.isFourChannelOutput()) {
-        if (SkXfermode::kSrcOver_Mode == fXfermode &&
+        if (SkBlendMode::kSrcOver == fXfermode &&
             kRGBA_GrColorComponentFlags == optimizations.fColorPOI.validFlags() &&
             !caps.shaderCaps()->dstReadInShaderSupport()) {
             return false;
@@ -827,7 +827,7 @@
 GR_DEFINE_XP_FACTORY_TEST(GrPorterDuffXPFactory);
 
 sk_sp<GrXPFactory> GrPorterDuffXPFactory::TestCreate(GrProcessorTestData* d) {
-    SkXfermode::Mode mode = SkXfermode::Mode(d->fRandom->nextULessThan(SkXfermode::kLastCoeffMode));
+    SkBlendMode mode = SkBlendMode(d->fRandom->nextULessThan((int)SkBlendMode::kLastCoeffMode));
     return GrPorterDuffXPFactory::Make(mode);
 }
 
@@ -860,7 +860,7 @@
         bool hasMixedSamples,
         const GrXferProcessor::DstTexture* dstTexture) {
     if (optimizations.fOverrides.fUsePLSDstRead) {
-        return new ShaderPDXferProcessor(dstTexture, hasMixedSamples, SkXfermode::kSrcOver_Mode);
+        return new ShaderPDXferProcessor(dstTexture, hasMixedSamples, SkBlendMode::kSrcOver);
     }
 
     // We want to not make an xfer processor if possible. Thus for the simple case where we are not
@@ -882,13 +882,13 @@
         // back to this trick for rendering SrcOver LCD text instead of doing a
         // dst copy.
         SkASSERT(!dstTexture || !dstTexture->texture());
-        return PDLCDXferProcessor::Create(SkXfermode::kSrcOver_Mode, optimizations.fColorPOI);
+        return PDLCDXferProcessor::Create(SkBlendMode::kSrcOver, optimizations.fColorPOI);
     }
 
     BlendFormula blendFormula;
-    blendFormula = get_lcd_blend_formula(optimizations.fCoveragePOI, SkXfermode::kSrcOver_Mode);
+    blendFormula = get_lcd_blend_formula(optimizations.fCoveragePOI, SkBlendMode::kSrcOver);
     if (blendFormula.hasSecondaryOutput() && !caps.shaderCaps()->dualSourceBlendingSupport()) {
-        return new ShaderPDXferProcessor(dstTexture, hasMixedSamples, SkXfermode::kSrcOver_Mode);
+        return new ShaderPDXferProcessor(dstTexture, hasMixedSamples, SkBlendMode::kSrcOver);
     }
 
     SkASSERT(!dstTexture || !dstTexture->texture());
@@ -911,7 +911,7 @@
             return false;
         }
         return get_lcd_blend_formula(optimizations.fCoveragePOI,
-                                     SkXfermode::kSrcOver_Mode).hasSecondaryOutput();
+                                     SkBlendMode::kSrcOver).hasSecondaryOutput();
     }
 
     // We fallback on the shader XP when the blend formula would use dual source blending but we
@@ -919,5 +919,5 @@
     static const bool kHasMixedSamples = false;
     SkASSERT(!caps.usesMixedSamples()); // We never use mixed samples without dual source blending.
     return get_blend_formula(optimizations.fColorPOI, optimizations.fCoveragePOI,
-                             kHasMixedSamples, SkXfermode::kSrcOver_Mode).hasSecondaryOutput();
+                             kHasMixedSamples, SkBlendMode::kSrcOver).hasSecondaryOutput();
 }
diff --git a/src/gpu/effects/GrXfermodeFragmentProcessor.cpp b/src/gpu/effects/GrXfermodeFragmentProcessor.cpp
index 935747b..0e8e16c 100644
--- a/src/gpu/effects/GrXfermodeFragmentProcessor.cpp
+++ b/src/gpu/effects/GrXfermodeFragmentProcessor.cpp
@@ -18,7 +18,7 @@
 class ComposeTwoFragmentProcessor : public GrFragmentProcessor {
 public:
     ComposeTwoFragmentProcessor(sk_sp<GrFragmentProcessor> src, sk_sp<GrFragmentProcessor> dst,
-                                SkXfermode::Mode mode)
+                                SkBlendMode mode)
         : fMode(mode) {
         this->initClassID<ComposeTwoFragmentProcessor>();
         SkDEBUGCODE(int shaderAChildIndex = )this->registerChildProcessor(std::move(src));
@@ -30,10 +30,10 @@
     const char* name() const override { return "ComposeTwo"; }
 
     void onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const override {
-        b->add32(fMode);
+        b->add32((int)fMode);
     }
 
-    SkXfermode::Mode getMode() const { return fMode; }
+    SkBlendMode getMode() const { return fMode; }
 
 protected:
     bool onIsEqual(const GrFragmentProcessor& other) const override {
@@ -48,7 +48,7 @@
 private:
     GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
 
-    SkXfermode::Mode fMode;
+    SkBlendMode fMode;
 
     GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
 
@@ -74,8 +74,8 @@
     sk_sp<GrFragmentProcessor> fpA(GrProcessorUnitTest::MakeChildFP(d));
     sk_sp<GrFragmentProcessor> fpB(GrProcessorUnitTest::MakeChildFP(d));
 
-    SkXfermode::Mode mode = static_cast<SkXfermode::Mode>(
-        d->fRandom->nextRangeU(0, SkXfermode::kLastMode));
+    SkBlendMode mode = static_cast<SkBlendMode>(
+        d->fRandom->nextRangeU(0, (int)SkBlendMode::kLastMode));
     return sk_sp<GrFragmentProcessor>(
         new ComposeTwoFragmentProcessor(std::move(fpA), std::move(fpB), mode));
 }
@@ -105,7 +105,7 @@
     this->emitChild(1, inputColor, &dstColor, args);
 
     // emit blend code
-    SkXfermode::Mode mode = cs.getMode();
+    SkBlendMode mode = cs.getMode();
     fragBuilder->codeAppendf("// Compose Xfer Mode: %s\n", SkXfermode::ModeName(mode));
     GrGLSLBlend::AppendMode(fragBuilder,
                             srcColor.c_str(),
@@ -120,14 +120,14 @@
 }
 
 sk_sp<GrFragmentProcessor> GrXfermodeFragmentProcessor::MakeFromTwoProcessors(
-         sk_sp<GrFragmentProcessor> src, sk_sp<GrFragmentProcessor> dst, SkXfermode::Mode mode) {
+         sk_sp<GrFragmentProcessor> src, sk_sp<GrFragmentProcessor> dst, SkBlendMode mode) {
     switch (mode) {
-        case SkXfermode::kClear_Mode:
+        case SkBlendMode::kClear:
             return GrConstColorProcessor::Make(GrColor4f::TransparentBlack(),
                                                GrConstColorProcessor::kIgnore_InputMode);
-        case SkXfermode::kSrc_Mode:
+        case SkBlendMode::kSrc:
             return src;
-        case SkXfermode::kDst_Mode:
+        case SkBlendMode::kDst:
             return dst;
         default:
             return sk_sp<GrFragmentProcessor>(
@@ -144,7 +144,7 @@
         kSrc_Child,
     };
 
-    ComposeOneFragmentProcessor(sk_sp<GrFragmentProcessor> dst, SkXfermode::Mode mode, Child child)
+    ComposeOneFragmentProcessor(sk_sp<GrFragmentProcessor> dst, SkBlendMode mode, Child child)
         : fMode(mode)
         , fChild(child) {
         this->initClassID<ComposeOneFragmentProcessor>();
@@ -164,11 +164,11 @@
     }
 
     void onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const override {
-        GR_STATIC_ASSERT((SkXfermode::kLastMode & SK_MaxU16) == SkXfermode::kLastMode);
-        b->add32(fMode | (fChild << 16));
+        GR_STATIC_ASSERT(((int)SkBlendMode::kLastMode & SK_MaxU16) == (int)SkBlendMode::kLastMode);
+        b->add32((int)fMode | (fChild << 16));
     }
 
-    SkXfermode::Mode mode() const { return fMode; }
+    SkBlendMode mode() const { return fMode; }
 
     Child child() const { return fChild; }
 
@@ -217,8 +217,8 @@
 private:
     GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
 
-    SkXfermode::Mode    fMode;
-    Child               fChild;
+    SkBlendMode fMode;
+    Child       fChild;
 
     GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
 
@@ -231,7 +231,7 @@
 public:
     void emitCode(EmitArgs& args) override {
         GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
-        SkXfermode::Mode mode = args.fFp.cast<ComposeOneFragmentProcessor>().mode();
+        SkBlendMode mode = args.fFp.cast<ComposeOneFragmentProcessor>().mode();
         ComposeOneFragmentProcessor::Child child =
             args.fFp.cast<ComposeOneFragmentProcessor>().child();
         SkString childColor("child");
@@ -267,8 +267,8 @@
     // For now, we'll prevent either children from being a shader with children to prevent the
     // possibility of an arbitrarily large tree of procs.
     sk_sp<GrFragmentProcessor> dst(GrProcessorUnitTest::MakeChildFP(d));
-    SkXfermode::Mode mode = static_cast<SkXfermode::Mode>(
-        d->fRandom->nextRangeU(0, SkXfermode::kLastMode));
+    SkBlendMode mode = static_cast<SkBlendMode>(
+        d->fRandom->nextRangeU(0, (int)SkBlendMode::kLastMode));
     ComposeOneFragmentProcessor::Child child = d->fRandom->nextBool() ?
         ComposeOneFragmentProcessor::kDst_Child :
         ComposeOneFragmentProcessor::kSrc_Child;
@@ -282,12 +282,12 @@
 //////////////////////////////////////////////////////////////////////////////
 
 sk_sp<GrFragmentProcessor> GrXfermodeFragmentProcessor::MakeFromDstProcessor(
-    sk_sp<GrFragmentProcessor> dst, SkXfermode::Mode mode) {
+    sk_sp<GrFragmentProcessor> dst, SkBlendMode mode) {
     switch (mode) {
-        case SkXfermode::kClear_Mode:
+        case SkBlendMode::kClear:
             return GrConstColorProcessor::Make(GrColor4f::TransparentBlack(),
                                                  GrConstColorProcessor::kIgnore_InputMode);
-        case SkXfermode::kSrc_Mode:
+        case SkBlendMode::kSrc:
             return nullptr;
         default:
             return sk_sp<GrFragmentProcessor>(
@@ -297,12 +297,12 @@
 }
 
 sk_sp<GrFragmentProcessor> GrXfermodeFragmentProcessor::MakeFromSrcProcessor(
-    sk_sp<GrFragmentProcessor> src, SkXfermode::Mode mode) {
+    sk_sp<GrFragmentProcessor> src, SkBlendMode mode) {
     switch (mode) {
-        case SkXfermode::kClear_Mode:
+        case SkBlendMode::kClear:
             return GrConstColorProcessor::Make(GrColor4f::TransparentBlack(),
                                                  GrConstColorProcessor::kIgnore_InputMode);
-        case SkXfermode::kDst_Mode:
+        case SkBlendMode::kDst:
             return nullptr;
         default:
             return sk_sp<GrFragmentProcessor>(
diff --git a/src/gpu/glsl/GrGLSLBlend.cpp b/src/gpu/glsl/GrGLSLBlend.cpp
index d2c3640..73a145b 100644
--- a/src/gpu/glsl/GrGLSLBlend.cpp
+++ b/src/gpu/glsl/GrGLSLBlend.cpp
@@ -237,7 +237,7 @@
 
 static void emit_advanced_xfermode_code(GrGLSLFragmentBuilder* fsBuilder, const char* srcColor,
                                         const char* dstColor, const char* outputColor,
-                                        SkXfermode::Mode mode) {
+                                        SkBlendMode mode) {
     SkASSERT(srcColor);
     SkASSERT(dstColor);
     SkASSERT(outputColor);
@@ -246,38 +246,38 @@
                            outputColor, srcColor, srcColor, dstColor);
 
     switch (mode) {
-        case SkXfermode::kOverlay_Mode:
+        case SkBlendMode::kOverlay:
             // Overlay is Hard-Light with the src and dst reversed
             hard_light(fsBuilder, outputColor, dstColor, srcColor);
             break;
-        case SkXfermode::kDarken_Mode:
+        case SkBlendMode::kDarken:
             fsBuilder->codeAppendf("%s.rgb = min((1.0 - %s.a) * %s.rgb + %s.rgb, "
                                    "(1.0 - %s.a) * %s.rgb + %s.rgb);",
                                    outputColor,
                                    srcColor, dstColor, srcColor,
                                    dstColor, srcColor, dstColor);
             break;
-        case SkXfermode::kLighten_Mode:
+        case SkBlendMode::kLighten:
             fsBuilder->codeAppendf("%s.rgb = max((1.0 - %s.a) * %s.rgb + %s.rgb, "
                                    "(1.0 - %s.a) * %s.rgb + %s.rgb);",
                                    outputColor,
                                    srcColor, dstColor, srcColor,
                                    dstColor, srcColor, dstColor);
             break;
-        case SkXfermode::kColorDodge_Mode:
+        case SkBlendMode::kColorDodge:
             color_dodge_component(fsBuilder, outputColor, srcColor, dstColor, 'r');
             color_dodge_component(fsBuilder, outputColor, srcColor, dstColor, 'g');
             color_dodge_component(fsBuilder, outputColor, srcColor, dstColor, 'b');
             break;
-        case SkXfermode::kColorBurn_Mode:
+        case SkBlendMode::kColorBurn:
             color_burn_component(fsBuilder, outputColor, srcColor, dstColor, 'r');
             color_burn_component(fsBuilder, outputColor, srcColor, dstColor, 'g');
             color_burn_component(fsBuilder, outputColor, srcColor, dstColor, 'b');
             break;
-        case SkXfermode::kHardLight_Mode:
+        case SkBlendMode::kHardLight:
             hard_light(fsBuilder, outputColor, srcColor, dstColor);
             break;
-        case SkXfermode::kSoftLight_Mode:
+        case SkBlendMode::kSoftLight:
             fsBuilder->codeAppendf("if (0.0 == %s.a) {", dstColor);
             fsBuilder->codeAppendf("%s.rgba = %s;", outputColor, srcColor);
             fsBuilder->codeAppendf("} else {");
@@ -286,25 +286,25 @@
             soft_light_component_pos_dst_alpha(fsBuilder, outputColor, srcColor, dstColor, 'b');
             fsBuilder->codeAppendf("}");
             break;
-        case SkXfermode::kDifference_Mode:
+        case SkBlendMode::kDifference:
             fsBuilder->codeAppendf("%s.rgb = %s.rgb + %s.rgb -"
                                    "2.0 * min(%s.rgb * %s.a, %s.rgb * %s.a);",
                                    outputColor, srcColor, dstColor, srcColor, dstColor,
                                    dstColor, srcColor);
             break;
-        case SkXfermode::kExclusion_Mode:
+        case SkBlendMode::kExclusion:
             fsBuilder->codeAppendf("%s.rgb = %s.rgb + %s.rgb - "
                                    "2.0 * %s.rgb * %s.rgb;",
                                    outputColor, dstColor, srcColor, dstColor, srcColor);
             break;
-        case SkXfermode::kMultiply_Mode:
+        case SkBlendMode::kMultiply:
             fsBuilder->codeAppendf("%s.rgb = (1.0 - %s.a) * %s.rgb + "
                                    "(1.0 - %s.a) * %s.rgb + "
                                    "%s.rgb * %s.rgb;",
                                    outputColor, srcColor, dstColor, dstColor, srcColor,
                                    srcColor, dstColor);
             break;
-        case SkXfermode::kHue_Mode: {
+        case SkBlendMode::kHue: {
             //  SetLum(SetSat(S * Da, Sat(D * Sa)), Sa*Da, D*Sa) + (1 - Sa) * D + (1 - Da) * S
             SkString setSat, setLum;
             add_sat_function(fsBuilder, &setSat);
@@ -319,7 +319,7 @@
                                    outputColor, srcColor, dstColor, dstColor, srcColor);
             break;
         }
-        case SkXfermode::kSaturation_Mode: {
+        case SkBlendMode::kSaturation: {
             // SetLum(SetSat(D * Sa, Sat(S * Da)), Sa*Da, D*Sa)) + (1 - Sa) * D + (1 - Da) * S
             SkString setSat, setLum;
             add_sat_function(fsBuilder, &setSat);
@@ -334,7 +334,7 @@
                                    outputColor, srcColor, dstColor, dstColor, srcColor);
             break;
         }
-        case SkXfermode::kColor_Mode: {
+        case SkBlendMode::kColor: {
             //  SetLum(S * Da, Sa* Da, D * Sa) + (1 - Sa) * D + (1 - Da) * S
             SkString setLum;
             add_lum_function(fsBuilder, &setLum);
@@ -346,7 +346,7 @@
                                    outputColor, srcColor, dstColor, dstColor, srcColor);
             break;
         }
-        case SkXfermode::kLuminosity_Mode: {
+        case SkBlendMode::kLuminosity: {
             //  SetLum(D * Sa, Sa* Da, S * Da) + (1 - Sa) * D + (1 - Da) * S
             SkString setLum;
             add_lum_function(fsBuilder, &setLum);
@@ -416,7 +416,7 @@
 
 void GrGLSLBlend::AppendMode(GrGLSLFragmentBuilder* fsBuilder, const char* srcColor,
                              const char* dstColor, const char* outColor,
-                             SkXfermode::Mode mode) {
+                             SkBlendMode mode) {
 
     SkXfermode::Coeff srcCoeff, dstCoeff;
     if (SkXfermode::ModeAsCoeff(mode, &srcCoeff, &dstCoeff)) {
diff --git a/src/gpu/glsl/GrGLSLBlend.h b/src/gpu/glsl/GrGLSLBlend.h
index c8047f8..63d6762 100644
--- a/src/gpu/glsl/GrGLSLBlend.h
+++ b/src/gpu/glsl/GrGLSLBlend.h
@@ -19,7 +19,7 @@
      * variables to the outColor variable.
      */
     void AppendMode(GrGLSLFragmentBuilder* fsBuilder, const char* srcColor,
-                    const char* dstColor, const char* outColor, SkXfermode::Mode mode);
+                    const char* dstColor, const char* outColor, SkBlendMode mode);
 
     void AppendRegionOp(GrGLSLFragmentBuilder* fsBuilder, const char* srcColor,
                         const char* dstColor, const char* outColor, SkRegion::Op regionOp);
diff --git a/src/image/SkImage_Gpu.cpp b/src/image/SkImage_Gpu.cpp
index cd26c8b..d7bdc9c 100644
--- a/src/image/SkImage_Gpu.cpp
+++ b/src/image/SkImage_Gpu.cpp
@@ -263,7 +263,7 @@
     }
 
     GrPaint paint;
-    paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode);
+    paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
     paint.addColorFragmentProcessor(
         GrYUVEffect::MakeYUVToRGB(yTex.get(), uTex.get(), vTex.get(), yuvSizes, colorSpace, nv12));
 
diff --git a/src/opts/SkXfermode_opts.h b/src/opts/SkXfermode_opts.h
index 54f906e..81e5bb9 100644
--- a/src/opts/SkXfermode_opts.h
+++ b/src/opts/SkXfermode_opts.h
@@ -217,7 +217,7 @@
 template <typename Xfermode>
 class Sk4pxXfermode : public SkProcCoeffXfermode {
 public:
-    Sk4pxXfermode(const ProcCoeff& rec, SkXfermode::Mode mode)
+    Sk4pxXfermode(const ProcCoeff& rec, SkBlendMode mode)
         : INHERITED(rec, mode) {}
 
     void xfer32(SkPMColor dst[], const SkPMColor src[], int n, const SkAlpha aa[]) const override {
@@ -269,7 +269,7 @@
 template <typename Xfermode>
 class Sk4fXfermode : public SkProcCoeffXfermode {
 public:
-    Sk4fXfermode(const ProcCoeff& rec, SkXfermode::Mode mode)
+    Sk4fXfermode(const ProcCoeff& rec, SkBlendMode mode)
         : INHERITED(rec, mode) {}
 
     void xfer32(SkPMColor dst[], const SkPMColor src[], int n, const SkAlpha aa[]) const override {
@@ -315,10 +315,10 @@
 
 namespace SK_OPTS_NS {
 
-static SkXfermode* create_xfermode(const ProcCoeff& rec, SkXfermode::Mode mode) {
+static SkXfermode* create_xfermode(const ProcCoeff& rec, SkBlendMode mode) {
     switch (mode) {
 #define CASE(Xfermode) \
-    case SkXfermode::k##Xfermode##_Mode: return new Sk4pxXfermode<Xfermode>(rec, mode)
+    case SkBlendMode::k##Xfermode: return new Sk4pxXfermode<Xfermode>(rec, mode)
         CASE(Clear);
         CASE(Src);
         CASE(Dst);
@@ -344,7 +344,7 @@
     #undef CASE
 
 #define CASE(Xfermode) \
-    case SkXfermode::k##Xfermode##_Mode: return new Sk4fXfermode<Xfermode>(rec, mode)
+    case SkBlendMode::k##Xfermode: return new Sk4fXfermode<Xfermode>(rec, mode)
         CASE(ColorDodge);
         CASE(ColorBurn);
         CASE(SoftLight);
diff --git a/src/pdf/SkPDFDevice.cpp b/src/pdf/SkPDFDevice.cpp
index 217dd3f..8b80de2 100644
--- a/src/pdf/SkPDFDevice.cpp
+++ b/src/pdf/SkPDFDevice.cpp
@@ -1427,7 +1427,7 @@
 void SkPDFDevice::drawVertices(const SkDraw& d, SkCanvas::VertexMode,
                                int vertexCount, const SkPoint verts[],
                                const SkPoint texs[], const SkColor colors[],
-                               SkXfermode* xmode, const uint16_t indices[],
+                               SK_XFERMODE_PARAM xmode, const uint16_t indices[],
                                int indexCount, const SkPaint& paint) {
     if (d.fRC->isEmpty()) {
         return;
diff --git a/src/pdf/SkPDFDevice.h b/src/pdf/SkPDFDevice.h
index 7d207e7..4bf4a58 100644
--- a/src/pdf/SkPDFDevice.h
+++ b/src/pdf/SkPDFDevice.h
@@ -116,7 +116,7 @@
     void drawVertices(const SkDraw&, SkCanvas::VertexMode,
                       int vertexCount, const SkPoint verts[],
                       const SkPoint texs[], const SkColor colors[],
-                      SkXfermode* xmode, const uint16_t indices[],
+                      SK_XFERMODE_PARAM, const uint16_t indices[],
                       int indexCount, const SkPaint& paint) override;
     void drawDevice(const SkDraw&, SkBaseDevice*, int x, int y,
                     const SkPaint&) override;
diff --git a/src/pipe/SkPipeCanvas.cpp b/src/pipe/SkPipeCanvas.cpp
index 31014ff..e7b04ce 100644
--- a/src/pipe/SkPipeCanvas.cpp
+++ b/src/pipe/SkPipeCanvas.cpp
@@ -352,7 +352,7 @@
 }
 
 void SkPipeCanvas::onDrawAtlas(const SkImage* image, const SkRSXform xform[], const SkRect rect[],
-                               const SkColor colors[], int count, SkXfermode::Mode mode,
+                               const SkColor colors[], int count, SK_XFERMODE_MODE_PARAM mode,
                                const SkRect* cull, const SkPaint* paint) {
     unsigned extra = (unsigned)mode;
     SkASSERT(0 == (extra & ~kMode_DrawAtlasMask));
@@ -732,7 +732,7 @@
 
 void SkPipeCanvas::onDrawVertices(VertexMode vmode, int vertexCount,
                                   const SkPoint vertices[], const SkPoint texs[],
-                                  const SkColor colors[], SkXfermode* xmode,
+                                  const SkColor colors[], SK_XFERMODE_PARAM xmode,
                                   const uint16_t indices[], int indexCount,
                                   const SkPaint& paint) {
     SkASSERT(vertexCount > 0);
@@ -743,11 +743,12 @@
     }
     extra |= (unsigned)vmode << kVMode_DrawVerticesShift;
 
-    SkXfermode::Mode mode = SkXfermode::kModulate_Mode;
-    if (xmode && !SkXfermode::AsMode(xmode, &mode)) {
-        mode = (SkXfermode::Mode)0xFF;  // sentinel for read the xfer later
-    }
-    extra |= (unsigned)mode << kXMode_DrawVerticesShift;
+#ifdef SK_SUPPORT_LEGACY_XFERMODE_PARAM
+    SkBlendMode bmode = xmode ? xmode->blend() : SkBlendMode::kModulate;
+#else
+    SkBlendMode bmode = xmode;
+#endif
+    extra |= (unsigned)bmode << kXMode_DrawVerticesShift;
 
     if (texs) {
         extra |= kHasTex_DrawVerticesMask;
@@ -764,9 +765,6 @@
     if (vertexCount > kVCount_DrawVerticesMask) {
         writer.write32(vertexCount);
     }
-    if (mode == (SkXfermode::Mode)0xFF) {
-        writer.writeFlattenable(xmode);
-    }
     writer.write(vertices, vertexCount * sizeof(SkPoint));
     if (texs) {
         writer.write(texs, vertexCount * sizeof(SkPoint));
@@ -783,18 +781,17 @@
 }
 
 void SkPipeCanvas::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
-                               const SkPoint texCoords[4], SkXfermode* xfer,
+                               const SkPoint texCoords[4], SK_XFERMODE_PARAM xmode,
                                const SkPaint& paint) {
     SkPipeWriter writer(this);
     unsigned extra = 0;
-    SkXfermode::Mode mode = SkXfermode::kModulate_Mode;
-    if (xfer && !xfer->asMode(&mode)) {
-        mode = (SkXfermode::Mode)kExplicitXfer_DrawPatchExtraValue;
-    } else {
-        xfer = nullptr;    // signal that we're using the mode enum
-    }
-    SkASSERT(0 == (mode & ~kModeEnum_DrawPatchExtraMask));
-    extra = (unsigned)mode;
+#ifdef SK_SUPPORT_LEGACY_XFERMODE_PARAM
+    SkBlendMode bmode = xmode ? xmode->blend() : SkBlendMode::kModulate;
+#else
+    SkBlendMode bmode = xmode;
+#endif
+    SkASSERT(0 == ((int)bmode & ~kModeEnum_DrawPatchExtraMask));
+    extra = (unsigned)bmode;
     if (colors) {
         extra |= kHasColors_DrawPatchExtraMask;
     }
@@ -809,9 +806,6 @@
     if (texCoords) {
         writer.write(texCoords, sizeof(SkPoint) * 4);
     }
-    if (xfer) {
-        xfer->flatten(writer);
-    }
     write_paint(writer, paint, kGeometry_PaintUsage);
 }
 
diff --git a/src/pipe/SkPipeCanvas.h b/src/pipe/SkPipeCanvas.h
index 33f7821..87a906f 100644
--- a/src/pipe/SkPipeCanvas.h
+++ b/src/pipe/SkPipeCanvas.h
@@ -105,7 +105,7 @@
     void onDrawArc(const SkRect&, SkScalar startAngle, SkScalar sweepAngle, bool useCenter,
                    const SkPaint&) override;
     void onDrawAtlas(const SkImage*, const SkRSXform[], const SkRect[], const SkColor[],
-                     int count, SkXfermode::Mode, const SkRect* cull, const SkPaint*) override;
+                     int count, SK_XFERMODE_MODE_PARAM, const SkRect* cull, const SkPaint*) override;
     void onDrawDRRect(const SkRRect&, const SkRRect&, const SkPaint&) override;
     void onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
                     const SkPaint&) override;
@@ -119,7 +119,7 @@
     void onDrawTextRSXform(const void* text, size_t byteLength, const SkRSXform xform[],
                            const SkRect* cull, const SkPaint& paint) override;
     void onDrawPatch(const SkPoint cubics[12], const SkColor colors[4], const SkPoint texCoords[4],
-                     SkXfermode*, const SkPaint&) override;
+                     SK_XFERMODE_PARAM, const SkPaint&) override;
 
     void onDrawPaint(const SkPaint&) override;
     void onDrawPoints(PointMode, size_t count, const SkPoint pts[], const SkPaint&) override;
@@ -138,7 +138,7 @@
                             const SkPaint*) override;
     void onDrawVertices(VertexMode vmode, int vertexCount,
                               const SkPoint vertices[], const SkPoint texs[],
-                              const SkColor colors[], SkXfermode* xmode,
+                              const SkColor colors[], SK_XFERMODE_PARAM,
                               const uint16_t indices[], int indexCount,
                               const SkPaint&) override;
 
diff --git a/src/pipe/SkPipeReader.cpp b/src/pipe/SkPipeReader.cpp
index 31718e9..2039bf2 100644
--- a/src/pipe/SkPipeReader.cpp
+++ b/src/pipe/SkPipeReader.cpp
@@ -310,7 +310,7 @@
 
 static void drawAtlas_handler(SkPipeReader& reader, uint32_t packedVerb, SkCanvas* canvas) {
     SkASSERT(SkPipeVerb::kDrawAtlas == unpack_verb(packedVerb));
-    SkXfermode::Mode mode = (SkXfermode::Mode)(packedVerb & kMode_DrawAtlasMask);
+    SkBlendMode mode = (SkBlendMode)(packedVerb & kMode_DrawAtlasMask);
     sk_sp<SkImage> image(reader.readImage());
     int count = reader.read32();
     const SkRSXform* xform = skip<SkRSXform>(reader, count);
@@ -433,16 +433,8 @@
     if (packedVerb & kHasTexture_DrawPatchExtraMask) {
         tex = skip<SkPoint>(reader, 4);
     }
-    sk_sp<SkXfermode> xfer;
-    unsigned mode = packedVerb & kModeEnum_DrawPatchExtraMask;
-    if (kExplicitXfer_DrawPatchExtraValue == mode) {
-        xfer = reader.readXfermode();
-    } else {
-        if (mode != SkXfermode::kSrcOver_Mode) {
-            xfer = SkXfermode::Make((SkXfermode::Mode)mode);
-        }
-    }
-    canvas->drawPatch(cubics, colors, tex, xfer.get(), read_paint(reader));
+    SkBlendMode mode = (SkBlendMode)(packedVerb & kModeEnum_DrawPatchExtraMask);
+    canvas->drawPatch(cubics, colors, tex, mode, read_paint(reader));
 }
 
 static void drawPaint_handler(SkPipeReader& reader, uint32_t packedVerb, SkCanvas* canvas) {
@@ -581,13 +573,8 @@
     if (0 == vertexCount) {
         vertexCount = reader.read32();
     }
-    sk_sp<SkXfermode> xfer;
-    unsigned xmode = (packedVerb & kXMode_DrawVerticesMask) >> kXMode_DrawVerticesShift;
-    if (0xFF == xmode) {
-        xfer = reader.readXfermode();
-    } else {
-        xfer = SkXfermode::Make((SkXfermode::Mode)xmode);
-    }
+    SkBlendMode bmode = (SkBlendMode)
+            ((packedVerb & kXMode_DrawVerticesMask) >> kXMode_DrawVerticesShift);
     const SkPoint* vertices = skip<SkPoint>(reader, vertexCount);
     const SkPoint* texs = nullptr;
     if (packedVerb & kHasTex_DrawVerticesMask) {
@@ -604,7 +591,7 @@
         indices = skip<uint16_t>(reader, indexCount);
     }
 
-    canvas->drawVertices(vmode, vertexCount, vertices, texs, colors, xfer.get(),
+    canvas->drawVertices(vmode, vertexCount, vertices, texs, colors, bmode,
                          indices, indexCount, read_paint(reader));
 }
 
diff --git a/src/svg/SkSVGDevice.cpp b/src/svg/SkSVGDevice.cpp
index 16e2b3f..b07e0aa 100644
--- a/src/svg/SkSVGDevice.cpp
+++ b/src/svg/SkSVGDevice.cpp
@@ -799,7 +799,7 @@
 
 void SkSVGDevice::drawVertices(const SkDraw&, SkCanvas::VertexMode, int vertexCount,
                                const SkPoint verts[], const SkPoint texs[],
-                               const SkColor colors[], SkXfermode* xmode,
+                               const SkColor colors[], SK_XFERMODE_PARAM xmode,
                                const uint16_t indices[], int indexCount,
                                const SkPaint& paint) {
     // todo
diff --git a/src/svg/SkSVGDevice.h b/src/svg/SkSVGDevice.h
index cb13ffd..d0b9a24 100644
--- a/src/svg/SkSVGDevice.h
+++ b/src/svg/SkSVGDevice.h
@@ -47,7 +47,7 @@
                         const SkPaint& paint) override;
     void drawVertices(const SkDraw&, SkCanvas::VertexMode, int vertexCount,
                       const SkPoint verts[], const SkPoint texs[],
-                      const SkColor colors[], SkXfermode* xmode,
+                      const SkColor colors[], SK_XFERMODE_PARAM xmode,
                       const uint16_t indices[], int indexCount,
                       const SkPaint& paint) override;
 
diff --git a/src/utils/SkDeferredCanvas.cpp b/src/utils/SkDeferredCanvas.cpp
index d2d75fe..6a6af0f 100644
--- a/src/utils/SkDeferredCanvas.cpp
+++ b/src/utils/SkDeferredCanvas.cpp
@@ -513,7 +513,7 @@
 
 void SkDeferredCanvas::onDrawAtlas(const SkImage* image, const SkRSXform xform[],
                                    const SkRect rects[], const SkColor colors[],
-                                   int count, SkXfermode::Mode mode,
+                                   int count, SK_XFERMODE_MODE_PARAM mode,
                                    const SkRect* cull, const SkPaint* paint) {
     this->flush_before_saves();
     fCanvas->drawAtlas(image, xform, rects, colors, count, mode, cull, paint);
@@ -521,7 +521,7 @@
 
 void SkDeferredCanvas::onDrawVertices(VertexMode vmode, int vertexCount,
                                   const SkPoint vertices[], const SkPoint texs[],
-                                  const SkColor colors[], SkXfermode* xmode,
+                                  const SkColor colors[], SK_XFERMODE_PARAM xmode,
                                   const uint16_t indices[], int indexCount,
                                   const SkPaint& paint) {
     this->flush_before_saves();
@@ -530,7 +530,7 @@
 }
 
 void SkDeferredCanvas::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
-                               const SkPoint texCoords[4], SkXfermode* xmode,
+                               const SkPoint texCoords[4], SK_XFERMODE_PARAM xmode,
                                const SkPaint& paint) {
     this->flush_before_saves();
     fCanvas->drawPatch(cubics, colors, texCoords, xmode, paint);
diff --git a/src/utils/SkDeferredCanvas.h b/src/utils/SkDeferredCanvas.h
index 68574ca..b48b9b6 100644
--- a/src/utils/SkDeferredCanvas.h
+++ b/src/utils/SkDeferredCanvas.h
@@ -57,7 +57,7 @@
     virtual void onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
                                 const SkPaint& paint) override;
     virtual void onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
-                             const SkPoint texCoords[4], SkXfermode* xmode,
+                             const SkPoint texCoords[4], SK_XFERMODE_PARAM xmode,
                              const SkPaint& paint) override;
 
     void onDrawPaint(const SkPaint&) override;
@@ -87,12 +87,12 @@
 
     void onDrawVertices(VertexMode vmode, int vertexCount,
                               const SkPoint vertices[], const SkPoint texs[],
-                              const SkColor colors[], SkXfermode* xmode,
+                              const SkColor colors[], SK_XFERMODE_PARAM xmode,
                               const uint16_t indices[], int indexCount,
                               const SkPaint&) override;
     void onDrawAtlas(const SkImage* image, const SkRSXform xform[],
                      const SkRect rects[], const SkColor colors[],
-                     int count, SkXfermode::Mode mode,
+                     int count, SK_XFERMODE_MODE_PARAM mode,
                      const SkRect* cull, const SkPaint* paint) override;
 
     void onClipRect(const SkRect&, ClipOp, ClipEdgeStyle) override;
diff --git a/src/utils/SkDumpCanvas.cpp b/src/utils/SkDumpCanvas.cpp
index eb56068..8b71975 100644
--- a/src/utils/SkDumpCanvas.cpp
+++ b/src/utils/SkDumpCanvas.cpp
@@ -468,7 +468,7 @@
 
 void SkDumpCanvas::onDrawVertices(VertexMode vmode, int vertexCount,
                                   const SkPoint vertices[], const SkPoint texs[],
-                                  const SkColor colors[], SkXfermode* xmode,
+                                  const SkColor colors[], SK_XFERMODE_PARAM xmode,
                                   const uint16_t indices[], int indexCount,
                                   const SkPaint& paint) {
     this->dump(kDrawVertices_Verb, &paint, "drawVertices(%s [%d] %g %g ...)",
@@ -477,7 +477,7 @@
 }
 
 void SkDumpCanvas::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
-                               const SkPoint texCoords[4], SkXfermode* xmode,
+                               const SkPoint texCoords[4], SK_XFERMODE_PARAM xmode,
                                const SkPaint& paint) {
     //dumps corner points and colors in clockwise order starting on upper-left corner
     this->dump(kDrawPatch_Verb, &paint, "drawPatch(Vertices{[%f, %f], [%f, %f], [%f, %f], [%f, %f]}\
diff --git a/src/utils/SkLua.cpp b/src/utils/SkLua.cpp
index ba311af..14f074c 100644
--- a/src/utils/SkLua.cpp
+++ b/src/utils/SkLua.cpp
@@ -573,7 +573,7 @@
         texs = texStorage;
     }
 
-    get_ref<SkCanvas>(L, 1)->drawPatch(cubics, colors, texs, nullptr, *get_obj<SkPaint>(L, 5));
+    get_ref<SkCanvas>(L, 1)->drawPatch(cubics, colors, texs, *get_obj<SkPaint>(L, 5));
     return 0;
 }
 
diff --git a/src/utils/SkLuaCanvas.cpp b/src/utils/SkLuaCanvas.cpp
index 6b769f0..10fc3b4 100644
--- a/src/utils/SkLuaCanvas.cpp
+++ b/src/utils/SkLuaCanvas.cpp
@@ -309,7 +309,7 @@
 
 void SkLuaCanvas::onDrawVertices(VertexMode vmode, int vertexCount,
                                  const SkPoint vertices[], const SkPoint texs[],
-                                 const SkColor colors[], SkXfermode* xmode,
+                                 const SkColor colors[], SK_XFERMODE_PARAM,
                                  const uint16_t indices[], int indexCount,
                                  const SkPaint& paint) {
     AUTO_LUA("drawVertices");
diff --git a/src/utils/SkMeshUtils.cpp b/src/utils/SkMeshUtils.cpp
index 27eccc2..4c9c0d0 100644
--- a/src/utils/SkMeshUtils.cpp
+++ b/src/utils/SkMeshUtils.cpp
@@ -95,7 +95,7 @@
                                          SkShader::kClamp_TileMode,
                                          SkShader::kClamp_TileMode));
         canvas->drawVertices(SkCanvas::kTriangles_VertexMode,
-                             rows * cols, verts, idx.tex(), colors, nullptr,
+                             rows * cols, verts, idx.tex(), colors, SkBlendMode::kModulate,
                              idx.indices(), idx.indexCount(), p);
     }
 }
diff --git a/src/utils/SkNWayCanvas.cpp b/src/utils/SkNWayCanvas.cpp
index e19e7a8..aa9f767 100644
--- a/src/utils/SkNWayCanvas.cpp
+++ b/src/utils/SkNWayCanvas.cpp
@@ -288,7 +288,7 @@
 
 void SkNWayCanvas::onDrawVertices(VertexMode vmode, int vertexCount,
                                   const SkPoint vertices[], const SkPoint texs[],
-                                  const SkColor colors[], SkXfermode* xmode,
+                                  const SkColor colors[], SK_XFERMODE_PARAM xmode,
                                   const uint16_t indices[], int indexCount,
                                   const SkPaint& paint) {
     Iter iter(fList);
@@ -299,7 +299,7 @@
 }
 
 void SkNWayCanvas::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
-                               const SkPoint texCoords[4], SkXfermode* xmode,
+                               const SkPoint texCoords[4], SK_XFERMODE_PARAM xmode,
                                const SkPaint& paint) {
     Iter iter(fList);
     while (iter.next()) {
diff --git a/src/utils/SkPaintFilterCanvas.cpp b/src/utils/SkPaintFilterCanvas.cpp
index 910647d..d3cc4c7 100644
--- a/src/utils/SkPaintFilterCanvas.cpp
+++ b/src/utils/SkPaintFilterCanvas.cpp
@@ -151,7 +151,7 @@
 
 void SkPaintFilterCanvas::onDrawVertices(VertexMode vmode, int vertexCount,
                                          const SkPoint vertices[], const SkPoint texs[],
-                                         const SkColor colors[], SkXfermode* xmode,
+                                         const SkColor colors[], SK_XFERMODE_PARAM xmode,
                                          const uint16_t indices[], int indexCount,
                                          const SkPaint& paint) {
     AutoPaintFilter apf(this, kVertices_Type, paint);
@@ -162,7 +162,7 @@
 }
 
 void SkPaintFilterCanvas::onDrawPatch(const SkPoint cubics[], const SkColor colors[],
-                                      const SkPoint texCoords[], SkXfermode* xmode,
+                                      const SkPoint texCoords[], SK_XFERMODE_PARAM xmode,
                                       const SkPaint& paint) {
     AutoPaintFilter apf(this, kPatch_Type, paint);
     if (apf.shouldDraw()) {
diff --git a/src/utils/SkPatchGrid.cpp b/src/utils/SkPatchGrid.cpp
index 3b7c06e..ee30ce1 100644
--- a/src/utils/SkPatchGrid.cpp
+++ b/src/utils/SkPatchGrid.cpp
@@ -8,7 +8,7 @@
 #include "SkPatchGrid.h"
 #include "SkPatchUtils.h"
 
-SkPatchGrid::SkPatchGrid(int rows, int cols, VertexType flags, SkXfermode* xfer)
+SkPatchGrid::SkPatchGrid(int rows, int cols, VertexType flags)
     : fRows(0)
     , fCols(0)
     , fModeFlags(kNone_VertexType)
@@ -17,8 +17,8 @@
     , fTexCoords(nullptr)
     , fHrzCtrlPts(nullptr)
     , fVrtCtrlPts(nullptr)
-    , fXferMode(nullptr) {
-        this->reset(rows, cols, flags, xfer);
+{
+    this->reset(rows, cols, flags, SkBlendMode::kModulate);
 }
 
 SkPatchGrid::~SkPatchGrid() {
@@ -119,7 +119,7 @@
     return true;
 }
 
-void SkPatchGrid::reset(int rows, int cols, VertexType flags, SkXfermode* xMode) {
+void SkPatchGrid::reset(int rows, int cols, VertexType flags, SkBlendMode blendmode) {
     delete[] fCornerPts;
     delete[] fCornerColors;
     delete[] fTexCoords;
@@ -129,7 +129,7 @@
     fCols = cols;
     fRows = rows;
     fModeFlags = flags;
-    fXferMode = xMode;
+    fBlendMode = blendmode;
 
     fCornerPts = new SkPoint[(fRows + 1) * (fCols + 1)];
     fHrzCtrlPts = new SkPoint[(fRows + 1) * fCols * 2];
@@ -179,7 +179,7 @@
                                             fModeFlags & kTexs_VertexType ? texCoords : nullptr,
                                             maxCols[x], maxRows[y])) {
                 canvas->drawVertices(SkCanvas::kTriangles_VertexMode, data.fVertexCount,
-                                     data.fPoints, data.fTexCoords, data.fColors, fXferMode,
+                                     data.fPoints, data.fTexCoords, data.fColors, fBlendMode,
                                      data.fIndices, data.fIndexCount, paint);
             }
         }
diff --git a/src/utils/SkPatchGrid.h b/src/utils/SkPatchGrid.h
index ca2a35b..dbb6138 100644
--- a/src/utils/SkPatchGrid.h
+++ b/src/utils/SkPatchGrid.h
@@ -87,8 +87,7 @@
         kColorsAndTexs_VertexType = 0x03
     };
 
-    SkPatchGrid(int rows = 0, int cols = 0, VertexType flags = kNone_VertexType,
-                SkXfermode* xfer = nullptr);
+    SkPatchGrid(int rows = 0, int cols = 0, VertexType flags = kNone_VertexType);
 
     ~SkPatchGrid();
 
@@ -113,7 +112,7 @@
     /**
      * Resets the grid of patches to contain rows and cols of patches.
      */
-    void reset(int rows, int cols, VertexType flags, SkXfermode* xMode);
+    void reset(int rows, int cols, VertexType flags, SkBlendMode);
 
     /**
      * Draws the grid of patches. The patches are drawn starting at patch (0,0) drawing columns, so
@@ -137,7 +136,7 @@
     SkPoint* fTexCoords;
     SkPoint* fHrzCtrlPts;
     SkPoint* fVrtCtrlPts;
-    SkXfermode* fXferMode;
+    SkBlendMode fBlendMode = SkBlendMode::kModulate;
 };
 
 
diff --git a/src/xps/SkXPSDevice.cpp b/src/xps/SkXPSDevice.cpp
index 946566c..7eb1587 100644
--- a/src/xps/SkXPSDevice.cpp
+++ b/src/xps/SkXPSDevice.cpp
@@ -1181,7 +1181,7 @@
 void SkXPSDevice::drawVertices(const SkDraw&, SkCanvas::VertexMode,
                                int vertexCount, const SkPoint verts[],
                                const SkPoint texs[], const SkColor colors[],
-                               SkXfermode* xmode, const uint16_t indices[],
+                               SK_XFERMODE_PARAM xmode, const uint16_t indices[],
                                int indexCount, const SkPaint& paint) {
     //TODO: override this for XPS
     SkDEBUGF(("XPS drawVertices not yet implemented."));
diff --git a/src/xps/SkXPSDevice.h b/src/xps/SkXPSDevice.h
index 9f660a7..1f66186 100644
--- a/src/xps/SkXPSDevice.h
+++ b/src/xps/SkXPSDevice.h
@@ -127,7 +127,7 @@
         SkCanvas::VertexMode,
         int vertexCount, const SkPoint verts[],
         const SkPoint texs[], const SkColor colors[],
-        SkXfermode* xmode,
+        SK_XFERMODE_PARAM xmode,
         const uint16_t indices[], int indexCount,
         const SkPaint& paint) override;