diff options
-rw-r--r-- | content/browser/aura/compositor_resize_lock.cc | 65 | ||||
-rw-r--r-- | content/browser/aura/compositor_resize_lock.h | 46 | ||||
-rw-r--r-- | content/browser/aura/image_transport_factory.h | 2 | ||||
-rw-r--r-- | content/browser/aura/resize_lock.cc | 35 | ||||
-rw-r--r-- | content/browser/aura/resize_lock.h | 37 | ||||
-rw-r--r-- | content/browser/renderer_host/render_widget_host_view_aura.cc | 193 | ||||
-rw-r--r-- | content/browser/renderer_host/render_widget_host_view_aura.h | 46 | ||||
-rw-r--r-- | content/browser/renderer_host/render_widget_host_view_aura_unittest.cc | 117 | ||||
-rw-r--r-- | content/content_browser.gypi | 4 |
9 files changed, 419 insertions, 126 deletions
diff --git a/content/browser/aura/compositor_resize_lock.cc b/content/browser/aura/compositor_resize_lock.cc new file mode 100644 index 0000000..e80baba --- /dev/null +++ b/content/browser/aura/compositor_resize_lock.cc @@ -0,0 +1,65 @@ +// Copyright 2013 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 "content/browser/aura/compositor_resize_lock.h" + +#include "base/debug/trace_event.h" +#include "content/public/browser/browser_thread.h" +#include "ui/aura/root_window.h" +#include "ui/compositor/compositor.h" + +namespace content { + +CompositorResizeLock::CompositorResizeLock(aura::RootWindow* root_window, + const gfx::Size new_size, + bool defer_compositor_lock, + const base::TimeDelta& timeout) + : ResizeLock(new_size, defer_compositor_lock), + root_window_(root_window), + weak_ptr_factory_(this), + cancelled_(false) { + DCHECK(root_window_); + + TRACE_EVENT_ASYNC_BEGIN2("ui", "CompositorResizeLock", this, + "width", expected_size().width(), + "height", expected_size().height()); + root_window_->HoldPointerMoves(); + + BrowserThread::PostDelayedTask( + BrowserThread::UI, FROM_HERE, + base::Bind(&CompositorResizeLock::CancelLock, + weak_ptr_factory_.GetWeakPtr()), + timeout); +} + +CompositorResizeLock::~CompositorResizeLock() { + CancelLock(); + TRACE_EVENT_ASYNC_END2("ui", "CompositorResizeLock", this, + "width", expected_size().width(), + "height", expected_size().height()); +} + +bool CompositorResizeLock::GrabDeferredLock() { + return ResizeLock::GrabDeferredLock(); +} + +void CompositorResizeLock::UnlockCompositor() { + ResizeLock::UnlockCompositor(); + compositor_lock_ = NULL; +} + +void CompositorResizeLock::LockCompositor() { + ResizeLock::LockCompositor(); + compositor_lock_ = root_window_->compositor()->GetCompositorLock(); +} + +void CompositorResizeLock::CancelLock() { + if (cancelled_) + return; + cancelled_ = true; + UnlockCompositor(); + root_window_->ReleasePointerMoves(); +} + +} // namespace content diff --git a/content/browser/aura/compositor_resize_lock.h b/content/browser/aura/compositor_resize_lock.h new file mode 100644 index 0000000..51787e4 --- /dev/null +++ b/content/browser/aura/compositor_resize_lock.h @@ -0,0 +1,46 @@ +// Copyright 2013 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 CONTENT_BROWSER_AURA_RESIZE_LOCK_AURA_H_ +#define CONTENT_BROWSER_AURA_RESIZE_LOCK_AURA_H_ + +#include "base/memory/ref_counted.h" +#include "base/memory/weak_ptr.h" +#include "base/time/time.h" +#include "content/browser/aura/resize_lock.h" + +namespace aura { class RootWindow; } + +namespace ui { class CompositorLock; } + +namespace content { + +// Used to prevent further resizes while a resize is pending. +class CompositorResizeLock : public ResizeLock { + public: + CompositorResizeLock(aura::RootWindow* root_window, + const gfx::Size new_size, + bool defer_compositor_lock, + const base::TimeDelta& timeout); + virtual ~CompositorResizeLock(); + + virtual bool GrabDeferredLock() OVERRIDE; + virtual void UnlockCompositor() OVERRIDE; + + protected: + virtual void LockCompositor() OVERRIDE; + void CancelLock(); + + private: + aura::RootWindow* root_window_; + scoped_refptr<ui::CompositorLock> compositor_lock_; + base::WeakPtrFactory<CompositorResizeLock> weak_ptr_factory_; + bool cancelled_; + + DISALLOW_COPY_AND_ASSIGN(CompositorResizeLock); +}; + +} // namespace content + +#endif // CONTENT_BROWSER_AURA_RESIZE_LOCK_AURA_H_ diff --git a/content/browser/aura/image_transport_factory.h b/content/browser/aura/image_transport_factory.h index e5964809..7cd2523 100644 --- a/content/browser/aura/image_transport_factory.h +++ b/content/browser/aura/image_transport_factory.h @@ -28,7 +28,7 @@ namespace content { class GLHelper; // This class provides a way to get notified when surface handles get lost. -class ImageTransportFactoryObserver { +class CONTENT_EXPORT ImageTransportFactoryObserver { public: virtual ~ImageTransportFactoryObserver() {} diff --git a/content/browser/aura/resize_lock.cc b/content/browser/aura/resize_lock.cc new file mode 100644 index 0000000..4c8cd95 --- /dev/null +++ b/content/browser/aura/resize_lock.cc @@ -0,0 +1,35 @@ +// Copyright 2013 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 "content/browser/aura/resize_lock.h" + +namespace content { + +ResizeLock::ResizeLock(const gfx::Size new_size, bool defer_compositor_lock) + : new_size_(new_size), + defer_compositor_lock_(defer_compositor_lock) { + if (!defer_compositor_lock_) + LockCompositor(); +} + +ResizeLock::~ResizeLock() { + UnlockCompositor(); +} + +bool ResizeLock::GrabDeferredLock() { + if (!defer_compositor_lock_) + return false; + LockCompositor(); + return true; +} + +void ResizeLock::UnlockCompositor() { + defer_compositor_lock_ = false; +} + +void ResizeLock::LockCompositor() { + defer_compositor_lock_ = false; +} + +} // namespace content diff --git a/content/browser/aura/resize_lock.h b/content/browser/aura/resize_lock.h new file mode 100644 index 0000000..cff9822 --- /dev/null +++ b/content/browser/aura/resize_lock.h @@ -0,0 +1,37 @@ +// Copyright 2013 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 CONTENT_BROWSER_AURA_RESIZE_LOCK_H_ +#define CONTENT_BROWSER_AURA_RESIZE_LOCK_H_ + +#include "base/basictypes.h" +#include "content/common/content_export.h" +#include "ui/gfx/size.h" + +namespace content { + +class CONTENT_EXPORT ResizeLock { + public: + virtual ~ResizeLock(); + + virtual bool GrabDeferredLock(); + virtual void UnlockCompositor(); + + const gfx::Size& expected_size() const { return new_size_; } + + protected: + ResizeLock(const gfx::Size new_size, bool defer_compositor_lock); + + virtual void LockCompositor(); + + private: + gfx::Size new_size_; + bool defer_compositor_lock_; + + DISALLOW_COPY_AND_ASSIGN(ResizeLock); +}; + +} // namespace content + +#endif // CONTENT_BROWSER_AURA_RESIZE_LOCK_H_ diff --git a/content/browser/renderer_host/render_widget_host_view_aura.cc b/content/browser/renderer_host/render_widget_host_view_aura.cc index d998867..7abad81 100644 --- a/content/browser/renderer_host/render_widget_host_view_aura.cc +++ b/content/browser/renderer_host/render_widget_host_view_aura.cc @@ -19,6 +19,7 @@ #include "cc/resources/texture_mailbox.h" #include "content/browser/accessibility/browser_accessibility_manager.h" #include "content/browser/accessibility/browser_accessibility_state_impl.h" +#include "content/browser/aura/compositor_resize_lock.h" #include "content/browser/renderer_host/backing_store_aura.h" #include "content/browser/renderer_host/dip_util.h" #include "content/browser/renderer_host/overscroll_controller.h" @@ -573,73 +574,6 @@ class RenderWidgetHostViewAura::TransientWindowObserver #endif -class RenderWidgetHostViewAura::ResizeLock { - public: - ResizeLock(aura::RootWindow* root_window, - const gfx::Size new_size, - bool defer_compositor_lock) - : root_window_(root_window), - new_size_(new_size), - compositor_lock_(defer_compositor_lock ? - NULL : - root_window_->compositor()->GetCompositorLock()), - weak_ptr_factory_(this), - defer_compositor_lock_(defer_compositor_lock) { - TRACE_EVENT_ASYNC_BEGIN2("ui", "ResizeLock", this, - "width", new_size_.width(), - "height", new_size_.height()); - root_window_->HoldPointerMoves(); - - BrowserThread::PostDelayedTask( - BrowserThread::UI, FROM_HERE, - base::Bind(&RenderWidgetHostViewAura::ResizeLock::CancelLock, - weak_ptr_factory_.GetWeakPtr()), - base::TimeDelta::FromMilliseconds(kResizeLockTimeoutMs)); - } - - ~ResizeLock() { - CancelLock(); - TRACE_EVENT_ASYNC_END2("ui", "ResizeLock", this, - "width", new_size_.width(), - "height", new_size_.height()); - } - - void UnlockCompositor() { - defer_compositor_lock_ = false; - compositor_lock_ = NULL; - } - - void CancelLock() { - if (!root_window_) - return; - UnlockCompositor(); - root_window_->ReleasePointerMoves(); - root_window_ = NULL; - } - - const gfx::Size& expected_size() const { - return new_size_; - } - - bool GrabDeferredLock() { - if (root_window_ && defer_compositor_lock_) { - compositor_lock_ = root_window_->compositor()->GetCompositorLock(); - defer_compositor_lock_ = false; - return true; - } - return false; - } - - private: - aura::RootWindow* root_window_; - gfx::Size new_size_; - scoped_refptr<ui::CompositorLock> compositor_lock_; - base::WeakPtrFactory<ResizeLock> weak_ptr_factory_; - bool defer_compositor_lock_; - - DISALLOW_COPY_AND_ASSIGN(ResizeLock); -}; - //////////////////////////////////////////////////////////////////////////////// // RenderWidgetHostViewAura, public: @@ -656,6 +590,7 @@ RenderWidgetHostViewAura::RenderWidgetHostViewAura(RenderWidgetHost* host) can_compose_inline_(true), has_composition_text_(false), last_output_surface_id_(0), + skipped_frames_(false), last_swapped_surface_scale_factor_(1.f), paint_canvas_(NULL), synthetic_move_sent_(false), @@ -811,39 +746,69 @@ void RenderWidgetHostViewAura::SetBounds(const gfx::Rect& rect) { } void RenderWidgetHostViewAura::MaybeCreateResizeLock() { - gfx::Size desired_size = window_->bounds().size(); - if (!host_->should_auto_resize() && - !resize_lock_.get() && - desired_size != current_frame_size_ && - host_->is_accelerated_compositing_active()) { - aura::RootWindow* root_window = window_->GetRootWindow(); - ui::Compositor* compositor = root_window ? - root_window->compositor() : NULL; - if (root_window && compositor) { - // Listen to changes in the compositor lock state. - if (!compositor->HasObserver(this)) - compositor->AddObserver(this); - -// On Windows while resizing, the the resize locks makes us mis-paint a white -// vertical strip (including the non-client area) if the content composition is -// lagging the UI composition. So here we disable the throttling so that the UI -// bits can draw ahead of the content thereby reducing the amount of whiteout. -// Because this causes the content to be drawn at wrong sizes while resizing -// we compensate by blocking the UI thread in Compositor::Draw() by issuing a -// FinishAllRendering() if we are resizing. -#if !defined (OS_WIN) - bool defer_compositor_lock = - can_lock_compositor_ == NO_PENDING_RENDERER_FRAME || - can_lock_compositor_ == NO_PENDING_COMMIT; - - if (can_lock_compositor_ == YES) - can_lock_compositor_ = YES_DID_LOCK; - - resize_lock_.reset(new ResizeLock(root_window, desired_size, - defer_compositor_lock)); + if (!ShouldCreateResizeLock()) + return; + DCHECK(window_->GetRootWindow()); + DCHECK(window_->GetRootWindow()->compositor()); + + // Listen to changes in the compositor lock state. + ui::Compositor* compositor = window_->GetRootWindow()->compositor(); + if (!compositor->HasObserver(this)) + compositor->AddObserver(this); + + bool defer_compositor_lock = + can_lock_compositor_ == NO_PENDING_RENDERER_FRAME || + can_lock_compositor_ == NO_PENDING_COMMIT; + + if (can_lock_compositor_ == YES) + can_lock_compositor_ = YES_DID_LOCK; + + resize_lock_ = CreateResizeLock(defer_compositor_lock); +} + +bool RenderWidgetHostViewAura::ShouldCreateResizeLock() { + // On Windows while resizing, the the resize locks makes us mis-paint a white + // vertical strip (including the non-client area) if the content composition + // is lagging the UI composition. So here we disable the throttling so that + // the UI bits can draw ahead of the content thereby reducing the amount of + // whiteout. Because this causes the content to be drawn at wrong sizes while + // resizing we compensate by blocking the UI thread in Compositor::Draw() by + // issuing a FinishAllRendering() if we are resizing. +#if defined (OS_WIN) + return false; #endif - } - } + + if (resize_lock_) + return false; + + if (host_->should_auto_resize()) + return false; + if (!host_->is_accelerated_compositing_active()) + return false; + + gfx::Size desired_size = window_->bounds().size(); + if (desired_size == current_frame_size_) + return false; + + aura::RootWindow* root_window = window_->GetRootWindow(); + if (!root_window) + return false; + + ui::Compositor* compositor = root_window->compositor(); + if (!compositor) + return false; + + return true; +} + +scoped_ptr<ResizeLock> RenderWidgetHostViewAura::CreateResizeLock( + bool defer_compositor_lock) { + gfx::Size desired_size = window_->bounds().size(); + return scoped_ptr<ResizeLock>(new CompositorResizeLock( + window_->GetRootWindow(), + desired_size, + defer_compositor_lock, + base::TimeDelta::FromMilliseconds(kResizeLockTimeoutMs))); } gfx::NativeView RenderWidgetHostViewAura::GetNativeView() const { @@ -1440,17 +1405,25 @@ void RenderWidgetHostViewAura::SwapDelegatedFrame( scoped_ptr<cc::DelegatedFrameData> frame_data, float frame_device_scale_factor, const ui::LatencyInfo& latency_info) { + gfx::Size frame_size; gfx::Size frame_size_in_dip; + gfx::Rect damage_rect; gfx::Rect damage_rect_in_dip; + if (!frame_data->render_pass_list.empty()) { cc::RenderPass* root_pass = frame_data->render_pass_list.back(); - frame_size_in_dip = ConvertSizeToDIP(frame_device_scale_factor, - root_pass->output_rect.size()); - damage_rect_in_dip = ConvertRectToDIP( - frame_device_scale_factor, - gfx::ToEnclosingRect(root_pass->damage_rect)); + + frame_size = root_pass->output_rect.size(); + frame_size_in_dip = ConvertSizeToDIP(frame_device_scale_factor, frame_size); + + damage_rect = gfx::ToEnclosingRect(root_pass->damage_rect); + damage_rect.Intersect(gfx::Rect(frame_size)); + damage_rect_in_dip = ConvertRectToDIP(frame_device_scale_factor, + damage_rect); } + framebuffer_holder_ = NULL; + if (ShouldSkipFrame(frame_size_in_dip)) { cc::CompositorFrameAck ack; cc::TransferableResource::ReturnResources(frame_data->resource_list, @@ -1458,8 +1431,20 @@ void RenderWidgetHostViewAura::SwapDelegatedFrame( RenderWidgetHostImpl::SendSwapCompositorFrameAck( host_->GetRoutingID(), output_surface_id, host_->GetProcess()->GetID(), ack); + skipped_frames_ = true; return; } + + if (skipped_frames_) { + skipped_frames_ = false; + damage_rect = gfx::Rect(frame_size); + damage_rect_in_dip = gfx::Rect(frame_size_in_dip); + + // Give the same damage rect to the compositor. + cc::RenderPass* root_pass = frame_data->render_pass_list.back(); + root_pass->damage_rect = damage_rect; + } + if (output_surface_id != last_output_surface_id_) { // Resource ids are scoped by the output surface. // If the originating output surface doesn't match the last one, it diff --git a/content/browser/renderer_host/render_widget_host_view_aura.h b/content/browser/renderer_host/render_widget_host_view_aura.h index 7f03b09..5b3853f 100644 --- a/content/browser/renderer_host/render_widget_host_view_aura.h +++ b/content/browser/renderer_host/render_widget_host_view_aura.h @@ -59,9 +59,10 @@ namespace content { class MemoryHolder; class RenderWidgetHostImpl; class RenderWidgetHostView; +class ResizeLock; // RenderWidgetHostView class hierarchy described in render_widget_host_view.h. -class RenderWidgetHostViewAura +class CONTENT_EXPORT RenderWidgetHostViewAura : public RenderWidgetHostViewBase, public ui::CompositorObserver, public ui::TextInputClient, @@ -337,26 +338,21 @@ class RenderWidgetHostViewAura protected: friend class RenderWidgetHostView; + virtual ~RenderWidgetHostViewAura(); - // Should construct only via RenderWidgetHostView::CreateViewForWidget. + // Should be constructed via RenderWidgetHostView::CreateViewForWidget. explicit RenderWidgetHostViewAura(RenderWidgetHost* host); RenderWidgetHostViewFrameSubscriber* frame_subscriber() const { return frame_subscriber_.get(); } - private: - FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewAuraTest, SetCompositionText); - FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewAuraTest, TouchEventState); - FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewAuraTest, TouchEventSyncAsync); - FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewAuraTest, SwapNotifiesWindow); + virtual bool ShouldCreateResizeLock(); + virtual scoped_ptr<ResizeLock> CreateResizeLock(bool defer_compositor_lock); - class WindowObserver; - friend class WindowObserver; -#if defined(OS_WIN) - class TransientWindowObserver; - friend class TransientWindowObserver; -#endif + // Exposed for tests. + aura::Window* window() { return window_; } + gfx::Size current_frame_size() const { return current_frame_size_; } // Overridden from ui::CompositorObserver: virtual void OnCompositingDidCommit(ui::Compositor* compositor) OVERRIDE; @@ -370,6 +366,21 @@ class RenderWidgetHostViewAura base::TimeTicks timebase, base::TimeDelta interval) OVERRIDE; + private: + FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewAuraTest, SetCompositionText); + FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewAuraTest, TouchEventState); + FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewAuraTest, TouchEventSyncAsync); + FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewAuraTest, SwapNotifiesWindow); + FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewAuraTest, + SkippedDelegatedFrames); + + class WindowObserver; + friend class WindowObserver; +#if defined(OS_WIN) + class TransientWindowObserver; + friend class TransientWindowObserver; +#endif + // Overridden from ImageTransportFactoryObserver: virtual void OnLostResources() OVERRIDE; @@ -385,8 +396,6 @@ class RenderWidgetHostViewAura virtual gfx::Point GetLastTouchEventLocation() const OVERRIDE; virtual void FatalAccessibilityTreeError() OVERRIDE; - virtual ~RenderWidgetHostViewAura(); - void UpdateCursorIfOverSelf(); bool ShouldSkipFrame(gfx::Size size_in_dip) const; @@ -599,6 +608,10 @@ class RenderWidgetHostViewAura // Pending damage from previous frames that we skipped. SkRegion skipped_damage_; + // True after a delegated frame has been skipped, until a frame is not + // skipped. + bool skipped_frames_; + // The size of the last frame that was swapped (even if we skipped it). // Used to determine when the skipped_damage_ needs to be reset due to // size changes between front- and backbuffer. @@ -630,9 +643,6 @@ class RenderWidgetHostViewAura // software backing store is updated. bool accelerated_compositing_state_changed_; - // Used to prevent further resizes while a resize is pending. - class ResizeLock; - // This lock is the one waiting for a frame of the right size to come back // from the renderer/GPU process. It is set from the moment the aura window // got resized, to the moment we committed the renderer frame of the same diff --git a/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc b/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc index 5d999f9..8fb69c7 100644 --- a/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc +++ b/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc @@ -11,6 +11,7 @@ #include "cc/output/compositor_frame.h" #include "cc/output/compositor_frame_metadata.h" #include "cc/output/gl_frame_data.h" +#include "content/browser/aura/resize_lock.h" #include "content/browser/browser_thread_impl.h" #include "content/browser/renderer_host/render_widget_host_delegate.h" #include "content/browser/renderer_host/render_widget_host_impl.h" @@ -37,6 +38,8 @@ #include "ui/base/events/event_utils.h" #include "ui/base/ui_base_types.h" +using testing::_; + namespace content { namespace { class MockRenderWidgetHostDelegate : public RenderWidgetHostDelegate { @@ -76,6 +79,41 @@ class TestWindowObserver : public aura::WindowObserver { DISALLOW_COPY_AND_ASSIGN(TestWindowObserver); }; +class FakeRenderWidgetHostViewAura : public RenderWidgetHostViewAura { + public: + FakeRenderWidgetHostViewAura(RenderWidgetHost* widget) + : RenderWidgetHostViewAura(widget), has_resize_lock_(false) {} + + virtual ~FakeRenderWidgetHostViewAura() {} + + virtual bool ShouldCreateResizeLock() OVERRIDE { + gfx::Size desired_size = window()->bounds().size(); + return desired_size != current_frame_size(); + } + + virtual scoped_ptr<ResizeLock> CreateResizeLock(bool defer_compositor_lock) + OVERRIDE { + gfx::Size desired_size = window()->bounds().size(); + return scoped_ptr<ResizeLock>( + new FakeResizeLock(desired_size, defer_compositor_lock)); + } + + void RunOnCompositingDidCommit() { + OnCompositingDidCommit(window()->GetRootWindow()->compositor()); + } + + // A lock that doesn't actually do anything to the compositor, and does not + // time out. + class FakeResizeLock : public ResizeLock { + public: + FakeResizeLock(const gfx::Size new_size, bool defer_compositor_lock) + : ResizeLock(new_size, defer_compositor_lock) {} + }; + + bool has_resize_lock_; + gfx::Size last_frame_size_; +}; + class RenderWidgetHostViewAuraTest : public testing::Test { public: RenderWidgetHostViewAuraTest() @@ -103,8 +141,9 @@ class RenderWidgetHostViewAuraTest : public testing::Test { widget_host_ = new RenderWidgetHostImpl( &delegate_, process_host, MSG_ROUTING_NONE, false); widget_host_->Init(); - view_ = static_cast<RenderWidgetHostViewAura*>( - RenderWidgetHostView::CreateViewForWidget(widget_host_)); + widget_host_->OnMessageReceived( + ViewHostMsg_DidActivateAcceleratedCompositing(0, true)); + view_ = new FakeRenderWidgetHostViewAura(widget_host_); } virtual void TearDown() { @@ -139,7 +178,7 @@ class RenderWidgetHostViewAuraTest : public testing::Test { // Tests should set these to NULL if they've already triggered their // destruction. RenderWidgetHostImpl* widget_host_; - RenderWidgetHostViewAura* view_; + FakeRenderWidgetHostViewAura* view_; IPC::TestSink* sink_; @@ -733,4 +772,76 @@ TEST_F(RenderWidgetHostViewAuraTest, SwapNotifiesWindow) { view_->window_->RemoveObserver(&observer); } +// Skipped frames should not drop their damage. +TEST_F(RenderWidgetHostViewAuraTest, SkippedDelegatedFrames) { + gfx::Rect view_rect(100, 100); + gfx::Size frame_size = view_rect.size(); + + view_->InitAsChild(NULL); + view_->GetNativeView()->SetDefaultParentByRootWindow( + parent_view_->GetNativeView()->GetRootWindow(), gfx::Rect()); + view_->SetSize(view_rect.size()); + + MockWindowObserver observer; + view_->window_->AddObserver(&observer); + + // A full frame of damage. + EXPECT_CALL(observer, OnWindowPaintScheduled(view_->window_, view_rect)); + view_->OnSwapCompositorFrame( + 0, MakeDelegatedFrame(1.f, frame_size, view_rect)); + testing::Mock::VerifyAndClearExpectations(&observer); + view_->RunOnCompositingDidCommit(); + + // A partial damage frame. + gfx::Rect partial_view_rect(30, 30, 20, 20); + EXPECT_CALL(observer, + OnWindowPaintScheduled(view_->window_, partial_view_rect)); + view_->OnSwapCompositorFrame( + 0, MakeDelegatedFrame(1.f, frame_size, partial_view_rect)); + testing::Mock::VerifyAndClearExpectations(&observer); + view_->RunOnCompositingDidCommit(); + + // Lock the compositor. Now we should drop frames. + view_rect = gfx::Rect(150, 150); + view_->SetSize(view_rect.size()); + view_->MaybeCreateResizeLock(); + + // This frame is dropped. + gfx::Rect dropped_damage_rect_1(10, 20, 30, 40); + EXPECT_CALL(observer, OnWindowPaintScheduled(_, _)).Times(0); + view_->OnSwapCompositorFrame( + 0, MakeDelegatedFrame(1.f, frame_size, dropped_damage_rect_1)); + testing::Mock::VerifyAndClearExpectations(&observer); + view_->RunOnCompositingDidCommit(); + + gfx::Rect dropped_damage_rect_2(40, 50, 10, 20); + EXPECT_CALL(observer, OnWindowPaintScheduled(_, _)).Times(0); + view_->OnSwapCompositorFrame( + 0, MakeDelegatedFrame(1.f, frame_size, dropped_damage_rect_2)); + testing::Mock::VerifyAndClearExpectations(&observer); + view_->RunOnCompositingDidCommit(); + + // Unlock the compositor. This frame should damage everything. + frame_size = view_rect.size(); + + gfx::Rect new_damage_rect(5, 6, 10, 10); + EXPECT_CALL(observer, + OnWindowPaintScheduled(view_->window_, view_rect)); + view_->OnSwapCompositorFrame( + 0, MakeDelegatedFrame(1.f, frame_size, new_damage_rect)); + testing::Mock::VerifyAndClearExpectations(&observer); + view_->RunOnCompositingDidCommit(); + + // A partial damage frame, this should not be dropped. + EXPECT_CALL(observer, + OnWindowPaintScheduled(view_->window_, partial_view_rect)); + view_->OnSwapCompositorFrame( + 0, MakeDelegatedFrame(1.f, frame_size, partial_view_rect)); + testing::Mock::VerifyAndClearExpectations(&observer); + view_->RunOnCompositingDidCommit(); + + + view_->window_->RemoveObserver(&observer); +} + } // namespace content diff --git a/content/content_browser.gypi b/content/content_browser.gypi index f97f544..49bd34d 100644 --- a/content/content_browser.gypi +++ b/content/content_browser.gypi @@ -291,6 +291,8 @@ 'browser/aura/browser_compositor_output_surface.h', 'browser/aura/browser_compositor_output_surface_proxy.cc', 'browser/aura/browser_compositor_output_surface_proxy.h', + 'browser/aura/compositor_resize_lock.cc', + 'browser/aura/compositor_resize_lock.h', 'browser/aura/gpu_process_transport_factory.cc', 'browser/aura/gpu_process_transport_factory.h', 'browser/aura/image_transport_factory.cc', @@ -299,6 +301,8 @@ 'browser/aura/no_transport_image_transport_factory.h', 'browser/aura/reflector_impl.cc', 'browser/aura/reflector_impl.h', + 'browser/aura/resize_lock.cc', + 'browser/aura/resize_lock.h', 'browser/aura/software_browser_compositor_output_surface.cc', 'browser/aura/software_browser_compositor_output_surface.h', 'browser/aura/software_output_device_win.cc', |