ui: Introduce CanvasPainter, remove PaintContext(gfx::Canvas*).

This adds a helper class called CanvasPainter for painting a View
into a bitmap-backed gfx::Canvas, for non-composited (off-screen)
painting.

This class uses a DisplayItemList-backed PaintContext, removing
the need for a PaintContext(gfx:Canvas*) constructor.

Also changes views_unittests to use DisplayItemList-backed
PaintContexts, so that the tests are explicitly testing View paint
cacheing.

R=sky
BUG=466426

Review URL: https://codereview.chromium.org/1161933007

Cr-Commit-Position: refs/heads/master@{#332963}
diff --git a/ui/compositor/BUILD.gn b/ui/compositor/BUILD.gn
index a0944fe..283d1ab 100644
--- a/ui/compositor/BUILD.gn
+++ b/ui/compositor/BUILD.gn
@@ -7,6 +7,8 @@
 
 component("compositor") {
   sources = [
+    "canvas_painter.cc",
+    "canvas_painter.h",
     "clip_transform_recorder.cc",
     "clip_transform_recorder.h",
     "closure_animation_observer.cc",
diff --git a/ui/compositor/canvas_painter.cc b/ui/compositor/canvas_painter.cc
new file mode 100644
index 0000000..ff187d9
--- /dev/null
+++ b/ui/compositor/canvas_painter.cc
@@ -0,0 +1,29 @@
+// 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 "ui/compositor/canvas_painter.h"
+
+#include "cc/playback/display_item_list.h"
+#include "cc/playback/display_item_list_settings.h"
+#include "ui/gfx/canvas.h"
+
+namespace ui {
+
+CanvasPainter::CanvasPainter(gfx::Canvas* canvas, float raster_scale_factor)
+    : canvas_(canvas),
+      raster_scale_factor_(raster_scale_factor),
+      rect_(gfx::ScaleToEnclosedRect(
+          gfx::Rect(canvas_->sk_canvas()->getBaseLayerSize().width(),
+                    canvas_->sk_canvas()->getBaseLayerSize().height()),
+          1.f / raster_scale_factor)),
+      list_(cc::DisplayItemList::Create(rect_, cc::DisplayItemListSettings())),
+      context_(list_.get(), raster_scale_factor_, rect_, rect_) {
+}
+
+CanvasPainter::~CanvasPainter() {
+  list_->Finalize();
+  list_->Raster(canvas_->sk_canvas(), nullptr, rect_, raster_scale_factor_);
+}
+
+}  // namespace ui
diff --git a/ui/compositor/canvas_painter.h b/ui/compositor/canvas_painter.h
new file mode 100644
index 0000000..6d8d3902
--- /dev/null
+++ b/ui/compositor/canvas_painter.h
@@ -0,0 +1,48 @@
+// 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.
+
+#ifndef UI_COMPOSITOR_CANVAS_PAINTER_H_
+#define UI_COMPOSITOR_CANVAS_PAINTER_H_
+
+#include "base/memory/ref_counted.h"
+#include "ui/compositor/compositor_export.h"
+#include "ui/compositor/paint_context.h"
+#include "ui/gfx/geometry/rect.h"
+
+namespace cc {
+class DisplayItemList;
+}
+
+namespace gfx {
+class Canvas;
+}
+
+namespace ui {
+
+// This class provides a simple helper for painting directly to a bitmap
+// backed canvas (for painting use-cases other than compositing). After
+// constructing an instance of a CanvasPainter, the context() can be used
+// to do painting using the normal composited paint paths. When
+// the painter is destroyed, any painting done with the context() will be
+// rastered into the canvas.
+class COMPOSITOR_EXPORT CanvasPainter {
+ public:
+  CanvasPainter(gfx::Canvas* canvas, float raster_scale_factor);
+  ~CanvasPainter();
+
+  const PaintContext& context() const { return context_; }
+
+ private:
+  gfx::Canvas* const canvas_;
+  const float raster_scale_factor_;
+  const gfx::Rect rect_;
+  scoped_refptr<cc::DisplayItemList> list_;
+  PaintContext context_;
+
+  DISALLOW_COPY_AND_ASSIGN(CanvasPainter);
+};
+
+}  // namespace ui
+
+#endif  // UI_COMPOSITOR_CANVAS_PAINTER_H_
diff --git a/ui/compositor/compositor.gyp b/ui/compositor/compositor.gyp
index 92f5ef4e..99392af 100644
--- a/ui/compositor/compositor.gyp
+++ b/ui/compositor/compositor.gyp
@@ -25,6 +25,8 @@
         'COMPOSITOR_IMPLEMENTATION',
       ],
       'sources': [
+        'canvas_painter.cc',
+        'canvas_painter.h',
         'clip_transform_recorder.cc',
         'clip_transform_recorder.h',
         'closure_animation_observer.cc',
diff --git a/ui/compositor/paint_context.cc b/ui/compositor/paint_context.cc
index 0d7d20f..7c44f449 100644
--- a/ui/compositor/paint_context.cc
+++ b/ui/compositor/paint_context.cc
@@ -38,10 +38,6 @@
 #endif
 }
 
-PaintContext::PaintContext(gfx::Canvas* canvas)
-    : PaintContext(canvas, gfx::Rect()) {
-}
-
 PaintContext::PaintContext(const PaintContext& other,
                            const gfx::Vector2d& offset)
     : canvas_(other.canvas_),
diff --git a/ui/compositor/paint_context.h b/ui/compositor/paint_context.h
index e091c5e..79c9142 100644
--- a/ui/compositor/paint_context.h
+++ b/ui/compositor/paint_context.h
@@ -38,10 +38,6 @@
                const gfx::Rect& bounds,
                const gfx::Rect& invalidation);
 
-  // Construct a PaintContext that will re-paint everything (no consideration
-  // for invalidation).
-  explicit PaintContext(gfx::Canvas* canvas);
-
   // Clone a PaintContext with an additional |offset|.
   PaintContext(const PaintContext& other, const gfx::Vector2d& offset);
 
diff --git a/ui/views/DEPS b/ui/views/DEPS
index c1d3570..3aa9664 100644
--- a/ui/views/DEPS
+++ b/ui/views/DEPS
@@ -25,4 +25,7 @@
   "examples_browser_main_parts\.cc": [
     "+ui/wm/test"
   ],
+  "view_unittest\.cc": [
+    "+cc/playback"
+  ],
 }
