Use new DlBlendMode Object (#32026)

diff --git a/display_list/BUILD.gn b/display_list/BUILD.gn
index 5997190..1f6366c 100644
--- a/display_list/BUILD.gn
+++ b/display_list/BUILD.gn
@@ -9,6 +9,8 @@
     "display_list.cc",
     "display_list.h",
     "display_list_attributes.h",
+    "display_list_blend_mode.cc",
+    "display_list_blend_mode.h",
     "display_list_builder.cc",
     "display_list_builder.h",
     "display_list_canvas_dispatcher.cc",
diff --git a/display_list/display_list_benchmarks.cc b/display_list/display_list_benchmarks.cc
index ee41cd1..e34b1a0 100644
--- a/display_list/display_list_benchmarks.cc
+++ b/display_list/display_list_benchmarks.cc
@@ -802,7 +802,7 @@
     sk_sp<SkVertices> vertices =
         GetTestVertices(p, radius, 50, mode, vertex_count);
     total_vertex_count += vertex_count;
-    builder.drawVertices(vertices, SkBlendMode::kSrc);
+    builder.drawVertices(vertices, DlBlendMode::kSrc);
   }
 
   state.counters["VertexCount"] = total_vertex_count;
diff --git a/display_list/display_list_blend_mode.cc b/display_list/display_list_blend_mode.cc
new file mode 100644
index 0000000..a8f2425
--- /dev/null
+++ b/display_list/display_list_blend_mode.cc
@@ -0,0 +1,7 @@
+// Copyright 2013 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "flutter/display_list/display_list_blend_mode.h"
+
+namespace flutter {}  // namespace flutter
diff --git a/display_list/display_list_blend_mode.h b/display_list/display_list_blend_mode.h
new file mode 100644
index 0000000..32753da
--- /dev/null
+++ b/display_list/display_list_blend_mode.h
@@ -0,0 +1,78 @@
+// Copyright 2013 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef FLUTTER_DISPLAY_LIST_DISPLAY_LIST_BLEND_MODE_H_
+#define FLUTTER_DISPLAY_LIST_DISPLAY_LIST_BLEND_MODE_H_
+
+#include "include/core/SkBlender.h"
+
+namespace flutter {
+
+/// A enum define the blend mode.
+/// Blends are operators that take in two colors (source, destination) and
+/// return a new color. Blends are operators that take in two colors (source,
+/// destination) and return a new color. Many of these operate the same on all 4
+/// components: red, green, blue, alpha. For these, we just document what
+/// happens to one component, rather than naming each one separately. Different
+/// SkColorTypes have different representations for color components:
+///     8-bit: 0..255
+///     6-bit: 0..63
+///     5-bit: 0..31
+///     4-bit: 0..15
+///    floats: 0...1
+/// The documentation is expressed as if the component values are always 0..1
+/// (floats). For brevity, the documentation uses the following abbreviations s
+/// : source d  : destination sa : source alpha da : destination alpha Results
+/// are abbreviated r  : if all 4 components are computed in the same manner ra
+/// : result alpha component rc : result "color": red, green, blue components
+enum class DlBlendMode {
+  kClear,     //!< r = 0
+  kSrc,       //!< r = s
+  kDst,       //!< r = d
+  kSrcOver,   //!< r = s + (1-sa)*d
+  kDstOver,   //!< r = d + (1-da)*s
+  kSrcIn,     //!< r = s * da
+  kDstIn,     //!< r = d * sa
+  kSrcOut,    //!< r = s * (1-da)
+  kDstOut,    //!< r = d * (1-sa)
+  kSrcATop,   //!< r = s*da + d*(1-sa)
+  kDstATop,   //!< r = d*sa + s*(1-da)
+  kXor,       //!< r = s*(1-da) + d*(1-sa)
+  kPlus,      //!< r = min(s + d, 1)
+  kModulate,  //!< r = s*d
+  kScreen,    //!< r = s + d - s*d
+
+  kOverlay,     //!< multiply or screen, depending on destination
+  kDarken,      //!< rc = s + d - max(s*da, d*sa), ra = kSrcOver
+  kLighten,     //!< rc = s + d - min(s*da, d*sa), ra = kSrcOver
+  kColorDodge,  //!< brighten destination to reflect source
+  kColorBurn,   //!< darken destination to reflect source
+  kHardLight,   //!< multiply or screen, depending on source
+  kSoftLight,   //!< lighten or darken, depending on source
+  kDifference,  //!< rc = s + d - 2*(min(s*da, d*sa)), ra = kSrcOver
+  kExclusion,   //!< rc = s + d - two(s*d), ra = kSrcOver
+  kMultiply,    //!< r = s*(1-da) + d*(1-sa) + s*d
+
+  kHue,         //!< hue of source with saturation and luminosity of destination
+  kSaturation,  //!< saturation of source with hue and luminosity of destination
+  kColor,       //!< hue and saturation of source with luminosity of destination
+  kLuminosity,  //!< luminosity of source with hue and saturation of destination
+
+  kLastCoeffMode = kScreen,  //!< last porter duff blend mode
+  kLastSeparableMode =
+      kMultiply,  //!< last blend mode operating separately on components
+  kLastMode = kLuminosity,  //!< last valid value
+};
+
+inline DlBlendMode ToDl(SkBlendMode mode) {
+  return static_cast<DlBlendMode>(mode);
+}
+
+inline SkBlendMode ToSk(DlBlendMode mode) {
+  return static_cast<SkBlendMode>(mode);
+}
+
+}  // namespace flutter
+
+#endif  // FLUTTER_DISPLAY_LIST_DISPLAY_LIST_BLEND_MODE_H_
diff --git a/display_list/display_list_builder.cc b/display_list/display_list_builder.cc
index 0d4f3bb..be2f60b 100644
--- a/display_list/display_list_builder.cc
+++ b/display_list/display_list_builder.cc
@@ -4,6 +4,7 @@
 
 #include "flutter/display_list/display_list_builder.h"
 
