diff options
author | jbauman <jbauman@chromium.org> | 2015-07-13 18:55:23 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-07-14 01:56:02 +0000 |
commit | 826aae36bc7da8a39f9b5eebefe9e51c59a63cfd (patch) | |
tree | a9f011ee9c234f0cdf388bd82a0cb53e1b9ee41c /cc/surfaces | |
parent | cd0ea9c552e554f44d66638937b4b8e001e96974 (diff) | |
download | chromium_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}
Diffstat (limited to 'cc/surfaces')
-rw-r--r-- | cc/surfaces/display.cc | 7 | ||||
-rw-r--r-- | cc/surfaces/surface_aggregator.cc | 112 | ||||
-rw-r--r-- | cc/surfaces/surface_aggregator.h | 22 | ||||
-rw-r--r-- | cc/surfaces/surface_aggregator_perftest.cc | 56 | ||||
-rw-r--r-- | cc/surfaces/surface_aggregator_unittest.cc | 214 | ||||
-rw-r--r-- | cc/surfaces/surfaces_pixeltest.cc | 6 |
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); |