diff --git a/ui/views/button_drag_utils.cc b/ui/views/button_drag_utils.cc
index 0e7b3982..a84fa62 100644
--- a/ui/views/button_drag_utils.cc
+++ b/ui/views/button_drag_utils.cc
@@ -8,7 +8,7 @@
 #include "ui/base/dragdrop/drag_utils.h"
 #include "ui/base/dragdrop/os_exchange_data.h"
 #include "ui/base/resource/resource_bundle.h"
-#include "ui/compositor/paint_context.h"
+#include "ui/compositor/canvas_painter.h"
 #include "ui/gfx/canvas.h"
 #include "ui/gfx/geometry/point.h"
 #include "ui/gfx/geometry/vector2d.h"
@@ -76,7 +76,7 @@
   // Render the image.
   scoped_ptr<gfx::Canvas> canvas(
       views::GetCanvasForDragImage(widget, prefsize));
-  button.Paint(ui::PaintContext(canvas.get()));
+  button.Paint(ui::CanvasPainter(canvas.get(), 1.f).context());
   drag_utils::SetDragImageOnDataObject(*canvas, press_point, data);
 }
 
diff --git a/ui/views/cocoa/bridged_content_view.mm b/ui/views/cocoa/bridged_content_view.mm
index fa0731c8..5325a58 100644
--- a/ui/views/cocoa/bridged_content_view.mm
+++ b/ui/views/cocoa/bridged_content_view.mm
@@ -8,7 +8,7 @@
 #import "base/mac/scoped_nsobject.h"
 #include "base/strings/sys_string_conversions.h"
 #include "ui/base/ime/text_input_client.h"
-#include "ui/compositor/paint_context.h"
+#include "ui/compositor/canvas_painter.h"
 #import "ui/events/cocoa/cocoa_event_utils.h"
 #include "ui/events/keycodes/dom/dom_code.h"
 #import "ui/events/keycodes/keyboard_code_conversion_mac.h"
@@ -312,7 +312,8 @@
     return;
 
   gfx::CanvasSkiaPaint canvas(dirtyRect, false /* opaque */);
