Allow a read-back request to wait for a first frame

if it was invoked while no frame was received yet.
This patch takes care of adding any readback request 
to a queue and ensure that this gets processed, once 
the frame arrives.This also takes care of discarding
all the readback requests if the delegated layer is 
destroyed or view is hidden, before a frame arrives.

BUG=376769

Review URL: https://codereview.chromium.org/415773007

Cr-Commit-Position: refs/heads/master@{#290802}
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@290802 0039d316-1c4b-4281-b951-d872f2087c98
parent dc3eb775
...@@ -217,6 +217,23 @@ bool HasMobileViewport(const cc::CompositorFrameMetadata& frame_metadata) { ...@@ -217,6 +217,23 @@ bool HasMobileViewport(const cc::CompositorFrameMetadata& frame_metadata) {
} // anonymous namespace } // 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( RenderWidgetHostViewAndroid::LastFrameInfo::LastFrameInfo(
uint32 output_id, uint32 output_id,
scoped_ptr<cc::CompositorFrame> output_frame) scoped_ptr<cc::CompositorFrame> output_frame)
...@@ -259,6 +276,7 @@ RenderWidgetHostViewAndroid::~RenderWidgetHostViewAndroid() { ...@@ -259,6 +276,7 @@ RenderWidgetHostViewAndroid::~RenderWidgetHostViewAndroid() {
ImageTransportFactoryAndroid::RemoveObserver(this); ImageTransportFactoryAndroid::RemoveObserver(this);
SetContentViewCore(NULL); SetContentViewCore(NULL);
DCHECK(ack_callbacks_.empty()); DCHECK(ack_callbacks_.empty());
DCHECK(readbacks_waiting_for_frame_.empty());
if (resource_collection_.get()) if (resource_collection_.get())
resource_collection_->SetClient(NULL); resource_collection_->SetClient(NULL);
} }
...@@ -342,6 +360,14 @@ void RenderWidgetHostViewAndroid::SetBounds(const gfx::Rect& rect) { ...@@ -342,6 +360,14 @@ void RenderWidgetHostViewAndroid::SetBounds(const gfx::Rect& rect) {
SetSize(rect.size()); 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( void RenderWidgetHostViewAndroid::GetScaledContentBitmap(
float scale, float scale,
SkColorType color_type, SkColorType color_type,
...@@ -352,9 +378,11 @@ void RenderWidgetHostViewAndroid::GetScaledContentBitmap( ...@@ -352,9 +378,11 @@ void RenderWidgetHostViewAndroid::GetScaledContentBitmap(
return; return;
} }
if (!IsSurfaceAvailableForCopy()) { if (!IsSurfaceAvailableForCopy()) {
// TODO(Sikugu): allow a read-back request to wait for a first frame if it // The view is visible, probably the frame has not yet arrived.
// was invoked while no frame was received yet // Just add the ReadbackRequest to queue and wait for frame arrival
result_callback.Run(false, SkBitmap()); // to get this request processed.
readbacks_waiting_for_frame_.push(
ReadbackRequest(scale, color_type, src_subrect, result_callback));
return; return;
} }
...@@ -381,7 +409,7 @@ bool RenderWidgetHostViewAndroid::HasValidFrame() const { ...@@ -381,7 +409,7 @@ bool RenderWidgetHostViewAndroid::HasValidFrame() const {
if (texture_size_in_layer_.IsEmpty()) if (texture_size_in_layer_.IsEmpty())
return false; return false;
// This tell us whether a valid frame has arrived or not.
if (!frame_evictor_->HasFrame()) if (!frame_evictor_->HasFrame())
return false; return false;
...@@ -457,6 +485,9 @@ void RenderWidgetHostViewAndroid::Hide() { ...@@ -457,6 +485,9 @@ void RenderWidgetHostViewAndroid::Hide() {
layer_->SetHideLayerAndSubtree(true); layer_->SetHideLayerAndSubtree(true);
frame_evictor_->SetVisible(false); 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(); WasHidden();
} }
...@@ -901,6 +932,9 @@ void RenderWidgetHostViewAndroid::DestroyDelegatedContent() { ...@@ -901,6 +932,9 @@ void RenderWidgetHostViewAndroid::DestroyDelegatedContent() {
RemoveLayers(); RemoveLayers();
frame_provider_ = NULL; frame_provider_ = NULL;
layer_ = 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( void RenderWidgetHostViewAndroid::SwapDelegatedFrame(
...@@ -1019,6 +1053,18 @@ void RenderWidgetHostViewAndroid::InternalSwapCompositorFrame( ...@@ -1019,6 +1053,18 @@ void RenderWidgetHostViewAndroid::InternalSwapCompositorFrame(
// As the metadata update may trigger view invalidation, always call it after // As the metadata update may trigger view invalidation, always call it after
// any potential compositor scheduling. // any potential compositor scheduling.
OnFrameMetadataUpdated(frame->metadata); 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( void RenderWidgetHostViewAndroid::OnSwapCompositorFrame(
...@@ -1246,6 +1292,9 @@ void RenderWidgetHostViewAndroid::EvictDelegatedFrame() { ...@@ -1246,6 +1292,9 @@ void RenderWidgetHostViewAndroid::EvictDelegatedFrame() {
if (layer_.get()) if (layer_.get())
DestroyDelegatedContent(); DestroyDelegatedContent();
frame_evictor_->DiscardedFrame(); 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( bool RenderWidgetHostViewAndroid::HasAcceleratedSurface(
...@@ -1611,6 +1660,8 @@ void RenderWidgetHostViewAndroid::OnLostResources() { ...@@ -1611,6 +1660,8 @@ void RenderWidgetHostViewAndroid::OnLostResources() {
if (layer_.get()) if (layer_.get())
DestroyDelegatedContent(); DestroyDelegatedContent();
DCHECK(ack_callbacks_.empty()); DCHECK(ack_callbacks_.empty());
// We should not loose a frame if we have readback requests pending.
DCHECK(readbacks_waiting_for_frame_.empty());
} }
// static // static
......
...@@ -58,6 +58,29 @@ class RenderWidgetHostImpl; ...@@ -58,6 +58,29 @@ class RenderWidgetHostImpl;
struct DidOverscrollParams; struct DidOverscrollParams;
struct NativeWebKeyboardEvent; struct NativeWebKeyboardEvent;
class ReadbackRequest {
public:
explicit ReadbackRequest(
float scale,
SkColorType color_type,
gfx::Rect src_subrect,
const base::Callback<void(bool, const SkBitmap&)>& result_callback);
~ReadbackRequest();
float GetScale() { return scale_; }
SkColorType GetColorFormat() { return color_type_; }
const gfx::Rect GetCaptureRect() { return src_subrect_; }
const base::Callback<void(bool, const SkBitmap&)>& GetResultCallback() {
return result_callback_;
}
private:
ReadbackRequest();
float scale_;
SkColorType color_type_;
gfx::Rect src_subrect_;
base::Callback<void(bool, const SkBitmap&)> result_callback_;
};
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// See comments in render_widget_host_view.h about this class and its members. // See comments in render_widget_host_view.h about this class and its members.
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
...@@ -316,6 +339,9 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid ...@@ -316,6 +339,9 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid
float GetDpiScale() const; float GetDpiScale() const;
// Handles all unprocessed and pending readback requests.
void AbortPendingReadbackRequests();
// The model object. // The model object.
RenderWidgetHostImpl* host_; RenderWidgetHostImpl* host_;
...@@ -392,6 +418,9 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid ...@@ -392,6 +418,9 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid
TextSurroundingSelectionCallback text_surrounding_selection_callback_; TextSurroundingSelectionCallback text_surrounding_selection_callback_;
// List of readbackrequests waiting for arrival of a valid frame.
std::queue<ReadbackRequest> readbacks_waiting_for_frame_;
DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostViewAndroid); DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostViewAndroid);
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment