Chromium Code Reviews| Index: content/browser/renderer_host/delegated_frame_host.cc |
| diff --git a/content/browser/renderer_host/delegated_frame_host.cc b/content/browser/renderer_host/delegated_frame_host.cc |
| index ed054ca41863bf769c613d639ba74b5995c0a703..965fab6443aa3190d63e466e89b94f5165c203ca 100644 |
| --- a/content/browser/renderer_host/delegated_frame_host.cc |
| +++ b/content/browser/renderer_host/delegated_frame_host.cc |
| @@ -51,7 +51,6 @@ DelegatedFrameHost::DelegatedFrameHost(const cc::FrameSinkId& frame_sink_id, |
| skipped_frames_(false), |
| background_color_(SK_ColorRED), |
| current_scale_factor_(1.f), |
| - can_lock_compositor_(YES_CAN_LOCK), |
| delegated_frame_evictor_(new DelegatedFrameEvictor(this)) { |
| ImageTransportFactory* factory = ImageTransportFactory::GetInstance(); |
| factory->GetContextFactory()->AddObserver(this); |
| @@ -83,45 +82,27 @@ void DelegatedFrameHost::WasHidden() { |
| } |
| void DelegatedFrameHost::MaybeCreateResizeLock() { |
| - if (!ShouldCreateResizeLock()) |
| - return; |
| - DCHECK(compositor_); |
| - |
| - bool defer_compositor_lock = |
| - can_lock_compositor_ == NO_PENDING_RENDERER_FRAME || |
| - can_lock_compositor_ == NO_PENDING_COMMIT; |
| - |
| - if (can_lock_compositor_ == YES_CAN_LOCK) |
| - can_lock_compositor_ = YES_DID_LOCK; |
| + DCHECK(!resize_lock_); |
| - resize_lock_ = client_->DelegatedFrameHostCreateResizeLock(); |
| - if (!defer_compositor_lock) { |
| - bool locked = resize_lock_->Lock(); |
| - DCHECK(locked); |
| - } |
| -} |
| + if (!compositor_) |
| + return; |
| -bool DelegatedFrameHost::ShouldCreateResizeLock() { |
| - static const bool is_disabled = |
| - base::CommandLine::ForCurrentProcess()->HasSwitch( |
| - switches::kDisableResizeLock); |
| - if (is_disabled) |
| - return false; |
| + if (base::CommandLine::ForCurrentProcess()->HasSwitch( |
| + switches::kDisableResizeLock)) |
| + return; |
| if (!client_->DelegatedFrameCanCreateResizeLock()) |
| - return false; |
| - |
| - if (resize_lock_) |
| - return false; |
| + return; |
| gfx::Size desired_size = client_->DelegatedFrameHostDesiredSizeInDIP(); |
| - if (desired_size == current_frame_size_in_dip_ || desired_size.IsEmpty()) |
| - return false; |
| - |
| - if (!compositor_) |
| - return false; |
| + if (desired_size.IsEmpty()) |
| + return; |
| + if (desired_size == current_frame_size_in_dip_) |
| + return; |
| - return true; |
| + resize_lock_ = client_->DelegatedFrameHostCreateResizeLock(); |
| + bool locked = resize_lock_->Lock(); |
| + DCHECK(locked); |
| } |
| void DelegatedFrameHost::CopyFromCompositingSurface( |
| @@ -252,14 +233,15 @@ void DelegatedFrameHost::BeginFrameDidNotSwap(const cc::BeginFrameAck& ack) { |
| support_->BeginFrameDidNotSwap(modified_ack); |
| } |
| -bool DelegatedFrameHost::ShouldSkipFrame(gfx::Size size_in_dip) const { |
| - // Should skip a frame only when another frame from the renderer is guaranteed |
| - // to replace it. Otherwise may cause hangs when the renderer is waiting for |
| - // the completion of latency infos (such as when taking a Snapshot.) |
| - if (can_lock_compositor_ == NO_PENDING_RENDERER_FRAME || |
| - can_lock_compositor_ == NO_PENDING_COMMIT || !resize_lock_.get()) |
| +bool DelegatedFrameHost::ShouldSkipFrame(const gfx::Size& size_in_dip) { |
| + if (!resize_lock_) |
| return false; |
| - |
| + // Allow a single renderer frame through even though there's a resize lock |
| + // currently in place. |
| + if (allow_one_renderer_frame_during_resize_lock_) { |
| + allow_one_renderer_frame_during_resize_lock_ = false; |
|
piman
2017/04/04 00:16:25
nit: maybe I would set this back to false in Submi
|
| + return false; |
| + } |
| return size_in_dip != resize_lock_->expected_size(); |
| } |
| @@ -268,7 +250,11 @@ void DelegatedFrameHost::WasResized() { |
| current_frame_size_in_dip_ && |
| !client_->DelegatedFrameHostIsVisible()) |
| EvictDelegatedFrame(); |
| - MaybeCreateResizeLock(); |
| + // If |create_resize_lock_after_commit_| is true, we're waiting to recreate |
| + // an expired resize lock after the next UI frame is submitted, so don't |
| + // make a lock here. |
| + if (!resize_lock_ && !create_resize_lock_after_commit_) |
| + MaybeCreateResizeLock(); |
| UpdateGutters(); |
| } |
| @@ -488,9 +474,6 @@ void DelegatedFrameHost::SubmitCompositorFrame( |
| damage_rect_in_dip); |
| } |
| - if (compositor_) |
| - can_lock_compositor_ = NO_PENDING_COMMIT; |
| - |
| if (has_frame_) { |
| delegated_frame_evictor_->SwappedFrame( |
| client_->DelegatedFrameHostIsVisible()); |
| @@ -710,18 +693,19 @@ void DelegatedFrameHost::CopyFromCompositingSurfaceHasResultForVideo( |
| // DelegatedFrameHost, ui::CompositorObserver implementation: |
| void DelegatedFrameHost::OnCompositingDidCommit(ui::Compositor* compositor) { |
| - if (can_lock_compositor_ == NO_PENDING_COMMIT) { |
| - can_lock_compositor_ = YES_CAN_LOCK; |
| - if (resize_lock_ && resize_lock_->Lock()) |
| - can_lock_compositor_ = YES_DID_LOCK; |
| - } |
| + // If |create_resize_lock_after_commit_| then we should have popped the old |
| + // lock already. |
| + DCHECK(!resize_lock_ || !create_resize_lock_after_commit_); |
| + |
| if (resize_lock_ && |
| resize_lock_->expected_size() == current_frame_size_in_dip_) { |
| resize_lock_.reset(); |
| - client_->DelegatedFrameHostResizeLockWasReleased(); |
| - // We may have had a resize while we had the lock (e.g. if the lock expired, |
| - // or if the UI still gave us some resizes), so make sure we grab a new lock |
| - // if necessary. |
| + // We had a lock but the UI may have resized in the meantime. |
| + create_resize_lock_after_commit_ = true; |
| + } |
| + |
| + if (create_resize_lock_after_commit_) { |
| + create_resize_lock_after_commit_ = false; |
| MaybeCreateResizeLock(); |
| } |
| } |
| @@ -733,10 +717,21 @@ void DelegatedFrameHost::OnCompositingStarted(ui::Compositor* compositor, |
| void DelegatedFrameHost::OnCompositingLockStateChanged( |
| ui::Compositor* compositor) { |
| - // A compositor lock that is part of a resize lock timed out. We |
| - // should display a renderer frame. |
| - if (!compositor->IsLocked() && can_lock_compositor_ == YES_DID_LOCK) { |
| - can_lock_compositor_ = NO_PENDING_RENDERER_FRAME; |
| + if (resize_lock_ && resize_lock_->timed_out()) { |
| + // A compositor lock that is part of a resize lock timed out. We allow |
| + // the UI to produce a frame before locking it again, so we don't lock here. |
| + // We release the |resize_lock_| though to allow any other resizes that are |
| + // desired at the same time since we're allowing the UI to make a frame |
| + // which will gutter anyways. |
| + resize_lock_.reset(); |
| + create_resize_lock_after_commit_ = true; |
| + // Because this timed out, we're going to allow the UI to update and lock |
| + // again. We would allow renderer frames through during this time if they |
| + // came late, but would stop them again once the UI finished its frame. We |
| + // want to allow the slow renderer to show us one frame even if its wrong |
| + // since we're guttering anyways, but not unlimited number of frames as that |
| + // would be a waste of power. |
| + allow_one_renderer_frame_during_resize_lock_ = true; |
| } |
| } |
| @@ -794,10 +789,7 @@ void DelegatedFrameHost::SetCompositor(ui::Compositor* compositor) { |
| void DelegatedFrameHost::ResetCompositor() { |
| if (!compositor_) |
| return; |
| - if (resize_lock_) { |
| - resize_lock_.reset(); |
| - client_->DelegatedFrameHostResizeLockWasReleased(); |
| - } |
| + resize_lock_.reset(); |
| if (compositor_->HasObserver(this)) |
| compositor_->RemoveObserver(this); |
| if (vsync_manager_) { |