diff options
author | danakj <danakj@chromium.org> | 2015-04-25 10:53:17 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-04-25 17:53:12 +0000 |
commit | 93f5730af51af283713ad19dd5e08c3b3ea34eaa (patch) | |
tree | 38e1eb1974410d8503476bb9d0d25218f3ec17c9 /ui/compositor | |
parent | ba5b67e27dc64c3c6793be8f9c991066c956c33f (diff) | |
download | chromium_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.gn | 2 | ||||
-rw-r--r-- | ui/compositor/compositor.gyp | 2 | ||||
-rw-r--r-- | ui/compositor/layer.cc | 9 | ||||
-rw-r--r-- | ui/compositor/paint_cache.cc | 31 | ||||
-rw-r--r-- | ui/compositor/paint_cache.h | 45 | ||||
-rw-r--r-- | ui/compositor/paint_context.h | 16 | ||||
-rw-r--r-- | ui/compositor/paint_recorder.cc | 21 | ||||
-rw-r--r-- | ui/compositor/paint_recorder.h | 5 |
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); }; |