summaryrefslogtreecommitdiffstats
path: root/ui/gfx/compositor
diff options
context:
space:
mode:
authorben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-09-01 00:02:09 +0000
committerben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-09-01 00:02:09 +0000
commit00b8698c798ba1fbc6994fdb8c28eff2be37b365 (patch)
tree67976f7a0a7a448f09b6c3e737b9a47ebab8eb0f /ui/gfx/compositor
parentf632555fcd45a3009ceea304f46aab8baa7c2c8e (diff)
downloadchromium_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.cc31
-rw-r--r--ui/gfx/compositor/layer.h18
-rw-r--r--ui/gfx/compositor/layer_delegate.h28
-rw-r--r--ui/gfx/compositor/layer_unittest.cc82
-rw-r--r--ui/gfx/compositor/test_compositor_host.h11
-rw-r--r--ui/gfx/compositor/test_compositor_host_win.cc15
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