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 613fca905efe1e60000847735d57812d776bd0a6..48f26896553ec5691e21fd07b6541f0f1a9c7aae 100644 |
--- a/content/browser/renderer_host/render_widget_host_view_android.cc |
+++ b/content/browser/renderer_host/render_widget_host_view_android.cc |
@@ -217,6 +217,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) |
@@ -259,6 +276,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); |
} |
@@ -342,6 +360,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, |
@@ -352,9 +378,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; |
} |
@@ -381,7 +409,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; |
@@ -457,6 +485,9 @@ void RenderWidgetHostViewAndroid::Hide() { |
layer_->SetHideLayerAndSubtree(true); |
frame_evictor_->SetVisible(false); |
+ // We don't know if we will ever get a frame if we are hiding the renderer, so |
+ // we need to cancel all requests |
+ AbortPendingReadbackRequests(); |
WasHidden(); |
} |
@@ -898,6 +929,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( |
@@ -1016,6 +1050,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()) { |
+ 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( |
@@ -1243,6 +1289,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( |
@@ -1608,6 +1657,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 |