+#include "flutter/display_list/display_list_blend_mode.h"
 #include "flutter/display_list/display_list_ops.h"
 
 namespace flutter {
@@ -103,7 +104,7 @@
 void DisplayListBuilder::onSetColor(SkColor color) {
   Push<SetColorOp>(0, 0, current_color_ = color);
 }
-void DisplayListBuilder::onSetBlendMode(SkBlendMode mode) {
+void DisplayListBuilder::onSetBlendMode(DlBlendMode mode) {
   current_blender_ = nullptr;
   Push<SetBlendModeOp>(0, 0, current_blend_mode_ = mode);
   UpdateCurrentOpacityCompatibility();
@@ -115,7 +116,7 @@
   SkPaint p;
   p.setBlender(blender);
   if (p.asBlendMode()) {
-    setBlendMode(p.asBlendMode().value());
+    setBlendMode(ToDl(p.asBlendMode().value()));
   } else {
     // |current_blender_| supersedes any value of |current_blend_mode_|
     (current_blender_ = blender)  //
@@ -263,7 +264,7 @@
   if (flags.applies_blend()) {
     std::optional<SkBlendMode> mode_optional = paint.asBlendMode();
     if (mode_optional) {
-      setBlendMode(mode_optional.value());
+      setBlendMode(ToDl(mode_optional.value()));
     } else {
       setBlender(sk_ref_sp(paint.getBlender()));
     }
@@ -479,7 +480,7 @@
   Push<DrawPaintOp>(0, 1);
   CheckLayerOpacityCompatibility();
 }
-void DisplayListBuilder::drawColor(SkColor color, SkBlendMode mode) {
+void DisplayListBuilder::drawColor(SkColor color, DlBlendMode mode) {
   Push<DrawColorOp>(0, 1, color, mode);
   CheckLayerOpacityCompatibility(mode);
 }
@@ -559,7 +560,7 @@
   UpdateLayerOpacityCompatibility(false);
 }
 void DisplayListBuilder::drawVertices(const sk_sp<SkVertices> vertices,
-                                      SkBlendMode mode) {
+                                      DlBlendMode mode) {
   Push<DrawVerticesOp>(0, 1, std::move(vertices), mode);
   // DrawVertices applies its colors to the paint so we have no way
   // of controlling opacity using the current paint attributes.
@@ -625,7 +626,7 @@
                                    const SkRect tex[],
                                    const SkColor colors[],
                                    int count,
-                                   SkBlendMode mode,
+                                   DlBlendMode mode,
                                    const SkSamplingOptions& sampling,
                                    const SkRect* cull_rect,
                                    bool render_with_attributes) {
diff --git a/display_list/display_list_builder.h b/display_list/display_list_builder.h
index 791105f..4c6ed0a 100644
--- a/display_list/display_list_builder.h
+++ b/display_list/display_list_builder.h
@@ -6,6 +6,7 @@
 #define FLUTTER_DISPLAY_LIST_DISPLAY_LIST_BUILDER_H_
 
 #include "flutter/display_list/display_list.h"
+#include "flutter/display_list/display_list_blend_mode.h"
 #include "flutter/display_list/display_list_comparable.h"
 #include "flutter/display_list/display_list_dispatcher.h"
 #include "flutter/display_list/display_list_flags.h"
@@ -72,14 +73,14 @@
       onSetColor(color);
     }
   }
-  void setBlendMode(SkBlendMode mode) override {
+  void setBlendMode(DlBlendMode mode) override {
     if (current_blender_ || current_blend_mode_ != mode) {
       onSetBlendMode(mode);
     }
   }
   void setBlender(sk_sp<SkBlender> blender) override {
     if (!blender) {
-      setBlendMode(SkBlendMode::kSrcOver);
+      setBlendMode(DlBlendMode::kSrcOver);
     } else if (current_blender_ != blender) {
       onSetBlender(std::move(blender));
     }
@@ -125,7 +126,7 @@
     return current_color_filter_;
   }
   bool isInvertColors() const { return current_invert_colors_; }
-  std::optional<SkBlendMode> getBlendMode() const {
+  std::optional<DlBlendMode> getBlendMode() const {
     if (current_blender_) {
       // The setters will turn "Mode" style blenders into "blend_mode"s
       return {};
@@ -134,7 +135,7 @@
   }
   sk_sp<SkBlender> getBlender() const {
     return current_blender_ ? current_blender_
-                            : SkBlender::Mode(current_blend_mode_);
+                            : SkBlender::Mode(ToSk(current_blend_mode_));
   }
   sk_sp<SkPathEffect> getPathEffect() const { return current_path_effect_; }
   std::shared_ptr<const DlMaskFilter> getMaskFilter() const {
@@ -184,7 +185,7 @@
   void clipPath(const SkPath& path, SkClipOp clip_op, bool is_aa) override;
 
   void drawPaint() override;
-  void drawColor(SkColor color, SkBlendMode mode) override;
+  void drawColor(SkColor color, DlBlendMode mode) override;
   void drawLine(const SkPoint& p0, const SkPoint& p1) override;
   void drawRect(const SkRect& rect) override;
   void drawOval(const SkRect& bounds) override;
@@ -200,7 +201,7 @@
                   uint32_t count,
                   const SkPoint pts[]) override;
   void drawVertices(const sk_sp<SkVertices> vertices,
-                    SkBlendMode mode) override;
+                    DlBlendMode mode) override;
   void drawImage(const sk_sp<SkImage> image,
                  const SkPoint point,
                  const SkSamplingOptions& sampling,
@@ -228,7 +229,7 @@
                  const SkRect tex[],
                  const SkColor colors[],
                  int count,
-                 SkBlendMode mode,
+                 DlBlendMode mode,
                  const SkSamplingOptions& sampling,
                  const SkRect* cullRect,
                  bool render_with_attributes) override;
@@ -322,8 +323,8 @@
   // in the future to include other (rarely used) modes that also modulate
   // the opacity of a rendering operation at the cost of a switch statement
   // or lookup table.
-  static bool IsOpacityCompatible(SkBlendMode mode) {
-    return (mode == SkBlendMode::kSrcOver);
+  static bool IsOpacityCompatible(DlBlendMode mode) {
+    return (mode == DlBlendMode::kSrcOver);
   }
 
   void UpdateCurrentOpacityCompatibility() {
@@ -363,7 +364,7 @@
   // Check for opacity compatibility for an op that ignores the current
   // attributes and uses the indicated blend |mode| to render to the layer.
   // This is only used by |drawColor| currently.
-  void CheckLayerOpacityCompatibility(SkBlendMode mode) {
+  void CheckLayerOpacityCompatibility(DlBlendMode mode) {
     UpdateLayerOpacityCompatibility(IsOpacityCompatible(mode));
   }
 
@@ -376,7 +377,7 @@
   void onSetStrokeWidth(SkScalar width);
   void onSetStrokeMiter(SkScalar limit);
   void onSetColor(SkColor color);
-  void onSetBlendMode(SkBlendMode mode);
+  void onSetBlendMode(DlBlendMode mode);
   void onSetBlender(sk_sp<SkBlender> blender);
   void onSetColorSource(const DlColorSource* source);
   void onSetImageFilter(sk_sp<SkImageFilter> filter);
@@ -396,7 +397,7 @@
   SkPaint::Cap current_stroke_cap_ = SkPaint::Cap::kButt_Cap;
   SkPaint::Join current_stroke_join_ = SkPaint::Join::kMiter_Join;
   // If |current_blender_| is set then |current_blend_mode_| should be ignored
-  SkBlendMode current_blend_mode_ = SkBlendMode::kSrcOver;
+  DlBlendMode current_blend_mode_ = DlBlendMode::kSrcOver;
   sk_sp<SkBlender> current_blender_;
   std::shared_ptr<const DlColorSource> current_color_source_;
   std::shared_ptr<const DlColorFilter> current_color_filter_;
diff --git a/display_list/display_list_canvas_dispatcher.cc b/display_list/display_list_canvas_dispatcher.cc
index c2d2223..db59c89 100644
--- a/display_list/display_list_canvas_dispatcher.cc
+++ b/display_list/display_list_canvas_dispatcher.cc
@@ -4,6 +4,7 @@
 
 #include "flutter/display_list/display_list_canvas_dispatcher.h"
 
+#include "flutter/display_list/display_list_blend_mode.h"
 #include "flutter/fml/trace_event.h"
 
 namespace flutter {
@@ -130,12 +131,12 @@
   }
   canvas_->drawPaint(sk_paint);
 }
-void DisplayListCanvasDispatcher::drawColor(SkColor color, SkBlendMode mode) {
+void DisplayListCanvasDispatcher::drawColor(SkColor color, DlBlendMode mode) {
   // SkCanvas::drawColor(SkColor) does the following conversion anyway
   // We do it here manually to increase precision on applying opacity
   SkColor4f color4f = SkColor4f::FromColor(color);
   color4f.fA *= opacity();
-  canvas_->drawColor(color4f, mode);
+  canvas_->drawColor(color4f, ToSk(mode));
 }
 void DisplayListCanvasDispatcher::drawLine(const SkPoint& p0,
                                            const SkPoint& p1) {
@@ -173,8 +174,8 @@
   canvas_->drawPoints(mode, count, pts, paint());
 }
 void DisplayListCanvasDispatcher::drawVertices(const sk_sp<SkVertices> vertices,
-                                               SkBlendMode mode) {
-  canvas_->drawVertices(vertices, mode, paint());
+                                               DlBlendMode mode) {
+  canvas_->drawVertices(vertices, ToSk(mode), paint());
 }
 void DisplayListCanvasDispatcher::drawImage(const sk_sp<SkImage> image,
                                             const SkPoint point,
@@ -215,12 +216,12 @@
                                             const SkRect tex[],
                                             const SkColor colors[],
                                             int count,
-                                            SkBlendMode mode,
+                                            DlBlendMode mode,
                                             const SkSamplingOptions& sampling,
                                             const SkRect* cullRect,
                                             bool render_with_attributes) {
-  canvas_->drawAtlas(atlas.get(), xform, tex, colors, count, mode, sampling,
-                     cullRect, safe_paint(render_with_attributes));
+  canvas_->drawAtlas(atlas.get(), xform, tex, colors, count, ToSk(mode),
+                     sampling, cullRect, safe_paint(render_with_attributes));
 }
 void DisplayListCanvasDispatcher::drawPicture(const sk_sp<SkPicture> picture,
                                               const SkMatrix* matrix,
diff --git a/display_list/display_list_canvas_dispatcher.h b/display_list/display_list_canvas_dispatcher.h
index 50f0ab0..0f1ffc6 100644
--- a/display_list/display_list_canvas_dispatcher.h
+++ b/display_list/display_list_canvas_dispatcher.h
@@ -6,6 +6,7 @@
 #define FLUTTER_DISPLAY_LIST_DISPLAY_LIST_CANVAS_DISPATCHER_H_
 
 #include "flutter/display_list/display_list.h"
+#include "flutter/display_list/display_list_blend_mode.h"
 #include "flutter/display_list/display_list_dispatcher.h"
 #include "flutter/display_list/display_list_utils.h"
 #include "flutter/fml/macros.h"
@@ -53,7 +54,7 @@
   void clipPath(const SkPath& path, SkClipOp clip_op, bool is_aa) override;
 
   void drawPaint() override;
-  void drawColor(SkColor color, SkBlendMode mode) override;
+  void drawColor(SkColor color, DlBlendMode mode) override;
   void drawLine(const SkPoint& p0, const SkPoint& p1) override;
   void drawRect(const SkRect& rect) override;
   void drawOval(const SkRect& bounds) override;
@@ -69,7 +70,7 @@
                   uint32_t count,
                   const SkPoint pts[]) override;
   void drawVertices(const sk_sp<SkVertices> vertices,
-                    SkBlendMode mode) override;
+                    DlBlendMode mode) override;
   void drawImage(const sk_sp<SkImage> image,
                  const SkPoint point,
                  const SkSamplingOptions& sampling,
@@ -95,7 +96,7 @@
                  const SkRect tex[],
                  const SkColor colors[],
                  int count,
-                 SkBlendMode mode,
+                 DlBlendMode mode,
                  const SkSamplingOptions& sampling,
                  const SkRect* cullRect,
                  bool render_with_attributes) override;
diff --git a/display_list/display_list_canvas_recorder.cc b/display_list/display_list_canvas_recorder.cc
index 011e6ee..49c3dfb 100644
--- a/display_list/display_list_canvas_recorder.cc
+++ b/display_list/display_list_canvas_recorder.cc
@@ -4,6 +4,7 @@
 
 #include "flutter/display_list/display_list_canvas_recorder.h"
 
+#include "flutter/display_list/display_list_blend_mode.h"
 #include "flutter/display_list/display_list_builder.h"
 
 namespace flutter {
@@ -147,7 +148,7 @@
                                                      SkBlendMode mode,
                                                      const SkPaint& paint) {
   builder_->setAttributesFromPaint(paint, kDrawVerticesFlags);
-  builder_->drawVertices(sk_ref_sp(vertices), mode);
+  builder_->drawVertices(sk_ref_sp(vertices), ToDl(mode));
 }
 
 void DisplayListCanvasRecorder::onDrawImage2(const SkImage* image,
@@ -204,7 +205,7 @@
   if (paint != nullptr) {
     builder_->setAttributesFromPaint(*paint, kDrawAtlasWithPaintFlags);
   }
-  builder_->drawAtlas(sk_ref_sp(image), xform, src, colors, count, mode,
+  builder_->drawAtlas(sk_ref_sp(image), xform, src, colors, count, ToDl(mode),
                       sampling, cull, paint != nullptr);
 }
 
diff --git a/display_list/display_list_canvas_unittests.cc b/display_list/display_list_canvas_unittests.cc
index 5d3cfeb..8460405 100644
--- a/display_list/display_list_canvas_unittests.cc
+++ b/display_list/display_list_canvas_unittests.cc
@@ -761,9 +761,9 @@
                      b.save();
                      b.clipRect(clip, SkClipOp::kIntersect, false);
                      b.drawRect(rect);
-                     b.setBlendMode(SkBlendMode::kClear);
+                     b.setBlendMode(DlBlendMode::kClear);
                      b.drawRect(rect);
-                     b.setBlendMode(SkBlendMode::kSrcOver);
+                     b.setBlendMode(DlBlendMode::kSrcOver);
                      b.restore();
                    }));
     RenderWith(testP, env, tolerance,
@@ -1039,7 +1039,7 @@
                        p.setColor(blendableColor);
                      },
                      [=](DisplayListBuilder& b) {
-                       b.setBlendMode(SkBlendMode::kSrcIn);
+                       b.setBlendMode(DlBlendMode::kSrcIn);
                        b.setColor(blendableColor);
                      })
                      .with_bg(bg));
@@ -1051,7 +1051,7 @@
                        p.setColor(blendableColor);
                      },
                      [=](DisplayListBuilder& b) {
-                       b.setBlendMode(SkBlendMode::kDstIn);
+                       b.setBlendMode(DlBlendMode::kDstIn);
                        b.setColor(blendableColor);
                      })
                      .with_bg(bg));
