diff options
author | powei@chromium.org <powei@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-03-21 00:50:46 +0000 |
---|---|---|
committer | powei@chromium.org <powei@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-03-21 00:50:46 +0000 |
commit | 5f9967d8e06faadbb3581ce9c17974d1ea383c37 (patch) | |
tree | 65443e8afbb4930621715f558c039e0263e5fd26 /content | |
parent | 1441e0f8e7840854227216f335db50d95818a664 (diff) | |
download | chromium_src-5f9967d8e06faadbb3581ce9c17974d1ea383c37.zip chromium_src-5f9967d8e06faadbb3581ce9c17974d1ea383c37.tar.gz chromium_src-5f9967d8e06faadbb3581ce9c17974d1ea383c37.tar.bz2 |
Expose locks for CopyFromCompositingSurface/CopyFromBackingStore API
For async implementation of CopyFromCompositingSurface/CopyFromBackingStore in
RenderWidgetHostView and RenderWidgetHost, we need locks to ensure that the
content cannot be evicted during copy.
BUG=326363
Review URL: https://codereview.chromium.org/174323003
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@258476 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content')
9 files changed, 151 insertions, 17 deletions
diff --git a/content/browser/renderer_host/delegated_frame_evictor.h b/content/browser/renderer_host/delegated_frame_evictor.h index d52b2d3..64df6f7 100644 --- a/content/browser/renderer_host/delegated_frame_evictor.h +++ b/content/browser/renderer_host/delegated_frame_evictor.h @@ -27,6 +27,7 @@ class CONTENT_EXPORT DelegatedFrameEvictor : public RendererFrameManagerClient { void SetVisible(bool visible); void LockFrame(); void UnlockFrame(); + bool HasFrame() { return has_frame_; } private: // RendererFrameManagerClient implementation. diff --git a/content/browser/renderer_host/render_widget_host_impl.cc b/content/browser/renderer_host/render_widget_host_impl.cc index a8dc5a5..7c3d98c5 100644 --- a/content/browser/renderer_host/render_widget_host_impl.cc +++ b/content/browser/renderer_host/render_widget_host_impl.cc @@ -742,6 +742,24 @@ void RenderWidgetHostImpl::CopyFromBackingStore( callback.Run(result, output.GetBitmap()); } +bool RenderWidgetHostImpl::CanCopyFromBackingStore() { + if (view_) + return view_->IsSurfaceAvailableForCopy(); + return false; +} + +#if defined(OS_ANDROID) +void RenderWidgetHostImpl::LockBackingStore() { + if (view_) + view_->LockCompositingSurface(); +} + +void RenderWidgetHostImpl::UnlockBackingStore() { + if (view_) + view_->UnlockCompositingSurface(); +} +#endif + #if defined(TOOLKIT_GTK) bool RenderWidgetHostImpl::CopyFromBackingStoreToGtkWindow( const gfx::Rect& dest_rect, GdkWindow* target) { diff --git a/content/browser/renderer_host/render_widget_host_impl.h b/content/browser/renderer_host/render_widget_host_impl.h index 22e4c79..52b3e2b 100644 --- a/content/browser/renderer_host/render_widget_host_impl.h +++ b/content/browser/renderer_host/render_widget_host_impl.h @@ -138,6 +138,11 @@ class CONTENT_EXPORT RenderWidgetHostImpl : virtual public RenderWidgetHost, const gfx::Size& accelerated_dst_size, const base::Callback<void(bool, const SkBitmap&)>& callback, const SkBitmap::Config& bitmap_config) OVERRIDE; + virtual bool CanCopyFromBackingStore() OVERRIDE; +#if defined(OS_ANDROID) + virtual void LockBackingStore() OVERRIDE; + virtual void UnlockBackingStore() OVERRIDE; +#endif #if defined(TOOLKIT_GTK) virtual bool CopyFromBackingStoreToGtkWindow(const gfx::Rect& dest_rect, GdkWindow* target) OVERRIDE; diff --git a/content/browser/renderer_host/render_widget_host_view_android.cc b/content/browser/renderer_host/render_widget_host_view_android.cc index 7696c1f..03e069a 100644 --- a/content/browser/renderer_host/render_widget_host_view_android.cc +++ b/content/browser/renderer_host/render_widget_host_view_android.cc @@ -124,6 +124,13 @@ ui::LatencyInfo CreateLatencyInfo(const blink::WebInputEvent& event) { } // anonymous namespace +RenderWidgetHostViewAndroid::LastFrameInfo::LastFrameInfo( + uint32 output_id, + scoped_ptr<cc::CompositorFrame> output_frame) + : output_surface_id(output_id), frame(output_frame.Pass()) {} + +RenderWidgetHostViewAndroid::LastFrameInfo::~LastFrameInfo() {} + RenderWidgetHostViewAndroid::RenderWidgetHostViewAndroid( RenderWidgetHostImpl* widget_host, ContentViewCoreImpl* content_view_core) @@ -136,9 +143,8 @@ RenderWidgetHostViewAndroid::RenderWidgetHostViewAndroid( texture_id_in_layer_(0), last_output_surface_id_(kUndefinedOutputSurfaceId), weak_ptr_factory_(this), - overscroll_effect_enabled_( - !CommandLine::ForCurrentProcess()-> - HasSwitch(switches::kDisableOverscrollEdgeEffect)), + overscroll_effect_enabled_(!CommandLine::ForCurrentProcess()->HasSwitch( + switches::kDisableOverscrollEdgeEffect)), overscroll_effect_(OverscrollGlow::Create(overscroll_effect_enabled_)), flush_input_requested_(false), accelerated_surface_route_id_(0), @@ -149,7 +155,8 @@ RenderWidgetHostViewAndroid::RenderWidgetHostViewAndroid( using_delegated_renderer_(CommandLine::ForCurrentProcess()->HasSwitch( switches::kEnableDelegatedRenderer) && !CommandLine::ForCurrentProcess()->HasSwitch( - switches::kDisableDelegatedRenderer)) { + switches::kDisableDelegatedRenderer)), + locks_on_frame_count_(0) { if (!using_delegated_renderer_) { texture_layer_ = cc::TextureLayer::Create(NULL); layer_ = texture_layer_; @@ -287,6 +294,9 @@ bool RenderWidgetHostViewAndroid::HasValidFrame() const { if (texture_size_in_layer_.IsEmpty()) return false; + if (!frame_evictor_->HasFrame()) + return false; + if (using_delegated_renderer_) { if (!delegated_renderer_layer_.get()) return false; @@ -377,16 +387,37 @@ bool RenderWidgetHostViewAndroid::IsShowing() { return is_showing_ && content_view_core_; } -void RenderWidgetHostViewAndroid::LockResources() { +void RenderWidgetHostViewAndroid::LockCompositingSurface() { DCHECK(HasValidFrame()); DCHECK(host_); - DCHECK(!host_->is_hidden()); + DCHECK(frame_evictor_->HasFrame()); frame_evictor_->LockFrame(); + locks_on_frame_count_++; } -void RenderWidgetHostViewAndroid::UnlockResources() { +void RenderWidgetHostViewAndroid::UnlockCompositingSurface() { + if (!frame_evictor_->HasFrame() || locks_on_frame_count_ == 0) + return; + DCHECK(HasValidFrame()); frame_evictor_->UnlockFrame(); + locks_on_frame_count_--; + + if (locks_on_frame_count_ == 0 && last_frame_info_) { + InternalSwapCompositorFrame(last_frame_info_->output_surface_id, + last_frame_info_->frame.Pass()); + last_frame_info_.reset(); + } +} + +void RenderWidgetHostViewAndroid::ReleaseLocksOnSurface() { + if (!frame_evictor_->HasFrame()) { + DCHECK_EQ(locks_on_frame_count_, 0u); + return; + } + while (locks_on_frame_count_ > 0) { + UnlockCompositingSurface(); + } } gfx::Rect RenderWidgetHostViewAndroid::GetViewBounds() const { @@ -786,10 +817,9 @@ void RenderWidgetHostViewAndroid::SwapDelegatedFrame( weak_ptr_factory_.GetWeakPtr(), output_surface_id); + ack_callbacks_.push(ack_callback); if (host_->is_hidden()) - ack_callback.Run(); - else - ack_callbacks_.push(ack_callback); + RunAckCallbacks(); } void RenderWidgetHostViewAndroid::ComputeContentsSize( @@ -807,9 +837,15 @@ void RenderWidgetHostViewAndroid::ComputeContentsSize( UpdateAnimationSize(frame_metadata); } -void RenderWidgetHostViewAndroid::OnSwapCompositorFrame( +void RenderWidgetHostViewAndroid::InternalSwapCompositorFrame( uint32 output_surface_id, scoped_ptr<cc::CompositorFrame> frame) { + if (locks_on_frame_count_ > 0) { + DCHECK(HasValidFrame()); + RetainFrame(output_surface_id, frame.Pass()); + return; + } + // Always let ContentViewCore know about the new frame first, so it can decide // to schedule a Draw immediately when it sees the texture layer invalidation. UpdateContentViewCoreFrameMetadata(frame->metadata); @@ -864,6 +900,33 @@ void RenderWidgetHostViewAndroid::OnSwapCompositorFrame( frame_evictor_->SwappedFrame(!host_->is_hidden()); } +void RenderWidgetHostViewAndroid::OnSwapCompositorFrame( + uint32 output_surface_id, + scoped_ptr<cc::CompositorFrame> frame) { + InternalSwapCompositorFrame(output_surface_id, frame.Pass()); +} + +void RenderWidgetHostViewAndroid::RetainFrame( + uint32 output_surface_id, + scoped_ptr<cc::CompositorFrame> frame) { + DCHECK(locks_on_frame_count_); + + // Store the incoming frame so that it can be swapped when all the locks have + // been released. If there is already a stored frame, then replace and skip + // the previous one but make sure we still eventually send the ACK. Holding + // the ACK also blocks the renderer when its max_frames_pending is reached. + if (last_frame_info_) { + base::Closure ack_callback = + base::Bind(&RenderWidgetHostViewAndroid::SendDelegatedFrameAck, + weak_ptr_factory_.GetWeakPtr(), + last_frame_info_->output_surface_id); + + ack_callbacks_.push(ack_callback); + } + + last_frame_info_.reset(new LastFrameInfo(output_surface_id, frame.Pass())); +} + void RenderWidgetHostViewAndroid::SynchronousFrameMetadata( const cc::CompositorFrameMetadata& frame_metadata) { // This is a subset of OnSwapCompositorFrame() used in the synchronous @@ -963,10 +1026,9 @@ void RenderWidgetHostViewAndroid::BuffersSwapped( current_mailbox_ = mailbox; last_output_surface_id_ = output_surface_id; + ack_callbacks_.push(ack_callback); if (host_->is_hidden()) - ack_callback.Run(); - else - ack_callbacks_.push(ack_callback); + RunAckCallbacks(); } void RenderWidgetHostViewAndroid::AttachLayers() { @@ -1280,6 +1342,9 @@ void RenderWidgetHostViewAndroid::SetContentViewCore( if (content_view_core_ && !using_synchronous_compositor_) content_view_core_->GetWindowAndroid()->RemoveObserver(this); + if (content_view_core != content_view_core_) + ReleaseLocksOnSurface(); + content_view_core_ = content_view_core; if (GetBrowserAccessibilityManager()) { @@ -1313,6 +1378,7 @@ void RenderWidgetHostViewAndroid::OnDetachCompositor() { } void RenderWidgetHostViewAndroid::OnLostResources() { + ReleaseLocksOnSurface(); if (texture_layer_.get()) texture_layer_->SetIsDrawable(false); if (delegated_renderer_layer_.get()) diff --git a/content/browser/renderer_host/render_widget_host_view_android.h b/content/browser/renderer_host/render_widget_host_view_android.h index c3c73f0..89bbeb9 100644 --- a/content/browser/renderer_host/render_widget_host_view_android.h +++ b/content/browser/renderer_host/render_widget_host_view_android.h @@ -175,6 +175,8 @@ class RenderWidgetHostViewAndroid const SkBitmap& zoomed_bitmap) OVERRIDE; virtual scoped_ptr<SyntheticGestureTarget> CreateSyntheticGestureTarget() OVERRIDE; + virtual void LockCompositingSurface() OVERRIDE; + virtual void UnlockCompositingSurface() OVERRIDE; // Implementation of BrowserAccessibilityDelegate: virtual void SetAccessibilityFocus(int acc_obj_id) OVERRIDE; @@ -220,9 +222,6 @@ class RenderWidgetHostViewAndroid void OnSetNeedsBeginFrame(bool enabled); void OnSmartClipDataExtracted(const base::string16& result); - void LockResources(); - void UnlockResources(); - long GetNativeImeAdapter(); void WasResized(); @@ -298,6 +297,19 @@ class RenderWidgetHostViewAndroid bool IsReadbackConfigSupported(SkBitmap::Config bitmap_config); + // If we have locks on a frame during a ContentViewCore swap or a context + // lost, the frame is no longer valid and we can safely release all the locks. + // Use this method to release all the locks. + void ReleaseLocksOnSurface(); + + // Drop any incoming frames from the renderer when there are locks on the + // current frame. + void RetainFrame(uint32 output_surface_id, + scoped_ptr<cc::CompositorFrame> frame); + + void InternalSwapCompositorFrame(uint32 output_surface_id, + scoped_ptr<cc::CompositorFrame> frame); + // The model object. RenderWidgetHostImpl* host_; @@ -363,6 +375,18 @@ class RenderWidgetHostViewAndroid bool using_delegated_renderer_; + size_t locks_on_frame_count_; + + struct LastFrameInfo { + LastFrameInfo(uint32 output_id, + scoped_ptr<cc::CompositorFrame> output_frame); + ~LastFrameInfo(); + uint32 output_surface_id; + scoped_ptr<cc::CompositorFrame> frame; + }; + + scoped_ptr<LastFrameInfo> last_frame_info_; + DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostViewAndroid); }; diff --git a/content/browser/renderer_host/render_widget_host_view_base.cc b/content/browser/renderer_host/render_widget_host_view_base.cc index fddb278..2e9e43e 100644 --- a/content/browser/renderer_host/render_widget_host_view_base.cc +++ b/content/browser/renderer_host/render_widget_host_view_base.cc @@ -593,6 +593,14 @@ void RenderWidgetHostViewBase::DidReceiveRendererFrame() { ++renderer_frame_number_; } +void RenderWidgetHostViewBase::LockCompositingSurface() { + NOTIMPLEMENTED(); +} + +void RenderWidgetHostViewBase::UnlockCompositingSurface() { + NOTIMPLEMENTED(); +} + void RenderWidgetHostViewBase::FlushInput() { RenderWidgetHostImpl* impl = NULL; if (GetRenderWidgetHost()) diff --git a/content/browser/renderer_host/render_widget_host_view_base.h b/content/browser/renderer_host/render_widget_host_view_base.h index 1d33275..163c484 100644 --- a/content/browser/renderer_host/render_widget_host_view_base.h +++ b/content/browser/renderer_host/render_widget_host_view_base.h @@ -89,6 +89,8 @@ class CONTENT_EXPORT RenderWidgetHostViewBase virtual void DidStopFlinging() OVERRIDE {} virtual uint32 RendererFrameNumber() OVERRIDE; virtual void DidReceiveRendererFrame() OVERRIDE; + virtual void LockCompositingSurface() OVERRIDE; + virtual void UnlockCompositingSurface() OVERRIDE; virtual SkBitmap::Config PreferredReadbackFormat() OVERRIDE; diff --git a/content/port/browser/render_widget_host_view_port.h b/content/port/browser/render_widget_host_view_port.h index 44fae3b..528ac86 100644 --- a/content/port/browser/render_widget_host_view_port.h +++ b/content/port/browser/render_widget_host_view_port.h @@ -189,6 +189,10 @@ class CONTENT_EXPORT RenderWidgetHostViewPort : public RenderWidgetHostView, const base::Callback<void(bool, const SkBitmap&)>& callback, const SkBitmap::Config config) = 0; + // Instructs the view to not drop the surface even when the view is hidden. + virtual void LockCompositingSurface() = 0; + virtual void UnlockCompositingSurface() = 0; + // Copies a given subset of the compositing surface's content into a YV12 // VideoFrame, and invokes a callback with a success/fail parameter. |target| // must contain an allocated, YV12 video frame of the intended size. If the diff --git a/content/public/browser/render_widget_host.h b/content/public/browser/render_widget_host.h index e08c461..b509fe9 100644 --- a/content/public/browser/render_widget_host.h +++ b/content/public/browser/render_widget_host.h @@ -197,6 +197,12 @@ class CONTENT_EXPORT RenderWidgetHost : public IPC::Sender { const gfx::Size& accelerated_dst_size, const base::Callback<void(bool, const SkBitmap&)>& callback, const SkBitmap::Config& bitmap_config) = 0; + // Ensures that the view does not drop the backing store even when hidden. + virtual bool CanCopyFromBackingStore() = 0; +#if defined(OS_ANDROID) + virtual void LockBackingStore() = 0; + virtual void UnlockBackingStore() = 0; +#endif #if defined(TOOLKIT_GTK) // Paint the backing store into the target's |dest_rect|. virtual bool CopyFromBackingStoreToGtkWindow(const gfx::Rect& dest_rect, |