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) {
} // 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();
}
......@@ -901,6 +932,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(
......@@ -1019,6 +1053,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(
......@@ -1246,6 +1292,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(
......@@ -1611,6 +1660,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
......
......@@ -58,6 +58,29 @@ class RenderWidgetHostImpl;
struct DidOverscrollParams;
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.
// -----------------------------------------------------------------------------
......@@ -316,6 +339,9 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid
float GetDpiScale() const;
// Handles all unprocessed and pending readback requests.
void AbortPendingReadbackRequests();
// The model object.
RenderWidgetHostImpl* host_;
......@@ -392,6 +418,9 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid
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);
};
......
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