@@ -2129,7 +2129,7 @@
             canvas->drawColor(SK_ColorMAGENTA);
           },
           [=](DisplayListBuilder& builder) {
-            builder.drawColor(SK_ColorMAGENTA, SkBlendMode::kSrcOver);
+            builder.drawColor(SK_ColorMAGENTA, DlBlendMode::kSrcOver);
           },
           kDrawColorFlags));
 }
@@ -2503,7 +2503,7 @@
             canvas->drawVertices(vertices.get(), SkBlendMode::kSrcOver, paint);
           },
           [=](DisplayListBuilder& builder) {  //
-            builder.drawVertices(vertices, SkBlendMode::kSrcOver);
+            builder.drawVertices(vertices, DlBlendMode::kSrcOver);
           },
           kDrawVerticesFlags)
           .set_draw_vertices());
@@ -2557,7 +2557,7 @@
               builder.setColorSource(
                   &CanvasCompareTester::testImageColorSource);
             }
-            builder.drawVertices(vertices, SkBlendMode::kSrcOver);
+            builder.drawVertices(vertices, DlBlendMode::kSrcOver);
           },
           kDrawVerticesFlags)
           .set_draw_vertices());
@@ -2834,7 +2834,7 @@
           },
           [=](DisplayListBuilder& builder) {
             builder.drawAtlas(image, xform, tex, colors, 4,  //
-                              SkBlendMode::kSrcOver, sampling, nullptr, true);
+                              DlBlendMode::kSrcOver, sampling, nullptr, true);
           },
           kDrawAtlasWithPaintFlags)
           .set_draw_atlas());
@@ -2874,7 +2874,7 @@
           },
           [=](DisplayListBuilder& builder) {
             builder.drawAtlas(image, xform, tex, colors, 4,     //
-                              SkBlendMode::kSrcOver, sampling,  //
+                              DlBlendMode::kSrcOver, sampling,  //
                               nullptr, false);
           },
           kDrawAtlasFlags)
@@ -2914,7 +2914,7 @@
           },
           [=](DisplayListBuilder& builder) {
             builder.drawAtlas(image, xform, tex, colors, 2,  //
-                              SkBlendMode::kSrcOver, sampling, nullptr, true);
+                              DlBlendMode::kSrcOver, sampling, nullptr, true);
           },
           kDrawAtlasWithPaintFlags)
           .set_draw_atlas());
diff --git a/display_list/display_list_complexity_gl.cc b/display_list/display_list_complexity_gl.cc
index e7364f5..71eb1b7 100644
--- a/display_list/display_list_complexity_gl.cc
+++ b/display_list/display_list_complexity_gl.cc
@@ -478,7 +478,7 @@
 
 void DisplayListGLComplexityCalculator::GLHelper::drawVertices(
     const sk_sp<SkVertices> vertices,
-    SkBlendMode mode) {
+    DlBlendMode mode) {
   // There is currently no way for us to get the VertexMode from the SkVertices
   // object, but for future reference:
   //
diff --git a/display_list/display_list_complexity_gl.h b/display_list/display_list_complexity_gl.h
index 55732c4..0d80f7e 100644
--- a/display_list/display_list_complexity_gl.h
+++ b/display_list/display_list_complexity_gl.h
@@ -55,7 +55,7 @@
                     uint32_t count,
                     const SkPoint points[]) override;
     void drawVertices(const sk_sp<SkVertices> vertices,
-                      SkBlendMode mode) override;
+                      DlBlendMode mode) override;
     void drawImage(const sk_sp<SkImage> image,
                    const SkPoint point,
                    const SkSamplingOptions& sampling,
diff --git a/display_list/display_list_complexity_helper.h b/display_list/display_list_complexity_helper.h
index 4e34b62..30176bd 100644
--- a/display_list/display_list_complexity_helper.h
+++ b/display_list/display_list_complexity_helper.h
@@ -5,6 +5,7 @@
 #ifndef FLUTTER_FLOW_DISPLAY_LIST_COMPLEXITY_HELPER_H_
 #define FLUTTER_FLOW_DISPLAY_LIST_COMPLEXITY_HELPER_H_
 
+#include "flutter/display_list/display_list_blend_mode.h"
 #include "flutter/display_list/display_list_complexity.h"
 #include "flutter/display_list/display_list_dispatcher.h"
 #include "flutter/display_list/display_list_utils.h"
@@ -106,7 +107,7 @@
   void setStrokeJoin(SkPaint::Join join) override {}
   void setStrokeMiter(SkScalar limit) override {}
   void setColor(SkColor color) override {}
-  void setBlendMode(SkBlendMode mode) override {}
+  void setBlendMode(DlBlendMode mode) override {}
   void setBlender(sk_sp<SkBlender> blender) override {}
   void setColorSource(const DlColorSource* source) override {}
   void setImageFilter(sk_sp<SkImageFilter> filter) override {}
@@ -128,7 +129,7 @@
     current_paint_.setStrokeWidth(width);
   }
 
