summaryrefslogtreecommitdiffstats
path: root/ui/compositor
diff options
context:
space:
mode:
authordanakj <danakj@chromium.org>2015-04-25 10:53:17 -0700
committerCommit bot <commit-bot@chromium.org>2015-04-25 17:53:12 +0000
commit93f5730af51af283713ad19dd5e08c3b3ea34eaa (patch)
tree38e1eb1974410d8503476bb9d0d25218f3ec17c9 /ui/compositor
parentba5b67e27dc64c3c6793be8f9c991066c956c33f (diff)
downloadchromium_src-93f5730af51af283713ad19dd5e08c3b3ea34eaa.zip
chromium_src-93f5730af51af283713ad19dd5e08c3b3ea34eaa.tar.gz
chromium_src-93f5730af51af283713ad19dd5e08c3b3ea34eaa.tar.bz2
ui: Cache the output of View::OnPaint when the View isn't invalid.
Store the output of View::OnPaint as a PaintCache object, and when the view has not been invalidated, use that cache output instead of doing work to build a recording. Performance data as follows when the loading spinner is going: Before impl-side (TOT): 0.13ms / paint With impl-side (no slimming paint): 0.22ms / paint With impl-side and slimming paint (this patch): 0.17ms / paint So this gets us some of the way there. I need to investigate why it's not doing more. R=piman@chromium.org, sky BUG=466426 Committed: https://crrev.com/7f686cdcff81d6779b962e98e529a7360be2809c Cr-Commit-Position: refs/heads/master@{#326592} Review URL: https://codereview.chromium.org/1101783002 Cr-Commit-Position: refs/heads/master@{#326976}
Diffstat (limited to 'ui/compositor')
-rw-r--r--ui/compositor/BUILD.gn2
-rw-r--r--ui/compositor/compositor.gyp2
-rw-r--r--ui/compositor/layer.cc9
-rw-r--r--ui/compositor/paint_cache.cc31
-rw-r--r--ui/compositor/paint_cache.h45
-rw-r--r--ui/compositor/paint_context.h16
-rw-r--r--ui/compositor/paint_recorder.cc21
-rw-r--r--ui/compositor/paint_recorder.h5
8 files changed, 116 insertions, 15 deletions
diff --git a/ui/compositor/BUILD.gn b/ui/compositor/BUILD.gn
index 590cb73..a0944fe 100644
--- a/ui/compositor/BUILD.gn
+++ b/ui/compositor/BUILD.gn
@@ -47,6 +47,8 @@ component("compositor") {
"layer_tree_owner.cc",
"layer_tree_owner.h",
"layer_type.h",
+ "paint_cache.cc",
+ "paint_cache.h",
"paint_context.cc",
"paint_context.h",
"paint_recorder.cc",
diff --git a/ui/compositor/compositor.gyp b/ui/compositor/compositor.gyp
index 11d6723..92f5ef4 100644
--- a/ui/compositor/compositor.gyp
+++ b/ui/compositor/compositor.gyp
@@ -65,6 +65,8 @@
'layer_tree_owner.cc',
'layer_tree_owner.h',
'layer_type.h',
+ 'paint_cache.cc',
+ 'paint_cache.h',
'paint_context.cc',
'paint_context.h',
'paint_recorder.cc',
diff --git a/ui/compositor/layer.cc b/ui/compositor/layer.cc
index 914e000..2b6f921 100644
--- a/ui/compositor/layer.cc
+++ b/ui/compositor/layer.cc
@@ -750,14 +750,13 @@ void Layer::PaintContentsToDisplayList(
const gfx::Rect& clip,
ContentLayerClient::PaintingControlSetting painting_control) {
TRACE_EVENT1("ui", "Layer::PaintContentsToDisplayList", "name", name_);
+ gfx::Rect local_bounds(bounds().size());
+ gfx::Rect invalidation(
+ gfx::IntersectRects(damaged_region_.bounds(), local_bounds));
+ DCHECK(clip.Contains(invalidation));
ClearDamagedRects();
if (!delegate_)
return;
- // TODO(danakj): Save the invalidation on the layer and pass that down
- // instead of the |clip| here. That will break everything until View
- // early-outs emit cached display items instead of nothing.
- gfx::Rect invalidation = clip;
- DCHECK(clip.Contains(invalidation));
delegate_->OnPaintLayer(
PaintContext(display_list, device_scale_factor_, clip, invalidation));
}
diff --git a/ui/compositor/paint_cache.cc b/ui/compositor/paint_cache.cc
new file mode 100644
index 0000000..ef0e5a7
--- /dev/null
+++ b/ui/compositor/paint_cache.cc
@@ -0,0 +1,31 @@
+// 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/paint_cache.h"
+
+#include "cc/resources/display_item_list.h"
+#include "cc/resources/drawing_display_item.h"
+#include "ui/compositor/paint_context.h"
+
+namespace ui {
+
+PaintCache::PaintCache() {
+}
+
+PaintCache::~PaintCache() {
+}
+
+bool PaintCache::UseCache(const PaintContext& context) {
+ if (!display_item_)
+ return false;
+ DCHECK(context.list_);
+ context.list_->AppendItem(display_item_->Clone());
+ return true;
+}
+
+void PaintCache::SetCache(scoped_ptr<cc::DrawingDisplayItem> item) {
+ display_item_ = item.Pass();
+}
+
+} // namespace ui
diff --git a/ui/compositor/paint_cache.h b/ui/compositor/paint_cache.h
new file mode 100644
index 0000000..599a8ac
--- /dev/null
+++ b/ui/compositor/paint_cache.h
@@ -0,0 +1,45 @@
+// 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_PAINT_CACHE_H_
+#define UI_COMPOSITOR_PAINT_CACHE_H_
+
+#include "base/memory/scoped_ptr.h"
+#include "ui/compositor/compositor_export.h"
+
+namespace cc {
+class DrawingDisplayItem;
+}
+
+namespace ui {
+class PaintContext;
+class PaintRecorder;
+
+// A class that holds the output of a PaintRecorder to be reused when the
+// object that created the PaintRecorder has not been changed/invalidated.
+class COMPOSITOR_EXPORT PaintCache {
+ public:
+ PaintCache();
+ ~PaintCache();
+
+ // Returns true if the PaintCache was able to insert a previously-saved
+ // painting output into the PaintContext. If it returns false, the caller
+ // needs to do the work of painting, which can be stored into the PaintCache
+ // to be used next time.
+ bool UseCache(const PaintContext& context);
+
+ private:
+ // Only PaintRecorder can modify these.
+ friend PaintRecorder;
+
+ void SetCache(scoped_ptr<cc::DrawingDisplayItem> item);
+
+ scoped_ptr<cc::DrawingDisplayItem> display_item_;
+
+ DISALLOW_COPY_AND_ASSIGN(PaintCache);
+};
+
+} // namespace ui
+
+#endif // UI_COMPOSITOR_PAINT_CACHE_H_
diff --git a/ui/compositor/paint_context.h b/ui/compositor/paint_context.h
index d63f11f..a754ee4 100644
--- a/ui/compositor/paint_context.h
+++ b/ui/compositor/paint_context.h
@@ -56,15 +56,20 @@ class COMPOSITOR_EXPORT PaintContext {
return PaintContext(canvas_);
}
- // When true, IsRectInvalidated() can be called, otherwise its result would be
+ // When true, IsRectInvalid() can be called, otherwise its result would be
// invalid.
- bool CanCheckInvalidated() const { return !invalidation_.IsEmpty(); }
+ bool CanCheckInvalid() const { return !invalidation_.IsEmpty(); }
+
+ // When true, if a thing is not invalidated it does not need to paint itself.
+ // When false, everything should provide an output when painting regardless of
+ // being invalidated in order to remain visible.
+ bool ShouldEarlyOutOfPaintingWhenValid() const { return !!canvas_; }
// When true, the |bounds| touches an invalidated area, so should be
// re-painted. When false, re-painting can be skipped. Bounds should be in
// the local space with offsets up to the painting root in the PaintContext.
- bool IsRectInvalidated(const gfx::Rect& bounds) const {
- DCHECK(CanCheckInvalidated());
+ bool IsRectInvalid(const gfx::Rect& bounds) const {
+ DCHECK(CanCheckInvalid());
return invalidation_.Intersects(bounds + offset_);
}
@@ -86,6 +91,9 @@ class COMPOSITOR_EXPORT PaintContext {
friend class ClipTransformRecorder;
friend class CompositingRecorder;
friend class PaintRecorder;
+ // The Cache class also needs to access the DisplayItemList to append its
+ // cache contents.
+ friend class PaintCache;
PaintContext& operator=(const PaintContext& other) = delete;
diff --git a/ui/compositor/paint_recorder.cc b/ui/compositor/paint_recorder.cc
index 15aa0fb..80fb616 100644
--- a/ui/compositor/paint_recorder.cc
+++ b/ui/compositor/paint_recorder.cc
@@ -7,14 +7,15 @@
#include "cc/resources/display_item_list.h"
#include "cc/resources/drawing_display_item.h"
#include "third_party/skia/include/core/SkPictureRecorder.h"
+#include "ui/compositor/paint_cache.h"
#include "ui/compositor/paint_context.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/skia_util.h"
namespace ui {
-PaintRecorder::PaintRecorder(const PaintContext& context)
- : context_(context), canvas_(context.canvas_) {
+PaintRecorder::PaintRecorder(const PaintContext& context, PaintCache* cache)
+ : context_(context), canvas_(context.canvas_), cache_(cache) {
#if DCHECK_IS_ON()
DCHECK(!context.inside_paint_recorder_);
context.inside_paint_recorder_ = true;
@@ -34,15 +35,23 @@ PaintRecorder::PaintRecorder(const PaintContext& context)
}
}
+PaintRecorder::PaintRecorder(const PaintContext& context)
+ : PaintRecorder(context, nullptr) {
+}
+
PaintRecorder::~PaintRecorder() {
#if DCHECK_IS_ON()
context_.inside_paint_recorder_ = false;
#endif
- if (context_.list_) {
- context_.list_->AppendItem(cc::DrawingDisplayItem::Create(
- skia::AdoptRef(context_.recorder_->endRecordingAsPicture())));
- }
+ if (!context_.list_)
+ return;
+
+ scoped_ptr<cc::DrawingDisplayItem> item = cc::DrawingDisplayItem::Create(
+ skia::AdoptRef(context_.recorder_->endRecordingAsPicture()));
+ if (cache_)
+ cache_->SetCache(item->Clone());
+ context_.list_->AppendItem(item.Pass());
}
} // namespace ui
diff --git a/ui/compositor/paint_recorder.h b/ui/compositor/paint_recorder.h
index 7c3df82..9cac7a8 100644
--- a/ui/compositor/paint_recorder.h
+++ b/ui/compositor/paint_recorder.h
@@ -22,6 +22,7 @@ class SkCanvas;
class SkPictureRecorder;
namespace ui {
+class PaintCache;
class PaintContext;
// A class to hide the complexity behind setting up a recording into a
@@ -30,6 +31,9 @@ class PaintContext;
// recording is complete and can be cached.
class COMPOSITOR_EXPORT PaintRecorder {
public:
+ // The |cache| is owned by the caller and must be kept alive while
+ // PaintRecorder is in use.
+ PaintRecorder(const PaintContext& context, PaintCache* cache);
explicit PaintRecorder(const PaintContext& context);
~PaintRecorder();
@@ -40,6 +44,7 @@ class COMPOSITOR_EXPORT PaintRecorder {
const PaintContext& context_;
gfx::Canvas* canvas_;
scoped_ptr<gfx::Canvas> owned_canvas_;
+ PaintCache* cache_;
DISALLOW_COPY_AND_ASSIGN(PaintRecorder);
};