summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjbauman <jbauman@chromium.org>2015-07-13 18:55:23 -0700
committerCommit bot <commit-bot@chromium.org>2015-07-14 01:56:02 +0000
commit826aae36bc7da8a39f9b5eebefe9e51c59a63cfd (patch)
treea9f011ee9c234f0cdf388bd82a0cb53e1b9ee41c
parentcd0ea9c552e554f44d66638937b4b8e001e96974 (diff)
downloadchromium_src-826aae36bc7da8a39f9b5eebefe9e51c59a63cfd.zip
chromium_src-826aae36bc7da8a39f9b5eebefe9e51c59a63cfd.tar.gz
chromium_src-826aae36bc7da8a39f9b5eebefe9e51c59a63cfd.tar.bz2
Don't aggregate quads outside of damage rect when using partial swap.
The quads will be scissored out, so aggregating them is a waste. For me on a webpage with a tiny spinner this reduces DisplayScheduler::OnBeginFrameDeadline time by around 30%, and reduces the GPU process CPU time by around 50%. BUG=490447 CQ_INCLUDE_TRYBOTS=tryserver.blink:linux_blink_rel Review URL: https://codereview.chromium.org/1172883004 Cr-Commit-Position: refs/heads/master@{#338619}
-rw-r--r--cc/surfaces/display.cc7
-rw-r--r--cc/surfaces/surface_aggregator.cc112
-rw-r--r--cc/surfaces/surface_aggregator.h22
-rw-r--r--cc/surfaces/surface_aggregator_perftest.cc56
-rw-r--r--cc/surfaces/surface_aggregator_unittest.cc214
-rw-r--r--cc/surfaces/surfaces_pixeltest.cc6
6 files changed, 359 insertions, 58 deletions
diff --git a/cc/surfaces/display.cc b/cc/surfaces/display.cc
index 9314c71..54a76ef 100644
--- a/cc/surfaces/display.cc
+++ b/cc/surfaces/display.cc
@@ -122,7 +122,12 @@ void Display::InitializeRenderer() {
}
resource_provider_ = resource_provider.Pass();
- aggregator_.reset(new SurfaceAggregator(manager_, resource_provider_.get()));
+ // TODO(jbauman): Outputting an incomplete quad list doesn't work when using
+ // overlays.
+ bool output_partial_list = renderer_->Capabilities().using_partial_swap &&
+ !output_surface_->GetOverlayCandidateValidator();
+ aggregator_.reset(new SurfaceAggregator(manager_, resource_provider_.get(),
+ output_partial_list));
}
void Display::DidLoseOutputSurface() {
diff --git a/cc/surfaces/surface_aggregator.cc b/cc/surfaces/surface_aggregator.cc
index ddfac76..8a1950b 100644
--- a/cc/surfaces/surface_aggregator.cc
+++ b/cc/surfaces/surface_aggregator.cc
@@ -41,8 +41,12 @@ void MoveMatchingRequests(
} // namespace
SurfaceAggregator::SurfaceAggregator(SurfaceManager* manager,
- ResourceProvider* provider)
- : manager_(manager), provider_(provider), next_render_pass_id_(1) {
+ ResourceProvider* provider,
+ bool aggregate_only_damaged)
+ : manager_(manager),
+ provider_(provider),
+ next_render_pass_id_(1),
+ aggregate_only_damaged_(aggregate_only_damaged) {
DCHECK(manager_);
}
@@ -154,11 +158,8 @@ void SurfaceAggregator::HandleSurfaceQuad(
if (referenced_surfaces_.count(surface_id))
return;
Surface* surface = manager_->GetSurfaceForId(surface_id);
- if (!surface) {
- contained_surfaces_[surface_id] = 0;
+ if (!surface)
return;
- }
- contained_surfaces_[surface_id] = surface->frame_index();
const CompositorFrame* frame = surface->GetEligibleFrame();
if (!frame)
return;
@@ -251,11 +252,10 @@ void SurfaceAggregator::HandleSurfaceQuad(
} else {
RenderPassId remapped_pass_id = RemapPassId(last_pass.id, surface_id);
- CopySharedQuadState(surface_quad->shared_quad_state, target_transform,
- clip_rect, dest_pass);
-
SharedQuadState* shared_quad_state =
- dest_pass->shared_quad_state_list.back();
+ CopySharedQuadState(surface_quad->shared_quad_state, target_transform,
+ clip_rect, dest_pass);
+
RenderPassDrawQuad* quad =
dest_pass->CreateAndAppendDrawQuad<RenderPassDrawQuad>();
quad->SetNew(shared_quad_state,
@@ -270,11 +270,10 @@ void SurfaceAggregator::HandleSurfaceQuad(
FilterOperations());
}
-
referenced_surfaces_.erase(it);
}
-void SurfaceAggregator::CopySharedQuadState(
+SharedQuadState* SurfaceAggregator::CopySharedQuadState(
const SharedQuadState* source_sqs,
const gfx::Transform& target_transform,
const ClipData& clip_rect,
@@ -296,6 +295,21 @@ void SurfaceAggregator::CopySharedQuadState(
target_transform);
copy_shared_quad_state->is_clipped = new_clip_rect.is_clipped;
copy_shared_quad_state->clip_rect = new_clip_rect.rect;
+ return copy_shared_quad_state;
+}
+
+static gfx::Rect CalculateQuadSpaceDamageRect(
+ const gfx::Transform& quad_to_target_transform,
+ const gfx::Transform& target_to_root_transform,
+ const gfx::Rect& root_damage_rect) {
+ gfx::Transform quad_to_root_transform(quad_to_target_transform,
+ target_to_root_transform);
+ gfx::Transform inverse_transform(gfx::Transform::kSkipInitialization);
+ bool inverse_valid = quad_to_root_transform.GetInverse(&inverse_transform);
+ DCHECK(inverse_valid);
+
+ return MathUtil::ProjectEnclosingClippedRect(inverse_transform,
+ root_damage_rect);
}
void SurfaceAggregator::CopyQuadsToPass(
@@ -306,7 +320,15 @@ void SurfaceAggregator::CopyQuadsToPass(
const ClipData& clip_rect,
RenderPass* dest_pass,
SurfaceId surface_id) {
- const SharedQuadState* last_copied_source_shared_quad_state = NULL;
+ const SharedQuadState* last_copied_source_shared_quad_state = nullptr;
+ const SharedQuadState* dest_shared_quad_state = nullptr;
+ // If the current frame has copy requests then aggregate the entire
+ // thing, as otherwise parts of the copy requests may be ignored.
+ const bool ignore_undamaged = aggregate_only_damaged_ && !has_copy_requests_;
+ // Damage rect in the quad space of the current shared quad state.
+ // TODO(jbauman): This rect may contain unnecessary area if
+ // transform isn't axis-aligned.
+ gfx::Rect damage_rect_in_quad_space;
SharedQuadStateList::ConstIterator sqs_iter =
source_shared_quad_state_list.begin();
@@ -319,13 +341,38 @@ void SurfaceAggregator::CopyQuadsToPass(
if (quad->material == DrawQuad::SURFACE_CONTENT) {
const SurfaceDrawQuad* surface_quad = SurfaceDrawQuad::MaterialCast(quad);
+ // HandleSurfaceQuad may add other shared quad state, so reset the
+ // current data.
+ last_copied_source_shared_quad_state = nullptr;
+
+ if (ignore_undamaged) {
+ gfx::Transform quad_to_target_transform(
+ quad->shared_quad_state->quad_to_target_transform,
+ target_transform);
+ damage_rect_in_quad_space = CalculateQuadSpaceDamageRect(
+ quad_to_target_transform, dest_pass->transform_to_root_target,
+ root_damage_rect_);
+ if (!damage_rect_in_quad_space.Intersects(quad->visible_rect))
+ continue;
+ }
HandleSurfaceQuad(surface_quad, target_transform, clip_rect, dest_pass);
} else {
if (quad->shared_quad_state != last_copied_source_shared_quad_state) {
- CopySharedQuadState(quad->shared_quad_state, target_transform,
- clip_rect, dest_pass);
+ dest_shared_quad_state = CopySharedQuadState(
+ quad->shared_quad_state, target_transform, clip_rect, dest_pass);
last_copied_source_shared_quad_state = quad->shared_quad_state;
+ if (aggregate_only_damaged_ && !has_copy_requests_) {
+ damage_rect_in_quad_space = CalculateQuadSpaceDamageRect(
+ dest_shared_quad_state->quad_to_target_transform,
+ dest_pass->transform_to_root_target, root_damage_rect_);
+ }
+ }
+
+ if (ignore_undamaged) {
+ if (!damage_rect_in_quad_space.Intersects(quad->visible_rect))
+ continue;
}
+
DrawQuad* dest_quad;
if (quad->material == DrawQuad::RENDER_PASS) {
const RenderPassDrawQuad* pass_quad =
@@ -335,11 +382,10 @@ void SurfaceAggregator::CopyQuadsToPass(
RemapPassId(original_pass_id, surface_id);
dest_quad = dest_pass->CopyFromAndAppendRenderPassDrawQuad(
- pass_quad, dest_pass->shared_quad_state_list.back(),
- remapped_pass_id);
+ pass_quad, dest_shared_quad_state, remapped_pass_id);
} else {
- dest_quad = dest_pass->CopyFromAndAppendDrawQuad(
- quad, dest_pass->shared_quad_state_list.back());
+ dest_quad =
+ dest_pass->CopyFromAndAppendDrawQuad(quad, dest_shared_quad_state);
}
if (!child_to_parent_map.empty()) {
for (ResourceId& resource_id : dest_quad->resources) {
@@ -415,15 +461,18 @@ void SurfaceAggregator::RemoveUnreferencedChildren() {
}
}
-// Validate the resources of the current surface and its descendants, and
-// calculate their combined damage rect.
-gfx::Rect SurfaceAggregator::ValidateAndCalculateDamageRect(
- SurfaceId surface_id) {
+// Walk the Surface tree from surface_id. Validate the resources of the current
+// surface and its descendants, check if there are any copy requests, and
+// return the combined damage rect.
+gfx::Rect SurfaceAggregator::PrewalkTree(SurfaceId surface_id) {
if (referenced_surfaces_.count(surface_id))
return gfx::Rect();
Surface* surface = manager_->GetSurfaceForId(surface_id);
- if (!surface)
+ if (!surface) {
+ contained_surfaces_[surface_id] = 0;
return gfx::Rect();
+ }
+ contained_surfaces_[surface_id] = surface->frame_index();
const CompositorFrame* surface_frame = surface->GetEligibleFrame();
if (!surface_frame)
return gfx::Rect();
@@ -492,11 +541,14 @@ gfx::Rect SurfaceAggregator::ValidateAndCalculateDamageRect(
if (provider_)
provider_->DeclareUsedResourcesFromChild(child_id, referenced_resources);
+ for (const auto& render_pass : frame_data->render_pass_list)
+ has_copy_requests_ |= !render_pass->copy_requests.empty();
+
gfx::Rect damage_rect;
if (!frame_data->render_pass_list.empty()) {
+ RenderPass* last_pass = frame_data->render_pass_list.back();
damage_rect =
- DamageRectForSurface(surface, *frame_data->render_pass_list.back(),
- frame_data->render_pass_list.back()->output_rect);
+ DamageRectForSurface(surface, *last_pass, last_pass->output_rect);
}
// Avoid infinite recursion by adding current surface to
@@ -504,8 +556,7 @@ gfx::Rect SurfaceAggregator::ValidateAndCalculateDamageRect(
SurfaceSet::iterator it =
referenced_surfaces_.insert(surface->surface_id()).first;
for (const auto& surface_info : child_surfaces) {
- gfx::Rect surface_damage =
- ValidateAndCalculateDamageRect(surface_info.first);
+ gfx::Rect surface_damage = PrewalkTree(surface_info.first);
damage_rect.Union(
MathUtil::MapEnclosingClippedRect(surface_info.second, surface_damage));
}
@@ -531,7 +582,8 @@ scoped_ptr<CompositorFrame> SurfaceAggregator::Aggregate(SurfaceId surface_id) {
dest_pass_list_ = &frame->delegated_frame_data->render_pass_list;
valid_surfaces_.clear();
- gfx::Rect damage_rect = ValidateAndCalculateDamageRect(surface_id);
+ has_copy_requests_ = false;
+ root_damage_rect_ = PrewalkTree(surface_id);
SurfaceSet::iterator it = referenced_surfaces_.insert(surface_id).first;
CopyPasses(root_surface_frame->delegated_frame_data.get(), surface);
@@ -541,7 +593,7 @@ scoped_ptr<CompositorFrame> SurfaceAggregator::Aggregate(SurfaceId surface_id) {
if (dest_pass_list_->empty())
return nullptr;
- dest_pass_list_->back()->damage_rect = damage_rect;
+ dest_pass_list_->back()->damage_rect = root_damage_rect_;
dest_pass_list_ = NULL;
RemoveUnreferencedChildren();
diff --git a/cc/surfaces/surface_aggregator.h b/cc/surfaces/surface_aggregator.h
index 17ea4c4..1ff4a45 100644
--- a/cc/surfaces/surface_aggregator.h
+++ b/cc/surfaces/surface_aggregator.h
@@ -29,7 +29,9 @@ class CC_SURFACES_EXPORT SurfaceAggregator {
public:
typedef base::hash_map<SurfaceId, int> SurfaceIndexMap;
- SurfaceAggregator(SurfaceManager* manager, ResourceProvider* provider);
+ SurfaceAggregator(SurfaceManager* manager,
+ ResourceProvider* provider,
+ bool aggregate_only_damaged);
~SurfaceAggregator();
scoped_ptr<CompositorFrame> Aggregate(SurfaceId surface_id);
@@ -60,10 +62,10 @@ class CC_SURFACES_EXPORT SurfaceAggregator {
const gfx::Transform& target_transform,
const ClipData& clip_rect,
RenderPass* dest_pass);
- void CopySharedQuadState(const SharedQuadState* source_sqs,
- const gfx::Transform& target_transform,
- const ClipData& clip_rect,
- RenderPass* dest_render_pass);
+ SharedQuadState* CopySharedQuadState(const SharedQuadState* source_sqs,
+ const gfx::Transform& target_transform,
+ const ClipData& clip_rect,
+ RenderPass* dest_render_pass);
void CopyQuadsToPass(
const QuadList& source_quad_list,
const SharedQuadStateList& source_shared_quad_state_list,
@@ -72,7 +74,7 @@ class CC_SURFACES_EXPORT SurfaceAggregator {
const ClipData& clip_rect,
RenderPass* dest_pass,
SurfaceId surface_id);
- gfx::Rect ValidateAndCalculateDamageRect(SurfaceId surface_id);
+ gfx::Rect PrewalkTree(SurfaceId surface_id);
void CopyPasses(const DelegatedFrameData* frame_data, Surface* surface);
// Remove Surfaces that were referenced before but aren't currently
@@ -92,6 +94,7 @@ class CC_SURFACES_EXPORT SurfaceAggregator {
RenderPassIdAllocatorMap;
RenderPassIdAllocatorMap render_pass_allocator_map_;
int next_render_pass_id_;
+ const bool aggregate_only_damaged_;
typedef base::hash_map<SurfaceId, int> SurfaceToResourceChildIdMap;
SurfaceToResourceChildIdMap surface_id_to_resource_child_id_;
@@ -116,6 +119,13 @@ class CC_SURFACES_EXPORT SurfaceAggregator {
// This is the pass list for the aggregated frame.
RenderPassList* dest_pass_list_;
+ // The root damage rect of the currently-aggregating frame.
+ gfx::Rect root_damage_rect_;
+
+ // True if the frame that's currently being aggregated has copy requests.
+ // This is valid during Aggregate after PrewalkTree is called.
+ bool has_copy_requests_;
+
// Resource list for the aggregated frame.
TransferableResourceArray* dest_resource_list_;
diff --git a/cc/surfaces/surface_aggregator_perftest.cc b/cc/surfaces/surface_aggregator_perftest.cc
index b5fddf5..b265816 100644
--- a/cc/surfaces/surface_aggregator_perftest.cc
+++ b/cc/surfaces/surface_aggregator_perftest.cc
@@ -36,14 +36,16 @@ class SurfaceAggregatorPerfTest : public testing::Test {
resource_provider_ = FakeResourceProvider::Create(
output_surface_.get(), shared_bitmap_manager_.get());
- aggregator_.reset(
- new SurfaceAggregator(&manager_, resource_provider_.get()));
}
void RunTest(int num_surfaces,
int num_textures,
float opacity,
+ bool optimize_damage,
+ bool full_damage,
const std::string& name) {
+ aggregator_.reset(new SurfaceAggregator(&manager_, resource_provider_.get(),
+ optimize_damage));
for (int i = 1; i <= num_surfaces; i++) {
factory_.Create(SurfaceId(i));
scoped_ptr<RenderPass> pass(RenderPass::Create());
@@ -60,7 +62,9 @@ class SurfaceAggregatorPerfTest : public testing::Test {
pass->CreateAndAppendDrawQuad<TextureDrawQuad>();
const gfx::Rect rect(0, 0, 1, 1);
const gfx::Rect opaque_rect;
- const gfx::Rect visible_rect(0, 0, 1, 1);
+ // Half of rects should be visible with partial damage.
+ gfx::Rect visible_rect =
+ j % 2 == 0 ? gfx::Rect(0, 0, 1, 1) : gfx::Rect(1, 1, 1, 1);
bool needs_blending = false;
bool premultiplied_alpha = false;
const gfx::PointF uv_top_left;
@@ -90,16 +94,38 @@ class SurfaceAggregatorPerfTest : public testing::Test {
SurfaceFactory::DrawCallback());
}
+ factory_.Create(SurfaceId(num_surfaces + 1));
timer_.Reset();
do {
+ scoped_ptr<RenderPass> pass(RenderPass::Create());
+ scoped_ptr<DelegatedFrameData> frame_data(new DelegatedFrameData);
+
+ SharedQuadState* sqs = pass->CreateAndAppendSharedQuadState();
+ SurfaceDrawQuad* surface_quad =
+ pass->CreateAndAppendDrawQuad<SurfaceDrawQuad>();
+ surface_quad->SetNew(sqs, gfx::Rect(0, 0, 100, 100),
+ gfx::Rect(0, 0, 100, 100), SurfaceId(num_surfaces));
+
+ if (full_damage)
+ pass->damage_rect = gfx::Rect(0, 0, 100, 100);
+ else
+ pass->damage_rect = gfx::Rect(0, 0, 1, 1);
+
+ frame_data->render_pass_list.push_back(pass.Pass());
+ scoped_ptr<CompositorFrame> frame(new CompositorFrame);
+ frame->delegated_frame_data = frame_data.Pass();
+ factory_.SubmitFrame(SurfaceId(num_surfaces + 1), frame.Pass(),
+ SurfaceFactory::DrawCallback());
+
scoped_ptr<CompositorFrame> aggregated =
- aggregator_->Aggregate(SurfaceId(num_surfaces));
+ aggregator_->Aggregate(SurfaceId(num_surfaces + 1));
timer_.NextLap();
} while (!timer_.HasTimeLimitExpired());
perf_test::PrintResult("aggregator_speed", "", name, timer_.LapsPerSecond(),
"runs/s", true);
+ factory_.Destroy(SurfaceId(num_surfaces + 1));
for (int i = 1; i <= num_surfaces; i++)
factory_.Destroy(SurfaceId(i));
}
@@ -117,15 +143,31 @@ class SurfaceAggregatorPerfTest : public testing::Test {
};
TEST_F(SurfaceAggregatorPerfTest, ManySurfacesOpaque) {
- RunTest(20, 100, 1.f, "many_surfaces_opaque");
+ RunTest(20, 100, 1.f, false, true, "many_surfaces_opaque");
}
TEST_F(SurfaceAggregatorPerfTest, ManySurfacesTransparent) {
- RunTest(20, 100, .5f, "many_surfaces_transparent");
+ RunTest(20, 100, .5f, false, true, "many_surfaces_transparent");
}
TEST_F(SurfaceAggregatorPerfTest, FewSurfaces) {
- RunTest(3, 1000, 1.f, "few_surfaces");
+ RunTest(3, 1000, 1.f, false, true, "few_surfaces");
+}
+
+TEST_F(SurfaceAggregatorPerfTest, ManySurfacesOpaqueDamageCalc) {
+ RunTest(20, 100, 1.f, true, true, "many_surfaces_opaque_damage_calc");
+}
+
+TEST_F(SurfaceAggregatorPerfTest, ManySurfacesTransparentDamageCalc) {
+ RunTest(20, 100, .5f, true, true, "many_surfaces_transparent_damage_calc");
+}
+
+TEST_F(SurfaceAggregatorPerfTest, FewSurfacesDamageCalc) {
+ RunTest(3, 1000, 1.f, true, true, "few_surfaces_damage_calc");
+}
+
+TEST_F(SurfaceAggregatorPerfTest, FewSurfacesAggregateDamaged) {
+ RunTest(3, 1000, 1.f, true, false, "few_surfaces_aggregate_damaged");
}
} // namespace
diff --git a/cc/surfaces/surface_aggregator_unittest.cc b/cc/surfaces/surface_aggregator_unittest.cc
index e4ade82..5385a05 100644
--- a/cc/surfaces/surface_aggregator_unittest.cc
+++ b/cc/surfaces/surface_aggregator_unittest.cc
@@ -48,8 +48,11 @@ class EmptySurfaceFactoryClient : public SurfaceFactoryClient {
class SurfaceAggregatorTest : public testing::Test {
public:
- SurfaceAggregatorTest()
- : factory_(&manager_, &empty_client_), aggregator_(&manager_, NULL) {}
+ explicit SurfaceAggregatorTest(bool use_damage_rect)
+ : factory_(&manager_, &empty_client_),
+ aggregator_(&manager_, NULL, use_damage_rect) {}
+
+ SurfaceAggregatorTest() : SurfaceAggregatorTest(false) {}
protected:
SurfaceManager manager_;
@@ -68,7 +71,12 @@ TEST_F(SurfaceAggregatorTest, ValidSurfaceNoFrame) {
class SurfaceAggregatorValidSurfaceTest : public SurfaceAggregatorTest {
public:
- SurfaceAggregatorValidSurfaceTest() : allocator_(1u), child_allocator_(2u) {}
+ explicit SurfaceAggregatorValidSurfaceTest(bool use_damage_rect)
+ : SurfaceAggregatorTest(use_damage_rect),
+ allocator_(1u),
+ child_allocator_(2u) {}
+ SurfaceAggregatorValidSurfaceTest()
+ : SurfaceAggregatorValidSurfaceTest(false) {}
void SetUp() override {
SurfaceAggregatorTest::SetUp();
@@ -112,14 +120,9 @@ class SurfaceAggregatorValidSurfaceTest : public SurfaceAggregatorTest {
}
}
- void SubmitFrame(test::Pass* passes,
- size_t pass_count,
- SurfaceId surface_id) {
- RenderPassList pass_list;
- AddPasses(&pass_list, gfx::Rect(SurfaceSize()), passes, pass_count);
-
+ void SubmitPassListAsFrame(SurfaceId surface_id, RenderPassList* pass_list) {
scoped_ptr<DelegatedFrameData> frame_data(new DelegatedFrameData);
- pass_list.swap(frame_data->render_pass_list);
+ pass_list->swap(frame_data->render_pass_list);
scoped_ptr<CompositorFrame> frame(new CompositorFrame);
frame->delegated_frame_data = frame_data.Pass();
@@ -128,6 +131,14 @@ class SurfaceAggregatorValidSurfaceTest : public SurfaceAggregatorTest {
SurfaceFactory::DrawCallback());
}
+ void SubmitFrame(test::Pass* passes,
+ size_t pass_count,
+ SurfaceId surface_id) {
+ RenderPassList pass_list;
+ AddPasses(&pass_list, gfx::Rect(SurfaceSize()), passes, pass_count);
+ SubmitPassListAsFrame(surface_id, &pass_list);
+ }
+
void QueuePassAsFrame(scoped_ptr<RenderPass> pass, SurfaceId surface_id) {
scoped_ptr<DelegatedFrameData> delegated_frame_data(new DelegatedFrameData);
delegated_frame_data->render_pass_list.push_back(pass.Pass());
@@ -1293,6 +1304,187 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateDamageRect) {
factory_.Destroy(child_surface_id);
}
+class SurfaceAggregatorPartialSwapTest
+ : public SurfaceAggregatorValidSurfaceTest {
+ public:
+ SurfaceAggregatorPartialSwapTest()
+ : SurfaceAggregatorValidSurfaceTest(true) {}
+};
+
+// Tests that quads outside the damage rect are ignored.
+TEST_F(SurfaceAggregatorPartialSwapTest, IgnoreOutside) {
+ SurfaceId child_surface_id = allocator_.GenerateId();
+ factory_.Create(child_surface_id);
+ // The child surface has two quads, one with a visible rect of 10,10 2x2 and
+ // the other other with a visible rect of 12,12 2x2 (relative to root target
+ // space).
+ {
+ RenderPassId child_pass_id = RenderPassId(1, 1);
+ test::Quad child_quads[] = {test::Quad::RenderPassQuad(child_pass_id),
+ test::Quad::RenderPassQuad(child_pass_id)};
+ test::Pass child_passes[] = {
+ test::Pass(child_quads, arraysize(child_quads), child_pass_id)};
+
+ RenderPassList child_pass_list;
+ AddPasses(&child_pass_list, gfx::Rect(SurfaceSize()), child_passes,
+ arraysize(child_passes));
+
+ RenderPass* child_root_pass = child_pass_list.at(0u);
+ child_root_pass->quad_list.ElementAt(0)->visible_rect =
+ gfx::Rect(0, 0, 2, 2);
+ child_root_pass->quad_list.ElementAt(1)->visible_rect =
+ gfx::Rect(1, 1, 2, 2);
+ SharedQuadState* child_sqs =
+ child_root_pass->shared_quad_state_list.ElementAt(1u);
+ child_sqs->quad_to_target_transform.Translate(1, 1);
+
+ SubmitPassListAsFrame(child_surface_id, &child_pass_list);
+ }
+
+ {
+ test::Quad root_quads[] = {test::Quad::SurfaceQuad(child_surface_id, 1.f)};
+
+ test::Pass root_passes[] = {test::Pass(root_quads, arraysize(root_quads))};
+
+ RenderPassList root_pass_list;
+ AddPasses(&root_pass_list, gfx::Rect(SurfaceSize()), root_passes,
+ arraysize(root_passes));
+
+ RenderPass* root_pass = root_pass_list.at(0u);
+ root_pass->shared_quad_state_list.front()
+ ->quad_to_target_transform.Translate(10, 10);
+ root_pass->damage_rect = gfx::Rect(0, 0, 1, 1);
+
+ SubmitPassListAsFrame(root_surface_id_, &root_pass_list);
+ }
+
+ 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();
+
+ const RenderPassList& aggregated_pass_list = frame_data->render_pass_list;
+
+ ASSERT_EQ(1u, aggregated_pass_list.size());
+
+ // Damage rect for first aggregation should contain entire root surface.
+ EXPECT_EQ(gfx::Rect(0, 0, 15, 15), aggregated_pass_list[0]->damage_rect);
+ EXPECT_EQ(2u, aggregated_pass_list[0]->quad_list.size());
+
+ // Create a root surface with a smaller damage rect.
+ {
+ test::Quad root_quads[] = {test::Quad::SurfaceQuad(child_surface_id, 1.f)};
+
+ test::Pass root_passes[] = {test::Pass(root_quads, arraysize(root_quads))};
+
+ RenderPassList root_pass_list;
+ AddPasses(&root_pass_list, gfx::Rect(SurfaceSize()), root_passes,
+ arraysize(root_passes));
+
+ RenderPass* root_pass = root_pass_list.at(0u);
+ root_pass->shared_quad_state_list.front()
+ ->quad_to_target_transform.Translate(10, 10);
+ root_pass->damage_rect = gfx::Rect(10, 10, 2, 2);
+ SubmitPassListAsFrame(root_surface_id_, &root_pass_list);
+ }
+
+ {
+ 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();
+
+ const RenderPassList& aggregated_pass_list = frame_data->render_pass_list;
+
+ ASSERT_EQ(1u, aggregated_pass_list.size());
+
+ // Only first quad from surface is inside damage rect and should be
+ // included.
+ EXPECT_EQ(gfx::Rect(10, 10, 2, 2), aggregated_pass_list[0]->damage_rect);
+ EXPECT_EQ(1u, aggregated_pass_list[0]->quad_list.size());
+ EXPECT_EQ(gfx::Rect(0, 0, 2, 2),
+ aggregated_pass_list[0]->quad_list.back()->visible_rect);
+ }
+
+ // New child frame has same content and no damage, but has a
+ // CopyOutputRequest.
+ {
+ RenderPassId child_pass_id = RenderPassId(1, 1);
+ test::Quad child_quads[] = {test::Quad::RenderPassQuad(child_pass_id),
+ test::Quad::RenderPassQuad(child_pass_id)};
+ test::Pass child_passes[] = {
+ test::Pass(child_quads, arraysize(child_quads), child_pass_id)};
+
+ RenderPassList child_pass_list;
+ AddPasses(&child_pass_list, gfx::Rect(SurfaceSize()), child_passes,
+ arraysize(child_passes));
+
+ RenderPass* child_root_pass = child_pass_list.at(0u);
+ child_root_pass->quad_list.ElementAt(0)->visible_rect =
+ gfx::Rect(0, 0, 2, 2);
+ child_root_pass->quad_list.ElementAt(1)->visible_rect =
+ gfx::Rect(1, 1, 2, 2);
+ SharedQuadState* child_sqs =
+ child_root_pass->shared_quad_state_list.ElementAt(1u);
+ child_sqs->quad_to_target_transform.Translate(1, 1);
+ child_root_pass->copy_requests.push_back(
+ CopyOutputRequest::CreateEmptyRequest());
+ child_root_pass->damage_rect = gfx::Rect();
+ SubmitPassListAsFrame(child_surface_id, &child_pass_list);
+ }
+
+ {
+ 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();
+
+ const RenderPassList& aggregated_pass_list = frame_data->render_pass_list;
+
+ // Output frame should have no damage, but all quads included.
+ ASSERT_EQ(2u, aggregated_pass_list.size());
+
+ EXPECT_TRUE(aggregated_pass_list[1]->damage_rect.IsEmpty());
+ ASSERT_EQ(2u, aggregated_pass_list[0]->quad_list.size());
+ const QuadList& child_quad_list = aggregated_pass_list[0]->quad_list;
+ EXPECT_EQ(gfx::Rect(0, 0, 2, 2),
+ child_quad_list.ElementAt(0)->visible_rect);
+ EXPECT_EQ(gfx::Rect(1, 1, 2, 2),
+ child_quad_list.ElementAt(1)->visible_rect);
+ }
+
+ {
+ 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();
+
+ const RenderPassList& aggregated_pass_list = frame_data->render_pass_list;
+ // There were no changes since last aggregation, so output should be empty
+ // and have no damage.
+ ASSERT_EQ(1u, aggregated_pass_list.size());
+ EXPECT_TRUE(aggregated_pass_list[0]->damage_rect.IsEmpty());
+ ASSERT_EQ(0u, aggregated_pass_list[0]->quad_list.size());
+ }
+
+ factory_.Destroy(child_surface_id);
+}
+
class SurfaceAggregatorWithResourcesTest : public testing::Test {
public:
void SetUp() override {
@@ -1305,7 +1497,7 @@ class SurfaceAggregatorWithResourcesTest : public testing::Test {
output_surface_.get(), shared_bitmap_manager_.get());
aggregator_.reset(
- new SurfaceAggregator(&manager_, resource_provider_.get()));
+ new SurfaceAggregator(&manager_, resource_provider_.get(), false));
}
protected:
diff --git a/cc/surfaces/surfaces_pixeltest.cc b/cc/surfaces/surfaces_pixeltest.cc
index bf8ad57..6c821a6 100644
--- a/cc/surfaces/surfaces_pixeltest.cc
+++ b/cc/surfaces/surfaces_pixeltest.cc
@@ -83,7 +83,7 @@ TEST_F(SurfacesPixelTest, DrawSimpleFrame) {
factory_.SubmitFrame(root_surface_id, root_frame.Pass(),
SurfaceFactory::DrawCallback());
- SurfaceAggregator aggregator(&manager_, resource_provider_.get());
+ SurfaceAggregator aggregator(&manager_, resource_provider_.get(), true);
scoped_ptr<CompositorFrame> aggregated_frame =
aggregator.Aggregate(root_surface_id);
factory_.Destroy(root_surface_id);
@@ -167,7 +167,7 @@ TEST_F(SurfacesPixelTest, DrawSimpleAggregatedFrame) {
SurfaceFactory::DrawCallback());
}
- SurfaceAggregator aggregator(&manager_, resource_provider_.get());
+ SurfaceAggregator aggregator(&manager_, resource_provider_.get(), true);
scoped_ptr<CompositorFrame> aggregated_frame =
aggregator.Aggregate(root_surface_id);
@@ -310,7 +310,7 @@ TEST_F(SurfacesPixelTest, DrawAggregatedFrameWithSurfaceTransforms) {
SurfaceFactory::DrawCallback());
}
- SurfaceAggregator aggregator(&manager_, resource_provider_.get());
+ SurfaceAggregator aggregator(&manager_, resource_provider_.get(), true);
scoped_ptr<CompositorFrame> aggregated_frame =
aggregator.Aggregate(root_surface_id);