Commit 2cd9f8f5 authored by jbauman's avatar jbauman Committed by Commit bot

Support doing CopyOutputRequests on surfaces.

If a surface has a copy output request pending, then the aggregator should avoid merging its root pass into its parent pass, and should instead place the copy request on it.

BUG=397730

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

Cr-Commit-Position: refs/heads/master@{#294957}
parent cba3d2fe
...@@ -22,6 +22,12 @@ Surface::Surface(SurfaceId id, const gfx::Size& size, SurfaceFactory* factory) ...@@ -22,6 +22,12 @@ Surface::Surface(SurfaceId id, const gfx::Size& size, SurfaceFactory* factory)
} }
Surface::~Surface() { Surface::~Surface() {
for (ScopedPtrVector<CopyOutputRequest>::iterator it = copy_requests_.begin();
it != copy_requests_.end();
++it) {
(*it)->SendEmptyResult();
}
copy_requests_.clear();
if (current_frame_) { if (current_frame_) {
ReturnedResourceArray current_resources; ReturnedResourceArray current_resources;
TransferableResource::ReturnResources( TransferableResource::ReturnResources(
...@@ -33,6 +39,13 @@ Surface::~Surface() { ...@@ -33,6 +39,13 @@ Surface::~Surface() {
void Surface::QueueFrame(scoped_ptr<CompositorFrame> frame, void Surface::QueueFrame(scoped_ptr<CompositorFrame> frame,
const base::Closure& callback) { const base::Closure& callback) {
for (ScopedPtrVector<CopyOutputRequest>::iterator it = copy_requests_.begin();
it != copy_requests_.end();
++it) {
(*it)->SendEmptyResult();
}
copy_requests_.clear();
TakeLatencyInfo(&frame->metadata.latency_info); TakeLatencyInfo(&frame->metadata.latency_info);
scoped_ptr<CompositorFrame> previous_frame = current_frame_.Pass(); scoped_ptr<CompositorFrame> previous_frame = current_frame_.Pass();
current_frame_ = frame.Pass(); current_frame_ = frame.Pass();
...@@ -53,8 +66,13 @@ void Surface::QueueFrame(scoped_ptr<CompositorFrame> frame, ...@@ -53,8 +66,13 @@ void Surface::QueueFrame(scoped_ptr<CompositorFrame> frame,
} }
void Surface::RequestCopyOfOutput(scoped_ptr<CopyOutputRequest> copy_request) { void Surface::RequestCopyOfOutput(scoped_ptr<CopyOutputRequest> copy_request) {
// TODO(jbauman): Make this work. copy_requests_.push_back(copy_request.Pass());
copy_request->SendEmptyResult(); }
void Surface::TakeCopyOutputRequests(
ScopedPtrVector<CopyOutputRequest>* copy_requests) {
DCHECK(copy_requests->empty());
copy_requests->swap(copy_requests_);
} }
const CompositorFrame* Surface::GetEligibleFrame() { const CompositorFrame* Surface::GetEligibleFrame() {
......
...@@ -11,6 +11,8 @@ ...@@ -11,6 +11,8 @@
#include "base/containers/hash_tables.h" #include "base/containers/hash_tables.h"
#include "base/macros.h" #include "base/macros.h"
#include "base/memory/scoped_ptr.h" #include "base/memory/scoped_ptr.h"
#include "cc/base/scoped_ptr_vector.h"
#include "cc/output/copy_output_request.h"
#include "cc/surfaces/surface_id.h" #include "cc/surfaces/surface_id.h"
#include "cc/surfaces/surfaces_export.h" #include "cc/surfaces/surfaces_export.h"
#include "ui/gfx/size.h" #include "ui/gfx/size.h"
...@@ -37,6 +39,8 @@ class CC_SURFACES_EXPORT Surface { ...@@ -37,6 +39,8 @@ class CC_SURFACES_EXPORT Surface {
void QueueFrame(scoped_ptr<CompositorFrame> frame, void QueueFrame(scoped_ptr<CompositorFrame> frame,
const base::Closure& draw_callback); const base::Closure& draw_callback);
void RequestCopyOfOutput(scoped_ptr<CopyOutputRequest> copy_request); void RequestCopyOfOutput(scoped_ptr<CopyOutputRequest> copy_request);
void TakeCopyOutputRequests(
ScopedPtrVector<CopyOutputRequest>* copy_requests);
// Returns the most recent frame that is eligible to be rendered. // Returns the most recent frame that is eligible to be rendered.
const CompositorFrame* GetEligibleFrame(); const CompositorFrame* GetEligibleFrame();
...@@ -55,6 +59,7 @@ class CC_SURFACES_EXPORT Surface { ...@@ -55,6 +59,7 @@ class CC_SURFACES_EXPORT Surface {
// TODO(jamesr): Support multiple frames in flight. // TODO(jamesr): Support multiple frames in flight.
scoped_ptr<CompositorFrame> current_frame_; scoped_ptr<CompositorFrame> current_frame_;
int frame_index_; int frame_index_;
ScopedPtrVector<CopyOutputRequest> copy_requests_;
base::Closure draw_callback_; base::Closure draw_callback_;
......
...@@ -176,8 +176,15 @@ void SurfaceAggregator::HandleSurfaceQuad(const SurfaceDrawQuad* surface_quad, ...@@ -176,8 +176,15 @@ void SurfaceAggregator::HandleSurfaceQuad(const SurfaceDrawQuad* surface_quad,
SurfaceSet::iterator it = referenced_surfaces_.insert(surface_id).first; SurfaceSet::iterator it = referenced_surfaces_.insert(surface_id).first;
ScopedPtrVector<CopyOutputRequest> copy_requests;
surface->TakeCopyOutputRequests(&copy_requests);
bool merge_pass = copy_requests.empty();
const RenderPassList& referenced_passes = render_pass_list; const RenderPassList& referenced_passes = render_pass_list;
for (size_t j = 0; j + 1 < referenced_passes.size(); ++j) { size_t passes_to_copy =
merge_pass ? referenced_passes.size() - 1 : referenced_passes.size();
for (size_t j = 0; j < passes_to_copy; ++j) {
const RenderPass& source = *referenced_passes[j]; const RenderPass& source = *referenced_passes[j];
scoped_ptr<RenderPass> copy_pass(RenderPass::Create()); scoped_ptr<RenderPass> copy_pass(RenderPass::Create());
...@@ -207,16 +214,37 @@ void SurfaceAggregator::HandleSurfaceQuad(const SurfaceDrawQuad* surface_quad, ...@@ -207,16 +214,37 @@ void SurfaceAggregator::HandleSurfaceQuad(const SurfaceDrawQuad* surface_quad,
dest_pass_list_->push_back(copy_pass.Pass()); dest_pass_list_->push_back(copy_pass.Pass());
} }
// TODO(jamesr): Clean up last pass special casing.
const RenderPass& last_pass = *render_pass_list.back(); const RenderPass& last_pass = *render_pass_list.back();
const QuadList& quads = last_pass.quad_list; if (merge_pass) {
// TODO(jamesr): Clean up last pass special casing.
// TODO(jamesr): Make sure clipping is enforced. const QuadList& quads = last_pass.quad_list;
CopyQuadsToPass(quads,
last_pass.shared_quad_state_list, // TODO(jamesr): Make sure clipping is enforced.
surface_quad->quadTransform(), CopyQuadsToPass(quads,
dest_pass, last_pass.shared_quad_state_list,
surface_id); surface_quad->quadTransform(),
dest_pass,
surface_id);
} else {
RenderPassId remapped_pass_id = RemapPassId(last_pass.id, surface_id);
dest_pass_list_->back()->copy_requests.swap(copy_requests);
SharedQuadState* shared_quad_state =
dest_pass->CreateAndAppendSharedQuadState();
shared_quad_state->CopyFrom(surface_quad->shared_quad_state);
scoped_ptr<RenderPassDrawQuad> quad(new RenderPassDrawQuad);
quad->SetNew(shared_quad_state,
surface_quad->rect,
surface_quad->visible_rect,
remapped_pass_id,
0,
gfx::RectF(),
FilterOperations(),
gfx::Vector2dF(),
FilterOperations());
dest_pass->quad_list.push_back(quad.PassAs<DrawQuad>());
}
dest_pass->damage_rect = dest_pass->damage_rect =
gfx::UnionRects(dest_pass->damage_rect, gfx::UnionRects(dest_pass->damage_rect,
MathUtil::MapEnclosingClippedRect( MathUtil::MapEnclosingClippedRect(
......
...@@ -117,6 +117,15 @@ void TestQuadMatchesExpectations(Quad expected_quad, DrawQuad* quad) { ...@@ -117,6 +117,15 @@ void TestQuadMatchesExpectations(Quad expected_quad, DrawQuad* quad) {
EXPECT_EQ(expected_quad.color, solid_color_quad->color); EXPECT_EQ(expected_quad.color, solid_color_quad->color);
break; break;
} }
case DrawQuad::RENDER_PASS: {
ASSERT_EQ(DrawQuad::RENDER_PASS, quad->material);
const RenderPassDrawQuad* render_pass_quad =
RenderPassDrawQuad::MaterialCast(quad);
EXPECT_EQ(expected_quad.render_pass_id, render_pass_quad->render_pass_id);
break;
}
default: default:
NOTREACHED(); NOTREACHED();
break; break;
......
...@@ -196,6 +196,62 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, SimpleSurfaceReference) { ...@@ -196,6 +196,62 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, SimpleSurfaceReference) {
factory_.Destroy(embedded_surface_id); factory_.Destroy(embedded_surface_id);
} }
TEST_F(SurfaceAggregatorValidSurfaceTest, CopyRequest) {
SurfaceId embedded_surface_id = allocator_.GenerateId();
factory_.Create(embedded_surface_id, SurfaceSize());
test::Quad embedded_quads[] = {test::Quad::SolidColorQuad(SK_ColorGREEN)};
test::Pass embedded_passes[] = {
test::Pass(embedded_quads, arraysize(embedded_quads))};
SubmitFrame(embedded_passes, arraysize(embedded_passes), embedded_surface_id);
scoped_ptr<CopyOutputRequest> copy_request(
CopyOutputRequest::CreateEmptyRequest());
CopyOutputRequest* copy_request_ptr = copy_request.get();
factory_.RequestCopyOfSurface(embedded_surface_id, copy_request.Pass());
test::Quad root_quads[] = {test::Quad::SolidColorQuad(SK_ColorWHITE),
test::Quad::SurfaceQuad(embedded_surface_id),
test::Quad::SolidColorQuad(SK_ColorBLACK)};
test::Pass root_passes[] = {test::Pass(root_quads, arraysize(root_quads))};
SubmitFrame(root_passes, arraysize(root_passes), root_surface_id_);
scoped_ptr<CompositorFrame> aggregated_frame =
aggregator_.Aggregate(root_surface_id_);
ASSERT_TRUE(aggregated_frame);
ASSERT_TRUE(aggregated_frame->delegated_frame_data);
DelegatedFrameData* frame_data = aggregated_frame->delegated_frame_data.get();
test::Quad expected_quads[] = {
test::Quad::SolidColorQuad(SK_ColorWHITE),
test::Quad::RenderPassQuad(frame_data->render_pass_list[0]->id),
test::Quad::SolidColorQuad(SK_ColorBLACK)};
test::Pass expected_passes[] = {
test::Pass(embedded_quads, arraysize(embedded_quads)),
test::Pass(expected_quads, arraysize(expected_quads))};
TestPassesMatchExpectations(expected_passes,
arraysize(expected_passes),
&frame_data->render_pass_list);
ASSERT_EQ(2u, frame_data->render_pass_list.size());
ASSERT_EQ(1u, frame_data->render_pass_list[0]->copy_requests.size());
DCHECK_EQ(copy_request_ptr,
frame_data->render_pass_list[0]->copy_requests[0]);
SurfaceId surface_ids[] = {root_surface_id_, embedded_surface_id};
EXPECT_EQ(arraysize(surface_ids),
aggregator_.previous_contained_surfaces().size());
for (size_t i = 0; i < arraysize(surface_ids); i++) {
EXPECT_TRUE(
aggregator_.previous_contained_surfaces().find(surface_ids[i]) !=
aggregator_.previous_contained_surfaces().end());
}
factory_.Destroy(embedded_surface_id);
}
// This tests referencing a surface that has multiple render passes. // This tests referencing a surface that has multiple render passes.
TEST_F(SurfaceAggregatorValidSurfaceTest, MultiPassSurfaceReference) { TEST_F(SurfaceAggregatorValidSurfaceTest, MultiPassSurfaceReference) {
SurfaceId embedded_surface_id = allocator_.GenerateId(); SurfaceId embedded_surface_id = allocator_.GenerateId();
......
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