-  hostedView_->GetWidget()->OnNativeWidgetPaint(ui::PaintContext(&canvas));
+  hostedView_->GetWidget()->OnNativeWidgetPaint(
+      ui::CanvasPainter(&canvas, 1.f).context());
 }
 
 - (NSTextInputContext*)inputContext {
diff --git a/ui/views/controls/label_unittest.cc b/ui/views/controls/label_unittest.cc
index 32fabd78..47cb37a 100644
--- a/ui/views/controls/label_unittest.cc
+++ b/ui/views/controls/label_unittest.cc
@@ -9,7 +9,7 @@
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/accessibility/ax_view_state.h"
 #include "ui/base/l10n/l10n_util.h"
-#include "ui/compositor/paint_context.h"
+#include "ui/compositor/canvas_painter.h"
 #include "ui/gfx/canvas.h"
 #include "ui/views/border.h"
 #include "ui/views/test/focus_manager_test.h"
@@ -305,14 +305,14 @@
   label.SetBounds(0, 0, 200, 200);
 
   gfx::Canvas canvas(gfx::Size(200, 200), 1.0f, true);
-  label.Paint(ui::PaintContext(&canvas));
+  label.Paint(ui::CanvasPainter(&canvas, 1.f).context());
   EXPECT_EQ(1u, label.lines_.size());
   EXPECT_EQ(ASCIIToUTF16("Example"), label.lines_[0]->GetDisplayText());
 
   label.SetText(ASCIIToUTF16("Altered"));
   // The altered text should be painted even though Layout() or SetBounds() are
   // not called.
-  label.Paint(ui::PaintContext(&canvas));
+  label.Paint(ui::CanvasPainter(&canvas, 1.f).context());
   EXPECT_EQ(1u, label.lines_.size());
   EXPECT_EQ(ASCIIToUTF16("Altered"), label.lines_[0]->GetDisplayText());
 }
@@ -482,7 +482,7 @@
 
   // Paint() doesn't change the preferred size.
   gfx::Canvas canvas;
-  label.Paint(ui::PaintContext(&canvas));
+  label.Paint(ui::CanvasPainter(&canvas, 1.f).context());
   EXPECT_EQ(narrow_size.ToString(), label.GetPreferredSize().ToString());
 }
 
@@ -555,7 +555,7 @@
   EXPECT_EQ(0u, label.lines_.size());
 
   gfx::Canvas canvas(preferred_size, 1.0f, true);
-  label.Paint(ui::PaintContext(&canvas));
+  label.Paint(ui::CanvasPainter(&canvas, 1.f).context());
   EXPECT_EQ(1u, label.lines_.size());
 
   // Label should recreate its RenderText object when it's invisible, to release
@@ -575,14 +575,14 @@
   label.SetVisible(true);
   EXPECT_EQ(0u, label.lines_.size());
 
-  label.Paint(ui::PaintContext(&canvas));
+  label.Paint(ui::CanvasPainter(&canvas, 1.f).context());
   EXPECT_EQ(1u, label.lines_.size());
 
   // Changing layout just resets |lines_|. It'll recover next time it's drawn.
   label.SetBounds(0, 0, 10, 10);
   EXPECT_EQ(0u, label.lines_.size());
 
-  label.Paint(ui::PaintContext(&canvas));
+  label.Paint(ui::CanvasPainter(&canvas, 1.f).context());
   EXPECT_EQ(1u, label.lines_.size());
 }
 
@@ -597,7 +597,7 @@
   label.SizeToPreferredSize();
 
   gfx::Canvas canvas(label.GetPreferredSize(), 1.0f, true);
-  label.Paint(ui::PaintContext(&canvas));
+  label.Paint(ui::CanvasPainter(&canvas, 1.f).context());
 
   // There's only one 'line', RenderText itself supports multiple lines.
   EXPECT_EQ(1u, label.lines_.size());
diff --git a/ui/views/controls/textfield/textfield.cc b/ui/views/controls/textfield/textfield.cc
index 9e4111d..347de70 100644
--- a/ui/views/controls/textfield/textfield.cc
+++ b/ui/views/controls/textfield/textfield.cc
@@ -14,7 +14,7 @@
 #include "ui/base/dragdrop/drag_utils.h"
 #include "ui/base/touch/selection_bound.h"
 #include "ui/base/ui_base_switches_util.h"
-#include "ui/compositor/paint_context.h"
+#include "ui/compositor/canvas_painter.h"
 #include "ui/compositor/scoped_animation_duration_scale_mode.h"
 #include "ui/events/event.h"
 #include "ui/events/keycodes/keyboard_codes.h"
