Commit 878e9535 authored by jbauman's avatar jbauman Committed by Commit bot

Add callback when queueing frame on Surface to create backpressure.

When a frame is queued on a surface, a callback can queued that will be called when that surface is used to draw a frame. This can be used to create backpressure on renderers or the browser compositor.

BUG=

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

Cr-Commit-Position: refs/heads/master@{#291605}
parent ef468cde
......@@ -116,6 +116,13 @@ bool Display::Draw() {
disable_picture_quad_image_filtering);
CompositorFrameMetadata metadata;
renderer_->SwapBuffers(metadata);
for (std::set<SurfaceId>::iterator it = contained_surfaces_.begin();
it != contained_surfaces_.end();
++it) {
Surface* surface = manager_->GetSurfaceForId(*it);
if (surface)
surface->RunDrawCallbacks();
}
return true;
}
......
......@@ -23,7 +23,8 @@ Surface::~Surface() {
}
}
void Surface::QueueFrame(scoped_ptr<CompositorFrame> frame) {
void Surface::QueueFrame(scoped_ptr<CompositorFrame> frame,
const base::Closure& callback) {
scoped_ptr<CompositorFrame> previous_frame = current_frame_.Pass();
current_frame_ = frame.Pass();
factory_->ReceiveFromChild(
......@@ -36,10 +37,21 @@ void Surface::QueueFrame(scoped_ptr<CompositorFrame> frame) {
&previous_resources);
factory_->UnrefResources(previous_resources);
}
if (!draw_callback_.is_null())
draw_callback_.Run();
draw_callback_ = callback;
}
const CompositorFrame* Surface::GetEligibleFrame() {
return current_frame_.get();
}
void Surface::RunDrawCallbacks() {
if (!draw_callback_.is_null()) {
base::Closure callback = draw_callback_;
draw_callback_ = base::Closure();
callback.Run();
}
}
} // namespace cc
......@@ -5,6 +5,7 @@
#ifndef CC_SURFACES_SURFACE_H_
#define CC_SURFACES_SURFACE_H_
#include "base/callback.h"
#include "base/containers/hash_tables.h"
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
......@@ -26,10 +27,13 @@ class CC_SURFACES_EXPORT Surface {
const gfx::Size& size() const { return size_; }
SurfaceId surface_id() const { return surface_id_; }
void QueueFrame(scoped_ptr<CompositorFrame> frame);
void QueueFrame(scoped_ptr<CompositorFrame> frame,
const base::Closure& draw_callback);
// Returns the most recent frame that is eligible to be rendered.
const CompositorFrame* GetEligibleFrame();
void RunDrawCallbacks();
SurfaceFactory* factory() { return factory_; }
private:
......@@ -39,6 +43,8 @@ class CC_SURFACES_EXPORT Surface {
// TODO(jamesr): Support multiple frames in flight.
scoped_ptr<CompositorFrame> current_frame_;
base::Closure draw_callback_;
DISALLOW_COPY_AND_ASSIGN(Surface);
};
......
......@@ -118,7 +118,7 @@ class SurfaceAggregatorValidSurfaceTest : public SurfaceAggregatorTest {
scoped_ptr<CompositorFrame> frame(new CompositorFrame);
frame->delegated_frame_data = frame_data.Pass();
factory_.SubmitFrame(surface_id, frame.Pass());
factory_.SubmitFrame(surface_id, frame.Pass(), base::Closure());
}
void QueuePassAsFrame(scoped_ptr<RenderPass> pass, SurfaceId surface_id) {
......@@ -128,7 +128,7 @@ class SurfaceAggregatorValidSurfaceTest : public SurfaceAggregatorTest {
scoped_ptr<CompositorFrame> child_frame(new CompositorFrame);
child_frame->delegated_frame_data = delegated_frame_data.Pass();
factory_.SubmitFrame(surface_id, child_frame.Pass());
factory_.SubmitFrame(surface_id, child_frame.Pass(), base::Closure());
}
protected:
......@@ -700,7 +700,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateMultiplePassWithTransform) {
scoped_ptr<CompositorFrame> child_frame(new CompositorFrame);
child_frame->delegated_frame_data = child_frame_data.Pass();
factory_.SubmitFrame(child_surface_id, child_frame.Pass());
factory_.SubmitFrame(child_surface_id, child_frame.Pass(), base::Closure());
test::Quad root_quads[] = {test::Quad::SolidColorQuad(1),
test::Quad::SurfaceQuad(child_surface_id)};
......@@ -725,7 +725,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateMultiplePassWithTransform) {
scoped_ptr<CompositorFrame> root_frame(new CompositorFrame);
root_frame->delegated_frame_data = root_frame_data.Pass();
factory_.SubmitFrame(root_surface_id_, root_frame.Pass());
factory_.SubmitFrame(root_surface_id_, root_frame.Pass(), base::Closure());
std::set<SurfaceId> surface_set;
scoped_ptr<CompositorFrame> aggregated_frame =
......@@ -887,7 +887,7 @@ void SubmitFrameWithResources(ResourceProvider::ResourceId* resource_ids,
frame_data->render_pass_list.push_back(pass.Pass());
scoped_ptr<CompositorFrame> frame(new CompositorFrame);
frame->delegated_frame_data = frame_data.Pass();
factory->SubmitFrame(surface_id, frame.Pass());
factory->SubmitFrame(surface_id, frame.Pass(), base::Closure());
}
TEST_F(SurfaceAggregatorWithResourcesTest, TakeResourcesOneSurface) {
......
......@@ -35,11 +35,12 @@ void SurfaceFactory::Destroy(SurfaceId surface_id) {
}
void SurfaceFactory::SubmitFrame(SurfaceId surface_id,
scoped_ptr<CompositorFrame> frame) {
scoped_ptr<CompositorFrame> frame,
const base::Closure& callback) {
OwningSurfaceMap::iterator it = surface_map_.find(surface_id);
DCHECK(it != surface_map_.end());
DCHECK(it->second->factory() == this);
it->second->QueueFrame(frame.Pass());
it->second->QueueFrame(frame.Pass(), callback);
manager_->SurfaceModified(surface_id);
}
......
......@@ -5,6 +5,7 @@
#ifndef CC_SURFACES_SURFACE_FACTORY_H_
#define CC_SURFACES_SURFACE_FACTORY_H_
#include "base/callback_forward.h"
#include "base/containers/scoped_ptr_hash_map.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
......@@ -37,7 +38,10 @@ class CC_SURFACES_EXPORT SurfaceFactory
void Destroy(SurfaceId surface_id);
// A frame can only be submitted to a surface created by this factory,
// although the frame may reference surfaces created by other factories.
void SubmitFrame(SurfaceId surface_id, scoped_ptr<CompositorFrame> frame);
// The callback is called the first time this frame is used to draw.
void SubmitFrame(SurfaceId surface_id,
scoped_ptr<CompositorFrame> frame,
const base::Closure& callback);
SurfaceFactoryClient* client() { return client_; }
......
......@@ -56,7 +56,7 @@ class SurfaceFactoryTest : public testing::Test {
}
scoped_ptr<CompositorFrame> frame(new CompositorFrame);
frame->delegated_frame_data = frame_data.Pass();
factory_.SubmitFrame(surface_id_, frame.Pass());
factory_.SubmitFrame(surface_id_, frame.Pass(), base::Closure());
}
void UnrefResources(ResourceProvider::ResourceId* ids_to_unref,
......
......@@ -87,7 +87,7 @@ TEST_F(SurfacesPixelTest, DrawSimpleFrame) {
SurfaceId root_surface_id = allocator_.GenerateId();
factory_.Create(root_surface_id, device_viewport_size_);
factory_.SubmitFrame(root_surface_id, root_frame.Pass());
factory_.SubmitFrame(root_surface_id, root_frame.Pass(), base::Closure());
SurfaceAggregator aggregator(&manager_, resource_provider_.get());
std::set<SurfaceId> surface_set;
......@@ -142,7 +142,7 @@ TEST_F(SurfacesPixelTest, DrawSimpleAggregatedFrame) {
scoped_ptr<CompositorFrame> root_frame(new CompositorFrame);
root_frame->delegated_frame_data = delegated_frame_data.Pass();
factory_.SubmitFrame(root_surface_id, root_frame.Pass());
factory_.SubmitFrame(root_surface_id, root_frame.Pass(), base::Closure());
}
{
......@@ -169,7 +169,7 @@ TEST_F(SurfacesPixelTest, DrawSimpleAggregatedFrame) {
scoped_ptr<CompositorFrame> child_frame(new CompositorFrame);
child_frame->delegated_frame_data = delegated_frame_data.Pass();
factory_.SubmitFrame(child_surface_id, child_frame.Pass());
factory_.SubmitFrame(child_surface_id, child_frame.Pass(), base::Closure());
}
SurfaceAggregator aggregator(&manager_, resource_provider_.get());
......@@ -240,7 +240,7 @@ TEST_F(SurfacesPixelTest, DrawAggregatedFrameWithSurfaceTransforms) {
scoped_ptr<CompositorFrame> root_frame(new CompositorFrame);
root_frame->delegated_frame_data = delegated_frame_data.Pass();
factory_.SubmitFrame(root_surface_id, root_frame.Pass());
factory_.SubmitFrame(root_surface_id, root_frame.Pass(), base::Closure());
}
{
......@@ -275,7 +275,7 @@ TEST_F(SurfacesPixelTest, DrawAggregatedFrameWithSurfaceTransforms) {
scoped_ptr<CompositorFrame> child_frame(new CompositorFrame);
child_frame->delegated_frame_data = delegated_frame_data.Pass();
factory_.SubmitFrame(left_child_id, child_frame.Pass());
factory_.SubmitFrame(left_child_id, child_frame.Pass(), base::Closure());
}
{
......@@ -310,7 +310,7 @@ TEST_F(SurfacesPixelTest, DrawAggregatedFrameWithSurfaceTransforms) {
scoped_ptr<CompositorFrame> child_frame(new CompositorFrame);
child_frame->delegated_frame_data = delegated_frame_data.Pass();
factory_.SubmitFrame(right_child_id, child_frame.Pass());
factory_.SubmitFrame(right_child_id, child_frame.Pass(), base::Closure());
}
SurfaceAggregator aggregator(&manager_, resource_provider_.get());
......
......@@ -379,7 +379,12 @@ void DelegatedFrameHost::SwapDelegatedFrame(
scoped_ptr<cc::CompositorFrame> compositor_frame =
make_scoped_ptr(new cc::CompositorFrame());
compositor_frame->delegated_frame_data = frame_data.Pass();
surface_factory_->SubmitFrame(surface_id_, compositor_frame.Pass());
surface_factory_->SubmitFrame(
surface_id_,
compositor_frame.Pass(),
base::Bind(&DelegatedFrameHost::SendDelegatedFrameAck,
AsWeakPtr(),
output_surface_id));
} else {
if (!resource_collection_) {
resource_collection_ = new cc::DelegatedFrameResourceCollection;
......@@ -416,9 +421,9 @@ void DelegatedFrameHost::SwapDelegatedFrame(
pending_delegated_ack_count_++;
ui::Compositor* compositor = client_->GetCompositor();
if (!compositor || !modified_layers) {
if (!compositor) {
SendDelegatedFrameAck(output_surface_id);
} else {
} else if (!use_surfaces_) {
std::vector<ui::LatencyInfo>::const_iterator it;
for (it = latency_info.begin(); it != latency_info.end(); ++it)
compositor->SetLatencyInfo(*it);
......
......@@ -48,10 +48,13 @@ void SurfaceDisplayOutputSurface::SwapBuffers(cc::CompositorFrame* frame) {
scoped_ptr<cc::CompositorFrame> frame_copy(new cc::CompositorFrame());
frame->AssignTo(frame_copy.get());
factory_.SubmitFrame(surface_id_, frame_copy.Pass());
factory_.SubmitFrame(
surface_id_,
frame_copy.Pass(),
base::Bind(&SurfaceDisplayOutputSurface::SwapBuffersComplete,
base::Unretained(this)));
client_->DidSwapBuffers();
client_->DidSwapBuffersComplete();
}
void SurfaceDisplayOutputSurface::ReturnResources(
......@@ -62,4 +65,8 @@ void SurfaceDisplayOutputSurface::ReturnResources(
client_->ReclaimResources(&ack);
}
void SurfaceDisplayOutputSurface::SwapBuffersComplete() {
client_->DidSwapBuffersComplete();
}
} // namespace content
......@@ -41,6 +41,8 @@ class SurfaceDisplayOutputSurface : public cc::OutputSurface,
const cc::ReturnedResourceArray& resources) OVERRIDE;
private:
void SwapBuffersComplete();
cc::Display* display_;
cc::SurfaceManager* surface_manager_;
cc::SurfaceFactory factory_;
......
......@@ -49,7 +49,8 @@ void SurfacesImpl::SubmitFrame(SurfaceIdPtr id, FramePtr frame_ptr) {
<< " should be namespace " << id_namespace_;
return;
}
factory_.SubmitFrame(id.To<cc::SurfaceId>(), mojo::ConvertTo(frame_ptr));
factory_.SubmitFrame(
id.To<cc::SurfaceId>(), mojo::ConvertTo(frame_ptr), base::Closure());
client_->FrameSubmitted();
}
......
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