[go: nahoru, domu]

Revert "Reland cc: Decode discardable images in PaintRecord backed shaders."

This reverts commit 53b8ed642644f245e3cb8d5cf2541bf3778ae7de.

Reason for revert: Causing flakiness on Linux Release (NVIDIA) for webgl_conformance_tests. See crbug.com/771156.

Original change's description:
> Reland cc: Decode discardable images in PaintRecord backed shaders.
> 
> This reverts commit fe24d7f3ac1b5bcfb840a5ada01627df90a099eb. Since we
> rasterize the SkPicture with decoded images in the test, we need to
> initialize its pixels. Fix that.
> 
> R=​enne@chromium.org
> TBR=chrishtr@chromium.org
> 
> Bug: 735741,728359
> Cq-Include-Trybots: master.tryserver.blink:linux_trusty_blink_rel
> Change-Id: I10989e2bc28594c9fa8e291559ae2753e65de29d
> Reviewed-on: https://chromium-review.googlesource.com/695449
> Reviewed-by: enne <enne@chromium.org>
> Commit-Queue: Khushal <khushalsagar@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#505885}

TBR=chrishtr@chromium.org,enne@chromium.org,khushalsagar@chromium.org

# Not skipping CQ checks because original CL landed > 1 day ago.

Bug: 735741, 728359
Change-Id: I9bc577e4f6488ef3bccb991609828db20467231f
Cq-Include-Trybots: master.tryserver.blink:linux_trusty_blink_rel
Reviewed-on: https://chromium-review.googlesource.com/699755
Reviewed-by: Khushal <khushalsagar@chromium.org>
Commit-Queue: Khushal <khushalsagar@chromium.org>
Cr-Commit-Position: refs/heads/master@{#506285}
diff --git a/cc/BUILD.gn b/cc/BUILD.gn
index 5c1b29be..447d732 100644
--- a/cc/BUILD.gn
+++ b/cc/BUILD.gn
@@ -606,8 +606,6 @@
     "paint/display_item_list_unittest.cc",
     "paint/paint_image_unittest.cc",
     "paint/paint_op_buffer_unittest.cc",
-    "paint/paint_shader_unittest.cc",
-    "paint/scoped_image_flags_unittest.cc",
     "paint/solid_color_analyzer_unittest.cc",
     "raster/playback_image_provider_unittest.cc",
     "raster/raster_buffer_provider_unittest.cc",
diff --git a/cc/paint/BUILD.gn b/cc/paint/BUILD.gn
index 037891d4..387800c5 100644
--- a/cc/paint/BUILD.gn
+++ b/cc/paint/BUILD.gn
@@ -45,8 +45,6 @@
     "paint_shader.h",
     "record_paint_canvas.cc",
     "record_paint_canvas.h",
-    "scoped_image_flags.cc",
-    "scoped_image_flags.h",
     "skia_paint_canvas.cc",
     "skia_paint_canvas.h",
     "skia_paint_image_generator.cc",
diff --git a/cc/paint/discardable_image_map.cc b/cc/paint/discardable_image_map.cc
index 05dbe8b..0d23dd3 100644
--- a/cc/paint/discardable_image_map.cc
+++ b/cc/paint/discardable_image_map.cc
@@ -27,8 +27,6 @@
   return dst;
 }
 