@@ -1082,7 +1082,7 @@
   // Desktop Linux Aura does not yet support transparency in drag images.
   canvas->DrawColor(GetBackgroundColor());
 #endif
-  label.Paint(ui::PaintContext(canvas.get()));
+  label.Paint(ui::CanvasPainter(canvas.get(), 1.f).context());
   const gfx::Vector2d kOffset(-15, 0);
   drag_utils::SetDragImageOnDataObject(*canvas, kOffset, data);
   if (controller_)
diff --git a/ui/views/view_unittest.cc b/ui/views/view_unittest.cc
index d4a270e..1a103b7 100644
--- a/ui/views/view_unittest.cc
+++ b/ui/views/view_unittest.cc
@@ -9,6 +9,8 @@
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
+#include "cc/playback/display_item_list.h"
+#include "cc/playback/display_item_list_settings.h"
 #include "ui/base/accelerators/accelerator.h"
 #include "ui/base/clipboard/clipboard.h"
 #include "ui/base/l10n/l10n_util.h"
@@ -445,21 +447,29 @@
   v2->SetBounds(3, 4, 6, 5);
   v1->AddChildView(v2);
 
-  gfx::Canvas canvas(root_view->size(), 1.f, true);
-  gfx::Rect paint_area(1, 1);
-
-  EXPECT_FALSE(v1->did_paint_);
-  EXPECT_FALSE(v2->did_paint_);
-  root_view->Paint(ui::PaintContext(&canvas));
-  EXPECT_TRUE(v1->did_paint_);
-  EXPECT_TRUE(v2->did_paint_);
-
+  // Paint everything once, since it has to build its cache. Then we can test
+  // invalidation.
+  gfx::Rect first_paint(1, 1);
+  scoped_refptr<cc::DisplayItemList> list =
+      cc::DisplayItemList::Create(first_paint, cc::DisplayItemListSettings());
+  root_view->Paint(ui::PaintContext(list.get(), 1.f, first_paint, first_paint));
   v1->Reset();
   v2->Reset();
+
+  gfx::Rect paint_area(1, 1);
+  gfx::Rect root_area(root_view->size());
+  list = cc::DisplayItemList::Create(root_area, cc::DisplayItemListSettings());
+
+  // With a known invalidation, v1 and v2 are not painted.
   EXPECT_FALSE(v1->did_paint_);
   EXPECT_FALSE(v2->did_paint_);
+  root_view->Paint(ui::PaintContext(list.get(), 1.f, root_area, paint_area));
+  EXPECT_FALSE(v1->did_paint_);
+  EXPECT_FALSE(v2->did_paint_);
+
+  // With unknown invalidation, v1 and v2 are painted.
   root_view->Paint(
-      ui::PaintContext(ui::PaintContext(&canvas, paint_area),
+      ui::PaintContext(ui::PaintContext(list.get(), 1.f, root_area, paint_area),
                        ui::PaintContext::CLONE_WITHOUT_INVALIDATION));
   EXPECT_TRUE(v1->did_paint_);
   EXPECT_TRUE(v2->did_paint_);
@@ -480,12 +490,22 @@
   v2->SetBounds(3, 4, 6, 5);
   v1->AddChildView(v2);
 
-  gfx::Canvas canvas(root_view->size(), 1.f, true);
+  // Paint everything once, since it has to build its cache. Then we can test
+  // invalidation.
+  gfx::Rect first_paint(1, 1);
+  scoped_refptr<cc::DisplayItemList> list =
+      cc::DisplayItemList::Create(first_paint, cc::DisplayItemListSettings());
+  root_view->Paint(ui::PaintContext(list.get(), 1.f, first_paint, first_paint));
+  v1->Reset();
+  v2->Reset();
+
   gfx::Rect paint_area(25, 26);
+  gfx::Rect root_area(root_view->size());
+  list = cc::DisplayItemList::Create(root_area, cc::DisplayItemListSettings());
 
   EXPECT_FALSE(v1->did_paint_);
   EXPECT_FALSE(v2->did_paint_);
-  root_view->Paint(ui::PaintContext(&canvas, paint_area));
+  root_view->Paint(ui::PaintContext(list.get(), 1.f, root_area, paint_area));
   EXPECT_TRUE(v1->did_paint_);
   EXPECT_TRUE(v2->did_paint_);
 }