-  void drawColor(SkColor color, SkBlendMode mode) override {
+  void drawColor(SkColor color, DlBlendMode mode) override {
     if (IsComplex()) {
       return;
     }
@@ -179,7 +180,7 @@
                  const SkRect tex[],
                  const SkColor colors[],
                  int count,
-                 SkBlendMode mode,
+                 DlBlendMode mode,
                  const SkSamplingOptions& sampling,
                  const SkRect* cull_rect,
                  bool render_with_attributes) override {
diff --git a/display_list/display_list_complexity_metal.cc b/display_list/display_list_complexity_metal.cc
index 6d4983f..17b6af9 100644
--- a/display_list/display_list_complexity_metal.cc
+++ b/display_list/display_list_complexity_metal.cc
@@ -430,7 +430,7 @@
 
 void DisplayListMetalComplexityCalculator::MetalHelper::drawVertices(
     const sk_sp<SkVertices> vertices,
-    SkBlendMode mode) {
+    DlBlendMode mode) {
   // There is currently no way for us to get the VertexMode from the SkVertices
   // object, but for future reference:
   //
diff --git a/display_list/display_list_complexity_metal.h b/display_list/display_list_complexity_metal.h
index 26131de..ffba4c8 100644
--- a/display_list/display_list_complexity_metal.h
+++ b/display_list/display_list_complexity_metal.h
@@ -55,7 +55,7 @@
                     uint32_t count,
                     const SkPoint points[]) override;
     void drawVertices(const sk_sp<SkVertices> vertices,
-                      SkBlendMode mode) override;
+                      DlBlendMode mode) override;
     void drawImage(const sk_sp<SkImage> image,
                    const SkPoint point,
                    const SkSamplingOptions& sampling,
diff --git a/display_list/display_list_complexity_unittests.cc b/display_list/display_list_complexity_unittests.cc
index 88c6b3c..c669a87 100644
--- a/display_list/display_list_complexity_unittests.cc
+++ b/display_list/display_list_complexity_unittests.cc
@@ -287,7 +287,7 @@
       SkVertices::MakeCopy(SkVertices::VertexMode::kTriangles_VertexMode,
                            points.size(), points.data(), nullptr, nullptr);
   DisplayListBuilder builder;
-  builder.drawVertices(vertices, SkBlendMode::kSrc);
+  builder.drawVertices(vertices, DlBlendMode::kSrc);
   auto display_list = builder.Build();
 
   auto calculators = AccumulatorCalculators();
@@ -419,7 +419,7 @@
 
   DisplayListBuilder builder;
   builder.drawAtlas(image, xforms.data(), rects.data(), nullptr, 10,
-                    SkBlendMode::kSrc, SkSamplingOptions(), nullptr, true);
+                    DlBlendMode::kSrc, SkSamplingOptions(), nullptr, true);
   auto display_list = builder.Build();
 
   auto calculators = AccumulatorCalculators();
diff --git a/display_list/display_list_dispatcher.h b/display_list/display_list_dispatcher.h
index e4bf53f..cd25d70 100644
--- a/display_list/display_list_dispatcher.h
+++ b/display_list/display_list_dispatcher.h
@@ -6,6 +6,7 @@
 #define FLUTTER_DISPLAY_LIST_DISPLAY_LIST_DISPATCHER_H_
 
 #include "flutter/display_list/display_list.h"
+#include "flutter/display_list/display_list_blend_mode.h"
 #include "flutter/display_list/display_list_color_filter.h"
 #include "flutter/display_list/display_list_color_source.h"
 #include "flutter/display_list/display_list_mask_filter.h"
@@ -45,7 +46,7 @@
   // It is not reset by |setColorFilter|, but instead composed with that
   // filter so that the color inversion happens after the ColorFilter.
   virtual void setInvertColors(bool invert) = 0;
-  virtual void setBlendMode(SkBlendMode mode) = 0;
+  virtual void setBlendMode(DlBlendMode mode) = 0;
   virtual void setBlender(sk_sp<SkBlender> blender) = 0;
   virtual void setPathEffect(sk_sp<SkPathEffect> effect) = 0;
   virtual void setMaskFilter(const DlMaskFilter* filter) = 0;
@@ -186,7 +187,7 @@
   // method, the methods here will generally offer a boolean parameter
   // which specifies whether to honor the attributes of the display list
   // stream, or assume default attributes.
-  virtual void drawColor(SkColor color, SkBlendMode mode) = 0;
+  virtual void drawColor(SkColor color, DlBlendMode mode) = 0;
   virtual void drawPaint() = 0;
   virtual void drawLine(const SkPoint& p0, const SkPoint& p1) = 0;
   virtual void drawRect(const SkRect& rect) = 0;
@@ -203,7 +204,7 @@
                           uint32_t count,
                           const SkPoint points[]) = 0;
   virtual void drawVertices(const sk_sp<SkVertices> vertices,
-                            SkBlendMode mode) = 0;
+                            DlBlendMode mode) = 0;
   virtual void drawImage(const sk_sp<SkImage> image,
                          const SkPoint point,
                          const SkSamplingOptions& sampling,
@@ -229,7 +230,7 @@
                          const SkRect tex[],
                          const SkColor colors[],
                          int count,
-                         SkBlendMode mode,
+                         DlBlendMode mode,
                          const SkSamplingOptions& sampling,
                          const SkRect* cull_rect,
                          bool render_with_attributes) = 0;
diff --git a/display_list/display_list_enum_unittests.cc b/display_list/display_list_enum_unittests.cc
index a45542b..9455624 100644
--- a/display_list/display_list_enum_unittests.cc
+++ b/display_list/display_list_enum_unittests.cc
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "flutter/display_list/display_list_blend_mode.h"
 #include "flutter/display_list/display_list_tile_mode.h"
 #include "flutter/display_list/types.h"
 #include "gtest/gtest.h"
@@ -23,5 +24,53 @@
   ASSERT_EQ(ToSk(DlTileMode::kDecal), SkTileMode::kDecal);
 }
 
+#define CHECK_TO_DLENUM(V) ASSERT_EQ(ToDl(SkBlendMode::V), DlBlendMode::V);
+#define CHECK_TO_SKENUM(V) ASSERT_EQ(ToSk(DlBlendMode::V), SkBlendMode::V);
+
+#define FOR_EACH_ENUM(FUNC) \
+  FUNC(kSrc)                \
+  FUNC(kClear)              \
+  FUNC(kSrc)                \
+  FUNC(kDst)                \
+  FUNC(kSrcOver)            \
+  FUNC(kDstOver)            \
+  FUNC(kSrcIn)              \
+  FUNC(kDstIn)              \
+  FUNC(kSrcOut)             \
+  FUNC(kDstOut)             \
+  FUNC(kSrcATop)            \
+  FUNC(kDstATop)            \
+  FUNC(kXor)                \
+  FUNC(kPlus)               \
+  FUNC(kModulate)           \
+  FUNC(kScreen)             \
+  FUNC(kOverlay)            \
+  FUNC(kDarken)             \
+  FUNC(kLighten)            \
+  FUNC(kColorDodge)         \
+  FUNC(kColorBurn)          \
+  FUNC(kHardLight)          \
+  FUNC(kSoftLight)          \
+  FUNC(kDifference)         \
+  FUNC(kExclusion)          \
+  FUNC(kMultiply)           \
+  FUNC(kHue)                \
+  FUNC(kSaturation)         \
+  FUNC(kColor)              \
+  FUNC(kLuminosity)         \
+  FUNC(kLastCoeffMode)      \
+  FUNC(kLastSeparableMode)  \
+  FUNC(kLastMode)
+
+TEST(DisplayListEnum, ToDlBlendMode){FOR_EACH_ENUM(CHECK_TO_DLENUM)}
+
+TEST(DisplayListEnum, ToSkBlendMode) {
+  FOR_EACH_ENUM(CHECK_TO_SKENUM)
+}
+
+#undef CHECK_TO_DLENUM
+#undef CHECK_TO_SKENUM
+#undef FOR_EACH_ENUM
+
 }  // namespace testing
 }  // namespace flutter
diff --git a/display_list/display_list_ops.h b/display_list/display_list_ops.h
index bb6abc5..6953581 100644
--- a/display_list/display_list_ops.h
+++ b/display_list/display_list_ops.h
@@ -6,6 +6,7 @@
 #define FLUTTER_DISPLAY_LIST_DISPLAY_LIST_OPS_H_
 
 #include "flutter/display_list/display_list.h"
