diff options
author | ben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-09-01 00:02:09 +0000 |
---|---|---|
committer | ben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-09-01 00:02:09 +0000 |
commit | 00b8698c798ba1fbc6994fdb8c28eff2be37b365 (patch) | |
tree | 67976f7a0a7a448f09b6c3e737b9a47ebab8eb0f /ui/gfx/compositor | |
parent | f632555fcd45a3009ceea304f46aab8baa7c2c8e (diff) | |
download | chromium_src-00b8698c798ba1fbc6994fdb8c28eff2be37b365.zip chromium_src-00b8698c798ba1fbc6994fdb8c28eff2be37b365.tar.gz chromium_src-00b8698c798ba1fbc6994fdb8c28eff2be37b365.tar.bz2 |
Add invalid rect tracking and repaint scheduling to Layer.
This adds a LayerDelegate interface that can be implemented by an object that wants to know when to repaint.
This is a different model to current layer updating, where code must call SetCanvas when it wishes to push an updated canvas to the layer's texture.
BUG=none
TEST=see unittest.
Review URL: http://codereview.chromium.org/7822002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@99080 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui/gfx/compositor')
-rw-r--r-- | ui/gfx/compositor/layer.cc | 31 | ||||
-rw-r--r-- | ui/gfx/compositor/layer.h | 18 | ||||
-rw-r--r-- | ui/gfx/compositor/layer_delegate.h | 28 | ||||
-rw-r--r-- | ui/gfx/compositor/layer_unittest.cc | 82 | ||||
-rw-r--r-- | ui/gfx/compositor/test_compositor_host.h | 11 | ||||
-rw-r--r-- | ui/gfx/compositor/test_compositor_host_win.cc | 15 |
6 files changed, 176 insertions, 9 deletions
diff --git a/ui/gfx/compositor/layer.cc b/ui/gfx/compositor/layer.cc index 4f1ed241..bf22832 100644 --- a/ui/gfx/compositor/layer.cc +++ b/ui/gfx/compositor/layer.cc @@ -7,6 +7,8 @@ #include <algorithm> #include "base/logging.h" +#include "base/scoped_ptr.h" +#include "ui/gfx/canvas_skia.h" #include "ui/gfx/point3.h" namespace ui { @@ -15,7 +17,8 @@ Layer::Layer(Compositor* compositor) : compositor_(compositor), texture_(compositor->CreateTexture()), parent_(NULL), - fills_bounds_opaquely_(false) { + fills_bounds_opaquely_(false), + delegate_(NULL) { } Layer::~Layer() { @@ -106,9 +109,17 @@ void Layer::SetTexture(ui::Texture* texture) { void Layer::SetCanvas(const SkCanvas& canvas, const gfx::Point& origin) { texture_->SetCanvas(canvas, origin, bounds_.size()); + invalid_rect_ = gfx::Rect(); +} + +void Layer::SchedulePaint(const gfx::Rect& invalid_rect) { + invalid_rect_ = invalid_rect_.Union(invalid_rect); + compositor_->SchedulePaint(); } void Layer::Draw() { + UpdateLayerCanvas(); + ui::TextureDrawParams texture_draw_params; for (Layer* layer = this; layer; layer = layer->parent_) { texture_draw_params.transform.ConcatTransform(layer->transform_); @@ -160,6 +171,24 @@ void Layer::DrawRegion(const ui::TextureDrawParams& params, texture_->Draw(params, region_to_draw); } +void Layer::UpdateLayerCanvas() { + // If we have no delegate, that means that whoever constructed the Layer is + // setting its canvas directly with SetCanvas(). + if (!delegate_) + return; + gfx::Rect local_bounds = gfx::Rect(gfx::Point(), bounds_.size()); + gfx::Rect draw_rect = invalid_rect_.Intersect(local_bounds); + if (draw_rect.IsEmpty()) { + invalid_rect_ = gfx::Rect(); + return; + } + scoped_ptr<gfx::Canvas> canvas(gfx::Canvas::CreateCanvas( + draw_rect.width(), draw_rect.height(), false)); + canvas->TranslateInt(draw_rect.x(), draw_rect.y()); + delegate_->OnPaint(canvas.get()); + SetCanvas(*canvas->AsCanvasSkia(), bounds().origin()); +} + void Layer::RecomputeHole() { for (size_t i = 0; i < children_.size(); ++i) { if (children_[i]->fills_bounds_opaquely() && diff --git a/ui/gfx/compositor/layer.h b/ui/gfx/compositor/layer.h index d523c9c..9270766 100644 --- a/ui/gfx/compositor/layer.h +++ b/ui/gfx/compositor/layer.h @@ -9,9 +9,11 @@ #include <vector> #include "base/memory/ref_counted.h" +#include "base/message_loop.h" #include "ui/gfx/rect.h" #include "ui/gfx/transform.h" #include "ui/gfx/compositor/compositor.h" +#include "ui/gfx/compositor/layer_delegate.h" class SkCanvas; @@ -31,6 +33,9 @@ class COMPOSITOR_EXPORT Layer { explicit Layer(Compositor* compositor); ~Layer(); + LayerDelegate* delegate() { return delegate_; } + void set_delegate(LayerDelegate* delegate) { delegate_ = delegate; } + // Adds a new Layer to this Layer. void Add(Layer* child); @@ -79,6 +84,11 @@ class COMPOSITOR_EXPORT Layer { // Resets the canvas of the texture. void SetCanvas(const SkCanvas& canvas, const gfx::Point& origin); + // Adds |invalid_rect| to the Layer's pending invalid rect, and schedules a + // repaint if the Layer has an associated LayerDelegate that can handle the + // repaint. + void SchedulePaint(const gfx::Rect& invalid_rect); + // Draws the layer with hole if hole is non empty. // hole looks like: // @@ -103,6 +113,10 @@ class COMPOSITOR_EXPORT Layer { void DrawRegion(const ui::TextureDrawParams& params, const gfx::Rect& region_to_draw); + // Called during the Draw() pass to freshen the Layer's contents from the + // delegate. + void UpdateLayerCanvas(); + // A hole in a layer is an area in the layer that does not get drawn // because this area is covered up with another layer which is known to be // opaque. @@ -134,6 +148,10 @@ class COMPOSITOR_EXPORT Layer { gfx::Rect hole_rect_; + gfx::Rect invalid_rect_; + + LayerDelegate* delegate_; + DISALLOW_COPY_AND_ASSIGN(Layer); }; diff --git a/ui/gfx/compositor/layer_delegate.h b/ui/gfx/compositor/layer_delegate.h new file mode 100644 index 0000000..316963a --- /dev/null +++ b/ui/gfx/compositor/layer_delegate.h @@ -0,0 +1,28 @@ +// Copyright (c) 2011 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_GFX_COMPOSITOR_LAYER_DELEGATE_H_ +#define UI_GFX_COMPOSITOR_LAYER_DELEGATE_H_ +#pragma once + +namespace gfx { +class Canvas; +} + +namespace ui { + +// A delegate interface implemented by an object that renders to a Layer. +class LayerDelegate { + public: + // Paint content for the layer to the specified canvas. It has already been + // clipped to the Layer's invalid rect. + virtual void OnPaint(gfx::Canvas* canvas) = 0; + + protected: + virtual ~LayerDelegate() {} +}; + +} // namespace ui + +#endif // UI_GFX_COMPOSITOR_LAYER_DELEGATE_H_ diff --git a/ui/gfx/compositor/layer_unittest.cc b/ui/gfx/compositor/layer_unittest.cc index 3a82d2a..e0d029d 100644 --- a/ui/gfx/compositor/layer_unittest.cc +++ b/ui/gfx/compositor/layer_unittest.cc @@ -3,6 +3,8 @@ // found in the LICENSE file. #include "base/basictypes.h" +#include "base/compiler_specific.h" +#include "base/scoped_ptr.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/gfx/canvas_skia.h" #include "ui/gfx/compositor/layer.h" @@ -12,15 +14,50 @@ namespace ui { namespace { -class LayerTest : public testing::Test { +class TestLayerDelegate : public LayerDelegate { +public: + explicit TestLayerDelegate(Layer* owner) : owner_(owner), color_index_(0) {} + virtual ~TestLayerDelegate() {} + + void AddColor(SkColor color) { + colors_.push_back(color); + } + + gfx::Size paint_size() const { return paint_size_; } + int color_index() const { return color_index_; } + + // Overridden from LayerDelegate: + virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE { + SkBitmap contents = canvas->AsCanvasSkia()->ExtractBitmap(); + paint_size_ = gfx::Size(contents.width(), contents.height()); + canvas->FillRectInt(colors_.at(color_index_), 0, 0, + contents.width(), + contents.height()); + color_index_ = ++color_index_ % colors_.size(); + + MessageLoop::current()->Quit(); + } + +private: + Layer* owner_; + std::vector<SkColor> colors_; + int color_index_; + gfx::Size paint_size_; + + DISALLOW_COPY_AND_ASSIGN(TestLayerDelegate); +}; + +class LayerTest : public testing::Test, + public TestCompositorHostDelegate { public: - LayerTest() {} + LayerTest() : root_layer_(NULL) {} virtual ~LayerTest() {} // Overridden from testing::Test: virtual void SetUp() OVERRIDE { + root_layer_ = NULL; const gfx::Rect host_bounds(10, 10, 500, 500); - window_.reset(TestCompositorHost::Create(host_bounds)); + window_.reset(TestCompositorHost::Create(host_bounds, this)); window_->Show(); } @@ -71,12 +108,22 @@ class LayerTest : public testing::Test { } void RunPendingMessages() { - MessageLoop main_message_loop(MessageLoop::TYPE_UI); MessageLoopForUI::current()->Run(NULL); } + protected: + void set_root_layer(Layer* root_layer) { root_layer_ = root_layer; } + private: + // Overridden from TestCompositorHostDelegate: + virtual void Draw() { + if (root_layer_) + DrawLayerChildren(root_layer_); + } + + MessageLoopForUI message_loop_; scoped_ptr<TestCompositorHost> window_; + Layer* root_layer_; DISALLOW_COPY_AND_ASSIGN(LayerTest); }; @@ -158,5 +205,32 @@ TEST_F(LayerTest, ConvertPointToLayer_Medium) { EXPECT_EQ(point2_in_l3_coords, point2_in_l1_coords); } +TEST_F(LayerTest, Delegate) { + scoped_ptr<Layer> l1(CreateColorLayer(SK_ColorBLACK, + gfx::Rect(20, 20, 400, 400))); + TestLayerDelegate delegate(l1.get()); + l1->set_delegate(&delegate); + delegate.AddColor(SK_ColorWHITE); + delegate.AddColor(SK_ColorYELLOW); + delegate.AddColor(SK_ColorGREEN); + + set_root_layer(l1.get()); + + l1->SchedulePaint(gfx::Rect(0, 0, 400, 400)); + RunPendingMessages(); + EXPECT_EQ(delegate.color_index(), 1); + EXPECT_EQ(delegate.paint_size(), l1->bounds().size()); + + l1->SchedulePaint(gfx::Rect(10, 10, 200, 200)); + RunPendingMessages(); + EXPECT_EQ(delegate.color_index(), 2); + EXPECT_EQ(delegate.paint_size(), gfx::Size(200, 200)); + + l1->SchedulePaint(gfx::Rect(5, 5, 50, 50)); + RunPendingMessages(); + EXPECT_EQ(delegate.color_index(), 0); + EXPECT_EQ(delegate.paint_size(), gfx::Size(50, 50)); +} + } // namespace ui diff --git a/ui/gfx/compositor/test_compositor_host.h b/ui/gfx/compositor/test_compositor_host.h index f0bdbaa..973663c 100644 --- a/ui/gfx/compositor/test_compositor_host.h +++ b/ui/gfx/compositor/test_compositor_host.h @@ -18,12 +18,21 @@ namespace ui { class Compositor; +class TestCompositorHostDelegate { + public: + virtual void Draw() = 0; + + protected: + virtual ~TestCompositorHostDelegate() {} +}; + class TestCompositorHost : public MessageLoop::Dispatcher { public: virtual ~TestCompositorHost() {} // Creates a new TestCompositorHost. The caller owns the returned value. - static TestCompositorHost* Create(const gfx::Rect& bounds); + static TestCompositorHost* Create(const gfx::Rect& bounds, + TestCompositorHostDelegate* delegate); // Shows the TestCompositorHost. virtual void Show() = 0; diff --git a/ui/gfx/compositor/test_compositor_host_win.cc b/ui/gfx/compositor/test_compositor_host_win.cc index f126b08..03cbcb6 100644 --- a/ui/gfx/compositor/test_compositor_host_win.cc +++ b/ui/gfx/compositor/test_compositor_host_win.cc @@ -4,6 +4,7 @@ #include "ui/gfx/compositor/test_compositor_host.h" +#include "base/compiler_specific.h" #include "ui/base/win/window_impl.h" #include "ui/gfx/compositor/compositor.h" @@ -12,7 +13,9 @@ namespace ui { class TestCompositorHostWin : public TestCompositorHost, public ui::WindowImpl { public: - explicit TestCompositorHostWin(const gfx::Rect& bounds) { + TestCompositorHostWin(const gfx::Rect& bounds, + TestCompositorHostDelegate* delegate) + : delegate_(delegate) { Init(NULL, bounds); compositor_ = ui::Compositor::Create(hwnd(), GetSize()); } @@ -42,6 +45,9 @@ class TestCompositorHostWin : public TestCompositorHost, END_MSG_MAP() void OnPaint(HDC dc) { + compositor_->NotifyStart(); + delegate_->Draw(); + compositor_->NotifyEnd(); ValidateRect(hwnd(), NULL); } @@ -52,12 +58,15 @@ class TestCompositorHostWin : public TestCompositorHost, } scoped_refptr<ui::Compositor> compositor_; + TestCompositorHostDelegate* delegate_; DISALLOW_COPY_AND_ASSIGN(TestCompositorHostWin); }; -TestCompositorHost* TestCompositorHost::Create(const gfx::Rect& bounds) { - return new TestCompositorHostWin(bounds); +TestCompositorHost* TestCompositorHost::Create( + const gfx::Rect& bounds, + TestCompositorHostDelegate* delegate) { + return new TestCompositorHostWin(bounds, delegate); } } // namespace ui |