@@ -518,12 +538,22 @@
   EXPECT_EQ(gfx::Rect(6, 15, 6, 5), v2->layer()->bounds());
   v2->SetPaintToLayer(false);
 
-  gfx::Canvas canvas(root_view->size(), 1.f, true);
+  // Paint everything once, since it has to build its cache. Then we can test
+  // invalidation.
+  gfx::Rect first_paint(1, 1);
+  scoped_refptr<cc::DisplayItemList> list =
+      cc::DisplayItemList::Create(first_paint, cc::DisplayItemListSettings());
+  root_view->Paint(ui::PaintContext(list.get(), 1.f, first_paint, first_paint));
+  v1->Reset();
+  v2->Reset();
+
   gfx::Rect paint_area(25, 26);
+  gfx::Rect root_area(root_view->size());
+  list = cc::DisplayItemList::Create(root_area, cc::DisplayItemListSettings());
 
   EXPECT_FALSE(v1->did_paint_);
   EXPECT_FALSE(v2->did_paint_);
-  root_view->Paint(ui::PaintContext(&canvas, paint_area));
+  root_view->Paint(ui::PaintContext(list.get(), 1.f, root_area, paint_area));
   EXPECT_TRUE(v1->did_paint_);
   EXPECT_TRUE(v2->did_paint_);
 }
@@ -543,12 +573,22 @@
   v2->SetBounds(3, 4, 6, 5);
   v1->AddChildView(v2);
 
-  gfx::Canvas canvas(root_view->size(), 1.f, true);
+  // Paint everything once, since it has to build its cache. Then we can test
+  // invalidation.
+  gfx::Rect first_paint(1, 1);
+  scoped_refptr<cc::DisplayItemList> list =
+      cc::DisplayItemList::Create(first_paint, cc::DisplayItemListSettings());
+  root_view->Paint(ui::PaintContext(list.get(), 1.f, first_paint, first_paint));
+  v1->Reset();
+  v2->Reset();
+
   gfx::Rect paint_area(9, 10, 5, 6);
+  gfx::Rect root_area(root_view->size());
+  list = cc::DisplayItemList::Create(root_area, cc::DisplayItemListSettings());
 
   EXPECT_FALSE(v1->did_paint_);
   EXPECT_FALSE(v2->did_paint_);
-  root_view->Paint(ui::PaintContext(&canvas, paint_area));
+  root_view->Paint(ui::PaintContext(list.get(), 1.f, root_area, paint_area));
   EXPECT_TRUE(v1->did_paint_);
   EXPECT_TRUE(v2->did_paint_);
 }
@@ -581,12 +621,22 @@
   EXPECT_EQ(gfx::Rect(6, 15, 6, 5), v2->layer()->bounds());
   v2->SetPaintToLayer(false);
 
-  gfx::Canvas canvas(root_view->size(), 1.f, true);
+  // Paint everything once, since it has to build its cache. Then we can test
+  // invalidation.
+  gfx::Rect first_paint(1, 1);
+  scoped_refptr<cc::DisplayItemList> list =
+      cc::DisplayItemList::Create(first_paint, cc::DisplayItemListSettings());
+  root_view->Paint(ui::PaintContext(list.get(), 1.f, first_paint, first_paint));
+  v1->Reset();
+  v2->Reset();
+
   gfx::Rect paint_area(2, 10, 5, 6);
+  gfx::Rect root_area(root_view->size());
+  list = cc::DisplayItemList::Create(root_area, cc::DisplayItemListSettings());
 
   EXPECT_FALSE(v1->did_paint_);
   EXPECT_FALSE(v2->did_paint_);
-  root_view->Paint(ui::PaintContext(&canvas, paint_area));
+  root_view->Paint(ui::PaintContext(list.get(), 1.f, root_area, paint_area));
   EXPECT_TRUE(v1->did_paint_);
   EXPECT_TRUE(v2->did_paint_);
 }
@@ -606,12 +656,22 @@
   v2->SetBounds(3, 4, 6, 5);
   v1->AddChildView(v2);
 
-  gfx::Canvas canvas(root_view->size(), 1.f, true);
+  // Paint everything once, since it has to build its cache. Then we can test
+  // invalidation.
+  gfx::Rect first_paint(1, 1);
+  scoped_refptr<cc::DisplayItemList> list =
+      cc::DisplayItemList::Create(first_paint, cc::DisplayItemListSettings());
+  root_view->Paint(ui::PaintContext(list.get(), 1.f, first_paint, first_paint));
+  v1->Reset();
+  v2->Reset();
+
   gfx::Rect paint_area(9, 10, 2, 3);