-// This canvas is used only for tracking transform/clip/filter state from the
-// non-drawing ops.
 class PaintTrackingCanvas final : public SkNoDrawCanvas {
  public:
   PaintTrackingCanvas(int width, int height) : SkNoDrawCanvas(width, height) {}
@@ -77,14 +75,52 @@
 
 class DiscardableImageGenerator {
  public:
-  DiscardableImageGenerator(int width,
-                            int height,
-                            const PaintOpBuffer* buffer) {
-    PaintTrackingCanvas canvas(width, height);
-    GatherDiscardableImages(buffer, nullptr, &canvas);
-  }
+  DiscardableImageGenerator(int width, int height) : canvas_(width, height) {}
   ~DiscardableImageGenerator() = default;
 
+  void GatherDiscardableImages(const PaintOpBuffer* buffer) {
+    if (!buffer->HasDiscardableImages())
+      return;
+
+    PlaybackParams params(nullptr, canvas_.getTotalMatrix());
+    canvas_.save();
+    // TODO(khushalsagar): Optimize out save/restore blocks if there are no
+    // images in the draw ops between them.
+    for (auto* op : PaintOpBuffer::Iterator(buffer)) {
+      if (op->IsDrawOp()) {
+        SkRect op_rect;
+        if (op->IsPaintOpWithFlags() && PaintOp::GetBounds(op, &op_rect)) {
+          AddImageFromFlags(op_rect,
+                            static_cast<const PaintOpWithFlags*>(op)->flags);
+        }
+
+        PaintOpType op_type = static_cast<PaintOpType>(op->type);
+        if (op_type == PaintOpType::DrawImage) {
+          auto* image_op = static_cast<DrawImageOp*>(op);
+          auto* sk_image = image_op->image.GetSkImage().get();
+          AddImage(image_op->image,
+                   SkRect::MakeIWH(sk_image->width(), sk_image->height()),
+                   SkRect::MakeXYWH(image_op->left, image_op->top,
+                                    sk_image->width(), sk_image->height()),
+                   nullptr, image_op->flags);
+        } else if (op_type == PaintOpType::DrawImageRect) {
+          auto* image_rect_op = static_cast<DrawImageRectOp*>(op);
+          SkMatrix matrix;
+          matrix.setRectToRect(image_rect_op->src, image_rect_op->dst,
+                               SkMatrix::kFill_ScaleToFit);
+          AddImage(image_rect_op->image, image_rect_op->src, image_rect_op->dst,
+                   &matrix, image_rect_op->flags);
+        } else if (op_type == PaintOpType::DrawRecord) {
+          GatherDiscardableImages(
+              static_cast<const DrawRecordOp*>(op)->record.get());
+        }
+      } else {
+        op->Raster(&canvas_, params);
+      }
+    }
+    canvas_.restore();
+  }
+
   std::vector<std::pair<DrawImage, gfx::Rect>> TakeImages() {
     return std::move(image_set_);
   }
@@ -117,112 +153,48 @@
   }
 
  private:
-  // Adds discardable images from |buffer| to the set of images tracked by
-  // this generator. If |buffer| is being used in a DrawOp that requires
-  // rasterization of the buffer as a pre-processing step for execution of the
-  // op (for instance, with PaintRecord backed PaintShaders),
-  // |top_level_op_rect| is set to the rect for that op. If provided, the
-  // |top_level_op_rect| will be used as the rect for tracking the position of
-  // this image in the top-level buffer.
-  void GatherDiscardableImages(const PaintOpBuffer* buffer,
-                               const gfx::Rect* top_level_op_rect,
-                               PaintTrackingCanvas* canvas) {
-    if (!buffer->HasDiscardableImages())
+  void AddImageFromFlags(const SkRect& rect, const PaintFlags& flags) {
+    if (!flags.HasShader() ||
+        flags.getShader()->shader_type() != PaintShader::Type::kImage)
       return;
 
-    // Prevent PaintOpBuffers from having side effects back into the canvas.
-    SkAutoCanvasRestore save_restore(canvas, true);
-
-    PlaybackParams params(nullptr, canvas->getTotalMatrix());
-    // TODO(khushalsagar): Optimize out save/restore blocks if there are no
-    // images in the draw ops between them.
-    for (auto* op : PaintOpBuffer::Iterator(buffer)) {
-      if (!op->IsDrawOp()) {
-        op->Raster(canvas, params);
-        continue;
-      } else if (!PaintOp::OpHasDiscardableImages(op)) {
-        continue;
-      }
-
-      gfx::Rect op_rect;
-      base::Optional<gfx::Rect> local_op_rect;
-
-      if (top_level_op_rect) {
-        op_rect = *top_level_op_rect;
-      } else {
-        local_op_rect = ComputePaintRect(op, canvas);
-        if (local_op_rect.value().IsEmpty())
-          continue;
-
-        op_rect = local_op_rect.value();
-      }
-
-      const SkMatrix& ctm = canvas->getTotalMatrix();
-      if (op->IsPaintOpWithFlags()) {
-        AddImageFromFlags(op_rect,
-                          static_cast<const PaintOpWithFlags*>(op)->flags, ctm);
-      }
-
-      PaintOpType op_type = static_cast<PaintOpType>(op->type);
-      if (op_type == PaintOpType::DrawImage) {
-        auto* image_op = static_cast<DrawImageOp*>(op);
-        auto* sk_image = image_op->image.GetSkImage().get();
-        AddImage(image_op->image,
-                 SkRect::MakeIWH(sk_image->width(), sk_image->height()),
-                 op_rect, ctm, image_op->flags.getFilterQuality());
-      } else if (op_type == PaintOpType::DrawImageRect) {
-        auto* image_rect_op = static_cast<DrawImageRectOp*>(op);
-        SkMatrix matrix = ctm;
-        matrix.postConcat(SkMatrix::MakeRectToRect(image_rect_op->src,
-                                                   image_rect_op->dst,
-                                                   SkMatrix::kFill_ScaleToFit));
-        AddImage(image_rect_op->image, image_rect_op->src, op_rect, matrix,
-                 image_rect_op->flags.getFilterQuality());
-      } else if (op_type == PaintOpType::DrawRecord) {
-        GatherDiscardableImages(
-            static_cast<const DrawRecordOp*>(op)->record.get(),
-            top_level_op_rect, canvas);
-      }
-    }
+    const PaintImage& paint_image = flags.getShader()->paint_image();
+    SkMatrix local_matrix = flags.getShader()->GetLocalMatrix();
+    AddImage(paint_image,
+             SkRect::MakeWH(paint_image.width(), paint_image.height()), rect,
+             &local_matrix, flags);
   }
 
-  // Given the |op_rect|, which is the rect for the draw op, returns the
-  // transformed rect accounting for the current transform, clip and paint
-  // state on |canvas_|.
-  gfx::Rect ComputePaintRect(const PaintOp* op, PaintTrackingCanvas* canvas) {
-    const SkRect& clip_rect = SkRect::Make(canvas->getDeviceClipBounds());
-    const SkMatrix& ctm = canvas->getTotalMatrix();
+  void AddImage(PaintImage paint_image,
+                const SkRect& src_rect,
+                const SkRect& rect,
+                const SkMatrix* local_matrix,
+                const PaintFlags& flags) {
+    if (!paint_image.IsLazyGenerated())
+      return;
 
-    gfx::Rect transformed_rect;
-    SkRect op_rect;
-    if (!PaintOp::GetBounds(op, &op_rect)) {
-      // If we can't provide a conservative bounding rect for the op, assume it
-      // covers the complete current clip.
-      transformed_rect = gfx::ToEnclosingRect(gfx::SkRectToRectF(clip_rect));
-    } else {
-      const PaintFlags* flags =
-          op->IsPaintOpWithFlags()
-              ? &static_cast<const PaintOpWithFlags*>(op)->flags
-              : nullptr;
-      SkPaint paint;
-      if (flags)
-        paint = flags->ToSkPaint();
+    const SkRect& clip_rect = SkRect::Make(canvas_.getDeviceClipBounds());
+    const SkMatrix& ctm = canvas_.getTotalMatrix();
 
-      SkRect paint_rect = MapRect(ctm, op_rect);
-      bool computed_paint_bounds =
-          canvas->ComputePaintBounds(paint_rect, &paint, &paint_rect);
-      if (!computed_paint_bounds) {
-        // TODO(vmpstr): UMA this case.
-        paint_rect = clip_rect;
-      }
-
-      // Clamp the image rect by the current clip rect.
-      if (!paint_rect.intersect(clip_rect))
-        return gfx::Rect();
-
-      transformed_rect = gfx::ToEnclosingRect(gfx::SkRectToRectF(paint_rect));
+    SkRect paint_rect = MapRect(ctm, rect);
+    SkPaint paint = flags.ToSkPaint();
+    bool computed_paint_bounds =
+        canvas_.ComputePaintBounds(paint_rect, &paint, &paint_rect);
+    if (!computed_paint_bounds) {
+      // TODO(vmpstr): UMA this case.
+      paint_rect = clip_rect;
     }
 
+    // Clamp the image rect by the current clip rect.
+    if (!paint_rect.intersect(clip_rect))
+      return;
+
+    SkFilterQuality filter_quality = flags.getFilterQuality();
+
+    SkIRect src_irect;
+    src_rect.roundOut(&src_irect);
+    gfx::Rect image_rect = gfx::ToEnclosingRect(gfx::SkRectToRectF(paint_rect));
+
     // During raster, we use the device clip bounds on the canvas, which outsets
     // the actual clip by 1 due to the possibility of antialiasing. Account for
     // this here by outsetting the image rect by 1. Note that this only affects
@@ -233,52 +205,7 @@
     // raster time, since we might be sending a larger-than-one-item display
     // item to skia, which means that skia will internally determine whether to
     // raster the picture (using device clip bounds that are outset).
-    transformed_rect.Inset(-1, -1);
-    return transformed_rect;
-  }
-
-  void AddImageFromFlags(const gfx::Rect& op_rect,
-                         const PaintFlags& flags,
-                         const SkMatrix& ctm) {
-    if (!flags.getShader())
-      return;
-
-    if (flags.getShader()->shader_type() == PaintShader::Type::kImage) {
-      const PaintImage& paint_image = flags.getShader()->paint_image();
-      SkMatrix matrix = ctm;
-      matrix.postConcat(flags.getShader()->GetLocalMatrix());
-      AddImage(paint_image,
-               SkRect::MakeWH(paint_image.width(), paint_image.height()),
-               op_rect, matrix, flags.getFilterQuality());
-    } else if (flags.getShader()->shader_type() ==
-                   PaintShader::Type::kPaintRecord &&
-               flags.getShader()->paint_record()->HasDiscardableImages()) {
-      SkRect scaled_tile_rect;
-      if (!flags.getShader()->GetRasterizationTileRect(ctm,
-                                                       &scaled_tile_rect)) {
-        return;
-      }
-
-      PaintTrackingCanvas canvas(scaled_tile_rect.width(),
-                                 scaled_tile_rect.height());
-      canvas.setMatrix(SkMatrix::MakeRectToRect(flags.getShader()->tile(),
-                                                scaled_tile_rect,
-                                                SkMatrix::kFill_ScaleToFit));
-      GatherDiscardableImages(flags.getShader()->paint_record().get(), &op_rect,
-                              &canvas);
-    }
-  }
-
-  void AddImage(PaintImage paint_image,
-                const SkRect& src_rect,
-                const gfx::Rect& image_rect,
-                const SkMatrix& matrix,
-                SkFilterQuality filter_quality) {
-    if (!paint_image.IsLazyGenerated())
-      return;
-
-    SkIRect src_irect;
-    src_rect.roundOut(&src_irect);
+    image_rect.Inset(-1, -1);
 
     // Make a note if any image was originally specified in a non-sRGB color
     // space.
@@ -290,6 +217,10 @@
       color_stats_srgb_image_count_++;
     }
 
+    SkMatrix matrix = ctm;
+    if (local_matrix)
+      matrix.postConcat(*local_matrix);
+
     image_id_to_rect_[paint_image.stable_id()].Union(image_rect);
 
     if (paint_image.ShouldAnimate()) {
@@ -304,6 +235,9 @@
         image_rect);
   }
 
+  // This canvas is used only for tracking transform/clip/filter state from the
+  // non-drawing ops.
+  PaintTrackingCanvas canvas_;
   std::vector<std::pair<DrawImage, gfx::Rect>> image_set_;
   base::flat_map<PaintImage::Id, gfx::Rect> image_id_to_rect_;
   std::vector<DiscardableImageMap::AnimatedImageMetadata>
@@ -329,8 +263,8 @@
   if (!paint_op_buffer->HasDiscardableImages())
     return;
 
-  DiscardableImageGenerator generator(bounds.right(), bounds.bottom(),
-                                      paint_op_buffer);
+  DiscardableImageGenerator generator(bounds.right(), bounds.bottom());
+  generator.GatherDiscardableImages(paint_op_buffer);
   generator.RecordColorHistograms();
   image_id_to_rect_ = generator.TakeImageIdToRectMap();
   animated_images_metadata_ = generator.TakeAnimatedImagesMetadata();
diff --git a/cc/paint/discardable_image_map_unittest.cc b/cc/paint/discardable_image_map_unittest.cc
index 4530746..0e8a6d20e 100644
--- a/cc/paint/discardable_image_map_unittest.cc
+++ b/cc/paint/discardable_image_map_unittest.cc
@@ -747,43 +747,6 @@
   EXPECT_DCHECK_DEATH(images[2]->frame_index());
 }
 
-TEST_F(DiscardableImageMapTest, CapturesImagesInPaintRecordShaders) {
-  // Create the record to use in the shader.
-  auto shader_record = sk_make_sp<PaintOpBuffer>();
-  shader_record->push<ScaleOp>(2.0f, 2.0f);
-  PaintImage paint_image = CreateDiscardablePaintImage(gfx::Size(100, 100));
-  shader_record->push<DrawImageOp>(paint_image, 0.f, 0.f, nullptr);
-
-  gfx::Rect visible_rect(500, 500);
-  scoped_refptr<DisplayItemList> display_list = new DisplayItemList();
-  display_list->StartPaint();
-  display_list->push<ScaleOp>(2.0f, 2.0f);
-  PaintFlags flags;
-  SkRect tile = SkRect::MakeWH(100, 100);
-  flags.setShader(PaintShader::MakePaintRecord(
-      shader_record, tile, SkShader::TileMode::kClamp_TileMode,
-      SkShader::TileMode::kClamp_TileMode, nullptr));
-  display_list->push<DrawRectOp>(SkRect::MakeWH(200, 200), flags);
-  display_list->EndPaintOfUnpaired(visible_rect);
-  display_list->Finalize();
-
-  display_list->GenerateDiscardableImagesMetadata();
-  const auto& image_map = display_list->discardable_image_map();
-
-  // The image rect is set to the rect for the DrawRectOp.
-  std::vector<PositionScaleDrawImage> draw_images =
-      GetDiscardableImagesInRect(image_map, visible_rect);
-  std::vector<gfx::Rect> inset_rects = InsetImageRects(draw_images);
-  ASSERT_EQ(draw_images.size(), 1u);
-  EXPECT_EQ(draw_images[0].image, paint_image);
-  // The position of the image is the position of the DrawRectOp that uses the
-  // shader.
-  EXPECT_EQ(gfx::Rect(400, 400), inset_rects[0]);
-  // The scale of the image includes the scale at which the shader record is
-  // rasterized.
-  EXPECT_EQ(SkSize::Make(4.f, 4.f), draw_images[0].scale);
-}
-
 class DiscardableImageMapColorSpaceTest
     : public DiscardableImageMapTest,
       public testing::WithParamInterface<gfx::ColorSpace> {};
diff --git a/cc/paint/paint_op_buffer.cc b/cc/paint/paint_op_buffer.cc
index 089746c..b7b1825 100644
--- a/cc/paint/paint_op_buffer.cc
+++ b/cc/paint/paint_op_buffer.cc
@@ -13,7 +13,6 @@
 #include "cc/paint/paint_op_reader.h"
 #include "cc/paint/paint_op_writer.h"
 #include "cc/paint/paint_record.h"
-#include "cc/paint/scoped_image_flags.h"
 #include "third_party/skia/include/core/SkAnnotation.h"
 #include "third_party/skia/include/core/SkCanvas.h"
 #include "third_party/skia/include/core/SkRegion.h"
@@ -26,6 +25,22 @@
   return result;
 }
 
+bool IsImageShader(const PaintFlags& flags) {
+  return flags.HasShader() &&
+         flags.getShader()->shader_type() == PaintShader::Type::kImage;
+}
+
+bool IsImageOp(const PaintOp* op) {
+  if (op->GetType() == PaintOpType::DrawImage)
+    return true;
+  else if (op->GetType() == PaintOpType::DrawImageRect)
+    return true;
+  else if (op->IsDrawOp() && op->IsPaintOpWithFlags())
+    return IsImageShader(static_cast<const PaintOpWithFlags*>(op)->flags);
+
+  return false;
+}
+
 bool QuickRejectDraw(const PaintOp* op, const SkCanvas* canvas) {
   DCHECK(op->IsDrawOp());
 
@@ -43,6 +58,65 @@
   return canvas->quickReject(rect);
 }
 
+// Encapsulates a ImageProvider::DecodedImageHolder and a SkPaint. Use of
+// this class ensures that the DecodedImageHolder outlives the dependent
+// SkPaint.
+class ScopedImageFlags {
+ public:
+  ScopedImageFlags(ImageProvider* image_provider,
+                   const PaintFlags& flags,
+                   const SkMatrix& ctm) {
+    DCHECK(IsImageShader(flags));
+
+    const PaintImage& paint_image = flags.getShader()->paint_image();
+    SkMatrix matrix = flags.getShader()->GetLocalMatrix();
+
+    SkMatrix total_image_matrix = matrix;
+    total_image_matrix.preConcat(ctm);
+    SkRect src_rect =
+        SkRect::MakeIWH(paint_image.width(), paint_image.height());
+    DrawImage draw_image(paint_image, RoundOutRect(src_rect),
+                         flags.getFilterQuality(), total_image_matrix);
+    scoped_decoded_draw_image_ =
+        image_provider->GetDecodedDrawImage(draw_image);
+
+    if (!scoped_decoded_draw_image_)
+      return;
+    const auto& decoded_image = scoped_decoded_draw_image_.decoded_image();
+    DCHECK(decoded_image.image());
+
+    bool need_scale = !decoded_image.is_scale_adjustment_identity();
+    if (need_scale) {
+      matrix.preScale(1.f / decoded_image.scale_adjustment().width(),
+                      1.f / decoded_image.scale_adjustment().height());
+    }
+
+    sk_sp<SkImage> sk_image =
+        sk_ref_sp<SkImage>(const_cast<SkImage*>(decoded_image.image().get()));
+    PaintImage decoded_paint_image = PaintImageBuilder()
+                                         .set_id(paint_image.stable_id())
+                                         .set_image(std::move(sk_image))
+                                         .TakePaintImage();
+    decoded_flags_.emplace(flags);
+    decoded_flags_.value().setFilterQuality(decoded_image.filter_quality());
+    decoded_flags_.value().setShader(
+        PaintShader::MakeImage(decoded_paint_image, flags.getShader()->tx(),
+                               flags.getShader()->ty(), &matrix));
+  }
+
+  PaintFlags* decoded_flags() {
+    return decoded_flags_ ? &decoded_flags_.value() : nullptr;
+  }
+
+  ~ScopedImageFlags() = default;
+
+ private:
+  base::Optional<PaintFlags> decoded_flags_;
+  ImageProvider::ScopedDecodedDrawImage scoped_decoded_draw_image_;
+
+  DISALLOW_COPY_AND_ASSIGN(ScopedImageFlags);
+};
+
 void RasterWithAlpha(const PaintOp* op,
                      SkCanvas* canvas,
                      const PlaybackParams& params,
@@ -59,7 +133,7 @@
     // ImageProvider if it consists of an image shader.
     base::Optional<ScopedImageFlags> scoped_flags;
     const PaintFlags* decoded_flags = &flags_op->flags;
-    if (params.image_provider && flags_op->HasDiscardableImagesFromFlags()) {
+    if (params.image_provider && IsImageShader(flags_op->flags)) {
       scoped_flags.emplace(params.image_provider, flags_op->flags,
                            canvas->getTotalMatrix());
       decoded_flags = scoped_flags.value().decoded_flags();
@@ -1381,47 +1455,12 @@
   return false;
 }
 
-// static
-bool PaintOp::OpHasDiscardableImages(const PaintOp* op) {
-  if (op->IsPaintOpWithFlags() && static_cast<const PaintOpWithFlags*>(op)
-                                      ->HasDiscardableImagesFromFlags()) {
-    return true;
-  }
-
-  if (op->GetType() == PaintOpType::DrawImage &&
-      static_cast<const DrawImageOp*>(op)->HasDiscardableImages()) {
-    return true;
-  } else if (op->GetType() == PaintOpType::DrawImageRect &&
-             static_cast<const DrawImageRectOp*>(op)->HasDiscardableImages()) {
-    return true;
-  } else if (op->GetType() == PaintOpType::DrawRecord &&
-             static_cast<const DrawRecordOp*>(op)->HasDiscardableImages()) {
-    return true;
-  }
-
-  return false;
-}
-
 void PaintOp::DestroyThis() {
   auto func = g_destructor_functions[type];
   if (func)
     func(this);
 }
 
-bool PaintOpWithFlags::HasDiscardableImagesFromFlags() const {
-  if (!IsDrawOp())
-    return false;
-
-  if (!flags.HasShader())
-    return false;
-  else if (flags.getShader()->shader_type() == PaintShader::Type::kImage)
-    return flags.getShader()->paint_image().IsLazyGenerated();
-  else if (flags.getShader()->shader_type() == PaintShader::Type::kPaintRecord)
-    return flags.getShader()->paint_record()->HasDiscardableImages();
-
-  return false;
-}
-
 void PaintOpWithFlags::RasterWithFlags(SkCanvas* canvas,
                                        const PaintFlags* flags,
                                        const PlaybackParams& params) const {
@@ -1699,8 +1738,7 @@
           // general case we defer this to the SkCanvas but if we will be
           // using an ImageProvider for pre-decoding images, we can save
           // performing an expensive decode that will never be rasterized.
-          const bool skip_op = params.image_provider &&
-                               PaintOp::OpHasDiscardableImages(draw_op) &&
+          const bool skip_op = params.image_provider && IsImageOp(draw_op) &&
                                QuickRejectDraw(draw_op, canvas);
           if (skip_op) {
             // Now that we know this op will be skipped, we can push the save
@@ -1730,15 +1768,15 @@
       }
     }
 
-    if (params.image_provider && PaintOp::OpHasDiscardableImages(op)) {
+    if (params.image_provider && IsImageOp(op)) {
       if (QuickRejectDraw(op, canvas))
         continue;
 
       auto* flags_op = op->IsPaintOpWithFlags()
                            ? static_cast<const PaintOpWithFlags*>(op)
                            : nullptr;
-      if (flags_op && flags_op->HasDiscardableImagesFromFlags()) {
-        ScopedImageFlags scoped_flags(params.image_provider, flags_op->flags,
+      if (flags_op && IsImageShader(flags_op->flags)) {
+        ScopedImageFlags scoped_flags(image_provider, flags_op->flags,
                                       canvas->getTotalMatrix());
 
         // Only rasterize the op if we successfully decoded the image.
diff --git a/cc/paint/paint_op_buffer.h b/cc/paint/paint_op_buffer.h
index 96eb7f7..17405ec 100644
--- a/cc/paint/paint_op_buffer.h
+++ b/cc/paint/paint_op_buffer.h
@@ -15,7 +15,6 @@
 #include "base/memory/aligned_memory.h"
 #include "base/optional.h"
 #include "cc/base/math_util.h"
-#include "cc/paint/image_provider.h"
 #include "cc/paint/paint_canvas.h"
 #include "cc/paint/paint_export.h"
 #include "cc/paint/paint_flags.h"
@@ -30,6 +29,7 @@
 
 namespace cc {
 class ImageDecodeCache;
+class ImageProvider;
 
 class CC_PAINT_EXPORT ThreadsafeMatrix : public SkMatrix {
  public:
@@ -137,10 +137,6 @@
   // for the op.
   static bool GetBounds(const PaintOp* op, SkRect* rect);
 
-  // Returns true if executing this op will require decoding of any lazy
-  // generated images.
-  static bool OpHasDiscardableImages(const PaintOp* op);
-
   int CountSlowPaths() const { return 0; }
   int CountSlowPathsFromFlags() const { return 0; }
 
@@ -199,7 +195,14 @@
 
   int CountSlowPathsFromFlags() const { return flags.getPathEffect() ? 1 : 0; }
   bool HasNonAAPaint() const { return !flags.isAntiAlias(); }
-  bool HasDiscardableImagesFromFlags() const;
+  bool HasDiscardableImagesFromFlags() const {
+    if (!IsDrawOp())
+      return false;
+
+    SkShader* shader = flags.getSkShader();
+    SkImage* image = shader ? shader->isAImage(nullptr, nullptr) : nullptr;
+    return image && image->isLazyGenerated();
+  }
 
   void RasterWithFlags(SkCanvas* canvas,
                        const PaintFlags* flags,
@@ -978,7 +981,6 @@
   friend class DisplayItemList;
   friend class PaintOpBufferOffsetsTest;
   friend class SolidColorAnalyzer;
-  friend class ScopedImageFlags;
 
   // Replays the paint op buffer into the canvas. If |indices| is specified, it
   // contains indices in an increasing order and only the indices specified in
diff --git a/cc/paint/paint_shader.cc b/cc/paint/paint_shader.cc
index 6f0767086..7d0b8cf 100644
--- a/cc/paint/paint_shader.cc
+++ b/cc/paint/paint_shader.cc
@@ -6,25 +6,9 @@
 
 #include "base/memory/ptr_util.h"
 #include "cc/paint/paint_record.h"
-#include "third_party/skia/include/core/SkPictureRecorder.h"
 #include "third_party/skia/include/effects/SkGradientShader.h"
 
 namespace cc {
-namespace {
-
-sk_sp<SkPicture> ToSkPicture(sk_sp<PaintRecord> record,
-                             const SkRect& bounds,
-                             const SkMatrix* matrix,
-                             ImageProvider* image_provider) {
-  SkPictureRecorder recorder;
-  SkCanvas* canvas = recorder.beginRecording(bounds);
-  if (matrix)
-    canvas->setMatrix(*matrix);
-  record->Playback(canvas, image_provider);
-  return recorder.finishRecordingAsPicture();
-}
-
-}  // namespace
 
 sk_sp<PaintShader> PaintShader::MakeColor(SkColor color) {
   sk_sp<PaintShader> shader(new PaintShader(Type::kColor));
@@ -155,96 +139,6 @@
 PaintShader::PaintShader(Type type) : shader_type_(type) {}
 PaintShader::~PaintShader() = default;
 
-bool PaintShader::GetRasterizationTileRect(const SkMatrix& ctm,
-                                           SkRect* tile_rect) const {
-  DCHECK_EQ(shader_type_, Type::kPaintRecord);
-
-  // If we are using a fixed scale, the record is rasterized with the original
-  // tile size and scaling is applied to the generated output.
-  if (scaling_behavior_ == ScalingBehavior::kFixedScale) {
-    *tile_rect = tile_;
-    return true;
-  }
-
-  SkMatrix matrix = ctm;
-  if (local_matrix_.has_value())
-    matrix.preConcat(local_matrix_.value());
-
-  SkSize scale;
-  if (!matrix.decomposeScale(&scale)) {
-    // Decomposition failed, use an approximation.
-    scale.set(SkScalarSqrt(matrix.getScaleX() * matrix.getScaleX() +
-                           matrix.getSkewX() * matrix.getSkewX()),
-              SkScalarSqrt(matrix.getScaleY() * matrix.getScaleY() +
-                           matrix.getSkewY() * matrix.getSkewY()));
-  }
-  SkSize scaled_size =
-      SkSize::Make(SkScalarAbs(scale.width() * tile_.width()),
-                   SkScalarAbs(scale.height() * tile_.height()));
-
-  // Clamp the tile size to about 4M pixels.
-  // TODO(khushalsagar): We need to consider the max texture size as well.
-  static const SkScalar kMaxTileArea = 2048 * 2048;
-  SkScalar tile_area = scaled_size.width() * scaled_size.height();
-  if (tile_area > kMaxTileArea) {
-    SkScalar clamp_scale = SkScalarSqrt(kMaxTileArea / tile_area);
-    scaled_size.set(scaled_size.width() * clamp_scale,
-                    scaled_size.height() * clamp_scale);
-  }
-
-  scaled_size = scaled_size.toCeil();
-  if (scaled_size.isEmpty())
-    return false;
-
-  *tile_rect = SkRect::MakeWH(scaled_size.width(), scaled_size.height());
-  return true;
-}
-
-sk_sp<PaintShader> PaintShader::CreateDecodedPaintRecord(
-    const SkMatrix& ctm,
-    ImageProvider* image_provider) const {
-  DCHECK_EQ(shader_type_, Type::kPaintRecord);
-
-  // For creating a decoded PaintRecord shader, we need to do the following:
-  // 1) Figure out the scale at which the record should be rasterization given
-  //    the ctm and local_matrix on the shader.
-  // 2) Transform this record to an SkPicture with this scale and replace
-  //    encoded images in this record with decodes from the ImageProvider. This
-  //    is done by setting the rasterization_matrix_ for this shader to be used
-  //    in GetSkShader.
-  // 3) Since the SkShader will use a scaled SkPicture, we use a kFixedScale for
-  //    the decoded shader which creates an SkPicture backed SkImage for
-  //    creating the decoded SkShader.
-  // Note that the scaling logic here is replicated from
-  // SkPictureShader::refBitmapShader.
-  SkRect tile_rect;
-  if (!GetRasterizationTileRect(ctm, &tile_rect))
-    return nullptr;
-
-  sk_sp<PaintShader> shader(new PaintShader(Type::kPaintRecord));
-  shader->record_ = record_;
-  shader->tile_ = tile_rect;
-  // Use a fixed scale since we have already scaled the tile rect and fixed the
-  // raster scale.
-  shader->scaling_behavior_ = ScalingBehavior::kFixedScale;
-  shader->rasterization_matrix_.emplace();
-  shader->rasterization_matrix_.value().setRectToRect(
-      tile_, tile_rect, SkMatrix::kFill_ScaleToFit);
-  shader->tx_ = tx_;
-  shader->ty_ = ty_;
-
-  const SkSize tile_scale =
-      SkSize::Make(SkIntToScalar(tile_rect.width()) / tile_.width(),
-                   SkIntToScalar(tile_rect.height()) / tile_.height());
-  shader->local_matrix_ = GetLocalMatrix();
-  shader->local_matrix_->preScale(1 / tile_scale.width(),
-                                  1 / tile_scale.height());
-
-  shader->image_provider_ = image_provider;
-
-  return shader;
-}
-
 sk_sp<SkShader> PaintShader::GetSkShader() const {
   if (cached_shader_)
     return cached_shader_;
@@ -288,12 +182,7 @@
           tx_, ty_, local_matrix_ ? &*local_matrix_ : nullptr);
       break;
     case Type::kPaintRecord: {
-      // Create a recording at the desired scale if this record has images which
-      // have been decoded before raster.
-      auto picture = ToSkPicture(
-          record_, tile_,
-          rasterization_matrix_ ? &rasterization_matrix_.value() : nullptr,
-          image_provider_);
+      auto picture = ToSkPicture(record_, tile_);
 
       switch (scaling_behavior_) {
         // For raster scale, we create a picture shader directly.
@@ -302,7 +191,7 @@
               std::move(picture), tx_, ty_,
               local_matrix_ ? &*local_matrix_ : nullptr, nullptr);
           break;
-        // For fixed scale, we create an image shader with an image backed by
+        // For fixed scale, we create an image shader with and image backed by
         // the picture.
         case ScalingBehavior::kFixedScale: {
           auto image = SkImage::MakeFromPicture(
diff --git a/cc/paint/paint_shader.h b/cc/paint/paint_shader.h
index 42ec44be..8a133709 100644
--- a/cc/paint/paint_shader.h
+++ b/cc/paint/paint_shader.h
@@ -16,7 +16,7 @@
 #include "third_party/skia/include/core/SkShader.h"
 
 namespace cc {
-class ImageProvider;
+
 class PaintOpBuffer;
 using PaintRecord = PaintOpBuffer;
 
@@ -111,12 +111,8 @@
     return image_;
   }
 
-  const sk_sp<PaintRecord>& paint_record() const { return record_; }
-  bool GetRasterizationTileRect(const SkMatrix& ctm, SkRect* tile_rect) const;
-
   SkShader::TileMode tx() const { return tx_; }
   SkShader::TileMode ty() const { return ty_; }
-  SkRect tile() const { return tile_; }
 
   bool IsOpaque() const;
 
@@ -131,17 +127,11 @@
   friend class PaintOpReader;
   friend class PaintOpSerializationTestUtils;
   friend class PaintOpWriter;
-  friend class ScopedImageFlags;
-  FRIEND_TEST_ALL_PREFIXES(PaintShaderTest, DecodePaintRecord);
 
   explicit PaintShader(Type type);
 
   sk_sp<SkShader> GetSkShader() const;
 
-  sk_sp<PaintShader> CreateDecodedPaintRecord(
-      const SkMatrix& ctm,
-      ImageProvider* image_provider) const;
-
   void SetColorsAndPositions(const SkColor* colors,
                              const SkScalar* positions,
                              int count);
@@ -176,12 +166,6 @@
   std::vector<SkColor> colors_;
   std::vector<SkScalar> positions_;
 
-  // The following are only used during raster to replace the decoded images in
-  // the record for this shader. The |image_provider_| and
-  // |decoded_image_stash_| must outlive this shader.
-  ImageProvider* image_provider_ = nullptr;
-  base::Optional<SkMatrix> rasterization_matrix_;
-
   mutable sk_sp<SkShader> cached_shader_;
 
   DISALLOW_COPY_AND_ASSIGN(PaintShader);
diff --git a/cc/paint/paint_shader_unittest.cc b/cc/paint/paint_shader_unittest.cc
deleted file mode 100644
index 340bbc3..0000000
--- a/cc/paint/paint_shader_unittest.cc
+++ /dev/null
@@ -1,120 +0,0 @@
-// Copyright 2015 The Chromium 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 "cc/paint/paint_shader.h"
-
-#include "cc/paint/draw_image.h"
-#include "cc/paint/image_provider.h"
-#include "cc/paint/paint_image_builder.h"
-#include "cc/paint/paint_op_buffer.h"
-#include "cc/test/fake_paint_image_generator.h"
-#include "cc/test/skia_common.h"
-#include "cc/test/test_skcanvas.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/skia/include/core/SkSurface.h"
-
-namespace cc {
-namespace {
-
-class MockImageGenerator : public FakePaintImageGenerator {
- public:
-  explicit MockImageGenerator(const gfx::Size& size)
-      : FakePaintImageGenerator(
-            SkImageInfo::MakeN32Premul(size.width(), size.height())) {}
-
-  MOCK_METHOD5(GetPixels,
-               bool(const SkImageInfo&, void*, size_t, size_t, uint32_t));
-};
-
-class MockImageProvider : public ImageProvider {
- public:
-  MockImageProvider() = default;
-  ~MockImageProvider() override = default;
-
-  ScopedDecodedDrawImage GetDecodedDrawImage(
-      const DrawImage& draw_image) override {
-    draw_image_ = draw_image;
-
-    SkBitmap bitmap;
-    bitmap.allocN32Pixels(10, 10);
-    bitmap.eraseColor(SK_ColorBLACK);
-    sk_sp<SkImage> image = SkImage::MakeFromBitmap(bitmap);
-    return ScopedDecodedDrawImage(
-        DecodedDrawImage(image, SkSize::MakeEmpty(), SkSize::Make(1.0f, 1.0f),
-                         draw_image.filter_quality()));
-  }
-
-  const DrawImage& draw_image() const { return draw_image_; }
-
- private:
-  DrawImage draw_image_;
-};
-
-}  // namespace
-
-TEST(PaintShaderTest, RasterizationRectForRecordShaders) {
-  SkMatrix local_matrix = SkMatrix::MakeScale(0.5f, 0.5f);
-  auto record_shader = PaintShader::MakePaintRecord(
-      sk_make_sp<PaintOpBuffer>(), SkRect::MakeWH(100, 100),
-      SkShader::TileMode::kClamp_TileMode, SkShader::TileMode::kClamp_TileMode,
-      &local_matrix);
-
-  SkRect tile_rect;
-  SkMatrix ctm = SkMatrix::MakeScale(0.5f, 0.5f);
-  EXPECT_TRUE(record_shader->GetRasterizationTileRect(ctm, &tile_rect));
-  EXPECT_EQ(tile_rect, SkRect::MakeWH(25, 25));
-}
-
-TEST(PaintShaderTest, DecodePaintRecord) {
-  auto record = sk_make_sp<PaintOpBuffer>();
-
-  // Use a strict mock for the generator. It should never be used when
-  // rasterizing this shader, since the decode should be done by the
-  // ImageProvider.
-  auto generator =
-      sk_make_sp<testing::StrictMock<MockImageGenerator>>(gfx::Size(100, 100));
-  PaintImage paint_image = PaintImageBuilder()
-                               .set_id(PaintImage::GetNextId())
-                               .set_paint_image_generator(generator)
-                               .TakePaintImage();
-
-  record->push<DrawImageOp>(paint_image, 0.f, 0.f, nullptr);
-  SkMatrix local_matrix = SkMatrix::MakeScale(0.5f, 0.5f);
-  auto record_shader = PaintShader::MakePaintRecord(
-      record, SkRect::MakeWH(100, 100), SkShader::TileMode::kClamp_TileMode,
-      SkShader::TileMode::kClamp_TileMode, &local_matrix);
-
-  PaintOpBuffer buffer;
-  PaintFlags flags;
-  flags.setShader(record_shader);
-  buffer.push<ScaleOp>(0.5f, 0.5f);
-  buffer.push<DrawRectOp>(SkRect::MakeWH(100, 100), flags);
-
-  MockImageProvider image_provider;
-  SaveCountingCanvas canvas;
-  buffer.Playback(&canvas, &image_provider);
-
-  EXPECT_EQ(canvas.draw_rect_, SkRect::MakeWH(100, 100));
-  SkShader* shader = canvas.paint_.getShader();
-  ASSERT_TRUE(shader);
-  SkMatrix decoded_local_matrix;
-  SkShader::TileMode xy[2];
-  SkImage* skia_image = shader->isAImage(&decoded_local_matrix, xy);
-  ASSERT_TRUE(skia_image);
-  EXPECT_TRUE(skia_image->isLazyGenerated());
-  EXPECT_EQ(xy[0], record_shader->tx());
-  EXPECT_EQ(xy[1], record_shader->ty());
-  EXPECT_EQ(decoded_local_matrix, SkMatrix::MakeScale(2.f, 2.f));
-
-  // The rasterization of the shader is internal to skia, so use a raster canvas
-  // to verify that the decoded paint does not have the encoded image.
-  auto surface = SkSurface::MakeRaster(SkImageInfo::MakeN32Premul(100, 100));
-  surface->getCanvas()->drawPaint(canvas.paint_);
-
-  // Using the shader requests decode for images at the correct scale.
-  EXPECT_EQ(image_provider.draw_image().paint_image(), paint_image);
-  EXPECT_EQ(image_provider.draw_image().scale(), SkSize::Make(0.25f, 0.25f));
-}
-
-}  // namespace cc
diff --git a/cc/paint/scoped_image_flags.cc b/cc/paint/scoped_image_flags.cc
deleted file mode 100644
index cadb1da..0000000
--- a/cc/paint/scoped_image_flags.cc
+++ /dev/null
@@ -1,103 +0,0 @@
-// Copyright 2017 The Chromium 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 "cc/paint/scoped_image_flags.h"
-
-#include "cc/paint/image_provider.h"
-#include "cc/paint/paint_image_builder.h"
-
-namespace cc {
-namespace {
-SkIRect RoundOutRect(const SkRect& rect) {
-  SkIRect result;
-  rect.roundOut(&result);
-  return result;
-}
-}  // namespace
-
-ScopedImageFlags::DecodeStashingImageProvider::DecodeStashingImageProvider(
-    ImageProvider* source_provider)
-    : source_provider_(source_provider) {}
-ScopedImageFlags::DecodeStashingImageProvider::~DecodeStashingImageProvider() =
-    default;
-
-ImageProvider::ScopedDecodedDrawImage
-ScopedImageFlags::DecodeStashingImageProvider::GetDecodedDrawImage(
-    const DrawImage& draw_image) {
-  auto decode = source_provider_->GetDecodedDrawImage(draw_image);
-  if (!decode)
-    return ScopedDecodedDrawImage();
-
-  // No need to add any destruction callback to the returned image. The images
-  // decoded here match the lifetime of this provider.
-  auto image_to_return = ScopedDecodedDrawImage(decode.decoded_image());
-  decoded_images_.push_back(std::move(decode));
-  return image_to_return;
-}
-
-ScopedImageFlags::ScopedImageFlags(ImageProvider* image_provider,
-                                   const PaintFlags& flags,
-                                   const SkMatrix& ctm)
-    : decode_stashing_image_provider_(image_provider) {
-  if (flags.getShader()->shader_type() == PaintShader::Type::kImage) {
-    DecodeImageShader(flags, ctm);
-  } else {
-    DCHECK_EQ(flags.getShader()->shader_type(),
-              PaintShader::Type::kPaintRecord);
-    DecodeRecordShader(flags, ctm);
-  }
-}
-
-ScopedImageFlags::~ScopedImageFlags() = default;
-
-void ScopedImageFlags::DecodeImageShader(const PaintFlags& flags,
-                                         const SkMatrix& ctm) {
-  const PaintImage& paint_image = flags.getShader()->paint_image();
-  SkMatrix matrix = flags.getShader()->GetLocalMatrix();
-
-  SkMatrix total_image_matrix = matrix;
-  total_image_matrix.preConcat(ctm);
-  SkRect src_rect = SkRect::MakeIWH(paint_image.width(), paint_image.height());
-  DrawImage draw_image(paint_image, RoundOutRect(src_rect),
-                       flags.getFilterQuality(), total_image_matrix);
-  auto decoded_draw_image =
-      decode_stashing_image_provider_.GetDecodedDrawImage(draw_image);
-
-  if (!decoded_draw_image)
-    return;
-
-  const auto& decoded_image = decoded_draw_image.decoded_image();
-  DCHECK(decoded_image.image());
-
-  bool need_scale = !decoded_image.is_scale_adjustment_identity();
-  if (need_scale) {
-    matrix.preScale(1.f / decoded_image.scale_adjustment().width(),
-                    1.f / decoded_image.scale_adjustment().height());
-  }
-
-  sk_sp<SkImage> sk_image =
-      sk_ref_sp<SkImage>(const_cast<SkImage*>(decoded_image.image().get()));
-  PaintImage decoded_paint_image = PaintImageBuilder()
-                                       .set_id(paint_image.stable_id())
-                                       .set_image(std::move(sk_image))
-                                       .TakePaintImage();
-  decoded_flags_.emplace(flags);
-  decoded_flags_.value().setFilterQuality(decoded_image.filter_quality());
-  decoded_flags_.value().setShader(
-      PaintShader::MakeImage(decoded_paint_image, flags.getShader()->tx(),
-                             flags.getShader()->ty(), &matrix));
-}
-
-void ScopedImageFlags::DecodeRecordShader(const PaintFlags& flags,
-                                          const SkMatrix& ctm) {
-  auto decoded_shader = flags.getShader()->CreateDecodedPaintRecord(
-      ctm, &decode_stashing_image_provider_);
-  if (!decoded_shader)
-    return;
-
-  decoded_flags_.emplace(flags);
-  decoded_flags_.value().setShader(std::move(decoded_shader));
-}
-
-}  // namespace cc
diff --git a/cc/paint/scoped_image_flags.h b/cc/paint/scoped_image_flags.h
deleted file mode 100644
index 9c39bf8..0000000
--- a/cc/paint/scoped_image_flags.h
+++ /dev/null
@@ -1,66 +0,0 @@
-// Copyright 2017 The Chromium 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 CC_PAINT_SCOPED_IMAGE_FLAGS_H_
-#define CC_PAINT_SCOPED_IMAGE_FLAGS_H_
-
-#include "base/macros.h"
-#include "cc/paint/paint_export.h"
-#include "cc/paint/paint_op_buffer.h"
-
-namespace cc {
-class ImageProvider;
-
-// A helper class to decode images inside the provided |flags| and provide a
-// PaintFlags with the decoded images that can directly be used for
-// rasterization.
-// This class should only be used if |flags| has any discardable images.
-class CC_PAINT_EXPORT ScopedImageFlags {
- public:
-  // |image_provider| must outlive this class.
-  ScopedImageFlags(ImageProvider* image_provider,
-                   const PaintFlags& flags,
-                   const SkMatrix& ctm);
-  ~ScopedImageFlags();
-
-  // The usage of these flags should not extend beyond the lifetime of this
-  // object.
-  PaintFlags* decoded_flags() {
-    return decoded_flags_ ? &decoded_flags_.value() : nullptr;
-  }
-
- private:
-  // An ImageProvider that passes decode requests through to the
-  // |source_provider| but keeps the decode cached throughtout its lifetime,
-  // instead of passing the ref to the caller.
-  class DecodeStashingImageProvider : public ImageProvider {
-   public:
-    // |source_provider| must outlive this class.
-    explicit DecodeStashingImageProvider(ImageProvider* source_provider);
-    ~DecodeStashingImageProvider() override;
-
-    // ImageProvider implementation.
-    ScopedDecodedDrawImage GetDecodedDrawImage(
-        const DrawImage& draw_image) override;
-
-   private:
-    ImageProvider* source_provider_;
-    std::vector<ScopedDecodedDrawImage> decoded_images_;
-
-    DISALLOW_COPY_AND_ASSIGN(DecodeStashingImageProvider);
-  };
-
-  void DecodeImageShader(const PaintFlags& flags, const SkMatrix& ctm);
-
-  void DecodeRecordShader(const PaintFlags& flags, const SkMatrix& ctm);
-
-  base::Optional<PaintFlags> decoded_flags_;
-  DecodeStashingImageProvider decode_stashing_image_provider_;
-
-  DISALLOW_COPY_AND_ASSIGN(ScopedImageFlags);
-};
-
-}  // namespace cc
-
-#endif  // CC_PAINT_SCOPED_IMAGE_FLAGS_H_
diff --git a/cc/paint/scoped_image_flags_unittest.cc b/cc/paint/scoped_image_flags_unittest.cc
deleted file mode 100644
index b8e919a9..0000000
--- a/cc/paint/scoped_image_flags_unittest.cc
+++ /dev/null
@@ -1,70 +0,0 @@
-// Copyright 2017 The Chromium 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 "cc/paint/scoped_image_flags.h"
-
-#include "base/bind.h"
-#include "base/callback.h"
-#include "cc/test/skia_common.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace cc {
-namespace {
-class MockImageProvider : public ImageProvider {
- public:
-  MockImageProvider() = default;
-  ~MockImageProvider() override { EXPECT_EQ(ref_count_, 0); }
-
-  ScopedDecodedDrawImage GetDecodedDrawImage(
-      const DrawImage& draw_image) override {
-    ref_count_++;
-
-    SkBitmap bitmap;
-    bitmap.allocN32Pixels(10, 10);
-    sk_sp<SkImage> image = SkImage::MakeFromBitmap(bitmap);
-
-    return ScopedDecodedDrawImage(
-        DecodedDrawImage(image, SkSize::MakeEmpty(), SkSize::Make(1.0f, 1.0f),
-                         draw_image.filter_quality()),
-        base::BindOnce(&MockImageProvider::UnrefImage, base::Unretained(this)));
-  }
-
-  void UnrefImage(DecodedDrawImage decoded_image) {
-    ref_count_--;
-    CHECK_GE(ref_count_, 0);
-  }
-
-  int ref_count() const { return ref_count_; }
-
- private:
-  int ref_count_ = 0;
-};
-}  // namespace
-
-TEST(ScopedImageFlagsTest, KeepsDecodesAlive) {
-  auto record = sk_make_sp<PaintOpBuffer>();
-  record->push<DrawImageOp>(CreateDiscardablePaintImage(gfx::Size(10, 10)), 0.f,
-                            0.f, nullptr);
-  record->push<DrawImageOp>(CreateDiscardablePaintImage(gfx::Size(10, 10)), 0.f,
-                            0.f, nullptr);
-  record->push<DrawImageOp>(CreateDiscardablePaintImage(gfx::Size(10, 10)), 0.f,
-                            0.f, nullptr);
-  auto record_shader = PaintShader::MakePaintRecord(
-      record, SkRect::MakeWH(100, 100), SkShader::TileMode::kClamp_TileMode,
-      SkShader::TileMode::kClamp_TileMode, &SkMatrix::I());
-
-  MockImageProvider provider;
-  PaintFlags flags;
-  flags.setShader(record_shader);
-  {
-    ScopedImageFlags scoped_flags(&provider, flags, SkMatrix::I());
-    ASSERT_TRUE(scoped_flags.decoded_flags());
-    SkPaint paint = scoped_flags.decoded_flags()->ToSkPaint();
-    ASSERT_TRUE(paint.getShader());
-    EXPECT_EQ(provider.ref_count(), 3);
-  }
-  EXPECT_EQ(provider.ref_count(), 0);
-}
-
-}  // namespace cc
diff --git a/third_party/WebKit/LayoutTests/images/color-profile-background-image-space-expected.png b/third_party/WebKit/LayoutTests/images/color-profile-background-image-space-expected.png
index c5d0b0f0..a811512 100644
--- a/third_party/WebKit/LayoutTests/images/color-profile-background-image-space-expected.png
+++ b/third_party/WebKit/LayoutTests/images/color-profile-background-image-space-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/http/tests/misc/slow-loading-image-in-pattern-expected.png b/third_party/WebKit/LayoutTests/platform/linux/http/tests/misc/slow-loading-image-in-pattern-expected.png
index cabe47b..424b4db 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/http/tests/misc/slow-loading-image-in-pattern-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/http/tests/misc/slow-loading-image-in-pattern-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-svg-fill-text-expected.png b/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-svg-fill-text-expected.png
index 5d8eaeae..c7e1f7b 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-svg-fill-text-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-svg-fill-text-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-svg-fill-text-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-svg-fill-text-expected.png
index 9c73ba8..66498a7 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-svg-fill-text-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-svg-fill-text-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/http/tests/misc/slow-loading-image-in-pattern-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/http/tests/misc/slow-loading-image-in-pattern-expected.png
index cabe47b..424b4db 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/http/tests/misc/slow-loading-image-in-pattern-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/http/tests/misc/slow-loading-image-in-pattern-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/images/color-profile-svg-fill-text-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/images/color-profile-svg-fill-text-expected.png
index 08343bfa..a773132 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/images/color-profile-svg-fill-text-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/images/color-profile-svg-fill-text-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/virtual/exotic-color-space/images/color-profile-svg-fill-text-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/virtual/exotic-color-space/images/color-profile-svg-fill-text-expected.png
index 05ebe12..07a3c2c 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/virtual/exotic-color-space/images/color-profile-svg-fill-text-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/virtual/exotic-color-space/images/color-profile-svg-fill-text-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/css3/masking/mask-repeat-space-padding-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/css3/masking/mask-repeat-space-padding-expected.png
index eedee93..47ed2d1 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/css3/masking/mask-repeat-space-padding-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/css3/masking/mask-repeat-space-padding-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/images/color-profile-svg-fill-text-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/images/color-profile-svg-fill-text-expected.png
index b2aeb5a..cde34596 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/images/color-profile-svg-fill-text-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/images/color-profile-svg-fill-text-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/virtual/exotic-color-space/images/color-profile-svg-fill-text-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/virtual/exotic-color-space/images/color-profile-svg-fill-text-expected.png
index 1df1cd4..0f4a16b 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/virtual/exotic-color-space/images/color-profile-svg-fill-text-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/virtual/exotic-color-space/images/color-profile-svg-fill-text-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/css3/masking/mask-repeat-space-padding-expected.png b/third_party/WebKit/LayoutTests/platform/mac/css3/masking/mask-repeat-space-padding-expected.png
index 636b74b..eb90563 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/css3/masking/mask-repeat-space-padding-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/css3/masking/mask-repeat-space-padding-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/backgrounds/background-repeat-with-background-color-expected.png b/third_party/WebKit/LayoutTests/platform/mac/fast/backgrounds/background-repeat-with-background-color-expected.png
index 6f502775..4dba2a8 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/fast/backgrounds/background-repeat-with-background-color-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/fast/backgrounds/background-repeat-with-background-color-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/http/tests/misc/slow-loading-image-in-pattern-expected.png b/third_party/WebKit/LayoutTests/platform/mac/http/tests/misc/slow-loading-image-in-pattern-expected.png
index 5c897cc..d8181498 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/http/tests/misc/slow-loading-image-in-pattern-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/http/tests/misc/slow-loading-image-in-pattern-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-svg-fill-text-expected.png b/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-svg-fill-text-expected.png
index 5773e7e..75c356c 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-svg-fill-text-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-svg-fill-text-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/images/cross-fade-background-size-expected.png b/third_party/WebKit/LayoutTests/platform/mac/images/cross-fade-background-size-expected.png
index 3359ed2..13c9b2e 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/images/cross-fade-background-size-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/images/cross-fade-background-size-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/virtual/exotic-color-space/images/color-profile-background-image-space-expected.png b/third_party/WebKit/LayoutTests/platform/mac/virtual/exotic-color-space/images/color-profile-background-image-space-expected.png
deleted file mode 100644
index 7b65507..0000000
--- a/third_party/WebKit/LayoutTests/platform/mac/virtual/exotic-color-space/images/color-profile-background-image-space-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/virtual/exotic-color-space/images/color-profile-svg-fill-text-expected.png b/third_party/WebKit/LayoutTests/platform/mac/virtual/exotic-color-space/images/color-profile-svg-fill-text-expected.png
index 8cde405..41f9297 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/virtual/exotic-color-space/images/color-profile-svg-fill-text-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/virtual/exotic-color-space/images/color-profile-svg-fill-text-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/virtual/exotic-color-space/images/cross-fade-background-size-expected.png b/third_party/WebKit/LayoutTests/platform/mac/virtual/exotic-color-space/images/cross-fade-background-size-expected.png
index 73cbaf7a..f268586 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/virtual/exotic-color-space/images/cross-fade-background-size-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/virtual/exotic-color-space/images/cross-fade-background-size-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/cross-fade-background-size-expected.png b/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/cross-fade-background-size-expected.png
index e138bc81..94f1612 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/cross-fade-background-size-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/cross-fade-background-size-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/virtual/mojo-loading/http/tests/misc/slow-loading-image-in-pattern-expected.png b/third_party/WebKit/LayoutTests/platform/mac/virtual/mojo-loading/http/tests/misc/slow-loading-image-in-pattern-expected.png
index 5c897cc..d8181498 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/virtual/mojo-loading/http/tests/misc/slow-loading-image-in-pattern-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/virtual/mojo-loading/http/tests/misc/slow-loading-image-in-pattern-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/css3/masking/mask-repeat-space-padding-expected.png b/third_party/WebKit/LayoutTests/platform/win/css3/masking/mask-repeat-space-padding-expected.png
index 6dd1e66..391076d 100644
--- a/third_party/WebKit/LayoutTests/platform/win/css3/masking/mask-repeat-space-padding-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/css3/masking/mask-repeat-space-padding-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/backgrounds/background-repeat-with-background-color-expected.png b/third_party/WebKit/LayoutTests/platform/win/fast/backgrounds/background-repeat-with-background-color-expected.png
index 47bfe99..f6ab2241 100644
--- a/third_party/WebKit/LayoutTests/platform/win/fast/backgrounds/background-repeat-with-background-color-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/fast/backgrounds/background-repeat-with-background-color-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/http/tests/misc/slow-loading-image-in-pattern-expected.png b/third_party/WebKit/LayoutTests/platform/win/http/tests/misc/slow-loading-image-in-pattern-expected.png
index fe19eb5..2304502 100644
--- a/third_party/WebKit/LayoutTests/platform/win/http/tests/misc/slow-loading-image-in-pattern-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/http/tests/misc/slow-loading-image-in-pattern-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/images/color-profile-svg-fill-text-expected.png b/third_party/WebKit/LayoutTests/platform/win/images/color-profile-svg-fill-text-expected.png
index 7d0f474..15b2a7c8 100644
--- a/third_party/WebKit/LayoutTests/platform/win/images/color-profile-svg-fill-text-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/images/color-profile-svg-fill-text-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/images/cross-fade-background-size-expected.png b/third_party/WebKit/LayoutTests/platform/win/images/cross-fade-background-size-expected.png
index af34a7c..6dd3d20b 100644
--- a/third_party/WebKit/LayoutTests/platform/win/images/cross-fade-background-size-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/images/cross-fade-background-size-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/exotic-color-space/images/color-profile-background-image-space-expected.png b/third_party/WebKit/LayoutTests/platform/win/virtual/exotic-color-space/images/color-profile-background-image-space-expected.png
index a8f389c6..8b8e6e0a 100644
--- a/third_party/WebKit/LayoutTests/platform/win/virtual/exotic-color-space/images/color-profile-background-image-space-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/virtual/exotic-color-space/images/color-profile-background-image-space-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/exotic-color-space/images/color-profile-svg-fill-text-expected.png b/third_party/WebKit/LayoutTests/platform/win/virtual/exotic-color-space/images/color-profile-svg-fill-text-expected.png
index 6a319b8..e6b8478 100644
--- a/third_party/WebKit/LayoutTests/platform/win/virtual/exotic-color-space/images/color-profile-svg-fill-text-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/virtual/exotic-color-space/images/color-profile-svg-fill-text-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/exotic-color-space/images/cross-fade-background-size-expected.png b/third_party/WebKit/LayoutTests/platform/win/virtual/exotic-color-space/images/cross-fade-background-size-expected.png
index 2699d76..6965947 100644
--- a/third_party/WebKit/LayoutTests/platform/win/virtual/exotic-color-space/images/cross-fade-background-size-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/virtual/exotic-color-space/images/cross-fade-background-size-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/cross-fade-background-size-expected.png b/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/cross-fade-background-size-expected.png
index 0123a81..54806de 100644
--- a/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/cross-fade-background-size-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/cross-fade-background-size-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/mojo-loading/http/tests/misc/slow-loading-image-in-pattern-expected.png b/third_party/WebKit/LayoutTests/platform/win/virtual/mojo-loading/http/tests/misc/slow-loading-image-in-pattern-expected.png
index fe19eb5..2304502 100644
--- a/third_party/WebKit/LayoutTests/platform/win/virtual/mojo-loading/http/tests/misc/slow-loading-image-in-pattern-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/virtual/mojo-loading/http/tests/misc/slow-loading-image-in-pattern-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/virtual/exotic-color-space/images/color-profile-background-image-space-expected.png b/third_party/WebKit/LayoutTests/virtual/exotic-color-space/images/color-profile-background-image-space-expected.png
new file mode 100644
index 0000000..9e5603dc
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/virtual/exotic-color-space/images/color-profile-background-image-space-expected.png
Binary files differ