summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorskaslev@chromium.org <skaslev@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-04-15 22:44:02 +0000
committerskaslev@chromium.org <skaslev@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-04-15 22:44:02 +0000
commit878705be811db12427023ccdf2dcf7d0ca6b06dc (patch)
tree795c756bf423665d8c2fe5fa2641296dc070d772
parent7ef4321c549f0d6c33e02090a6714d424adb65bb (diff)
downloadchromium_src-878705be811db12427023ccdf2dcf7d0ca6b06dc.zip
chromium_src-878705be811db12427023ccdf2dcf7d0ca6b06dc.tar.gz
chromium_src-878705be811db12427023ccdf2dcf7d0ca6b06dc.tar.bz2
Propagate back damaged rects coming from the UI to the renderer.
This patch also fixes top level controls rendering in s/w compositing for Aura on Windows. BUG=161008,229553 Review URL: https://codereview.chromium.org/14197002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@194248 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--cc/test/fake_proxy.h2
-rw-r--r--cc/test/layer_tree_test.cc14
-rw-r--r--cc/test/layer_tree_test.h2
-rw-r--r--cc/trees/layer_tree_host.cc6
-rw-r--r--cc/trees/layer_tree_host.h1
-rw-r--r--cc/trees/layer_tree_host_impl.cc12
-rw-r--r--cc/trees/layer_tree_host_impl.h3
-rw-r--r--cc/trees/layer_tree_host_unittest.cc128
-rw-r--r--cc/trees/proxy.h2
-rw-r--r--cc/trees/single_thread_proxy.cc4
-rw-r--r--cc/trees/single_thread_proxy.h2
-rw-r--r--cc/trees/thread_proxy.cc9
-rw-r--r--cc/trees/thread_proxy.h4
-rw-r--r--ui/aura/root_window.cc14
-rw-r--r--ui/aura/root_window.h7
-rw-r--r--ui/aura/root_window_host_delegate.h3
-rw-r--r--ui/aura/root_window_host_win.cc6
-rw-r--r--ui/aura/root_window_host_x11.cc7
-rw-r--r--ui/compositor/compositor.cc8
-rw-r--r--ui/compositor/compositor.h12
-rw-r--r--ui/compositor/layer_unittest.cc2
-rw-r--r--ui/compositor/test/test_compositor_host_linux.cc2
-rw-r--r--ui/compositor/test/test_compositor_host_mac.mm2
-rw-r--r--ui/compositor/test/test_compositor_host_win.cc2
-rw-r--r--ui/views/widget/desktop_aura/desktop_root_window_host_win.cc2
-rw-r--r--ui/views/widget/desktop_aura/desktop_root_window_host_x11.cc10
-rw-r--r--ui/views/widget/widget.cc31
27 files changed, 189 insertions, 108 deletions
diff --git a/cc/test/fake_proxy.h b/cc/test/fake_proxy.h
index 60bbdf7..e26a0fc 100644
--- a/cc/test/fake_proxy.h
+++ b/cc/test/fake_proxy.h
@@ -27,7 +27,7 @@ class FakeProxy : public Proxy {
virtual const RendererCapabilities& GetRendererCapabilities() const OVERRIDE;
virtual void SetNeedsAnimate() OVERRIDE {}
virtual void SetNeedsCommit() OVERRIDE {}
- virtual void SetNeedsRedraw() OVERRIDE {}
+ virtual void SetNeedsRedraw(const gfx::Rect& damage_rect) OVERRIDE {}
virtual void SetDeferCommits(bool defer_commits) OVERRIDE {}
virtual void MainThreadHasStoppedFlinging() OVERRIDE {}
virtual bool CommitRequested() const OVERRIDE;
diff --git a/cc/test/layer_tree_test.cc b/cc/test/layer_tree_test.cc
index 61c9a04..c8d16d5 100644
--- a/cc/test/layer_tree_test.cc
+++ b/cc/test/layer_tree_test.cc
@@ -371,6 +371,13 @@ void LayerTreeTest::PostSetNeedsRedrawToMainThread() {
main_thread_weak_ptr_));
}
+void LayerTreeTest::PostSetNeedsRedrawRectToMainThread(
+ const gfx::Rect& damage_rect) {
+ proxy()->MainThread()->PostTask(
+ base::Bind(&LayerTreeTest::DispatchSetNeedsRedrawRect,
+ main_thread_weak_ptr_, damage_rect));
+}
+
void LayerTreeTest::PostSetVisibleToMainThread(bool visible) {
proxy()->MainThread()->PostTask(
base::Bind(&LayerTreeTest::DispatchSetVisible,
@@ -495,6 +502,13 @@ void LayerTreeTest::DispatchSetNeedsRedraw() {
layer_tree_host_->SetNeedsRedraw();
}
+void LayerTreeTest::DispatchSetNeedsRedrawRect(const gfx::Rect& damage_rect) {
+ DCHECK(!proxy() || proxy()->IsMainThread());
+
+ if (layer_tree_host_)
+ layer_tree_host_->SetNeedsRedrawRect(damage_rect);
+}
+
void LayerTreeTest::DispatchSetVisible(bool visible) {
DCHECK(!proxy() || proxy()->IsMainThread());
diff --git a/cc/test/layer_tree_test.h b/cc/test/layer_tree_test.h
index 6be09b8..f95c7f4 100644
--- a/cc/test/layer_tree_test.h
+++ b/cc/test/layer_tree_test.h
@@ -111,6 +111,7 @@ class LayerTreeTest : public testing::Test, public TestHooks {
void PostSetNeedsCommitToMainThread();
void PostAcquireLayerTextures();
void PostSetNeedsRedrawToMainThread();
+ void PostSetNeedsRedrawRectToMainThread(const gfx::Rect& damage_rect);
void PostSetVisibleToMainThread(bool visible);
void DoBeginTest();
@@ -130,6 +131,7 @@ class LayerTreeTest : public testing::Test, public TestHooks {
void DispatchSetNeedsCommit();
void DispatchAcquireLayerTextures();
void DispatchSetNeedsRedraw();
+ void DispatchSetNeedsRedrawRect(const gfx::Rect& damage_rect);
void DispatchSetVisible(bool visible);
void DispatchComposite();
void DispatchDidAddAnimation();
diff --git a/cc/trees/layer_tree_host.cc b/cc/trees/layer_tree_host.cc
index 81f9051..22b6db5 100644
--- a/cc/trees/layer_tree_host.cc
+++ b/cc/trees/layer_tree_host.cc
@@ -555,7 +555,11 @@ void LayerTreeHost::SetNeedsFullTreeSync() {
}
void LayerTreeHost::SetNeedsRedraw() {
- proxy_->SetNeedsRedraw();
+ SetNeedsRedrawRect(gfx::Rect(device_viewport_size_));
+}
+
+void LayerTreeHost::SetNeedsRedrawRect(const gfx::Rect& damage_rect) {
+ proxy_->SetNeedsRedraw(damage_rect);
if (!proxy_->ImplThread())
client_->ScheduleComposite();
}
diff --git a/cc/trees/layer_tree_host.h b/cc/trees/layer_tree_host.h
index bd2298c..8e28f31 100644
--- a/cc/trees/layer_tree_host.h
+++ b/cc/trees/layer_tree_host.h
@@ -164,6 +164,7 @@ class CC_EXPORT LayerTreeHost : NON_EXPORTED_BASE(public RateLimiterClient) {
virtual void SetNeedsCommit();
virtual void SetNeedsFullTreeSync();
void SetNeedsRedraw();
+ void SetNeedsRedrawRect(const gfx::Rect& damage_rect);
bool CommitRequested() const;
void SetAnimationEvents(scoped_ptr<AnimationEventsVector> events,
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc
index 7b0a7e1..a500663 100644
--- a/cc/trees/layer_tree_host_impl.cc
+++ b/cc/trees/layer_tree_host_impl.cc
@@ -183,7 +183,6 @@ LayerTreeHostImpl::LayerTreeHostImpl(
last_sent_memory_visible_bytes_(0),
last_sent_memory_visible_and_nearby_bytes_(0),
last_sent_memory_use_bytes_(0),
- next_frame_damages_full_device_viewport_(false),
animation_registrar_(AnimationRegistrar::Create()),
rendering_stats_instrumentation_(rendering_stats_instrumentation) {
DCHECK(proxy_->IsImplThread());
@@ -715,6 +714,10 @@ void LayerTreeHostImpl::UpdateBackgroundAnimateTicking(
time_source_client_adapter_->SetActive(enabled);
}
+void LayerTreeHostImpl::SetViewportDamage(const gfx::Rect& damage_rect) {
+ viewport_damage_rect_.Union(damage_rect);
+}
+
static inline RenderPass* FindRenderPassById(
RenderPass::Id render_pass_id,
const LayerTreeHostImpl::FrameData& frame) {
@@ -862,13 +865,12 @@ bool LayerTreeHostImpl::PrepareToDraw(FrameData* frame,
frame->has_no_damage = false;
if (active_tree_->root_layer()) {
- if (next_frame_damages_full_device_viewport_)
- device_viewport_damage_rect.Union(gfx::Rect(device_viewport_size_));
+ device_viewport_damage_rect.Union(viewport_damage_rect_);
+ viewport_damage_rect_ = gfx::Rect();
active_tree_->root_layer()->render_surface()->damage_tracker()->
AddDamageNextUpdate(device_viewport_damage_rect);
}
- next_frame_damages_full_device_viewport_ = false;
if (!CalculateRenderPasses(frame))
return false;
@@ -1800,7 +1802,7 @@ scoped_ptr<ScrollAndScaleSet> LayerTreeHostImpl::ProcessScrollDeltas() {
}
void LayerTreeHostImpl::SetFullRootLayerDamage() {
- next_frame_damages_full_device_viewport_ = true;
+ SetViewportDamage(gfx::Rect(device_viewport_size_));
}
void LayerTreeHostImpl::AnimatePageScale(base::TimeTicks time) {
diff --git a/cc/trees/layer_tree_host_impl.h b/cc/trees/layer_tree_host_impl.h
index ffdfb5f..6c884f1 100644
--- a/cc/trees/layer_tree_host_impl.h
+++ b/cc/trees/layer_tree_host_impl.h
@@ -142,6 +142,7 @@ class CC_EXPORT LayerTreeHostImpl : public InputHandlerClient,
base::Time wall_clock_time);
virtual void UpdateAnimationState(bool start_ready_animations);
void UpdateBackgroundAnimateTicking(bool should_background_tick);
+ void SetViewportDamage(const gfx::Rect& damage_rect);
void ManageTiles();
void SetAnticipatedDrawTime(base::TimeTicks time);
@@ -461,7 +462,7 @@ class CC_EXPORT LayerTreeHostImpl : public InputHandlerClient,
size_t last_sent_memory_visible_and_nearby_bytes_;
size_t last_sent_memory_use_bytes_;
- bool next_frame_damages_full_device_viewport_;
+ gfx::Rect viewport_damage_rect_;
base::TimeTicks current_frame_time_;
diff --git a/cc/trees/layer_tree_host_unittest.cc b/cc/trees/layer_tree_host_unittest.cc
index cd3d0fd..bbc3f27 100644
--- a/cc/trees/layer_tree_host_unittest.cc
+++ b/cc/trees/layer_tree_host_unittest.cc
@@ -179,6 +179,68 @@ class LayerTreeHostTestSetNeedsRedraw : public LayerTreeHostTest {
MULTI_THREAD_TEST_F(LayerTreeHostTestSetNeedsRedraw);
+// After setNeedsRedrawRect(invalid_rect) the final damage_rect
+// must contain invalid_rect.
+class LayerTreeHostTestSetNeedsRedrawRect : public LayerTreeHostTest {
+ public:
+ LayerTreeHostTestSetNeedsRedrawRect()
+ : num_draws_(0),
+ bounds_(50, 50),
+ invalid_rect_(10, 10, 20, 20),
+ root_layer_(ContentLayer::Create(&client_)) {
+ }
+
+ virtual void BeginTest() OVERRIDE {
+ root_layer_->SetIsDrawable(true);
+ root_layer_->SetBounds(bounds_);
+ layer_tree_host()->SetRootLayer(root_layer_);
+ layer_tree_host()->SetViewportSize(bounds_);
+ PostSetNeedsCommitToMainThread();
+ }
+
+ virtual bool PrepareToDrawOnThread(LayerTreeHostImpl* host_impl,
+ LayerTreeHostImpl::FrameData* frame_data,
+ bool result) OVERRIDE {
+ EXPECT_TRUE(result);
+
+ gfx::RectF root_damage_rect;
+ if (!frame_data->render_passes.empty())
+ root_damage_rect = frame_data->render_passes.back()->damage_rect;
+
+ if (!num_draws_) {
+ // If this is the first frame, expect full frame damage.
+ EXPECT_RECT_EQ(root_damage_rect, gfx::Rect(bounds_));
+ } else {
+ // Check that invalid_rect_ is indeed repainted.
+ EXPECT_TRUE(root_damage_rect.Contains(invalid_rect_));
+ }
+
+ return result;
+ }
+
+ virtual void DrawLayersOnThread(LayerTreeHostImpl* impl) OVERRIDE {
+ if (!num_draws_) {
+ PostSetNeedsRedrawRectToMainThread(invalid_rect_);
+ } else {
+ EndTest();
+ }
+ num_draws_++;
+ }
+
+ virtual void AfterTest() OVERRIDE {
+ EXPECT_EQ(2, num_draws_);
+ }
+
+ private:
+ int num_draws_;
+ const gfx::Size bounds_;
+ const gfx::Rect invalid_rect_;
+ FakeContentLayerClient client_;
+ scoped_refptr<ContentLayer> root_layer_;
+};
+
+SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestSetNeedsRedrawRect);
+
class LayerTreeHostTestNoExtraCommitFromInvalidate : public LayerTreeHostTest {
public:
LayerTreeHostTestNoExtraCommitFromInvalidate()
@@ -472,39 +534,39 @@ MULTI_THREAD_TEST_F(LayerTreeHostTestCommit);
// Verifies that StartPageScaleAnimation events propagate correctly
// from LayerTreeHost to LayerTreeHostImpl in the MT compositor.
class LayerTreeHostTestStartPageScaleAnimation : public LayerTreeHostTest {
-public:
- LayerTreeHostTestStartPageScaleAnimation() {}
-
- virtual void BeginTest() OVERRIDE {
- layer_tree_host()->root_layer()->SetScrollable(true);
- layer_tree_host()->root_layer()->SetScrollOffset(gfx::Vector2d());
- layer_tree_host()->SetPageScaleFactorAndLimits(1.f, 0.5f, 2.f);
- layer_tree_host()->StartPageScaleAnimation(
- gfx::Vector2d(), false, 1.25f, base::TimeDelta());
- PostSetNeedsCommitToMainThread();
- PostSetNeedsRedrawToMainThread();
- }
-
- virtual void ApplyScrollAndScale(gfx::Vector2d scroll_delta, float scale)
- OVERRIDE {
- gfx::Vector2d offset = layer_tree_host()->root_layer()->scroll_offset();
- layer_tree_host()->root_layer()->SetScrollOffset(offset + scroll_delta);
- layer_tree_host()->SetPageScaleFactorAndLimits(scale, 0.5f, 2.f);
- }
-
- virtual void CommitCompleteOnThread(LayerTreeHostImpl* impl) OVERRIDE {
- impl->ProcessScrollDeltas();
- // We get one commit before the first draw, and the animation doesn't happen
- // until the second draw.
- if (impl->active_tree()->source_frame_number() == 1) {
- EXPECT_EQ(1.25f, impl->active_tree()->page_scale_factor());
- EndTest();
- } else {
- PostSetNeedsRedrawToMainThread();
- }
- }
-
- virtual void AfterTest() OVERRIDE {}
+ public:
+ LayerTreeHostTestStartPageScaleAnimation() {}
+
+ virtual void BeginTest() OVERRIDE {
+ layer_tree_host()->root_layer()->SetScrollable(true);
+ layer_tree_host()->root_layer()->SetScrollOffset(gfx::Vector2d());
+ layer_tree_host()->SetPageScaleFactorAndLimits(1.f, 0.5f, 2.f);
+ layer_tree_host()->StartPageScaleAnimation(
+ gfx::Vector2d(), false, 1.25f, base::TimeDelta());
+ PostSetNeedsCommitToMainThread();
+ PostSetNeedsRedrawToMainThread();
+ }
+
+ virtual void ApplyScrollAndScale(gfx::Vector2d scroll_delta, float scale)
+ OVERRIDE {
+ gfx::Vector2d offset = layer_tree_host()->root_layer()->scroll_offset();
+ layer_tree_host()->root_layer()->SetScrollOffset(offset + scroll_delta);
+ layer_tree_host()->SetPageScaleFactorAndLimits(scale, 0.5f, 2.f);
+ }
+
+ virtual void CommitCompleteOnThread(LayerTreeHostImpl* impl) OVERRIDE {
+ impl->ProcessScrollDeltas();
+ // We get one commit before the first draw, and the animation doesn't happen
+ // until the second draw.
+ if (impl->active_tree()->source_frame_number() == 1) {
+ EXPECT_EQ(1.25f, impl->active_tree()->page_scale_factor());
+ EndTest();
+ } else {
+ PostSetNeedsRedrawToMainThread();
+ }
+ }
+
+ virtual void AfterTest() OVERRIDE {}
};
MULTI_THREAD_TEST_F(LayerTreeHostTestStartPageScaleAnimation);
diff --git a/cc/trees/proxy.h b/cc/trees/proxy.h
index 824cd06..ff7ef40 100644
--- a/cc/trees/proxy.h
+++ b/cc/trees/proxy.h
@@ -76,7 +76,7 @@ class CC_EXPORT Proxy {
virtual void SetNeedsAnimate() = 0;
virtual void SetNeedsCommit() = 0;
- virtual void SetNeedsRedraw() = 0;
+ virtual void SetNeedsRedraw(const gfx::Rect& damage_rect) = 0;
// Defers commits until it is reset. It is only supported when in threaded
// mode. It's an error to make a sync call like CompositeAndReadback while
diff --git a/cc/trees/single_thread_proxy.cc b/cc/trees/single_thread_proxy.cc
index 31a7054..14bdddd 100644
--- a/cc/trees/single_thread_proxy.cc
+++ b/cc/trees/single_thread_proxy.cc
@@ -227,10 +227,10 @@ void SingleThreadProxy::SetNeedsCommit() {
layer_tree_host_->ScheduleComposite();
}
-void SingleThreadProxy::SetNeedsRedraw() {
+void SingleThreadProxy::SetNeedsRedraw(const gfx::Rect& damage_rect) {
// FIXME: Once we move render_widget scheduling into this class, we can
// treat redraw requests more efficiently than CommitAndRedraw requests.
- layer_tree_host_impl_->SetFullRootLayerDamage();
+ layer_tree_host_impl_->SetViewportDamage(damage_rect);
SetNeedsCommit();
}
diff --git a/cc/trees/single_thread_proxy.h b/cc/trees/single_thread_proxy.h
index bfd054d..fa5d5fe 100644
--- a/cc/trees/single_thread_proxy.h
+++ b/cc/trees/single_thread_proxy.h
@@ -34,7 +34,7 @@ class SingleThreadProxy : public Proxy, LayerTreeHostImplClient {
virtual const RendererCapabilities& GetRendererCapabilities() const OVERRIDE;
virtual void SetNeedsAnimate() OVERRIDE;
virtual void SetNeedsCommit() OVERRIDE;
- virtual void SetNeedsRedraw() OVERRIDE;
+ virtual void SetNeedsRedraw(const gfx::Rect& damage_rect) OVERRIDE;
virtual void SetDeferCommits(bool defer_commits) OVERRIDE;
virtual bool CommitRequested() const OVERRIDE;
virtual void MainThreadHasStoppedFlinging() OVERRIDE {}
diff --git a/cc/trees/thread_proxy.cc b/cc/trees/thread_proxy.cc
index 237d2ac..3cc54e6 100644
--- a/cc/trees/thread_proxy.cc
+++ b/cc/trees/thread_proxy.cc
@@ -455,11 +455,12 @@ void ThreadProxy::SendManagedMemoryStats() {
bool ThreadProxy::IsInsideDraw() { return inside_draw_; }
-void ThreadProxy::SetNeedsRedraw() {
+void ThreadProxy::SetNeedsRedraw(const gfx::Rect& damage_rect) {
DCHECK(IsMainThread());
TRACE_EVENT0("cc", "ThreadProxy::SetNeedsRedraw");
Proxy::ImplThread()->PostTask(base::Bind(
- &ThreadProxy::SetFullRootLayerDamageOnImplThread, impl_thread_weak_ptr_));
+ &ThreadProxy::SetViewportDamageOnImplThread,
+ impl_thread_weak_ptr_, damage_rect));
Proxy::ImplThread()->PostTask(base::Bind(
&ThreadProxy::SetNeedsRedrawOnImplThread, impl_thread_weak_ptr_));
}
@@ -1161,9 +1162,9 @@ void ThreadProxy::LayerTreeHostClosedOnImplThread(CompletionEvent* completion) {
completion->Signal();
}
-void ThreadProxy::SetFullRootLayerDamageOnImplThread() {
+void ThreadProxy::SetViewportDamageOnImplThread(const gfx::Rect& damage_rect) {
DCHECK(IsImplThread());
- layer_tree_host_impl_->SetFullRootLayerDamage();
+ layer_tree_host_impl_->SetViewportDamage(damage_rect);
}
size_t ThreadProxy::MaxPartialTextureUpdates() const {
diff --git a/cc/trees/thread_proxy.h b/cc/trees/thread_proxy.h
index 5d6837c..fccde44 100644
--- a/cc/trees/thread_proxy.h
+++ b/cc/trees/thread_proxy.h
@@ -49,7 +49,7 @@ class ThreadProxy : public Proxy,
virtual const RendererCapabilities& GetRendererCapabilities() const OVERRIDE;
virtual void SetNeedsAnimate() OVERRIDE;
virtual void SetNeedsCommit() OVERRIDE;
- virtual void SetNeedsRedraw() OVERRIDE;
+ virtual void SetNeedsRedraw(const gfx::Rect& damage_rect) OVERRIDE;
virtual void SetDeferCommits(bool defer_commits) OVERRIDE;
virtual bool CommitRequested() const OVERRIDE;
virtual void MainThreadHasStoppedFlinging() OVERRIDE;
@@ -162,7 +162,7 @@ class ThreadProxy : public Proxy,
RendererCapabilities* capabilities);
void LayerTreeHostClosedOnImplThread(CompletionEvent* completion);
void ManageTilesOnImplThread();
- void SetFullRootLayerDamageOnImplThread();
+ void SetViewportDamageOnImplThread(const gfx::Rect& damage_rect);
void AcquireLayerTexturesForMainThreadOnImplThread(
CompletionEvent* completion);
void RecreateOutputSurfaceOnImplThread(
diff --git a/ui/aura/root_window.cc b/ui/aura/root_window.cc
index f378116..968a25c 100644
--- a/ui/aura/root_window.cc
+++ b/ui/aura/root_window.cc
@@ -320,11 +320,15 @@ void RootWindow::Draw() {
TRACE_EVENT_ASYNC_BEGIN0("ui", "RootWindow::Draw",
compositor_->last_started_frame() + 1);
- compositor_->Draw(false);
+ compositor_->Draw();
}
-void RootWindow::ScheduleFullDraw() {
- compositor_->ScheduleFullDraw();
+void RootWindow::ScheduleFullRedraw() {
+ compositor_->ScheduleFullRedraw();
+}
+
+void RootWindow::ScheduleRedrawRect(const gfx::Rect& damage_rect) {
+ compositor_->ScheduleRedrawRect(damage_rect);
}
Window* RootWindow::GetGestureTarget(ui::GestureEvent* event) {
@@ -998,8 +1002,8 @@ void RootWindow::OnHostLostMouseGrab() {
ClearMouseHandlers();
}
-void RootWindow::OnHostPaint() {
- Draw();
+void RootWindow::OnHostPaint(const gfx::Rect& damage_rect) {
+ compositor_->ScheduleRedrawRect(damage_rect);
}
void RootWindow::OnHostMoved(const gfx::Point& origin) {
diff --git a/ui/aura/root_window.h b/ui/aura/root_window.h
index 272f920..11f59773a 100644
--- a/ui/aura/root_window.h
+++ b/ui/aura/root_window.h
@@ -136,7 +136,10 @@ class AURA_EXPORT RootWindow : public ui::CompositorDelegate,
void Draw();
// Draw the whole screen.
- void ScheduleFullDraw();
+ void ScheduleFullRedraw();
+
+ // Draw the damage_rect.
+ void ScheduleRedrawRect(const gfx::Rect& damage_rect);
// Returns a target window for the given gesture event.
Window* GetGestureTarget(ui::GestureEvent* event);
@@ -369,7 +372,7 @@ class AURA_EXPORT RootWindow : public ui::CompositorDelegate,
virtual void OnHostActivated() OVERRIDE;
virtual void OnHostLostWindowCapture() OVERRIDE;
virtual void OnHostLostMouseGrab() OVERRIDE;
- virtual void OnHostPaint() OVERRIDE;
+ virtual void OnHostPaint(const gfx::Rect& damage_rect) OVERRIDE;
virtual void OnHostMoved(const gfx::Point& origin) OVERRIDE;
virtual void OnHostResized(const gfx::Size& size) OVERRIDE;
virtual float GetDeviceScaleFactor() OVERRIDE;
diff --git a/ui/aura/root_window_host_delegate.h b/ui/aura/root_window_host_delegate.h
index ee33be8..a787651 100644
--- a/ui/aura/root_window_host_delegate.h
+++ b/ui/aura/root_window_host_delegate.h
@@ -9,6 +9,7 @@
namespace gfx {
class Point;
+class Rect;
class Size;
}
@@ -44,7 +45,7 @@ class AURA_EXPORT RootWindowHostDelegate {
// window move on our behalf, but we should still paint as if we're active.
virtual void OnHostLostMouseGrab() = 0;
- virtual void OnHostPaint() = 0;
+ virtual void OnHostPaint(const gfx::Rect& damage_rect) = 0;
virtual void OnHostMoved(const gfx::Point& origin) = 0;
virtual void OnHostResized(const gfx::Size& size) = 0;
diff --git a/ui/aura/root_window_host_win.cc b/ui/aura/root_window_host_win.cc
index 6a607a3..f2ad0e7 100644
--- a/ui/aura/root_window_host_win.cc
+++ b/ui/aura/root_window_host_win.cc
@@ -305,7 +305,11 @@ void RootWindowHostWin::OnMove(const CPoint& point) {
}
void RootWindowHostWin::OnPaint(HDC dc) {
- delegate_->OnHostPaint();
+ gfx::Rect damage_rect;
+ RECT update_rect = {0};
+ if (GetUpdateRect(hwnd(), &update_rect, FALSE))
+ damage_rect = gfx::Rect(update_rect);
+ delegate_->OnHostPaint(damage_rect);
ValidateRect(hwnd(), NULL);
}
diff --git a/ui/aura/root_window_host_x11.cc b/ui/aura/root_window_host_x11.cc
index a174dc5..1180422 100644
--- a/ui/aura/root_window_host_x11.cc
+++ b/ui/aura/root_window_host_x11.cc
@@ -444,9 +444,12 @@ bool RootWindowHostX11::Dispatch(const base::NativeEvent& event) {
TranslateAndDispatchMouseEvent(&mouseenter_event);
break;
}
- case Expose:
- delegate_->AsRootWindow()->ScheduleFullDraw();
+ case Expose: {
+ gfx::Rect damage_rect(xev->xexpose.x, xev->xexpose.y,
+ xev->xexpose.width, xev->xexpose.height);
+ delegate_->AsRootWindow()->ScheduleRedrawRect(damage_rect);
break;
+ }
case KeyPress: {
ui::KeyEvent keydown_event(xev, false);
delegate_->OnHostKeyEvent(&keydown_event);
diff --git a/ui/compositor/compositor.cc b/ui/compositor/compositor.cc
index 683562a..fe66c3e 100644
--- a/ui/compositor/compositor.cc
+++ b/ui/compositor/compositor.cc
@@ -574,7 +574,7 @@ void Compositor::SetHostHasTransparentBackground(
host_->set_has_transparent_background(host_has_transparent_background);
}
-void Compositor::Draw(bool force_clear) {
+void Compositor::Draw() {
DCHECK(!g_compositor_thread);
if (!root_layer_)
@@ -604,10 +604,14 @@ void Compositor::Draw(bool force_clear) {
NotifyEnd();
}
-void Compositor::ScheduleFullDraw() {
+void Compositor::ScheduleFullRedraw() {
host_->SetNeedsRedraw();
}
+void Compositor::ScheduleRedrawRect(const gfx::Rect& damage_rect) {
+ host_->SetNeedsRedrawRect(damage_rect);
+}
+
bool Compositor::ReadPixels(SkBitmap* bitmap,
const gfx::Rect& bounds_in_pixel) {
if (bounds_in_pixel.right() > size().width() ||
diff --git a/ui/compositor/compositor.h b/ui/compositor/compositor.h
index 19f5869..5777d65 100644
--- a/ui/compositor/compositor.h
+++ b/ui/compositor/compositor.h
@@ -282,15 +282,17 @@ class COMPOSITOR_EXPORT Compositor
// compositing layers on.
float device_scale_factor() const { return device_scale_factor_; }
- // Draws the scene created by the layer tree and any visual effects. If
- // |force_clear| is true, this will cause the compositor to clear before
- // compositing.
- void Draw(bool force_clear);
+ // Draws the scene created by the layer tree and any visual effects.
+ void Draw();
// Where possible, draws are scissored to a damage region calculated from
// changes to layer properties. This bypasses that and indicates that
// the whole frame needs to be drawn.
- void ScheduleFullDraw();
+ void ScheduleFullRedraw();
+
+ // Schedule redraw and append damage_rect to the damage region calculated
+ // from changes to layer properties.
+ void ScheduleRedrawRect(const gfx::Rect& damage_rect);
// Reads the region |bounds_in_pixel| of the contents of the last rendered
// frame into the given bitmap.
diff --git a/ui/compositor/layer_unittest.cc b/ui/compositor/layer_unittest.cc
index 21cf0c6..4f8b728 100644
--- a/ui/compositor/layer_unittest.cc
+++ b/ui/compositor/layer_unittest.cc
@@ -437,7 +437,7 @@ class LayerWithDelegateTest : public testing::Test, public CompositorDelegate {
if (compositor_) {
MessageLoop::current()->PostTask(
FROM_HERE,
- base::Bind(&Compositor::Draw, compositor_->AsWeakPtr(), false));
+ base::Bind(&Compositor::Draw, compositor_->AsWeakPtr()));
}
}
diff --git a/ui/compositor/test/test_compositor_host_linux.cc b/ui/compositor/test/test_compositor_host_linux.cc
index 7fb6d1f..789ac19 100644
--- a/ui/compositor/test/test_compositor_host_linux.cc
+++ b/ui/compositor/test/test_compositor_host_linux.cc
@@ -96,7 +96,7 @@ void TestCompositorHostLinux::ScheduleDraw() {
void TestCompositorHostLinux::Draw() {
if (compositor_.get())
- compositor_->Draw(false);
+ compositor_->Draw();
}
// static
diff --git a/ui/compositor/test/test_compositor_host_mac.mm b/ui/compositor/test/test_compositor_host_mac.mm
index fd49668..02c3ed6 100644
--- a/ui/compositor/test/test_compositor_host_mac.mm
+++ b/ui/compositor/test/test_compositor_host_mac.mm
@@ -39,7 +39,7 @@
- (void)drawRect:(NSRect)rect {
DCHECK(compositor_) << "Drawing with no compositor set.";
- compositor_->Draw(false);
+ compositor_->Draw();
}
@end
diff --git a/ui/compositor/test/test_compositor_host_win.cc b/ui/compositor/test/test_compositor_host_win.cc
index 7e635a1..452acee 100644
--- a/ui/compositor/test/test_compositor_host_win.cc
+++ b/ui/compositor/test/test_compositor_host_win.cc
@@ -47,7 +47,7 @@ class TestCompositorHostWin : public TestCompositorHost,
END_MSG_MAP()
void OnPaint(HDC dc) {
- compositor_->Draw(false);
+ compositor_->Draw();
ValidateRect(hwnd(), NULL);
}
diff --git a/ui/views/widget/desktop_aura/desktop_root_window_host_win.cc b/ui/views/widget/desktop_aura/desktop_root_window_host_win.cc
index 19de4ce..4b75010 100644
--- a/ui/views/widget/desktop_aura/desktop_root_window_host_win.cc
+++ b/ui/views/widget/desktop_aura/desktop_root_window_host_win.cc
@@ -809,7 +809,7 @@ bool DesktopRootWindowHostWin::HandlePaintAccelerated(
}
void DesktopRootWindowHostWin::HandlePaint(gfx::Canvas* canvas) {
- root_window_host_delegate_->OnHostPaint();
+ root_window_host_delegate_->OnHostPaint(gfx::Rect());
}
bool DesktopRootWindowHostWin::HandleTooltipNotify(int w_param,
diff --git a/ui/views/widget/desktop_aura/desktop_root_window_host_x11.cc b/ui/views/widget/desktop_aura/desktop_root_window_host_x11.cc
index c1ade45..0e13273 100644
--- a/ui/views/widget/desktop_aura/desktop_root_window_host_x11.cc
+++ b/ui/views/widget/desktop_aura/desktop_root_window_host_x11.cc
@@ -729,7 +729,7 @@ void DesktopRootWindowHostX11::SetBounds(const gfx::Rect& bounds) {
if (size_changed)
root_window_host_delegate_->OnHostResized(bounds.size());
else
- root_window_host_delegate_->OnHostPaint();
+ root_window_host_delegate_->OnHostPaint(gfx::Rect(bounds.size()));
}
gfx::Insets DesktopRootWindowHostX11::GetInsets() const {
@@ -893,10 +893,12 @@ bool DesktopRootWindowHostX11::Dispatch(const base::NativeEvent& event) {
// May want to factor CheckXEventForConsistency(xev); into a common location
// since it is called here.
switch (xev->type) {
- case Expose:
- // TODO(erg): Can we only redraw the affected areas?
- root_window_host_delegate_->OnHostPaint();
+ case Expose: {
+ gfx::Rect damage_rect(xev->xexpose.x, xev->xexpose.y,
+ xev->xexpose.width, xev->xexpose.height);
+ root_window_host_delegate_->OnHostPaint(damage_rect);
break;
+ }
case KeyPress: {
ui::KeyEvent keydown_event(xev, false);
root_window_host_delegate_->OnHostKeyEvent(&keydown_event);
diff --git a/ui/views/widget/widget.cc b/ui/views/widget/widget.cc
index bf3ee47..e2896bd 100644
--- a/ui/views/widget/widget.cc
+++ b/ui/views/widget/widget.cc
@@ -1086,36 +1086,7 @@ bool Widget::OnNativeWidgetPaintAccelerated(const gfx::Rect& dirty_region) {
if (!compositor)
return false;
-#if defined(OS_WIN) && defined(USE_AURA)
- compositor->ScheduleDraw();
-#else
- // If the root view is animating, it is likely that it does not cover the same
- // set of pixels it did at the last frame, so we must clear when compositing
- // to avoid leaving ghosts.
- bool force_clear = false;
- if (GetRootView()->layer()) {
- const gfx::Transform& layer_transform = GetRootView()->layer()->transform();
- if (layer_transform != GetRootView()->GetTransform()) {
- // The layer has not caught up to the view (i.e., the layer is still
- // animating), and so a clear is required.
- force_clear = true;
- } else {
- // Determine if the layer fills the client area.
- gfx::RectF layer_bounds = GetRootView()->layer()->bounds();
- layer_transform.TransformRect(&layer_bounds);
- gfx::Rect client_bounds = GetClientAreaBoundsInScreen();
- // Translate bounds to origin (client area bounds are offset to account
- // for buttons, etc).
- client_bounds.set_origin(gfx::Point(0, 0));
- if (!layer_bounds.Contains(client_bounds)) {
- // It doesn't, and so a clear is required.
- force_clear = true;
- }
- }
- }
-
- compositor->Draw(force_clear);
-#endif
+ compositor->ScheduleRedrawRect(dirty_region);
return true;
}