+  gfx::Rect root_area(root_view->size());
+  list = cc::DisplayItemList::Create(root_area, cc::DisplayItemListSettings());
 
   EXPECT_FALSE(v1->did_paint_);
   EXPECT_FALSE(v2->did_paint_);
-  root_view->Paint(ui::PaintContext(&canvas, paint_area));
+  root_view->Paint(ui::PaintContext(list.get(), 1.f, root_area, paint_area));
   EXPECT_TRUE(v1->did_paint_);
   EXPECT_FALSE(v2->did_paint_);
 }
@@ -644,12 +704,22 @@
   EXPECT_EQ(gfx::Rect(6, 15, 6, 5), v2->layer()->bounds());
   v2->SetPaintToLayer(false);
 
-  gfx::Canvas canvas(root_view->size(), 1.f, true);
+  // Paint everything once, since it has to build its cache. Then we can test
+  // invalidation.
+  gfx::Rect first_paint(1, 1);
+  scoped_refptr<cc::DisplayItemList> list =
+      cc::DisplayItemList::Create(first_paint, cc::DisplayItemListSettings());
+  root_view->Paint(ui::PaintContext(list.get(), 1.f, first_paint, first_paint));
+  v1->Reset();
+  v2->Reset();
+
   gfx::Rect paint_area(2, 10, 2, 3);
+  gfx::Rect root_area(root_view->size());
+  list = cc::DisplayItemList::Create(root_area, cc::DisplayItemListSettings());
 
   EXPECT_FALSE(v1->did_paint_);
   EXPECT_FALSE(v2->did_paint_);
-  root_view->Paint(ui::PaintContext(&canvas, paint_area));
+  root_view->Paint(ui::PaintContext(list.get(), 1.f, root_area, paint_area));
   EXPECT_TRUE(v1->did_paint_);
   EXPECT_FALSE(v2->did_paint_);
 }
@@ -669,12 +739,22 @@
   v2->SetBounds(3, 4, 6, 5);
   v1->AddChildView(v2);
 
-  gfx::Canvas canvas(root_view->size(), 1.f, true);
+  // Paint everything once, since it has to build its cache. Then we can test
+  // invalidation.
+  gfx::Rect first_paint(1, 1);
+  scoped_refptr<cc::DisplayItemList> list =
+      cc::DisplayItemList::Create(first_paint, cc::DisplayItemListSettings());
+  root_view->Paint(ui::PaintContext(list.get(), 1.f, first_paint, first_paint));
+  v1->Reset();
+  v2->Reset();
+
   gfx::Rect paint_area(9, 10, 2, 1);
+  gfx::Rect root_area(root_view->size());
+  list = cc::DisplayItemList::Create(root_area, cc::DisplayItemListSettings());
 
   EXPECT_FALSE(v1->did_paint_);
   EXPECT_FALSE(v2->did_paint_);
-  root_view->Paint(ui::PaintContext(&canvas, paint_area));
+  root_view->Paint(ui::PaintContext(list.get(), 1.f, root_area, paint_area));
   EXPECT_FALSE(v1->did_paint_);
   EXPECT_FALSE(v2->did_paint_);
 }
@@ -707,12 +787,22 @@
   EXPECT_EQ(gfx::Rect(6, 15, 6, 5), v2->layer()->bounds());
   v2->SetPaintToLayer(false);
 
-  gfx::Canvas canvas(root_view->size(), 1.f, true);
+  // Paint everything once, since it has to build its cache. Then we can test
+  // invalidation.
+  gfx::Rect first_paint(1, 1);
+  scoped_refptr<cc::DisplayItemList> list =
+      cc::DisplayItemList::Create(first_paint, cc::DisplayItemListSettings());
+  root_view->Paint(ui::PaintContext(list.get(), 1.f, first_paint, first_paint));
+  v1->Reset();
+  v2->Reset();
+
   gfx::Rect paint_area(2, 10, 2, 1);
+  gfx::Rect root_area(root_view->size());
+  list = cc::DisplayItemList::Create(root_area, cc::DisplayItemListSettings());
 
   EXPECT_FALSE(v1->did_paint_);
   EXPECT_FALSE(v2->did_paint_);