+#include "flutter/display_list/display_list_blend_mode.h"
 #include "flutter/display_list/display_list_dispatcher.h"
 #include "flutter/display_list/types.h"
 #include "flutter/fml/macros.h"
@@ -141,9 +142,9 @@
 struct SetBlendModeOp final : DLOp {
   static const auto kType = DisplayListOpType::kSetBlendMode;
 
-  explicit SetBlendModeOp(SkBlendMode mode) : mode(mode) {}
+  explicit SetBlendModeOp(DlBlendMode mode) : mode(mode) {}
 
-  const SkBlendMode mode;
+  const DlBlendMode mode;
 
   void dispatch(Dispatcher& dispatcher) const { dispatcher.setBlendMode(mode); }
 };
@@ -458,10 +459,10 @@
 struct DrawColorOp final : DLOp {
   static const auto kType = DisplayListOpType::kDrawColor;
 
-  DrawColorOp(SkColor color, SkBlendMode mode) : color(color), mode(mode) {}
+  DrawColorOp(SkColor color, DlBlendMode mode) : color(color), mode(mode) {}
 
   const SkColor color;
-  const SkBlendMode mode;
+  const DlBlendMode mode;
 
   void dispatch(Dispatcher& dispatcher) const {
     dispatcher.drawColor(color, mode);
@@ -577,10 +578,10 @@
 struct DrawVerticesOp final : DLOp {
   static const auto kType = DisplayListOpType::kDrawVertices;
 
-  DrawVerticesOp(sk_sp<SkVertices> vertices, SkBlendMode mode)
+  DrawVerticesOp(sk_sp<SkVertices> vertices, DlBlendMode mode)
       : mode(mode), vertices(std::move(vertices)) {}
 
-  const SkBlendMode mode;
+  const DlBlendMode mode;
   const sk_sp<SkVertices> vertices;
 
   void dispatch(Dispatcher& dispatcher) const {
@@ -721,7 +722,7 @@
 struct DrawAtlasBaseOp : DLOp {
   DrawAtlasBaseOp(const sk_sp<SkImage> atlas,
                   int count,
-                  SkBlendMode mode,
+                  DlBlendMode mode,
                   const SkSamplingOptions& sampling,
                   bool has_colors,
                   bool render_with_attributes)
@@ -747,7 +748,7 @@
 
   DrawAtlasOp(const sk_sp<SkImage> atlas,
               int count,
-              SkBlendMode mode,
+              DlBlendMode mode,
               const SkSamplingOptions& sampling,
               bool has_colors,
               bool render_with_attributes)
@@ -763,7 +764,7 @@
     const SkRect* tex = reinterpret_cast<const SkRect*>(xform + count);
     const SkColor* colors =
         has_colors ? reinterpret_cast<const SkColor*>(tex + count) : nullptr;
-    const SkBlendMode mode = static_cast<SkBlendMode>(mode_index);
+    const DlBlendMode mode = static_cast<DlBlendMode>(mode_index);
     dispatcher.drawAtlas(atlas, xform, tex, colors, count, mode, sampling,
                          nullptr, render_with_attributes);
   }
@@ -778,7 +779,7 @@
 
   DrawAtlasCulledOp(const sk_sp<SkImage> atlas,
                     int count,
-                    SkBlendMode mode,
+                    DlBlendMode mode,
                     const SkSamplingOptions& sampling,
                     bool has_colors,
                     const SkRect& cull_rect,
@@ -798,7 +799,7 @@
     const SkRect* tex = reinterpret_cast<const SkRect*>(xform + count);
     const SkColor* colors =
         has_colors ? reinterpret_cast<const SkColor*>(tex + count) : nullptr;
-    const SkBlendMode mode = static_cast<SkBlendMode>(mode_index);
+    const DlBlendMode mode = static_cast<DlBlendMode>(mode_index);
     dispatcher.drawAtlas(atlas, xform, tex, colors, count, mode, sampling,
                          &cull_rect, render_with_attributes);
   }
diff --git a/display_list/display_list_test_utils.cc b/display_list/display_list_test_utils.cc
index bdf455c..3ba91c1 100644
--- a/display_list/display_list_test_utils.cc
+++ b/display_list/display_list_test_utils.cc
@@ -62,7 +62,7 @@
 sk_sp<DisplayList> GetSampleDisplayList(int ops) {
   DisplayListBuilder builder(SkRect::MakeWH(150, 100));
   for (int i = 0; i < ops; i++) {
-    builder.drawColor(SK_ColorRED, SkBlendMode::kSrc);
+    builder.drawColor(SK_ColorRED, DlBlendMode::kSrc);
   }
   return builder.Build();
 }
diff --git a/display_list/display_list_unittests.cc b/display_list/display_list_unittests.cc
index 8e00a98..cfc8b25 100644
--- a/display_list/display_list_unittests.cc
+++ b/display_list/display_list_unittests.cc
@@ -338,12 +338,12 @@
     }
   },
   { "SetBlendModeOrBlender", {
-      {0, 8, 0, 0, [](DisplayListBuilder& b) {b.setBlendMode(SkBlendMode::kSrcIn);}},
-      {0, 8, 0, 0, [](DisplayListBuilder& b) {b.setBlendMode(SkBlendMode::kDstIn);}},
+      {0, 8, 0, 0, [](DisplayListBuilder& b) {b.setBlendMode(DlBlendMode::kSrcIn);}},
+      {0, 8, 0, 0, [](DisplayListBuilder& b) {b.setBlendMode(DlBlendMode::kDstIn);}},
       {0, 16, 0, 0, [](DisplayListBuilder& b) {b.setBlender(TestBlender1);}},
       {0, 16, 0, 0, [](DisplayListBuilder& b) {b.setBlender(TestBlender2);}},
       {0, 16, 0, 0, [](DisplayListBuilder& b) {b.setBlender(TestBlender3);}},
-      {0, 0, 0, 0, [](DisplayListBuilder& b) {b.setBlendMode(SkBlendMode::kSrcOver);}},
+      {0, 0, 0, 0, [](DisplayListBuilder& b) {b.setBlendMode(DlBlendMode::kSrcOver);}},
       {0, 0, 0, 0, [](DisplayListBuilder& b) {b.setBlender(nullptr);}},
     }
   },
@@ -524,9 +524,9 @@
   },
   { "DrawColor", {
       // cv.drawColor becomes cv.drawPaint(paint)
-      {1, 16, 1, 24, [](DisplayListBuilder& b) {b.drawColor(SK_ColorBLUE, SkBlendMode::kSrcIn);}},
-      {1, 16, 1, 24, [](DisplayListBuilder& b) {b.drawColor(SK_ColorBLUE, SkBlendMode::kDstIn);}},
-      {1, 16, 1, 24, [](DisplayListBuilder& b) {b.drawColor(SK_ColorCYAN, SkBlendMode::kSrcIn);}},
+      {1, 16, 1, 24, [](DisplayListBuilder& b) {b.drawColor(SK_ColorBLUE, DlBlendMode::kSrcIn);}},
+      {1, 16, 1, 24, [](DisplayListBuilder& b) {b.drawColor(SK_ColorBLUE, DlBlendMode::kDstIn);}},
+      {1, 16, 1, 24, [](DisplayListBuilder& b) {b.drawColor(SK_ColorCYAN, DlBlendMode::kSrcIn);}},
     }
   },
   { "DrawLine", {
@@ -605,9 +605,9 @@
     }
   },
   { "DrawVertices", {
-      {1, 16, 1, 16, [](DisplayListBuilder& b) {b.drawVertices(TestVertices1, SkBlendMode::kSrcIn);}},
-      {1, 16, 1, 16, [](DisplayListBuilder& b) {b.drawVertices(TestVertices1, SkBlendMode::kDstIn);}},
-      {1, 16, 1, 16, [](DisplayListBuilder& b) {b.drawVertices(TestVertices2, SkBlendMode::kSrcIn);}},
+      {1, 16, 1, 16, [](DisplayListBuilder& b) {b.drawVertices(TestVertices1, DlBlendMode::kSrcIn);}},
+      {1, 16, 1, 16, [](DisplayListBuilder& b) {b.drawVertices(TestVertices1, DlBlendMode::kDstIn);}},
+      {1, 16, 1, 16, [](DisplayListBuilder& b) {b.drawVertices(TestVertices2, DlBlendMode::kSrcIn);}},
     }
   },
   { "DrawImage", {
@@ -700,51 +700,51 @@
       {1, 40 + 32 + 32, 1, 40 + 32 + 32, [](DisplayListBuilder& b) {
         static SkRSXform xforms[] = { {1, 0, 0, 0}, {0, 1, 0, 0} };
         static SkRect texs[] = { { 10, 10, 20, 20 }, {20, 20, 30, 30} };
-        b.drawAtlas(TestImage1, xforms, texs, nullptr, 2, SkBlendMode::kSrcIn,
+        b.drawAtlas(TestImage1, xforms, texs, nullptr, 2, DlBlendMode::kSrcIn,
                     DisplayList::NearestSampling, nullptr, false);}},
       {1, 40 + 32 + 32, 1, 40 + 32 + 32, [](DisplayListBuilder& b) {
         static SkRSXform xforms[] = { {1, 0, 0, 0}, {0, 1, 0, 0} };
         static SkRect texs[] = { { 10, 10, 20, 20 }, {20, 20, 30, 30} };
-        b.drawAtlas(TestImage1, xforms, texs, nullptr, 2, SkBlendMode::kSrcIn,
+        b.drawAtlas(TestImage1, xforms, texs, nullptr, 2, DlBlendMode::kSrcIn,
                     DisplayList::NearestSampling, nullptr, true);}},
       {1, 40 + 32 + 32, 1, 40 + 32 + 32, [](DisplayListBuilder& b) {
         static SkRSXform xforms[] = { {0, 1, 0, 0}, {0, 1, 0, 0} };
         static SkRect texs[] = { { 10, 10, 20, 20 }, {20, 20, 30, 30} };
-        b.drawAtlas(TestImage1, xforms, texs, nullptr, 2, SkBlendMode::kSrcIn,
+        b.drawAtlas(TestImage1, xforms, texs, nullptr, 2, DlBlendMode::kSrcIn,
                     DisplayList::NearestSampling, nullptr, false);}},
       {1, 40 + 32 + 32, 1, 40 + 32 + 32, [](DisplayListBuilder& b) {
         static SkRSXform xforms[] = { {1, 0, 0, 0}, {0, 1, 0, 0} };
         static SkRect texs[] = { { 10, 10, 20, 20 }, {20, 25, 30, 30} };
-        b.drawAtlas(TestImage1, xforms, texs, nullptr, 2, SkBlendMode::kSrcIn,
+        b.drawAtlas(TestImage1, xforms, texs, nullptr, 2, DlBlendMode::kSrcIn,
                     DisplayList::NearestSampling, nullptr, false);}},
       {1, 40 + 32 + 32, 1, 40 + 32 + 32, [](DisplayListBuilder& b) {
         static SkRSXform xforms[] = { {1, 0, 0, 0}, {0, 1, 0, 0} };
         static SkRect texs[] = { { 10, 10, 20, 20 }, {20, 20, 30, 30} };
-        b.drawAtlas(TestImage1, xforms, texs, nullptr, 2, SkBlendMode::kSrcIn,
+        b.drawAtlas(TestImage1, xforms, texs, nullptr, 2, DlBlendMode::kSrcIn,
                     DisplayList::LinearSampling, nullptr, false);}},
       {1, 40 + 32 + 32, 1, 40 + 32 + 32, [](DisplayListBuilder& b) {
         static SkRSXform xforms[] = { {1, 0, 0, 0}, {0, 1, 0, 0} };
         static SkRect texs[] = { { 10, 10, 20, 20 }, {20, 20, 30, 30} };
-        b.drawAtlas(TestImage1, xforms, texs, nullptr, 2, SkBlendMode::kDstIn,
+        b.drawAtlas(TestImage1, xforms, texs, nullptr, 2, DlBlendMode::kDstIn,
                     DisplayList::NearestSampling, nullptr, false);}},
       {1, 56 + 32 + 32, 1, 56 + 32 + 32, [](DisplayListBuilder& b) {
         static SkRSXform xforms[] = { {1, 0, 0, 0}, {0, 1, 0, 0} };
         static SkRect texs[] = { { 10, 10, 20, 20 }, {20, 20, 30, 30} };
         static SkRect cullRect = { 0, 0, 200, 200 };
-        b.drawAtlas(TestImage2, xforms, texs, nullptr, 2, SkBlendMode::kSrcIn,
+        b.drawAtlas(TestImage2, xforms, texs, nullptr, 2, DlBlendMode::kSrcIn,
                     DisplayList::NearestSampling, &cullRect, false);}},
       {1, 40 + 32 + 32 + 8, 1, 40 + 32 + 32 + 8, [](DisplayListBuilder& b) {
         static SkRSXform xforms[] = { {1, 0, 0, 0}, {0, 1, 0, 0} };
         static SkRect texs[] = { { 10, 10, 20, 20 }, {20, 20, 30, 30} };
         static SkColor colors[] = { SK_ColorBLUE, SK_ColorGREEN };
-        b.drawAtlas(TestImage1, xforms, texs, colors, 2, SkBlendMode::kSrcIn,
+        b.drawAtlas(TestImage1, xforms, texs, colors, 2, DlBlendMode::kSrcIn,
                     DisplayList::NearestSampling, nullptr, false);}},
       {1, 56 + 32 + 32 + 8, 1, 56 + 32 + 32 + 8, [](DisplayListBuilder& b) {
         static SkRSXform xforms[] = { {1, 0, 0, 0}, {0, 1, 0, 0} };
         static SkRect texs[] = { { 10, 10, 20, 20 }, {20, 20, 30, 30} };
         static SkColor colors[] = { SK_ColorBLUE, SK_ColorGREEN };
         static SkRect cullRect = { 0, 0, 200, 200 };
-        b.drawAtlas(TestImage1, xforms, texs, colors, 2, SkBlendMode::kSrcIn,
+        b.drawAtlas(TestImage1, xforms, texs, colors, 2, DlBlendMode::kSrcIn,
                     DisplayList::NearestSampling, &cullRect, false);}},
     }
   },
@@ -930,7 +930,7 @@
 
 TEST(DisplayList, AllBlendModeNops) {
   DisplayListBuilder builder;
-  builder.setBlendMode(SkBlendMode::kSrcOver);
+  builder.setBlendMode(DlBlendMode::kSrcOver);
   builder.setBlender(nullptr);
   sk_sp<DisplayList> dl = builder.Build();
   ASSERT_EQ(dl->bytes(false), sizeof(DisplayList));
@@ -1138,9 +1138,9 @@
   {
     // Testing behavior with an unboundable blend mode
     DisplayListBuilder builder(build_bounds);
-    builder.setBlendMode(SkBlendMode::kClear);
+    builder.setBlendMode(DlBlendMode::kClear);
     builder.saveLayer(&save_bounds, true);
-    builder.setBlendMode(SkBlendMode::kSrcOver);
+    builder.setBlendMode(DlBlendMode::kSrcOver);
     builder.drawRect(rect);
     builder.restore();
     sk_sp<DisplayList> display_list = builder.Build();
@@ -1150,9 +1150,9 @@
   {
     // Same as previous with no save bounds
     DisplayListBuilder builder(build_bounds);
-    builder.setBlendMode(SkBlendMode::kClear);
+    builder.setBlendMode(DlBlendMode::kClear);
     builder.saveLayer(nullptr, true);
-    builder.setBlendMode(SkBlendMode::kSrcOver);
+    builder.setBlendMode(DlBlendMode::kSrcOver);
     builder.drawRect(rect);
     builder.restore();
     sk_sp<DisplayList> display_list = builder.Build();
@@ -1401,7 +1401,7 @@
       // Second test i the draw op with kSrc,
       // (usually fails group opacity)
       DisplayListBuilder builder;
-      builder.setBlendMode(SkBlendMode::kSrc);
+      builder.setBlendMode(DlBlendMode::kSrc);
       build(builder);
       auto display_list = builder.Build();
       EXPECT_EQ(display_list->can_apply_group_opacity(), expect_with_kSrc)
@@ -1420,8 +1420,8 @@
       #body, [](DisplayListBuilder& builder) { body }, expect, expect)
 
   RUN_TESTS(builder.drawPaint(););
-  RUN_TESTS2(builder.drawColor(SK_ColorRED, SkBlendMode::kSrcOver);, true);
-  RUN_TESTS2(builder.drawColor(SK_ColorRED, SkBlendMode::kSrc);, false);
+  RUN_TESTS2(builder.drawColor(SK_ColorRED, DlBlendMode::kSrcOver);, true);
+  RUN_TESTS2(builder.drawColor(SK_ColorRED, DlBlendMode::kSrc);, false);
   RUN_TESTS(builder.drawLine({0, 0}, {10, 10}););
   RUN_TESTS(builder.drawRect({0, 0, 10, 10}););
   RUN_TESTS(builder.drawOval({0, 0, 10, 10}););
@@ -1435,7 +1435,7 @@
   RUN_TESTS2(builder.drawPoints(SkCanvas::kPoints_PointMode, TestPointCount,
                                 TestPoints);
              , false);
-  RUN_TESTS2(builder.drawVertices(TestVertices1, SkBlendMode::kSrc);, false);
+  RUN_TESTS2(builder.drawVertices(TestVertices1, DlBlendMode::kSrc);, false);
   RUN_TESTS(builder.drawImage(TestImage1, {0, 0}, DisplayList::LinearSampling,
                               true););
   RUN_TESTS2(
@@ -1463,11 +1463,11 @@
   static SkRSXform xforms[] = {{1, 0, 0, 0}, {0, 1, 0, 0}};
   static SkRect texs[] = {{10, 10, 20, 20}, {20, 20, 30, 30}};
   RUN_TESTS2(builder.drawAtlas(TestImage1, xforms, texs, nullptr, 2,
-                               SkBlendMode::kSrcIn,
+                               DlBlendMode::kSrcIn,
                                DisplayList::NearestSampling, nullptr, true);
              , false);
   RUN_TESTS2(builder.drawAtlas(TestImage1, xforms, texs, nullptr, 2,
-                               SkBlendMode::kSrcIn,
+                               DlBlendMode::kSrcIn,
                                DisplayList::NearestSampling, nullptr, false);
              , false);
   RUN_TESTS(builder.drawPicture(TestPicture1, nullptr, true););
@@ -1522,7 +1522,7 @@
 
 TEST(DisplayList, SaveLayerFalseWithSrcBlendSupportsGroupOpacity) {
   DisplayListBuilder builder;
-  builder.setBlendMode(SkBlendMode::kSrc);
+  builder.setBlendMode(DlBlendMode::kSrc);
   builder.saveLayer(nullptr, false);
   builder.drawRect({0, 0, 10, 10});
   builder.restore();
@@ -1532,7 +1532,7 @@
 
 TEST(DisplayList, SaveLayerTrueWithSrcBlendDoesNotSupportGroupOpacity) {
   DisplayListBuilder builder;
-  builder.setBlendMode(SkBlendMode::kSrc);
+  builder.setBlendMode(DlBlendMode::kSrc);
   builder.saveLayer(nullptr, true);
   builder.drawRect({0, 0, 10, 10});
   builder.restore();
@@ -1543,7 +1543,7 @@
 TEST(DisplayList, SaveLayerFalseSupportsGroupOpacityWithChildSrcBlend) {
   DisplayListBuilder builder;
   builder.saveLayer(nullptr, false);
-  builder.setBlendMode(SkBlendMode::kSrc);
+  builder.setBlendMode(DlBlendMode::kSrc);
   builder.drawRect({0, 0, 10, 10});
   builder.restore();
   auto display_list = builder.Build();
@@ -1553,7 +1553,7 @@
 TEST(DisplayList, SaveLayerTrueSupportsGroupOpacityWithChildSrcBlend) {
   DisplayListBuilder builder;
   builder.saveLayer(nullptr, true);
-  builder.setBlendMode(SkBlendMode::kSrc);
+  builder.setBlendMode(DlBlendMode::kSrc);
   builder.drawRect({0, 0, 10, 10});
   builder.restore();
   auto display_list = builder.Build();
@@ -1721,9 +1721,9 @@
 
   DisplayListBuilder builder;
   builder.setColor(SkColorSetARGB(127, 255, 255, 255));
-  builder.setBlendMode(SkBlendMode::kSrc);
+  builder.setBlendMode(DlBlendMode::kSrc);
   builder.saveLayer(nullptr, true);
-  builder.setBlendMode(SkBlendMode::kSrcOver);
+  builder.setBlendMode(DlBlendMode::kSrcOver);
   builder.drawRect({10, 10, 20, 20});
   builder.restore();
 
@@ -1769,7 +1769,7 @@
   DisplayListBuilder builder;
   builder.setColor(SkColorSetARGB(127, 255, 255, 255));
   builder.saveLayer(nullptr, true);
-  builder.setBlendMode(SkBlendMode::kSrc);
+  builder.setBlendMode(DlBlendMode::kSrc);
   builder.drawRect({10, 10, 20, 20});
   builder.restore();
 
diff --git a/display_list/display_list_utils.cc b/display_list/display_list_utils.cc
index e05485e..6cd7ef7 100644
--- a/display_list/display_list_utils.cc
+++ b/display_list/display_list_utils.cc
@@ -5,8 +5,10 @@
 #include "flutter/display_list/display_list_utils.h"
 
 #include <math.h>
+#include <optional>
 #include <type_traits>
 
+#include "flutter/display_list/display_list_blend_mode.h"
 #include "flutter/display_list/display_list_canvas_dispatcher.h"
 #include "flutter/fml/logging.h"
 #include "third_party/skia/include/core/SkMaskFilter.h"
@@ -67,8 +69,8 @@
     paint_.setAlphaf(paint_.getAlphaf() * opacity());
   }
 }
-void SkPaintDispatchHelper::setBlendMode(SkBlendMode mode) {
-  paint_.setBlendMode(mode);
+void SkPaintDispatchHelper::setBlendMode(DlBlendMode mode) {
+  paint_.setBlendMode(ToSk(mode));
 }
 void SkPaintDispatchHelper::setBlender(sk_sp<SkBlender> blender) {
   paint_.setBlender(blender);
@@ -256,13 +258,18 @@
 void DisplayListBoundsCalculator::setStrokeMiter(SkScalar limit) {
   miter_limit_ = std::max(limit, 1.0f);
 }
-void DisplayListBoundsCalculator::setBlendMode(SkBlendMode mode) {
+void DisplayListBoundsCalculator::setBlendMode(DlBlendMode mode) {
   blend_mode_ = mode;
 }
 void DisplayListBoundsCalculator::setBlender(sk_sp<SkBlender> blender) {
   SkPaint paint;
   paint.setBlender(std::move(blender));
-  blend_mode_ = paint.asBlendMode();
+  auto blend_mode = paint.asBlendMode();
+  if (blend_mode.has_value()) {
+    blend_mode_ = ToDl(blend_mode.value());
+  } else {
+    blend_mode_ = std::nullopt;
+  }
 }
 void DisplayListBoundsCalculator::setImageFilter(sk_sp<SkImageFilter> filter) {
   image_filter_ = std::move(filter);
@@ -371,7 +378,7 @@
 void DisplayListBoundsCalculator::drawPaint() {
   AccumulateUnbounded();
 }
-void DisplayListBoundsCalculator::drawColor(SkColor color, SkBlendMode mode) {
+void DisplayListBoundsCalculator::drawColor(SkColor color, DlBlendMode mode) {
   AccumulateUnbounded();
 }
 void DisplayListBoundsCalculator::drawLine(const SkPoint& p0,
@@ -443,7 +450,7 @@
   }
 }
 void DisplayListBoundsCalculator::drawVertices(const sk_sp<SkVertices> vertices,
-                                               SkBlendMode mode) {
+                                               DlBlendMode mode) {
   AccumulateOpBounds(vertices->bounds(), kDrawVerticesFlags);
 }
 void DisplayListBoundsCalculator::drawImage(const sk_sp<SkImage> image,
@@ -495,7 +502,7 @@
                                             const SkRect tex[],
                                             const SkColor colors[],
                                             int count,
-                                            SkBlendMode mode,
+                                            DlBlendMode mode,
                                             const SkSamplingOptions& sampling,
                                             const SkRect* cullRect,
                                             bool render_with_attributes) {
@@ -674,43 +681,43 @@
     // destination pixel.
     // Mathematically, any time in the following equations where
     // the result is not d assuming source is 0
-    case SkBlendMode::kClear:     // r = 0
-    case SkBlendMode::kSrc:       // r = s
-    case SkBlendMode::kSrcIn:     // r = s * da
-    case SkBlendMode::kDstIn:     // r = d * sa
-    case SkBlendMode::kSrcOut:    // r = s * (1-da)
-    case SkBlendMode::kDstATop:   // r = d*sa + s*(1-da)
-    case SkBlendMode::kModulate:  // r = s*d
+    case DlBlendMode::kClear:     // r = 0
+    case DlBlendMode::kSrc:       // r = s
+    case DlBlendMode::kSrcIn:     // r = s * da
+    case DlBlendMode::kDstIn:     // r = d * sa
+    case DlBlendMode::kSrcOut:    // r = s * (1-da)
+    case DlBlendMode::kDstATop:   // r = d*sa + s*(1-da)
+    case DlBlendMode::kModulate:  // r = s*d
       return false;
       break;
 
     // And in these equations, the result must be d if the
     // source is 0
-    case SkBlendMode::kDst:         // r = d
-    case SkBlendMode::kSrcOver:     // r = s + (1-sa)*d
-    case SkBlendMode::kDstOver:     // r = d + (1-da)*s
-    case SkBlendMode::kDstOut:      // r = d * (1-sa)
-    case SkBlendMode::kSrcATop:     // r = s*da + d*(1-sa)
-    case SkBlendMode::kXor:         // r = s*(1-da) + d*(1-sa)
-    case SkBlendMode::kPlus:        // r = min(s + d, 1)
-    case SkBlendMode::kScreen:      // r = s + d - s*d
-    case SkBlendMode::kOverlay:     // multiply or screen, depending on dest
-    case SkBlendMode::kDarken:      // rc = s + d - max(s*da, d*sa),
+    case DlBlendMode::kDst:         // r = d
+    case DlBlendMode::kSrcOver:     // r = s + (1-sa)*d
+    case DlBlendMode::kDstOver:     // r = d + (1-da)*s
+    case DlBlendMode::kDstOut:      // r = d * (1-sa)
+    case DlBlendMode::kSrcATop:     // r = s*da + d*(1-sa)
+    case DlBlendMode::kXor:         // r = s*(1-da) + d*(1-sa)
+    case DlBlendMode::kPlus:        // r = min(s + d, 1)
+    case DlBlendMode::kScreen:      // r = s + d - s*d
+    case DlBlendMode::kOverlay:     // multiply or screen, depending on dest
+    case DlBlendMode::kDarken:      // rc = s + d - max(s*da, d*sa),
                                     // ra = kSrcOver
-    case SkBlendMode::kLighten:     // rc = s + d - min(s*da, d*sa),
+    case DlBlendMode::kLighten:     // rc = s + d - min(s*da, d*sa),
                                     // ra = kSrcOver
-    case SkBlendMode::kColorDodge:  // brighten destination to reflect source
-    case SkBlendMode::kColorBurn:   // darken destination to reflect source
-    case SkBlendMode::kHardLight:   // multiply or screen, depending on source
-    case SkBlendMode::kSoftLight:   // lighten or darken, depending on source
-    case SkBlendMode::kDifference:  // rc = s + d - 2*(min(s*da, d*sa)),
+    case DlBlendMode::kColorDodge:  // brighten destination to reflect source
+    case DlBlendMode::kColorBurn:   // darken destination to reflect source
+    case DlBlendMode::kHardLight:   // multiply or screen, depending on source
+    case DlBlendMode::kSoftLight:   // lighten or darken, depending on source
+    case DlBlendMode::kDifference:  // rc = s + d - 2*(min(s*da, d*sa)),
                                     // ra = kSrcOver
-    case SkBlendMode::kExclusion:   // rc = s + d - two(s*d), ra = kSrcOver
-    case SkBlendMode::kMultiply:    // r = s*(1-da) + d*(1-sa) + s*d
-    case SkBlendMode::kHue:         // ra = kSrcOver
-    case SkBlendMode::kSaturation:  // ra = kSrcOver
-    case SkBlendMode::kColor:       // ra = kSrcOver
-    case SkBlendMode::kLuminosity:  // ra = kSrcOver
+    case DlBlendMode::kExclusion:   // rc = s + d - two(s*d), ra = kSrcOver
+    case DlBlendMode::kMultiply:    // r = s*(1-da) + d*(1-sa) + s*d
+    case DlBlendMode::kHue:         // ra = kSrcOver
+    case DlBlendMode::kSaturation:  // ra = kSrcOver
+    case DlBlendMode::kColor:       // ra = kSrcOver
+    case DlBlendMode::kLuminosity:  // ra = kSrcOver
       return true;
       break;
   }
diff --git a/display_list/display_list_utils.h b/display_list/display_list_utils.h
index 4361bf6..7646c56 100644
--- a/display_list/display_list_utils.h
+++ b/display_list/display_list_utils.h
@@ -8,6 +8,7 @@
 #include <optional>
 
 #include "flutter/display_list/display_list.h"
+#include "flutter/display_list/display_list_blend_mode.h"
 #include "flutter/display_list/display_list_builder.h"
 #include "flutter/fml/logging.h"
 #include "flutter/fml/macros.h"
@@ -52,7 +53,7 @@
   void setStrokeWidth(SkScalar width) override {}
   void setStrokeMiter(SkScalar limit) override {}
   void setColor(SkColor color) override {}
-  void setBlendMode(SkBlendMode mode) override {}
+  void setBlendMode(DlBlendMode mode) override {}
   void setBlender(sk_sp<SkBlender> blender) override {}
   void setColorSource(const DlColorSource* source) override {}
   void setImageFilter(sk_sp<SkImageFilter> filter) override {}
@@ -97,7 +98,7 @@
   void saveLayer(const SkRect* bounds,
                  const SaveLayerOptions options) override {}
   void restore() override {}
-  void drawColor(SkColor color, SkBlendMode mode) override {}
+  void drawColor(SkColor color, DlBlendMode mode) override {}
   void drawPaint() override {}
   void drawLine(const SkPoint& p0, const SkPoint& p1) override {}
   void drawRect(const SkRect& rect) override {}
@@ -114,7 +115,7 @@
                   uint32_t count,
                   const SkPoint points[]) override {}
   void drawVertices(const sk_sp<SkVertices> vertices,
-                    SkBlendMode mode) override {}
+                    DlBlendMode mode) override {}
   void drawImage(const sk_sp<SkImage> image,
                  const SkPoint point,
                  const SkSamplingOptions& sampling,
@@ -140,7 +141,7 @@
                  const SkRect tex[],
                  const SkColor colors[],
                  int count,
-                 SkBlendMode mode,
+                 DlBlendMode mode,
                  const SkSamplingOptions& sampling,
                  const SkRect* cull_rect,
                  bool render_with_attributes) override {}
@@ -181,7 +182,7 @@
   void setColorSource(const DlColorSource* source) override;
   void setColorFilter(const DlColorFilter* filter) override;
   void setInvertColors(bool invert) override;
-  void setBlendMode(SkBlendMode mode) override;
+  void setBlendMode(DlBlendMode mode) override;
   void setBlender(sk_sp<SkBlender> blender) override;
   void setPathEffect(sk_sp<SkPathEffect> effect) override;
   void setMaskFilter(const DlMaskFilter* filter) override;
@@ -398,7 +399,7 @@
   void setStyle(SkPaint::Style style) override;
   void setStrokeWidth(SkScalar width) override;
   void setStrokeMiter(SkScalar limit) override;
-  void setBlendMode(SkBlendMode mode) override;
+  void setBlendMode(DlBlendMode mode) override;
   void setBlender(sk_sp<SkBlender> blender) override;
   void setImageFilter(sk_sp<SkImageFilter> filter) override;
   void setColorFilter(const DlColorFilter* filter) override;
@@ -410,7 +411,7 @@
   void restore() override;
 
   void drawPaint() override;
-  void drawColor(SkColor color, SkBlendMode mode) override;
+  void drawColor(SkColor color, DlBlendMode mode) override;
   void drawLine(const SkPoint& p0, const SkPoint& p1) override;
   void drawRect(const SkRect& rect) override;
   void drawOval(const SkRect& bounds) override;
@@ -426,7 +427,7 @@
                   uint32_t count,
                   const SkPoint pts[]) override;
   void drawVertices(const sk_sp<SkVertices> vertices,
-                    SkBlendMode mode) override;
+                    DlBlendMode mode) override;
   void drawImage(const sk_sp<SkImage> image,
                  const SkPoint point,
                  const SkSamplingOptions& sampling,
@@ -452,7 +453,7 @@
                  const SkRect tex[],
                  const SkColor colors[],
                  int count,
-                 SkBlendMode mode,
+                 DlBlendMode mode,
                  const SkSamplingOptions& sampling,
                  const SkRect* cullRect,
                  bool render_with_attributes) override;
@@ -570,7 +571,7 @@
 
   static constexpr SkScalar kMinStrokeWidth = 0.01;
 
-  std::optional<SkBlendMode> blend_mode_ = SkBlendMode::kSrcOver;
+  std::optional<DlBlendMode> blend_mode_ = DlBlendMode::kSrcOver;
   std::shared_ptr<const DlColorFilter> color_filter_;
 
   SkScalar half_stroke_width_ = kMinStrokeWidth;