Index: content/browser/renderer_host/render_widget_host_view_android.cc |
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 940a4a4778aa2a2c1892c2ecf000dbf53c3a720a..433d2f93650637e33a5e73741e48e171e118d806 100644 |
--- a/content/browser/renderer_host/render_widget_host_view_android.cc |
+++ b/content/browser/renderer_host/render_widget_host_view_android.cc |
@@ -123,6 +123,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) |
@@ -135,9 +142,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), |
@@ -148,7 +154,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_; |
@@ -286,6 +293,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; |
@@ -376,16 +386,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 { |
@@ -755,10 +786,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( |
@@ -776,9 +806,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); |
@@ -833,6 +869,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 |
@@ -932,10 +995,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() { |
@@ -1249,6 +1311,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()) { |
@@ -1282,6 +1347,7 @@ void RenderWidgetHostViewAndroid::OnDetachCompositor() { |
} |
void RenderWidgetHostViewAndroid::OnLostResources() { |
+ ReleaseLocksOnSurface(); |
if (texture_layer_.get()) |
texture_layer_->SetIsDrawable(false); |
if (delegated_renderer_layer_.get()) |