-  root_view->Paint(ui::PaintContext(&canvas, paint_area));
+  root_view->Paint(ui::PaintContext(list.get(), 1.f, root_area, paint_area));
   EXPECT_FALSE(v1->did_paint_);
   EXPECT_FALSE(v2->did_paint_);
 }
@@ -732,13 +822,23 @@
   v2->SetBounds(3, 4, 6, 5);
   root_view->AddChildView(v2);
 
-  gfx::Canvas canvas(root_view->size(), 1.f, true);
+  // Paint everything once, since it has to build its cache. Then we can test
+  // invalidation.
+  gfx::Rect first_paint(1, 1);
+  scoped_refptr<cc::DisplayItemList> list =
+      cc::DisplayItemList::Create(first_paint, cc::DisplayItemListSettings());
+  root_view->Paint(ui::PaintContext(list.get(), 1.f, first_paint, first_paint));
+  v1->Reset();
+  v2->Reset();
+
   // Intersects with the second child only.
   gfx::Rect paint_area(3, 3, 1, 2);
+  gfx::Rect root_area(root_view->size());
+  list = cc::DisplayItemList::Create(root_area, cc::DisplayItemListSettings());
 
   EXPECT_FALSE(v1->did_paint_);
   EXPECT_FALSE(v2->did_paint_);
-  root_view->Paint(ui::PaintContext(&canvas, paint_area));
+  root_view->Paint(ui::PaintContext(list.get(), 1.f, root_area, paint_area));
   EXPECT_FALSE(v1->did_paint_);
   EXPECT_TRUE(v2->did_paint_);
 
@@ -749,7 +849,7 @@
   v2->Reset();
   EXPECT_FALSE(v1->did_paint_);
   EXPECT_FALSE(v2->did_paint_);
-  root_view->Paint(ui::PaintContext(&canvas, paint_area));
+  root_view->Paint(ui::PaintContext(list.get(), 1.f, root_area, paint_area));
   EXPECT_TRUE(v1->did_paint_);
   EXPECT_FALSE(v2->did_paint_);
 }
@@ -782,13 +882,23 @@
   EXPECT_EQ(gfx::Rect(16, 4, 6, 5), v2->layer()->bounds());
   v2->SetPaintToLayer(false);
 
-  gfx::Canvas canvas(root_view->size(), 1.f, true);
+  // Paint everything once, since it has to build its cache. Then we can test
+  // invalidation.
+  gfx::Rect first_paint(1, 1);
+  scoped_refptr<cc::DisplayItemList> list =
+      cc::DisplayItemList::Create(first_paint, cc::DisplayItemListSettings());
+  root_view->Paint(ui::PaintContext(list.get(), 1.f, first_paint, first_paint));
+  v1->Reset();
+  v2->Reset();
+
   // Intersects with the first child only.
   gfx::Rect paint_area(3, 10, 1, 2);
+  gfx::Rect root_area(root_view->size());
+  list = cc::DisplayItemList::Create(root_area, cc::DisplayItemListSettings());
 
   EXPECT_FALSE(v1->did_paint_);
   EXPECT_FALSE(v2->did_paint_);
-  root_view->Paint(ui::PaintContext(&canvas, paint_area));
+  root_view->Paint(ui::PaintContext(list.get(), 1.f, root_area, paint_area));
   EXPECT_TRUE(v1->did_paint_);
   EXPECT_FALSE(v2->did_paint_);
 
@@ -799,7 +909,7 @@
   v2->Reset();
   EXPECT_FALSE(v1->did_paint_);
   EXPECT_FALSE(v2->did_paint_);
-  root_view->Paint(ui::PaintContext(&canvas, paint_area));
+  root_view->Paint(ui::PaintContext(list.get(), 1.f, root_area, paint_area));
   EXPECT_FALSE(v1->did_paint_);
   EXPECT_TRUE(v2->did_paint_);
 }
@@ -820,26 +930,36 @@
   v2->SetBounds(3, 4, 6, 5);
   v1->AddChildView(v2);
 
