diff options
author | skaslev@chromium.org <skaslev@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-04-15 22:44:02 +0000 |
---|---|---|
committer | skaslev@chromium.org <skaslev@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-04-15 22:44:02 +0000 |
commit | 878705be811db12427023ccdf2dcf7d0ca6b06dc (patch) | |
tree | 795c756bf423665d8c2fe5fa2641296dc070d772 | |
parent | 7ef4321c549f0d6c33e02090a6714d424adb65bb (diff) | |
download | chromium_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
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; } |