make SkXfermode.h go away

This is step one:
- make SkXfermode useless to public clients
- everything they should need is in SkBlendMode.h

Step two:
- remove SkXfermode.h entirely (since skia core will already be using SkXfermodePriv.h)

BUG=skia:

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

Change-Id: If2cea9f71df92430ed6644edb98dd306c5572cbc
Reviewed-on: https://skia-review.googlesource.com/4534
Commit-Queue: Mike Reed <reed@google.com>
Reviewed-by: Florin Malita <fmalita@chromium.org>
diff --git a/bench/RotatedRectBench.cpp b/bench/RotatedRectBench.cpp
index f81bfb1..d9ee582 100644
--- a/bench/RotatedRectBench.cpp
+++ b/bench/RotatedRectBench.cpp
@@ -6,6 +6,7 @@
  */
 
 #include "Benchmark.h"
+#include "SkBlendModePriv.h"
 #include "SkCanvas.h"
 #include "SkPaint.h"
 
@@ -144,7 +145,7 @@
                 fName.append("_alternating_transparent_and_opaque");
                 break;
         }
-        fName.appendf("_%s", to_lower(SkXfermode::ModeName(fMode)).c_str());
+        fName.appendf("_%s", to_lower(SkBlendMode_Name(fMode)).c_str());
     }
 
     bool        fAA;
diff --git a/bench/Xfer4fBench.cpp b/bench/Xfer4fBench.cpp
index 0e99c8c..5e679a8 100644
--- a/bench/Xfer4fBench.cpp
+++ b/bench/Xfer4fBench.cpp
@@ -8,7 +8,7 @@
 #include "Benchmark.h"
 #include "SkPM4f.h"
 #include "SkString.h"
-#include "SkXfermode.h"
+#include "SkXfermodePriv.h"
 
 #define USE_AA      (1 << 31)   // merge with Xfermode::PMFlags w/o conflict
 
diff --git a/bench/XferF16Bench.cpp b/bench/XferF16Bench.cpp
index 14505fd..bd44eff 100644
--- a/bench/XferF16Bench.cpp
+++ b/bench/XferF16Bench.cpp
@@ -8,7 +8,7 @@
 #include "Benchmark.h"
 #include "SkPM4f.h"
 #include "SkString.h"
-#include "SkXfermode.h"
+#include "SkXfermodePriv.h"
 
 #define USE_AA      (1 << 31)   // merge with Xfermode::PMFlags w/o conflict
 
diff --git a/bench/XfermodeBench.cpp b/bench/XfermodeBench.cpp
index 9e148d4..605d167 100644
--- a/bench/XfermodeBench.cpp
+++ b/bench/XfermodeBench.cpp
@@ -6,18 +6,18 @@
  */
 
 #include "Benchmark.h"
+#include "SkBlendModePriv.h"
 #include "SkCanvas.h"
 #include "SkPaint.h"
 #include "SkRandom.h"
 #include "SkString.h"
