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 19b64c6f5043fcfa27550f8a4529401dd24284a6..6f2ab093402e0a023aeca6382a740c0f0fa0b1d9 100644 |
--- a/content/browser/renderer_host/render_widget_host_view_android.cc |
+++ b/content/browser/renderer_host/render_widget_host_view_android.cc |
@@ -170,6 +170,23 @@ bool HasMobileViewport(const cc::CompositorFrameMetadata& frame_metadata) { |
} // anonymous namespace |
+ReadbackRequest::ReadbackRequest( |
+ float scale, |
+ SkColorType color_type, |
+ gfx::Rect src_subrect, |
+ const base::Callback<void(bool, const SkBitmap&)>& result_callback) |
+ : scale_(scale), |
+ color_type_(color_type), |
+ src_subrect_(src_subrect), |
+ result_callback_(result_callback) { |
+} |
+ |
+ReadbackRequest::ReadbackRequest() { |
+} |
+ |
+ReadbackRequest::~ReadbackRequest() { |
+} |
+ |
RenderWidgetHostViewAndroid::LastFrameInfo::LastFrameInfo( |
uint32 output_id, |
scoped_ptr<cc::CompositorFrame> output_frame) |
@@ -212,6 +229,7 @@ RenderWidgetHostViewAndroid::~RenderWidgetHostViewAndroid() { |
ImageTransportFactoryAndroid::RemoveObserver(this); |
SetContentViewCore(NULL); |
DCHECK(ack_callbacks_.empty()); |
+ DCHECK(readbacks_waiting_for_frame_.empty()); |
if (resource_collection_.get()) |
resource_collection_->SetClient(NULL); |
} |
@@ -295,6 +313,14 @@ void RenderWidgetHostViewAndroid::SetBounds(const gfx::Rect& rect) { |
SetSize(rect.size()); |
} |
+void RenderWidgetHostViewAndroid::AbortPendingReadbackRequests() { |
+ while (!readbacks_waiting_for_frame_.empty()) { |
+ ReadbackRequest& readback_request = readbacks_waiting_for_frame_.front(); |
+ readback_request.GetResultCallback().Run(false, SkBitmap()); |
+ readbacks_waiting_for_frame_.pop(); |
+ } |
+} |
+ |
void RenderWidgetHostViewAndroid::GetScaledContentBitmap( |
float scale, |
SkColorType color_type, |
@@ -305,9 +331,11 @@ void RenderWidgetHostViewAndroid::GetScaledContentBitmap( |
return; |
} |
if (!IsSurfaceAvailableForCopy()) { |
- // TODO(Sikugu): allow a read-back request to wait for a first frame if it |
- // was invoked while no frame was received yet |
- result_callback.Run(false, SkBitmap()); |
+ // The view is visible, probably the frame has not yet arrived. |
+ // Just add the ReadbackRequest to queue and wait for frame arrival |
+ // to get this request processed. |
+ readbacks_waiting_for_frame_.push( |
+ ReadbackRequest(scale, color_type, src_subrect, result_callback)); |
return; |
} |
@@ -334,7 +362,7 @@ bool RenderWidgetHostViewAndroid::HasValidFrame() const { |
if (texture_size_in_layer_.IsEmpty()) |
return false; |
- |
+ // This tell us whether a valid frame has arrived or not. |
if (!frame_evictor_->HasFrame()) |
return false; |
@@ -409,6 +437,9 @@ void RenderWidgetHostViewAndroid::Hide() { |
layer_->SetHideLayerAndSubtree(true); |
frame_evictor_->SetVisible(false); |
+ // We are hiding a renderer and any readback requests pending on frame arrival |
+ // need to be addressed here. |
no sievers
2014/08/19 17:47:07
nit: I'd say that we don't know if we will ever ge
sivag
2014/08/20 07:10:53
Done.
|
+ AbortPendingReadbackRequests(); |
WasHidden(); |
} |
@@ -849,6 +880,9 @@ void RenderWidgetHostViewAndroid::DestroyDelegatedContent() { |
RemoveLayers(); |
frame_provider_ = NULL; |
layer_ = NULL; |
+ // This gets called when ever any eviction, loosing resources, swapping |
+ // problems are encountered and so we abort any pending readbacks here. |
+ AbortPendingReadbackRequests(); |
} |
void RenderWidgetHostViewAndroid::SwapDelegatedFrame( |
@@ -965,6 +999,18 @@ void RenderWidgetHostViewAndroid::InternalSwapCompositorFrame( |
// As the metadata update may trigger view invalidation, always call it after |
// any potential compositor scheduling. |
OnFrameMetadataUpdated(frame->metadata); |
+ // Check if we have any pending readbacks, see if we have a frame available |
+ // and process them here. |
+ if (!readbacks_waiting_for_frame_.empty() && HasValidFrame()) { |
no sievers
2014/08/19 17:47:07
nit: Isn't HasValidFrame() always true at this loc
sivag
2014/08/20 07:10:53
Done.
|
+ while (!readbacks_waiting_for_frame_.empty()) { |
+ ReadbackRequest& readback_request = readbacks_waiting_for_frame_.front(); |
+ GetScaledContentBitmap(readback_request.GetScale(), |
+ readback_request.GetColorFormat(), |
+ readback_request.GetCaptureRect(), |
+ readback_request.GetResultCallback()); |
+ readbacks_waiting_for_frame_.pop(); |
+ } |
+ } |
} |
void RenderWidgetHostViewAndroid::OnSwapCompositorFrame( |
@@ -1190,6 +1236,9 @@ void RenderWidgetHostViewAndroid::EvictDelegatedFrame() { |
if (layer_.get()) |
DestroyDelegatedContent(); |
frame_evictor_->DiscardedFrame(); |
+ // We are evicting the delegated frame, |
+ // so there should be no pending readback requests |
+ DCHECK(readbacks_waiting_for_frame_.empty()); |
} |
bool RenderWidgetHostViewAndroid::HasAcceleratedSurface( |
@@ -1518,6 +1567,8 @@ void RenderWidgetHostViewAndroid::OnLostResources() { |
if (layer_.get()) |
DestroyDelegatedContent(); |
DCHECK(ack_callbacks_.empty()); |
+ // We should not loose a frame if we have readback requests pending. |
+ DCHECK(readbacks_waiting_for_frame_.empty()); |
} |
// static |