-  EXPECT_FALSE(v1->did_paint_);
-  EXPECT_FALSE(v2->did_paint_);
+  // Paint everything once, since it has to build its cache. Then we can test
+  // invalidation.
+  gfx::Rect first_paint(1, 1);
+  scoped_refptr<cc::DisplayItemList> list =
+      cc::DisplayItemList::Create(first_paint, cc::DisplayItemListSettings());
+  v1->Paint(ui::PaintContext(list.get(), 1.f, first_paint, first_paint));
+  v1->Reset();
+  v2->Reset();
 
   {
-    gfx::Canvas canvas(root_view->size(), 1.f, true);
     gfx::Rect paint_area(25, 26);
+    gfx::Rect view_area(root_view->size());
+    scoped_refptr<cc::DisplayItemList> list =
+        cc::DisplayItemList::Create(view_area, cc::DisplayItemListSettings());
 
     // The promoted views are not painted as they are separate paint roots.
-    root_view->Paint(ui::PaintContext(&canvas, paint_area));
+    root_view->Paint(ui::PaintContext(list.get(), 1.f, view_area, paint_area));
     EXPECT_FALSE(v1->did_paint_);
     EXPECT_FALSE(v2->did_paint_);
   }
 
   {
-    gfx::Canvas canvas(v1->size(), 1.f, true);
     gfx::Rect paint_area(1, 1);
+    gfx::Rect view_area(v1->size());
+    scoped_refptr<cc::DisplayItemList> list =
+        cc::DisplayItemList::Create(view_area, cc::DisplayItemListSettings());
 
     // The |v1| view is painted. If it used its offset incorrect, it would think
     // its at (10,11) instead of at (0,0) since it is the paint root.
-    v1->Paint(ui::PaintContext(&canvas, paint_area));
+    v1->Paint(ui::PaintContext(list.get(), 1.f, view_area, paint_area));
     EXPECT_TRUE(v1->did_paint_);
     EXPECT_FALSE(v2->did_paint_);
   }
@@ -847,12 +967,14 @@
   v1->Reset();
 
   {
-    gfx::Canvas canvas(v1->size(), 1.f, true);
     gfx::Rect paint_area(3, 3, 1, 2);
+    gfx::Rect view_area(v1->size());
+    scoped_refptr<cc::DisplayItemList> list =
+        cc::DisplayItemList::Create(view_area, cc::DisplayItemListSettings());
 
     // The |v2| view is painted also. If it used its offset incorrect, it would
     // think its at (13,15) instead of at (3,4) since |v1| is the paint root.
-    v1->Paint(ui::PaintContext(&canvas, paint_area));
+    v1->Paint(ui::PaintContext(list.get(), 1.f, view_area, paint_area));
     EXPECT_TRUE(v1->did_paint_);
     EXPECT_TRUE(v2->did_paint_);
   }
diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc b/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc
index a927a48..a663f38 100644
--- a/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc
+++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc
@@ -678,10 +678,6 @@
   GetWidget()->non_client_view()->ResetWindowControls();
 }
 
-void DesktopWindowTreeHostWin::PaintLayeredWindow(gfx::Canvas* canvas) {
-  GetWidget()->GetRootView()->Paint(ui::PaintContext(canvas));
-}
-
 gfx::NativeViewAccessible DesktopWindowTreeHostWin::GetNativeViewAccessible() {
   return GetWidget()->GetRootView()->GetNativeViewAccessible();
 }
diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_win.h b/ui/views/widget/desktop_aura/desktop_window_tree_host_win.h
index dc9f1be..413c0c13 100644
--- a/ui/views/widget/desktop_aura/desktop_window_tree_host_win.h
+++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_win.h
@@ -147,7 +147,6 @@
   void GetMinMaxSize(gfx::Size* min_size, gfx::Size* max_size) const override;
   gfx::Size GetRootViewSize() const override;
   void ResetWindowControls() override;
-  void PaintLayeredWindow(gfx::Canvas* canvas) override;
   gfx::NativeViewAccessible GetNativeViewAccessible() override;
   bool ShouldHandleSystemCommands() const override;
   InputMethod* GetInputMethod() override;
diff --git a/ui/views/win/hwnd_message_handler_delegate.h b/ui/views/win/hwnd_message_handler_delegate.h
index eda75f3..d5f5f813 100644
--- a/ui/views/win/hwnd_message_handler_delegate.h
+++ b/ui/views/win/hwnd_message_handler_delegate.h
@@ -74,8 +74,6 @@
 
   virtual void ResetWindowControls() = 0;
 
-  virtual void PaintLayeredWindow(gfx::Canvas* canvas) = 0;
-
   virtual InputMethod* GetInputMethod() = 0;
 
   virtual gfx::NativeViewAccessible GetNativeViewAccessible() = 0;