-#include "SkXfermode.h"
 
 // Benchmark that draws non-AA rects or AA text with an SkXfermode::Mode.
 class XfermodeBench : public Benchmark {
 public:
     XfermodeBench(SkBlendMode mode, bool aa) : fBlendMode(mode) {
         fAA = aa;
-        fName.printf("Xfermode_%s%s", SkXfermode::ModeName(mode), aa ? "_aa" : "");
+        fName.printf("Xfermode_%s%s", SkBlendMode_Name(mode), aa ? "_aa" : "");
     }
 
 protected:
diff --git a/gm/SkLinearBitmapPipelineGM.cpp b/gm/SkLinearBitmapPipelineGM.cpp
index f6f7c9e..13f6004 100644
--- a/gm/SkLinearBitmapPipelineGM.cpp
+++ b/gm/SkLinearBitmapPipelineGM.cpp
@@ -12,7 +12,7 @@
 #include "SkImage.h"
 #include "SkImageInfo.h"
 #include "SkLinearBitmapPipeline.h"
-#include "SkXfermode.h"
+#include "SkXfermodePriv.h"
 #include "SkPM4fPriv.h"
 #include "SkShader.h"
 
diff --git a/gm/aaxfermodes.cpp b/gm/aaxfermodes.cpp
index 7106ce8..df09a0b 100644
--- a/gm/aaxfermodes.cpp
+++ b/gm/aaxfermodes.cpp
@@ -4,14 +4,15 @@
  * Use of this source code is governed by a BSD-style license that can be
  * found in the LICENSE file.
  */
+
 #include "gm.h"
 #include "SkArithmeticMode.h"
+#include "SkBlendModePriv.h"
 #include "SkPath.h"
 #include "SkShader.h"
-#include "SkXfermode.h"
 
 enum {
-    kXfermodeCount = SkXfermode::kLastMode + 2, // All xfermodes plus arithmetic mode.
+    kXfermodeCount = (int)SkBlendMode::kLastMode + 1 + 1,   // extra for arith
     kShapeSize = 22,
     kShapeSpacing = 36,
     kShapeTypeSpacing = 4 * kShapeSpacing / 3,
@@ -62,7 +63,7 @@
         return SkISize::Make(2 * kMargin + 2 * kXfermodeTypeSpacing -
                              (kXfermodeTypeSpacing - (kLabelSpacing + 2 * kPaintSpacing)),
                              2 * kMargin + kTitleSpacing + kSubtitleSpacing +
-                             (1 + SkXfermode::kLastCoeffMode) * kShapeSpacing);
+                             (1 + (int)SkBlendMode::kLastCoeffMode) * kShapeSpacing);
     }
 
     void onOnceBeforeDraw() override {
@@ -101,7 +102,7 @@
         canvas->translate(0, kTitleSpacing);
 
         for (size_t xfermodeSet = 0; xfermodeSet < 2; xfermodeSet++) {
-            size_t firstMode = (SkXfermode::kLastCoeffMode + 1) * xfermodeSet;
+            size_t firstMode = ((size_t)SkBlendMode::kLastCoeffMode + 1) * xfermodeSet;
             canvas->save();
 
             if (kShape_Pass == drawingPass) {
@@ -117,8 +118,8 @@
 
             canvas->translate(0, kSubtitleSpacing + kShapeSpacing/2);
 
-            for (size_t m = 0; m <= SkXfermode::kLastCoeffMode; m++) {
-                if (firstMode + m > SkXfermode::kLastMode) {
+            for (size_t m = 0; m <= (size_t)SkBlendMode::kLastCoeffMode; m++) {
+                if (firstMode + m > (size_t)SkBlendMode::kLastMode) {
                     break;
                 }
                 SkBlendMode mode = static_cast<SkBlendMode>(firstMode + m);
@@ -191,7 +192,7 @@
     }
 
     void drawModeName(SkCanvas* canvas, SkBlendMode mode) {
-        const char* modeName = SkXfermode::ModeName(mode);
+        const char* modeName = SkBlendMode_Name(mode);
         fLabelPaint.setTextAlign(SkPaint::kRight_Align);
         canvas->drawText(modeName, strlen(modeName), kLabelSpacing - kShapeSize / 4,
                          fLabelPaint.getTextSize() / 4, fLabelPaint);
diff --git a/gm/gamma.cpp b/gm/gamma.cpp
index 4e80bbf..09f80dd 100644
--- a/gm/gamma.cpp
+++ b/gm/gamma.cpp
@@ -8,6 +8,7 @@
 #include "gm.h"
 
 #include "Resources.h"
+#include "SkBlendModePriv.h"
 #include "SkGradientShader.h"
 #include "SkPM4fPriv.h"
 
@@ -86,7 +87,7 @@
         SkString dstText = SkStringPrintf("%08X", dstColor);
         canvas->drawText(srcText.c_str(), srcText.size(), 0, sz + textPaint.getFontSpacing(),
                          textPaint);
-        const char* modeName = SkXfermode::ModeName(mode);
+        const char* modeName = SkBlendMode_Name(mode);
         canvas->drawText(modeName, strlen(modeName), 0, sz + 2 * textPaint.getFontSpacing(),
                          textPaint);
         canvas->drawText(dstText.c_str(), dstText.size(), 0, sz + 3 * textPaint.getFontSpacing(),
diff --git a/gm/lumafilter.cpp b/gm/lumafilter.cpp
index 3852d93..abce994 100644
--- a/gm/lumafilter.cpp
+++ b/gm/lumafilter.cpp
@@ -6,6 +6,7 @@
  */
 
 #include "gm.h"
+#include "SkBlendModePriv.h"
 #include "SkCanvas.h"
 #include "SkGradientShader.h"
 #include "SkLumaColorFilter.h"
@@ -121,7 +122,7 @@
 
         SkScalar gridStep = kSize + 2 * kInset;
         for (size_t i = 0; i < SK_ARRAY_COUNT(modes); ++i) {
-            draw_label(canvas, SkXfermode::ModeName(modes[i]),
+            draw_label(canvas, SkBlendMode_Name(modes[i]),
                        SkPoint::Make(gridStep * (0.5f + i), 20));
         }
 
diff --git a/gm/xfermodes2.cpp b/gm/xfermodes2.cpp
index 03da0d3..4d6b5e7 100644
--- a/gm/xfermodes2.cpp
+++ b/gm/xfermodes2.cpp
@@ -7,7 +7,7 @@
 #include "gm.h"
 #include "SkBitmap.h"
 #include "SkShader.h"
-#include "SkXfermode.h"
+#include "SkBlendModePriv.h"
 #include "SkColorPriv.h"
 
 namespace skiagm {
@@ -39,7 +39,7 @@
         const int W = 6;
 
         SkScalar x = 0, y = 0;
-        for (size_t m = 0; m <= SkXfermode::kLastMode; m++) {
+        for (size_t m = 0; m <= (size_t)SkBlendMode::kLastMode; m++) {
             SkBlendMode mode = static_cast<SkBlendMode>(m);
 
             canvas->save();
@@ -71,7 +71,7 @@
             canvas->restore();
 
 #if 1
-            canvas->drawText(SkXfermode::ModeName(mode), strlen(SkXfermode::ModeName(mode)),
+            canvas->drawText(SkBlendMode_Name(mode), strlen(SkBlendMode_Name(mode)),
                              x + w/2, y - labelP.getTextSize()/2, labelP);
 #endif
             x += w + SkIntToScalar(10);
diff --git a/gm/xfermodes3.cpp b/gm/xfermodes3.cpp
index 36702bf..e6ee750 100644
--- a/gm/xfermodes3.cpp
+++ b/gm/xfermodes3.cpp
@@ -9,7 +9,7 @@
 #include "SkBitmap.h"
 #include "SkGradientShader.h"
 #include "SkSurface.h"
-#include "SkXfermode.h"
+#include "SkBlendModePriv.h"
 #include "SkColorPriv.h"
 
 #if SK_SUPPORT_GPU
@@ -68,10 +68,10 @@
             {SkPaint::kStroke_Style, SkIntToScalar(kSize) / 2},
         };
         for (size_t s = 0; s < SK_ARRAY_COUNT(kStrokes); ++s) {
-            for (size_t m = 0; m <= SkXfermode::kLastMode; ++m) {
+            for (size_t m = 0; m <= (size_t)SkBlendMode::kLastMode; ++m) {
                 SkBlendMode mode = static_cast<SkBlendMode>(m);
-                canvas->drawText(SkXfermode::ModeName(mode),
-                                 strlen(SkXfermode::ModeName(mode)),
+                canvas->drawText(SkBlendMode_Name(mode),
+                                 strlen(SkBlendMode_Name(mode)),
                                  SkIntToScalar(x),
                                  SkIntToScalar(y + kSize + 3) + labelP.getTextSize(),
                                  labelP);
diff --git a/gn/android_framework_defines.gni b/gn/android_framework_defines.gni
index 90fea2f..1e61d37 100644
--- a/gn/android_framework_defines.gni
+++ b/gn/android_framework_defines.gni
@@ -15,4 +15,5 @@
   "SK_SUPPORT_LEGACY_CANVAS_IS_REFCNT",
   "SK_SUPPORT_LEGACY_CLIP_REGIONOPS",
   "SK_SUPPORT_LEGACY_SHADER_ISABITMAP",
+  "SK_SUPPORT_LEGACY_XFERMODE_IS_PUBLIC",
 ]
diff --git a/gn/core.gni b/gn/core.gni
index 60c7761..d7f1156 100644
--- a/gn/core.gni
+++ b/gn/core.gni
@@ -442,7 +442,6 @@
   "$_include/core/SkTypes.h",
   "$_include/core/SkUnPreMultiply.h",
   "$_include/core/SkWriter32.h",
-  "$_include/core/SkXfermode.h",
 
   # private
   "$_include/private/SkAtomics.h",
diff --git a/gn/tests.gni b/gn/tests.gni
index d828297..d888c6a 100644
--- a/gn/tests.gni
+++ b/gn/tests.gni
@@ -245,7 +245,6 @@
   "$_tests/WindowRectanglesTest.cpp",
   "$_tests/WritePixelsTest.cpp",
   "$_tests/Writer32Test.cpp",
-  "$_tests/XfermodeTest.cpp",
   "$_tests/YUVCacheTest.cpp",
   "$_tests/YUVTest.cpp",
 ]
diff --git a/include/core/SkMaskFilter.h b/include/core/SkMaskFilter.h
index 3498935..2d00477 100644
--- a/include/core/SkMaskFilter.h
+++ b/include/core/SkMaskFilter.h
@@ -20,7 +20,9 @@
 class GrContext;
 class GrRenderTargetContext;
 class GrPaint;
+class GrFragmentProcessor;
 class GrRenderTarget;
+class GrTexture;
 class GrTextureProvider;
 class SkBitmap;
 class SkBlitter;
diff --git a/include/core/SkXfermode.h b/include/core/SkXfermode.h
index e865e66..59f2058 100644
--- a/include/core/SkXfermode.h
+++ b/include/core/SkXfermode.h
@@ -12,6 +12,8 @@
 #include "SkColor.h"
 #include "SkFlattenable.h"
 
+#ifdef SK_SUPPORT_LEGACY_XFERMODE_IS_PUBLIC
+
 class GrFragmentProcessor;
 class GrTexture;
 class GrXPFactory;
@@ -303,3 +305,5 @@
 };
 
 #endif
+
+#endif
diff --git a/include/gpu/GrProcessorUnitTest.h b/include/gpu/GrProcessorUnitTest.h
index 075581f..3e9fe5e 100644
--- a/include/gpu/GrProcessorUnitTest.h
+++ b/include/gpu/GrProcessorUnitTest.h
@@ -17,6 +17,7 @@
 class GrContext;
 class GrRenderTargetContext;
 struct GrProcessorTestData;
+class GrTexture;
 
 namespace GrProcessorUnitTest {
 
diff --git a/include/gpu/effects/GrCustomXfermode.h b/include/gpu/effects/GrCustomXfermode.h
index 8632093..a8c868e 100644
--- a/include/gpu/effects/GrCustomXfermode.h
+++ b/include/gpu/effects/GrCustomXfermode.h
@@ -8,9 +8,11 @@
 #ifndef GrCustomXfermode_DEFINED
 #define GrCustomXfermode_DEFINED
 
-#include "SkXfermode.h"
+#include "SkBlendMode.h"
+#include "SkRefCnt.h"
 
 class GrTexture;
+class GrXPFactory;
 
 /**
  * Custom Xfer modes are used for blending when the blend mode cannot be represented using blend
diff --git a/public.bzl b/public.bzl
index 4e10012..dee0fb8 100644
--- a/public.bzl
+++ b/public.bzl
@@ -602,6 +602,7 @@
     "SK_SUPPORT_LEGACY_ACCESSBITMAP",
     "SK_SUPPORT_LEGACY_CANVAS_IS_REFCNT",
     "SK_SUPPORT_LEGACY_CLIP_REGIONOPS",
+    "SK_SUPPORT_LEGACY_XFERMODE_IS_PUBLIC",
     # Temporarily Disable analytic AA for Google3
     "SK_NO_ANALYTIC_AA",
 ]
diff --git a/samplecode/SampleFilterFuzz.cpp b/samplecode/SampleFilterFuzz.cpp
index 5f65c9f..682db92 100644
--- a/samplecode/SampleFilterFuzz.cpp
+++ b/samplecode/SampleFilterFuzz.cpp
@@ -158,7 +158,7 @@
 }
 
 static SkBlendMode make_xfermode() {
-    return static_cast<SkBlendMode>(R(SkXfermode::kLastMode+1));
+    return static_cast<SkBlendMode>(R((int)SkBlendMode::kLastMode+1));
 }
 
 static SkPaint::Align make_paint_align() {
diff --git a/src/core/SkBitmapProcShader.cpp b/src/core/SkBitmapProcShader.cpp
index 218e919..b17d3e3 100644
--- a/src/core/SkBitmapProcShader.cpp
+++ b/src/core/SkBitmapProcShader.cpp
@@ -8,6 +8,7 @@
 #include "SkBitmapProcShader.h"
 #include "SkBitmapProcState.h"
 #include "SkBitmapProvider.h"
+#include "SkXfermodePriv.h"
 
 static bool only_scale_and_translate(const SkMatrix& matrix) {
     unsigned mask = SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask;
@@ -102,7 +103,6 @@
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 #include "SkLinearBitmapPipeline.h"
 #include "SkPM4f.h"
-#include "SkXfermode.h"
 
 class LinearPipelineContext : public BitmapProcInfoContext {
 public:
diff --git a/src/core/SkBlendModePriv.h b/src/core/SkBlendModePriv.h
index 29df639..c4628fd 100644
--- a/src/core/SkBlendModePriv.h
+++ b/src/core/SkBlendModePriv.h
@@ -15,6 +15,8 @@
 bool SkBlendMode_CanOverflow(SkBlendMode);
 bool SkBlendMode_AppendStages(SkBlendMode, SkRasterPipeline* = nullptr);
 
+const char* SkBlendMode_Name(SkBlendMode);
+
 #if SK_SUPPORT_GPU
 #include "GrXferProcessor.h"
 sk_sp<GrXPFactory> SkBlendMode_AsXPFactory(SkBlendMode);
diff --git a/src/core/SkBlitter_A8.cpp b/src/core/SkBlitter_A8.cpp
index cb7d718..1fd4d5f 100644
--- a/src/core/SkBlitter_A8.cpp
+++ b/src/core/SkBlitter_A8.cpp
@@ -9,7 +9,7 @@
 #include "SkCoreBlitters.h"
 #include "SkColorPriv.h"
 #include "SkShader.h"
-#include "SkXfermode.h"
+#include "SkXfermodePriv.h"
 
 SkA8_Blitter::SkA8_Blitter(const SkPixmap& device, const SkPaint& paint) : INHERITED(device) {
     fSrcA = paint.getAlpha();
diff --git a/src/core/SkBlitter_ARGB32.cpp b/src/core/SkBlitter_ARGB32.cpp
index ea0554d..958ad27 100644
--- a/src/core/SkBlitter_ARGB32.cpp
+++ b/src/core/SkBlitter_ARGB32.cpp
@@ -9,7 +9,7 @@
 #include "SkColorPriv.h"
 #include "SkShader.h"
 #include "SkUtils.h"
-#include "SkXfermode.h"
+#include "SkXfermodePriv.h"
 #include "SkBlitMask.h"
 
 ///////////////////////////////////////////////////////////////////////////////
diff --git a/src/core/SkBlitter_PM4f.cpp b/src/core/SkBlitter_PM4f.cpp
index 2084972..ce66580 100644
--- a/src/core/SkBlitter_PM4f.cpp
+++ b/src/core/SkBlitter_PM4f.cpp
@@ -9,7 +9,7 @@
 #include "SkColorPriv.h"
 #include "SkShader.h"
 #include "SkUtils.h"
-#include "SkXfermode.h"
+#include "SkXfermodePriv.h"
 #include "SkBlitMask.h"
 #include "SkTemplates.h"
 #include "SkPM4f.h"
diff --git a/src/core/SkBlitter_RGB16.cpp b/src/core/SkBlitter_RGB16.cpp
index 7860b7c..015112a 100644
--- a/src/core/SkBlitter_RGB16.cpp
+++ b/src/core/SkBlitter_RGB16.cpp
@@ -12,7 +12,7 @@
 #include "SkShader.h"
 #include "SkUtils.h"
 #include "SkUtilsArm.h"
-#include "SkXfermode.h"
+#include "SkXfermodePriv.h"
 
 #if defined(__mips_dsp)
 extern void blitmask_d565_opaque_mips(int width, int height, uint16_t* device,
diff --git a/src/core/SkCoreBlitters.h b/src/core/SkCoreBlitters.h
index aa5deb2..23fca0f 100644
--- a/src/core/SkCoreBlitters.h
+++ b/src/core/SkCoreBlitters.h
@@ -13,6 +13,7 @@
 #include "SkBlitRow.h"
 #include "SkShader.h"
 #include "SkSmallAllocator.h"
+#include "SkXfermodePriv.h"
 
 class SkRasterBlitter : public SkBlitter {
 public:
diff --git a/src/core/SkLinearBitmapPipeline.h b/src/core/SkLinearBitmapPipeline.h
index ea78489..3e7be5c 100644
--- a/src/core/SkLinearBitmapPipeline.h
+++ b/src/core/SkLinearBitmapPipeline.h
@@ -38,7 +38,7 @@
     SkLinearBitmapPipeline(
         const SkLinearBitmapPipeline& pipeline,
         const SkPixmap& srcPixmap,
-        SkBlendMode blendMode,
+        SkBlendMode,
         const SkImageInfo& dstInfo);
 
     static bool ClonePipelineForBlitting(
diff --git a/src/core/SkOpts.h b/src/core/SkOpts.h
index ccd38ac..1d5e333 100644
--- a/src/core/SkOpts.h
+++ b/src/core/SkOpts.h
@@ -11,7 +11,7 @@
 #include "SkRasterPipeline.h"
 #include "SkTextureCompressor.h"
 #include "SkTypes.h"
-#include "SkXfermode.h"
+#include "SkXfermodePriv.h"
 #include <functional>
 
 struct ProcCoeff;
diff --git a/src/core/SkPaintPriv.cpp b/src/core/SkPaintPriv.cpp
index cbe2558..ffa818c 100644
--- a/src/core/SkPaintPriv.cpp
+++ b/src/core/SkPaintPriv.cpp
@@ -11,6 +11,7 @@
 #include "SkImage.h"
 #include "SkPaint.h"
 #include "SkShader.h"
+#include "SkXfermodePriv.h"
 
 static bool changes_alpha(const SkPaint& paint) {
     SkColorFilter* cf = paint.getColorFilter();
diff --git a/src/core/SkReadBuffer.h b/src/core/SkReadBuffer.h
index c49b01c..25928d1 100644
--- a/src/core/SkReadBuffer.h
+++ b/src/core/SkReadBuffer.h
@@ -23,7 +23,7 @@
 #include "SkShader.h"
 #include "SkTHash.h"
 #include "SkWriteBuffer.h"
-#include "SkXfermode.h"
+#include "SkXfermodePriv.h"
 
 class SkBitmap;
 class SkImage;
diff --git a/src/core/SkSpriteBlitter4f.cpp b/src/core/SkSpriteBlitter4f.cpp
index ddf044e..977a264 100644
--- a/src/core/SkSpriteBlitter4f.cpp
+++ b/src/core/SkSpriteBlitter4f.cpp
@@ -8,7 +8,7 @@
 #include "SkSpriteBlitter.h"
 #include "SkSpanProcs.h"
 #include "SkTemplates.h"
-#include "SkXfermode.h"
+#include "SkXfermodePriv.h"
 
 class Sprite_4f : public SkSpriteBlitter {
 public:
diff --git a/src/core/SkSpriteBlitter_ARGB32.cpp b/src/core/SkSpriteBlitter_ARGB32.cpp
index 1a76b1b..99856a1 100644
--- a/src/core/SkSpriteBlitter_ARGB32.cpp
+++ b/src/core/SkSpriteBlitter_ARGB32.cpp
@@ -11,7 +11,7 @@
 #include "SkColorPriv.h"
 #include "SkTemplates.h"
 #include "SkUtils.h"
-#include "SkXfermode.h"
+#include "SkXfermodePriv.h"
 
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/src/core/SkXfermode.cpp b/src/core/SkXfermode.cpp
index 64ce04d..3f3927e 100644
--- a/src/core/SkXfermode.cpp
+++ b/src/core/SkXfermode.cpp
@@ -1280,6 +1280,10 @@
     static_assert(SK_ARRAY_COUNT(gModeStrings) == kLastMode + 1, "mode_count");
 }
 
+const char* SkBlendMode_Name(SkBlendMode mode) {
+    return SkXfermode::ModeName((SkXfermode::Mode)mode);
+}
+
 #ifndef SK_IGNORE_TO_STRING
 void SkProcCoeffXfermode::toString(SkString* str) const {
     str->append("SkProcCoeffXfermode: ");
diff --git a/src/core/SkXfermode4f.cpp b/src/core/SkXfermode4f.cpp
index d5bdfe5..e9d5590 100644
--- a/src/core/SkXfermode4f.cpp
+++ b/src/core/SkXfermode4f.cpp
@@ -7,7 +7,7 @@
 
 #include "SkPM4fPriv.h"
 #include "SkUtils.h"
-#include "SkXfermode.h"
+#include "SkXfermodePriv.h"
 #include "Sk4x4f.h"
 
 static SkPM4f rgba_to_pmcolor_order(const SkPM4f& x) {
diff --git a/src/core/SkXfermodeF16.cpp b/src/core/SkXfermodeF16.cpp
index 868ee08..ece4a09 100644
--- a/src/core/SkXfermodeF16.cpp
+++ b/src/core/SkXfermodeF16.cpp
@@ -8,7 +8,7 @@
 #include "SkHalf.h"
 #include "SkPM4fPriv.h"
 #include "SkUtils.h"
-#include "SkXfermode.h"
+#include "SkXfermodePriv.h"
 
 static Sk4f lerp_by_coverage(const Sk4f& src, const Sk4f& dst, uint8_t srcCoverage) {
     return dst + (src - dst) * Sk4f(srcCoverage * (1/255.0f));
diff --git a/src/core/SkXfermodePriv.h b/src/core/SkXfermodePriv.h
new file mode 100644
index 0000000..b7d85ea
--- /dev/null
+++ b/src/core/SkXfermodePriv.h
@@ -0,0 +1,311 @@
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkXfermodePriv_DEFINED
+#define SkXfermodePriv_DEFINED
+
+#include "SkBlendMode.h"
+#include "SkColor.h"
+#include "SkFlattenable.h"
+
+#ifdef SK_SUPPORT_LEGACY_XFERMODE_IS_PUBLIC
+#include "SkXfermode.h"
+#else
+
+class GrFragmentProcessor;
+class GrTexture;
+class GrXPFactory;
+class SkRasterPipeline;
+class SkString;
+
+struct SkArithmeticParams;
+
+struct SkPM4f;
+typedef SkPM4f (*SkXfermodeProc4f)(const SkPM4f& src, const SkPM4f& dst);
+
+/** \class SkXfermode
+ *
+ *  SkXfermode is the base class for objects that are called to implement custom
+ *  "transfer-modes" in the drawing pipeline. The static function Create(Modes)
+ *  can be called to return an instance of any of the predefined subclasses as
+ *  specified in the Modes enum. When an SkXfermode is assigned to an SkPaint,
+ *  then objects drawn with that paint have the xfermode applied.
+ *
+ *  All subclasses are required to be reentrant-safe : it must be legal to share
+ *  the same instance between several threads.
+ */
+class SK_API SkXfermode : public SkFlattenable {
+public:
+    virtual void xfer32(SkPMColor dst[], const SkPMColor src[], int count,
+                        const SkAlpha aa[]) const;
+    virtual void xfer16(uint16_t dst[], const SkPMColor src[], int count,
+                        const SkAlpha aa[]) const;
+    virtual void xferA8(SkAlpha dst[], const SkPMColor src[], int count,
+                        const SkAlpha aa[]) const;
+
+    /** Enum of possible coefficients to describe some xfermodes
+     */
+    enum Coeff {
+        kZero_Coeff,    /** 0 */
+        kOne_Coeff,     /** 1 */
+        kSC_Coeff,      /** src color */
+        kISC_Coeff,     /** inverse src color (i.e. 1 - sc) */
+        kDC_Coeff,      /** dst color */
+        kIDC_Coeff,     /** inverse dst color (i.e. 1 - dc) */
+        kSA_Coeff,      /** src alpha */
+        kISA_Coeff,     /** inverse src alpha (i.e. 1 - sa) */
+        kDA_Coeff,      /** dst alpha */
+        kIDA_Coeff,     /** inverse dst alpha (i.e. 1 - da) */
+
+        kCoeffCount
+    };
+
+    /** List of predefined xfermodes.
+        The algebra for the modes uses the following symbols:
+        Sa, Sc  - source alpha and color
+        Da, Dc - destination alpha and color (before compositing)
+        [a, c] - Resulting (alpha, color) values
+        For these equations, the colors are in premultiplied state.
+        If no xfermode is specified, kSrcOver is assumed.
+        The modes are ordered by those that can be expressed as a pair of Coeffs, followed by those
+        that aren't Coeffs but have separable r,g,b computations, and finally
+        those that are not separable.
+     */
+    enum Mode {
+        kClear_Mode,    //!< [0, 0]
+        kSrc_Mode,      //!< [Sa, Sc]
+        kDst_Mode,      //!< [Da, Dc]
+        kSrcOver_Mode,  //!< [Sa + Da * (1 - Sa), Sc + Dc * (1 - Sa)]
+        kDstOver_Mode,  //!< [Da + Sa * (1 - Da), Dc + Sc * (1 - Da)]
+        kSrcIn_Mode,    //!< [Sa * Da, Sc * Da]
+        kDstIn_Mode,    //!< [Da * Sa, Dc * Sa]
+        kSrcOut_Mode,   //!< [Sa * (1 - Da), Sc * (1 - Da)]
+        kDstOut_Mode,   //!< [Da * (1 - Sa), Dc * (1 - Sa)]
+        kSrcATop_Mode,  //!< [Da, Sc * Da + Dc * (1 - Sa)]
+        kDstATop_Mode,  //!< [Sa, Dc * Sa + Sc * (1 - Da)]
+        kXor_Mode,      //!< [Sa + Da - 2 * Sa * Da, Sc * (1 - Da) + Dc * (1 - Sa)]
+        kPlus_Mode,     //!< [Sa + Da, Sc + Dc]
+        kModulate_Mode, // multiplies all components (= alpha and color)
+
+        // Following blend modes are defined in the CSS Compositing standard:
+        // https://dvcs.w3.org/hg/FXTF/rawfile/tip/compositing/index.html#blending
+        kScreen_Mode,
+        kLastCoeffMode = kScreen_Mode,
+
+        kOverlay_Mode,
+        kDarken_Mode,
+        kLighten_Mode,
+        kColorDodge_Mode,
+        kColorBurn_Mode,
+        kHardLight_Mode,
+        kSoftLight_Mode,
+        kDifference_Mode,
+        kExclusion_Mode,
+        kMultiply_Mode,
+        kLastSeparableMode = kMultiply_Mode,
+
+        kHue_Mode,
+        kSaturation_Mode,
+        kColor_Mode,
+        kLuminosity_Mode,
+        kLastMode = kLuminosity_Mode
+    };
+
+    /**
+     * Gets the name of the Mode as a string.
+     */
+    static const char* ModeName(Mode);
+    static const char* ModeName(SkBlendMode mode) {
+        return ModeName(Mode(mode));
+    }
+
+    /**
+     *  If the xfermode is one of the modes in the Mode enum, then asMode()
+     *  returns true and sets (if not null) mode accordingly. Otherwise it
+     *  returns false and ignores the mode parameter.
+     */
+    virtual bool asMode(Mode* mode) const;
+
+    /**
+     *  The same as calling xfermode->asMode(mode), except that this also checks
+     *  if the xfermode is NULL, and if so, treats it as kSrcOver_Mode.
+     */
+    static bool AsMode(const SkXfermode*, Mode* mode);
+    static bool AsMode(const sk_sp<SkXfermode>& xfer, Mode* mode) {
+        return AsMode(xfer.get(), mode);
+    }
+
+    /**
+     *  Returns true if the xfermode claims to be the specified Mode. This works
+     *  correctly even if the xfermode is NULL (which equates to kSrcOver.) Thus
+     *  you can say this without checking for a null...
+     *
+     *  If (SkXfermode::IsMode(paint.getXfermode(),
+     *                         SkXfermode::kDstOver_Mode)) {
+     *      ...
+     *  }
+     */
+    static bool IsMode(const SkXfermode* xfer, Mode mode);
+    static bool IsMode(const sk_sp<SkXfermode>& xfer, Mode mode) {
+        return IsMode(xfer.get(), mode);
+    }
+
+    /** Return an SkXfermode object for the specified mode.
+     */
+    static sk_sp<SkXfermode> Make(SkBlendMode);
+    static sk_sp<SkXfermode> Make(Mode m) { return Make((SkBlendMode)m); }
+
+    /**
+     *  Skia maintains global xfermode objects corresponding to each BlendMode. This returns a
+     *  ptr to that global xfermode (or null if the mode is srcover). Thus the caller may use
+     *  the returned ptr, but it should leave its refcnt untouched.
+     */
+    static SkXfermode* Peek(SkBlendMode mode) {
+        sk_sp<SkXfermode> xfer = Make(mode);
+        if (!xfer) {
+            SkASSERT(SkBlendMode::kSrcOver == mode);
+            return nullptr;
+        }
+        SkASSERT(!xfer->unique());
+        return xfer.get();
+    }
+
+    SkBlendMode blend() const {
+        Mode mode;
+        SkAssertResult(this->asMode(&mode));
+        return (SkBlendMode)mode;
+    }
+
+    static SkXfermodeProc GetProc(SkBlendMode);
+    static SkXfermodeProc4f GetProc4f(SkBlendMode);
+
+    /**
+     *  If the specified mode can be represented by a pair of Coeff, then return
+     *  true and set (if not NULL) the corresponding coeffs. If the mode is
+     *  not representable as a pair of Coeffs, return false and ignore the
+     *  src and dst parameters.
+     */
+    static bool ModeAsCoeff(Mode mode, Coeff* src, Coeff* dst);
+    static bool ModeAsCoeff(SkBlendMode mode, Coeff* src, Coeff* dst) {
+        return ModeAsCoeff((Mode)mode, src, dst);
+    }
+
+    /**
+     * Returns whether or not the xfer mode can support treating coverage as alpha
+     */
+    virtual bool supportsCoverageAsAlpha() const;
+
+    /**
+     *  The same as calling xfermode->supportsCoverageAsAlpha(), except that this also checks if
+     *  the xfermode is NULL, and if so, treats it as kSrcOver_Mode.
+     */
+    static bool SupportsCoverageAsAlpha(const SkXfermode* xfer);
+    static bool SupportsCoverageAsAlpha(const sk_sp<SkXfermode>& xfer) {
+        return SupportsCoverageAsAlpha(xfer.get());
+    }
+
+    enum SrcColorOpacity {
+        // The src color is known to be opaque (alpha == 255)
+        kOpaque_SrcColorOpacity = 0,
+        // The src color is known to be fully transparent (color == 0)
+        kTransparentBlack_SrcColorOpacity = 1,
+        // The src alpha is known to be fully transparent (alpha == 0)
+        kTransparentAlpha_SrcColorOpacity = 2,
+        // The src color opacity is unknown
+        kUnknown_SrcColorOpacity = 3
+    };
+
+    /**
+     * Returns whether or not the result of the draw with the xfer mode will be opaque or not. The
+     * input to this call is an enum describing known information about the opacity of the src color
+     * that will be given to the xfer mode.
+     */
+    virtual bool isOpaque(SrcColorOpacity opacityType) const;
+
+    /**
+     *  The same as calling xfermode->isOpaque(...), except that this also checks if
+     *  the xfermode is NULL, and if so, treats it as kSrcOver_Mode.
+     */
+    static bool IsOpaque(const SkXfermode* xfer, SrcColorOpacity opacityType);
+    static bool IsOpaque(const sk_sp<SkXfermode>& xfer, SrcColorOpacity opacityType) {
+        return IsOpaque(xfer.get(), opacityType);
+    }
+    static bool IsOpaque(SkBlendMode, SrcColorOpacity);
+
+#if SK_SUPPORT_GPU
+    /** Used by the SkXfermodeImageFilter to blend two colors via a GrFragmentProcessor.
+        The input to the returned FP is the src color. The dst color is
+        provided by the dst param which becomes a child FP of the returned FP.
+        It is legal for the function to return a null output. This indicates that
+        the output of the blend is simply the src color.
+     */
+    virtual sk_sp<GrFragmentProcessor> makeFragmentProcessorForImageFilter(
+                                                            sk_sp<GrFragmentProcessor> dst) const;
+
+    /** A subclass must implement this factory function to work with the GPU backend.
+        The xfermode will return a factory for which the caller will get a ref. It is up
+        to the caller to install it. XferProcessors cannot use a background texture.
+      */
+    virtual sk_sp<GrXPFactory> asXPFactory() const;
+#endif
+
+    SK_TO_STRING_PUREVIRT()
+    SK_DECLARE_FLATTENABLE_REGISTRAR_GROUP()
+    SK_DEFINE_FLATTENABLE_TYPE(SkXfermode)
+
+    enum D32Flags {
+        kSrcIsOpaque_D32Flag  = 1 << 0,
+        kSrcIsSingle_D32Flag  = 1 << 1,
+        kDstIsSRGB_D32Flag    = 1 << 2,
+    };
+    typedef void (*D32Proc)(SkBlendMode, uint32_t dst[], const SkPM4f src[],
+                            int count, const SkAlpha coverage[]);
+    static D32Proc GetD32Proc(SkBlendMode, uint32_t flags);
+
+    enum F16Flags {
+        kSrcIsOpaque_F16Flag  = 1 << 0,
+        kSrcIsSingle_F16Flag  = 1 << 1,
+    };
+    typedef void (*F16Proc)(SkBlendMode, uint64_t dst[], const SkPM4f src[], int count,
+                            const SkAlpha coverage[]);
+    static F16Proc GetF16Proc(SkBlendMode, uint32_t flags);
+
+    enum LCDFlags {
+        kSrcIsOpaque_LCDFlag    = 1 << 0,   // else src(s) may have alpha < 1
+        kSrcIsSingle_LCDFlag    = 1 << 1,   // else src[count]
+        kDstIsSRGB_LCDFlag      = 1 << 2,   // else l32 or f16
+    };
+    typedef void (*LCD32Proc)(uint32_t* dst, const SkPM4f* src, int count, const uint16_t lcd[]);
+    typedef void (*LCDF16Proc)(uint64_t* dst, const SkPM4f* src, int count, const uint16_t lcd[]);
+    static LCD32Proc GetLCD32Proc(uint32_t flags);
+    static LCDF16Proc GetLCDF16Proc(uint32_t) { return nullptr; }
+
+    virtual bool isArithmetic(SkArithmeticParams*) const { return false; }
+
+protected:
+    SkXfermode() {}
+    /** The default implementation of xfer32/xfer16/xferA8 in turn call this
+        method, 1 color at a time (upscaled to a SkPMColor). The default
+        implementation of this method just returns dst. If performance is
+        important, your subclass should override xfer32/xfer16/xferA8 directly.
+
+        This method will not be called directly by the client, so it need not
+        be implemented if your subclass has overridden xfer32/xfer16/xferA8
+    */
+    virtual SkPMColor xferColor(SkPMColor src, SkPMColor dst) const;
+
+private:
+    enum {
+        kModeCount = kLastMode + 1
+    };
+
+    typedef SkFlattenable INHERITED;
+};
+
+#endif
+
+#endif
diff --git a/src/effects/SkArithmeticModePriv.h b/src/effects/SkArithmeticModePriv.h
index ca469a7..5cb1093 100644
--- a/src/effects/SkArithmeticModePriv.h
+++ b/src/effects/SkArithmeticModePriv.h
@@ -10,6 +10,8 @@
 
 #include "SkArithmeticMode.h"
 
+class SkXfermode;
+
 struct SkArithmeticParams {
     float fK[4];
     bool fEnforcePMColor;
diff --git a/src/gpu/SkGrPriv.h b/src/gpu/SkGrPriv.h
index ecbe558..bd1d715 100644
--- a/src/gpu/SkGrPriv.h
+++ b/src/gpu/SkGrPriv.h
@@ -12,7 +12,7 @@
 #include "GrBlend.h"
 #include "SkImageInfo.h"
 #include "SkMatrix.h"
-#include "SkXfermode.h"
+#include "SkXfermodePriv.h"
 
 class GrCaps;
 class GrContext;
diff --git a/src/gpu/effects/GrCustomXfermode.cpp b/src/gpu/effects/GrCustomXfermode.cpp
index 3895f57..8a54d44 100644
--- a/src/gpu/effects/GrCustomXfermode.cpp
+++ b/src/gpu/effects/GrCustomXfermode.cpp
@@ -384,8 +384,8 @@
 
 GR_DEFINE_XP_FACTORY_TEST(CustomXPFactory);
 sk_sp<GrXPFactory> CustomXPFactory::TestCreate(GrProcessorTestData* d) {
-    int mode = d->fRandom->nextRangeU(SkXfermode::kLastCoeffMode + 1,
-                                      SkXfermode::kLastSeparableMode);
+    int mode = d->fRandom->nextRangeU((int)SkBlendMode::kLastCoeffMode + 1,
+                                      (int)SkBlendMode::kLastSeparableMode);
 
     return sk_sp<GrXPFactory>(new CustomXPFactory(static_cast<SkBlendMode>(mode)));
 }
diff --git a/src/gpu/effects/GrPorterDuffXferProcessor.cpp b/src/gpu/effects/GrPorterDuffXferProcessor.cpp
index d511fae..ff95dac 100644
--- a/src/gpu/effects/GrPorterDuffXferProcessor.cpp
+++ b/src/gpu/effects/GrPorterDuffXferProcessor.cpp
@@ -227,7 +227,7 @@
  * with and without an opaque input color. Optimization properties are deduced at compile time so we
  * can make runtime decisions quickly. RGB coverage is not supported.
  */
-static const BlendFormula gBlendTable[2][2][SkXfermode::kLastCoeffMode + 1] = {
+static const BlendFormula gBlendTable[2][2][(int)SkBlendMode::kLastCoeffMode + 1] = {
 
                      /*>> No coverage, input color unknown <<*/ {{
 
@@ -302,7 +302,7 @@
     /* screen */     COEFF_FORMULA(   kOne_GrBlendCoeff,    kISC_GrBlendCoeff),
 }}};
 
-static const BlendFormula gLCDBlendTable[SkXfermode::kLastCoeffMode + 1] = {
+static const BlendFormula gLCDBlendTable[(int)SkBlendMode::kLastCoeffMode + 1] = {
     /* clear */      COVERAGE_SRC_COEFF_ZERO_FORMULA(BlendFormula::kCoverage_OutputType),
     /* src */        COVERAGE_FORMULA(BlendFormula::kCoverage_OutputType, kOne_GrBlendCoeff),
     /* dst */        NO_DST_WRITE_FORMULA,
diff --git a/src/gpu/glsl/GrGLSLBlend.cpp b/src/gpu/glsl/GrGLSLBlend.cpp
index 73a145b..da73b66 100644
--- a/src/gpu/glsl/GrGLSLBlend.cpp
+++ b/src/gpu/glsl/GrGLSLBlend.cpp
@@ -4,8 +4,10 @@
  * Use of this source code is governed by a BSD-style license that can be
  * found in the LICENSE file.
  */
+
 #include "GrGLSLBlend.h"
 #include "glsl/GrGLSLFragmentShaderBuilder.h"
+#include "SkXfermodePriv.h"
 
 //////////////////////////////////////////////////////////////////////////////
 //  Advanced (non-coeff) blend helpers
diff --git a/tests/BlendTest.cpp b/tests/BlendTest.cpp
index ca9e46e..cd5e8ef 100644
--- a/tests/BlendTest.cpp
+++ b/tests/BlendTest.cpp
@@ -67,36 +67,3 @@
     };
     for (auto multiply : perfect) { REPORTER_ASSERT(r, test(multiply).diffs == 0); }
 }
-
-DEF_TEST(Blend_premul_begets_premul, r) {
-    // This test is quite slow, even if you have enough cores to run each mode in parallel.
-    if (!r->allowExtendedTest()) {
-        return;
-    }
-
-    // No matter what xfermode we use, premul inputs should create premul outputs.
-    auto test_mode = [&](int m) {
-        SkXfermode::Mode mode = (SkXfermode::Mode)m;
-        if (mode == SkXfermode::kSrcOver_Mode) {
-            return;  // TODO: can't create a SrcOver xfermode.
-        }
-        auto xfermode(SkXfermode::Make(mode));
-        SkASSERT(xfermode);
-        // We'll test all alphas and legal color values, assuming all colors work the same.
-        // This is not true for non-separable blend modes, but this test still can't hurt.
-        for (int sa = 0; sa <= 255; sa++) {
-        for (int da = 0; da <= 255; da++) {
-        for (int  s = 0;  s <= sa;   s++) {
-        for (int  d = 0;  d <= da;   d++) {
-            SkPMColor src = SkPackARGB32(sa, s, s, s),
-                      dst = SkPackARGB32(da, d, d, d);
-            xfermode->xfer32(&dst, &src, 1, nullptr);  // To keep it simple, no AA.
-            if (!SkPMColorValid(dst)) {
-                ERRORF(r, "%08x is not premul using %s", dst, SkXfermode::ModeName(mode));
-            }
-        }}}}
-    };
-
-    // Parallelism helps speed things up on my desktop from ~725s to ~50s.
-    SkTaskGroup().batch(SkXfermode::kLastMode, test_mode);
-}
diff --git a/tests/RecordingXfermodeTest.cpp b/tests/RecordingXfermodeTest.cpp
index 32aec36..db4262c 100644
--- a/tests/RecordingXfermodeTest.cpp
+++ b/tests/RecordingXfermodeTest.cpp
@@ -12,6 +12,7 @@
 #include "../include/core/SkStream.h"
 #include "../include/core/SkString.h"
 #include "../include/core/SkPictureRecorder.h"
+#include "../src/core/SkBlendModePriv.h"
 #include <cstring>
 
 // Verify that replay of a recording into a clipped canvas
@@ -160,7 +161,7 @@
         if (memcmp(goldenBM.getPixels(), pictureBM.getPixels(), pixelsSize)) {
             numErrors++;
             errors.appendf("For SkXfermode %d %s:    SkPictureRecorder bitmap is wrong\n",
-                           iMode, SkXfermode::ModeName(mode));
+                           iMode, SkBlendMode_Name(mode));
         }
 #endif
     }
diff --git a/tests/SkColor4fTest.cpp b/tests/SkColor4fTest.cpp
index 028b99f..f268e5f 100644
--- a/tests/SkColor4fTest.cpp
+++ b/tests/SkColor4fTest.cpp
@@ -23,15 +23,6 @@
     return fabsf(a - b) <= tol;
 }
 
-static bool nearly_equal(const SkPM4f a, const SkPM4f& b, float tol = kTolerance) {
-    for (int i = 0; i < 4; ++i) {
-        if (!nearly_equal(a.fVec[i], b.fVec[i], tol)) {
-            return false;
-        }
-    }
-    return true;
-}
-
 DEF_TEST(SkColor4f_FromColor, reporter) {
     const struct {
         SkColor     fC;
@@ -75,45 +66,3 @@
         REPORTER_ASSERT(reporter, nearly_equal(pm4.b(), c4.fA * c4.fB));
     }
 }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-typedef SkPM4f (*SkXfermodeProc4f)(const SkPM4f& src, const SkPM4f& dst);
-
-static bool compare_procs(SkXfermodeProc proc32, SkXfermodeProc4f proc4f) {
-    const float kTolerance = 1.0f / 255;
-
-    const SkColor colors[] = {
-        0, 0xFF000000, 0xFFFFFFFF, 0x80FF0000
-    };
-
-    for (auto s32 : colors) {
-        SkPMColor s_pm32 = SkPreMultiplyColor(s32);
-        SkPM4f    s_pm4f = SkColor4f::FromColor(s32).premul();
-        for (auto d32 : colors) {
-            SkPMColor d_pm32 = SkPreMultiplyColor(d32);
-            SkPM4f    d_pm4f = SkColor4f::FromColor(d32).premul();
-
-            SkPMColor r32 = proc32(s_pm32, d_pm32);
-            SkPM4f    r4f = proc4f(s_pm4f, d_pm4f);
-
-            SkPM4f r32_4f = SkPM4f::FromPMColor(r32);
-            if (!nearly_equal(r4f, r32_4f, kTolerance)) {
-                return false;
-            }
-        }
-    }
-    return true;
-}
-
-// Check that our Proc and Proc4f return (nearly) the same results
-//
-DEF_TEST(Color4f_xfermode_proc4f, reporter) {
-    // TODO: extend xfermodes so that all cases can be tested.
-    //
-    for (int mode = (int)SkBlendMode::kClear; mode <= (int)SkBlendMode::kScreen; ++mode) {
-        SkXfermodeProc   proc32 = SkXfermode::GetProc((SkBlendMode)mode);
-        SkXfermodeProc4f proc4f = SkXfermode::GetProc4f((SkBlendMode)mode);
-        REPORTER_ASSERT(reporter, compare_procs(proc32, proc4f));
-    }
-}
diff --git a/tests/XfermodeTest.cpp b/tests/XfermodeTest.cpp
deleted file mode 100644
index c3a4d96..0000000
--- a/tests/XfermodeTest.cpp
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright 2011 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "SkColor.h"
-#include "SkXfermode.h"
-#include "Test.h"
-
-#define ILLEGAL_MODE    ((SkXfermode::Mode)-1)
-
-static void test_asMode(skiatest::Reporter* reporter) {
-    for (int mode = 0; mode <= SkXfermode::kLastMode; mode++) {
-        auto xfer = SkXfermode::Make((SkXfermode::Mode) mode);
-
-        SkXfermode::Mode reportedMode = ILLEGAL_MODE;
-        REPORTER_ASSERT(reporter, reportedMode != mode);
-
-        // test IsMode
-        REPORTER_ASSERT(reporter, SkXfermode::AsMode(xfer, &reportedMode));
-        REPORTER_ASSERT(reporter, reportedMode == mode);
-
-        // repeat that test, but with asMode instead
-        if (xfer) {
-            reportedMode = (SkXfermode::Mode) -1;
-            REPORTER_ASSERT(reporter, xfer->asMode(&reportedMode));
-            REPORTER_ASSERT(reporter, reportedMode == mode);
-        } else {
-            REPORTER_ASSERT(reporter, SkXfermode::kSrcOver_Mode == mode);
-        }
-    }
-}
-
-static void test_IsMode(skiatest::Reporter* reporter) {
-    REPORTER_ASSERT(reporter, SkXfermode::IsMode(nullptr,
-                                                 SkXfermode::kSrcOver_Mode));
-
-    for (int i = 0; i <= SkXfermode::kLastMode; ++i) {
-        SkXfermode::Mode mode = (SkXfermode::Mode)i;
-
-        auto xfer = SkXfermode::Make(mode);
-        REPORTER_ASSERT(reporter, SkXfermode::IsMode(xfer, mode));
-
-        if (SkXfermode::kSrcOver_Mode != mode) {
-            REPORTER_ASSERT(reporter, !SkXfermode::IsMode(nullptr, mode));
-        }
-    }
-}
-
-DEF_TEST(Xfermode, reporter) {
-    test_asMode(reporter);
-    test_IsMode(reporter);
-}