summaryrefslogtreecommitdiffstats
path: root/content
diff options
context:
space:
mode:
authorpowei@chromium.org <powei@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-03-21 00:50:46 +0000
committerpowei@chromium.org <powei@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-03-21 00:50:46 +0000
commit5f9967d8e06faadbb3581ce9c17974d1ea383c37 (patch)
tree65443e8afbb4930621715f558c039e0263e5fd26 /content
parent1441e0f8e7840854227216f335db50d95818a664 (diff)
downloadchromium_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')
-rw-r--r--content/browser/renderer_host/delegated_frame_evictor.h1
-rw-r--r--content/browser/renderer_host/render_widget_host_impl.cc18
-rw-r--r--content/browser/renderer_host/render_widget_host_impl.h5
-rw-r--r--content/browser/renderer_host/render_widget_host_view_android.cc94
-rw-r--r--content/browser/renderer_host/render_widget_host_view_android.h30
-rw-r--r--content/browser/renderer_host/render_widget_host_view_base.cc8
-rw-r--r--content/browser/renderer_host/render_widget_host_view_base.h2
-rw-r--r--content/port/browser/render_widget_host_view_port.h4
-rw-r--r--content/public/browser/render_widget_host.h6
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,