diff options
author | danakj@chromium.org <danakj@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-03-05 20:38:59 +0000 |
---|---|---|
committer | danakj@chromium.org <danakj@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-03-05 20:38:59 +0000 |
commit | 5d910f5a95b6aa3e15bd27428b2907360e51b9f5 (patch) | |
tree | 300478490e3f3a85d5b4fe8fddbaca4c2d888891 /cc | |
parent | 6d65223d5129c232db8e8650f578e2d070263dfd (diff) | |
download | chromium_src-5d910f5a95b6aa3e15bd27428b2907360e51b9f5.zip chromium_src-5d910f5a95b6aa3e15bd27428b2907360e51b9f5.tar.gz chromium_src-5d910f5a95b6aa3e15bd27428b2907360e51b9f5.tar.bz2 |
cc: Unused resources should be given back to the child compositor
If a frame passes ownership of a resource, but no quads in the frame use
it, the resource should be passed back to the child, not held forever.
If a new frame is given to the delegated renderer layer before the
taking unused resources from it, they are re-added to the new frame
in case it uses any of them. The resources not used by the new frame
will be returned after the next commit.
Tested by existing delegated renderer tests, and also by:
LayerTreeHostDelegatedTestUnnamedResource.runSingleThread
LayerTreeHostDelegatedTestUnnamedResource.runMultiThread
LayerTreeHostDelegatedTestDontLeakResource.runSingleThread
LayerTreeHostDelegatedTestDontLeakResource.runMultiThread
LayerTreeHostDelegatedTestResourceSentToParent.runSingleThread
LayerTreeHostDelegatedTestResourceSentToParent.runMultiThread
LayerTreeHostDelegatedTestCommitWithoutTake.runSingleThread
LayerTreeHostDelegatedTestCommitWithoutTake.runMultiThread
R=piman
BUG=123444
NOTRY=true
Review URL: https://chromiumcodereview.appspot.com/12385085
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@186246 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'cc')
-rw-r--r-- | cc/delegated_renderer_layer.cc | 19 | ||||
-rw-r--r-- | cc/delegated_renderer_layer_impl.cc | 106 | ||||
-rw-r--r-- | cc/layer_tree_host_unittest_delegated.cc | 401 |
3 files changed, 424 insertions, 102 deletions
diff --git a/cc/delegated_renderer_layer.cc b/cc/delegated_renderer_layer.cc index 7e06e4f..297a5e8 100644 --- a/cc/delegated_renderer_layer.cc +++ b/cc/delegated_renderer_layer.cc @@ -37,10 +37,11 @@ void DelegatedRendererLayer::pushPropertiesTo(LayerImpl* impl) { delegated_impl->SetDisplaySize(display_size_); - if (!frame_data_) - return; - - if (frame_size_.IsEmpty()) { + if (!frame_data_) { + delegated_impl->SetFrameData(scoped_ptr<DelegatedFrameData>(), + gfx::Rect(), + &unused_resources_for_child_compositor_); + } else if (frame_size_.IsEmpty()) { scoped_ptr<DelegatedFrameData> empty_frame(new DelegatedFrameData); delegated_impl->SetFrameData(empty_frame.Pass(), gfx::Rect(), @@ -75,6 +76,16 @@ void DelegatedRendererLayer::SetFrameData( RenderPass* root_pass = frame_data_->render_pass_list.back(); damage_in_frame_.Union(root_pass->damage_rect); frame_size_ = root_pass->output_rect.size(); + + // TODO(danakj): This could be optimized to only add resources to the + // frame_data_ if they are actually used in the frame. For now, it will + // cause the parent (this layer) to hold onto some resources it doesn't + // need to for an extra frame. + for (size_t i = 0; i < unused_resources_for_child_compositor_.size(); ++i) { + frame_data_->resource_list.push_back( + unused_resources_for_child_compositor_[i]); + } + unused_resources_for_child_compositor_.clear(); } else { frame_size_ = gfx::Size(); } diff --git a/cc/delegated_renderer_layer_impl.cc b/cc/delegated_renderer_layer_impl.cc index e271b57..4b9b38a 100644 --- a/cc/delegated_renderer_layer_impl.cc +++ b/cc/delegated_renderer_layer_impl.cc @@ -60,75 +60,63 @@ void DelegatedRendererLayerImpl::SetFrameData( scoped_ptr<DelegatedFrameData> frame_data, gfx::RectF damage_in_frame, TransferableResourceArray* resources_for_ack) { - // A frame with an empty root render pass is invalid. - DCHECK(frame_data->render_pass_list.empty() || - !frame_data->render_pass_list.back()->output_rect.IsEmpty()); - CreateChildIdIfNeeded(); DCHECK(child_id_); - // Display size is already set so we can compute what the damage rect - // will be in layer space. - if (!frame_data->render_pass_list.empty()) { - RenderPass* new_root_pass = frame_data->render_pass_list.back(); - gfx::RectF damage_in_layer = MathUtil::mapClippedRect( - DelegatedFrameToLayerSpaceTransform(new_root_pass->output_rect.size()), - damage_in_frame); - setUpdateRect(gfx::UnionRects(updateRect(), damage_in_layer)); - } - - // Save the resources from the last frame. - ResourceProvider::ResourceIdSet new_resources; - - // Receive the current frame's resources from the child compositor. ResourceProvider* resource_provider = layerTreeImpl()->resource_provider(); - resource_provider->receiveFromChild(child_id_, frame_data->resource_list); - - // Remap resource ids in the current frame's quads to the parent's namespace. - bool invalid_frame = false; - DrawQuad::ResourceIteratorCallback remap_callback = base::Bind( - &ResourceRemapHelper, - &invalid_frame, - resource_provider->getChildToParentMap(child_id_), - &new_resources); - for (size_t i = 0; i < frame_data->render_pass_list.size(); ++i) { - RenderPass* pass = frame_data->render_pass_list[i]; - for (size_t j = 0; j < pass->quad_list.size(); ++j) { - DrawQuad* quad = pass->quad_list[j]; - quad->IterateResources(remap_callback); + const ResourceProvider::ResourceIdMap& resource_map = + resource_provider->getChildToParentMap(child_id_); + + if (frame_data) { + // A frame with an empty root render pass is invalid. + DCHECK(frame_data->render_pass_list.empty() || + !frame_data->render_pass_list.back()->output_rect.IsEmpty()); + + // Display size is already set so we can compute what the damage rect + // will be in layer space. + if (!frame_data->render_pass_list.empty()) { + RenderPass* new_root_pass = frame_data->render_pass_list.back(); + gfx::RectF damage_in_layer = MathUtil::mapClippedRect( + DelegatedFrameToLayerSpaceTransform( + new_root_pass->output_rect.size()), + damage_in_frame); + setUpdateRect(gfx::UnionRects(updateRect(), damage_in_layer)); } - } - - // If the frame has invalid data in it, don't display it. - if (invalid_frame) { - // Keep the resources given to us this frame. - for (ResourceProvider::ResourceIdSet::iterator it = new_resources.begin(); - it != new_resources.end(); - ++it) - resources_.insert(*it); - return; - } - // Save the resources that this layer owns now. - ResourceProvider::ResourceIdSet previous_frame_resources; - previous_frame_resources.swap(resources_); - resources_.swap(new_resources); + resource_provider->receiveFromChild(child_id_, frame_data->resource_list); + + bool invalid_frame = false; + ResourceProvider::ResourceIdSet used_resources; + DrawQuad::ResourceIteratorCallback remap_resources_to_parent_callback = + base::Bind(&ResourceRemapHelper, + &invalid_frame, + resource_map, + &used_resources); + for (size_t i = 0; i < frame_data->render_pass_list.size(); ++i) { + RenderPass* pass = frame_data->render_pass_list[i]; + for (size_t j = 0; j < pass->quad_list.size(); ++j) { + DrawQuad* quad = pass->quad_list[j]; + quad->IterateResources(remap_resources_to_parent_callback); + } + } - // Save the remapped quads on the layer. This steals the quads and render - // passes from the frame_data. - SetRenderPasses(&frame_data->render_pass_list); + if (!invalid_frame) { + // Save the remapped quads on the layer. This steals the quads and render + // passes from the frame_data. + SetRenderPasses(&frame_data->render_pass_list); + resources_.swap(used_resources); + } + } - // Release the resources from the previous frame to prepare them for transport - // back to the child compositor. ResourceProvider::ResourceIdArray unused_resources; - for (ResourceProvider::ResourceIdSet::iterator it = - previous_frame_resources.begin(); - it != previous_frame_resources.end(); + for (ResourceProvider::ResourceIdMap::const_iterator it = + resource_map.begin(); + it != resource_map.end(); ++it) { - bool resource_is_not_in_current_frame = - resources_.find(*it) == resources_.end(); - if (resource_is_not_in_current_frame) - unused_resources.push_back(*it); + bool resource_is_in_current_frame = resources_.count(it->second); + bool resource_is_in_use = resource_provider->inUseByConsumer(it->second); + if (!resource_is_in_current_frame && !resource_is_in_use) + unused_resources.push_back(it->second); } resource_provider->prepareSendToChild( child_id_, unused_resources, resources_for_ack); diff --git a/cc/layer_tree_host_unittest_delegated.cc b/cc/layer_tree_host_unittest_delegated.cc index 098a941..df90a13 100644 --- a/cc/layer_tree_host_unittest_delegated.cc +++ b/cc/layer_tree_host_unittest_delegated.cc @@ -364,7 +364,6 @@ class LayerTreeHostDelegatedTestMergeResources EXPECT_EQ(1u, map.count(999)); EXPECT_EQ(1u, map.count(555)); - // Both frames' resources should be saved on the layer. EXPECT_EQ(2u, delegated_impl->Resources().size()); EXPECT_EQ(1u, delegated_impl->Resources().count(map.find(999)->second)); EXPECT_EQ(1u, delegated_impl->Resources().count(map.find(555)->second)); @@ -704,20 +703,11 @@ class LayerTreeHostDelegatedTestFrameBeforeTakeResources AddTextureQuad(frame.get(), 444); delegated_->SetFrameData(frame.Pass()); - // When we take resources, it should have the resources that were - // released during the last valid frame committed. + // The resources are used by the new frame so are not returned. delegated_->TakeUnusedResourcesForChildCompositor(&resources); - EXPECT_EQ(2u, resources.size()); - if (resources[0].id == 555) { - EXPECT_EQ(555, resources[0].id); - EXPECT_EQ(444, resources[1].id); - } else { - EXPECT_EQ(444, resources[0].id); - EXPECT_EQ(555, resources[1].id); - } + EXPECT_EQ(0u, resources.size()); break; case 4: - // The invalid frame doesn't cause anything to be released. delegated_->TakeUnusedResourcesForChildCompositor(&resources); EXPECT_EQ(0u, resources.size()); endTest(); @@ -737,20 +727,29 @@ class LayerTreeHostDelegatedTestFrameBeforeTakeResources host_impl->resourceProvider()->getChildToParentMap( delegated_impl->ChildId()); - // The bad frame should be dropped. So we should only have one quad (the - // one with resource 999) on the impl tree. And only 999 will be present - // in the parent's resource provider. - EXPECT_EQ(1u, map.size()); + // The third frame has all of the resources in it again, the delegated + // renderer layer should continue to own the resources for it. + EXPECT_EQ(3u, map.size()); EXPECT_EQ(1u, map.count(999)); + EXPECT_EQ(1u, map.count(555)); + EXPECT_EQ(1u, map.count(444)); - EXPECT_EQ(1u, delegated_impl->Resources().size()); + EXPECT_EQ(3u, delegated_impl->Resources().size()); EXPECT_EQ(1u, delegated_impl->Resources().count(map.find(999)->second)); + EXPECT_EQ(1u, delegated_impl->Resources().count(map.find(555)->second)); + EXPECT_EQ(1u, delegated_impl->Resources().count(map.find(444)->second)); const RenderPass* pass = delegated_impl->RenderPassesInDrawOrder()[0]; - EXPECT_EQ(1u, pass->quad_list.size()); - const TextureDrawQuad* quad = TextureDrawQuad::MaterialCast( + EXPECT_EQ(3u, pass->quad_list.size()); + const TextureDrawQuad* quad1 = TextureDrawQuad::MaterialCast( pass->quad_list[0]); - EXPECT_EQ(map.find(999)->second, quad->resource_id); + EXPECT_EQ(map.find(999)->second, quad1->resource_id); + const TextureDrawQuad* quad2 = TextureDrawQuad::MaterialCast( + pass->quad_list[1]); + EXPECT_EQ(map.find(555)->second, quad2->resource_id); + const TextureDrawQuad* quad3 = TextureDrawQuad::MaterialCast( + pass->quad_list[2]); + EXPECT_EQ(map.find(444)->second, quad3->resource_id); } virtual void afterTest() OVERRIDE {} @@ -801,10 +800,10 @@ class LayerTreeHostDelegatedTestBadFrame // The parent compositor (this one) does a commit. break; case 3: - // The bad frame does not cause resources to be released, and the - // resources given in it are held onto. + // The bad frame's resource is given back to the child compositor. delegated_->TakeUnusedResourcesForChildCompositor(&resources); - EXPECT_EQ(0u, resources.size()); + EXPECT_EQ(1u, resources.size()); + EXPECT_EQ(444, resources[0].id); // Now send a good frame with 999 again. frame = CreateFrameData(gfx::Rect(0, 0, 1, 1), gfx::Rect(0, 0, 1, 1)); @@ -812,17 +811,10 @@ class LayerTreeHostDelegatedTestBadFrame delegated_->SetFrameData(frame.Pass()); break; case 4: - // The unused 444 resource from the bad frame will be released along - // with the unused 555. + // The unused 555 from the last good frame is now released. delegated_->TakeUnusedResourcesForChildCompositor(&resources); - EXPECT_EQ(2u, resources.size()); - if (resources[0].id == 555) { - EXPECT_EQ(555, resources[0].id); - EXPECT_EQ(444, resources[1].id); - } else { - EXPECT_EQ(444, resources[0].id); - EXPECT_EQ(555, resources[1].id); - } + EXPECT_EQ(1u, resources.size()); + EXPECT_EQ(555, resources[0].id); endTest(); break; @@ -864,17 +856,14 @@ class LayerTreeHostDelegatedTestBadFrame break; } case 2: { - // We have all resources whose ownership has been given to the delegated - // layer. - EXPECT_EQ(3u, map.size()); + // We only keep resources from the last valid frame. + EXPECT_EQ(2u, map.size()); EXPECT_EQ(1u, map.count(999)); EXPECT_EQ(1u, map.count(555)); - EXPECT_EQ(1u, map.count(444)); - EXPECT_EQ(3u, delegated_impl->Resources().size()); + EXPECT_EQ(2u, delegated_impl->Resources().size()); EXPECT_EQ(1u, delegated_impl->Resources().count(map.find(999)->second)); EXPECT_EQ(1u, delegated_impl->Resources().count(map.find(555)->second)); - EXPECT_EQ(1u, delegated_impl->Resources().count(map.find(444)->second)); // The bad frame is dropped though, we still have the frame with 999 and // 555 in it. @@ -911,5 +900,339 @@ class LayerTreeHostDelegatedTestBadFrame SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostDelegatedTestBadFrame) +class LayerTreeHostDelegatedTestUnnamedResource + : public LayerTreeHostDelegatedTestCaseSingleDelegatedLayer { + public: + virtual void beginTest() OVERRIDE { + postSetNeedsCommitToMainThread(); + } + + virtual void didCommit() OVERRIDE { + scoped_ptr<DelegatedFrameData> frame; + TransferableResourceArray resources; + + int next_source_frame_number = m_layerTreeHost->commitNumber(); + switch (next_source_frame_number) { + case 1: + // This frame includes two resources in it, but only uses one. + frame = CreateFrameData(gfx::Rect(0, 0, 1, 1), gfx::Rect(0, 0, 1, 1)); + AddTransferableResource(frame.get(), 999); + AddTextureQuad(frame.get(), 555); + AddTransferableResource(frame.get(), 555); + delegated_->SetFrameData(frame.Pass()); + break; + case 2: + // The unused resource should be returned. + delegated_->TakeUnusedResourcesForChildCompositor(&resources); + EXPECT_EQ(1u, resources.size()); + EXPECT_EQ(999, resources[0].id); + + endTest(); + break; + } + } + + virtual void treeActivatedOnThread(LayerTreeHostImpl* host_impl) OVERRIDE { + if (host_impl->activeTree()->source_frame_number() != 1) + return; + + LayerImpl* root_impl = host_impl->activeTree()->RootLayer(); + FakeDelegatedRendererLayerImpl* delegated_impl = + static_cast<FakeDelegatedRendererLayerImpl*>(root_impl->children()[0]); + + const ResourceProvider::ResourceIdMap& map = + host_impl->resourceProvider()->getChildToParentMap( + delegated_impl->ChildId()); + + // The layer only held on to the resource that was used. + EXPECT_EQ(1u, map.size()); + EXPECT_EQ(1u, map.count(555)); + + EXPECT_EQ(1u, delegated_impl->Resources().size()); + EXPECT_EQ(1u, delegated_impl->Resources().count(map.find(555)->second)); + } + + virtual void afterTest() OVERRIDE {} +}; + +SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostDelegatedTestUnnamedResource) + +class LayerTreeHostDelegatedTestDontLeakResource + : public LayerTreeHostDelegatedTestCaseSingleDelegatedLayer { + public: + virtual void beginTest() OVERRIDE { + postSetNeedsCommitToMainThread(); + } + + virtual void didCommit() OVERRIDE { + scoped_ptr<DelegatedFrameData> frame; + TransferableResourceArray resources; + + int next_source_frame_number = m_layerTreeHost->commitNumber(); + switch (next_source_frame_number) { + case 1: + // This frame includes two resources in it. + frame = CreateFrameData(gfx::Rect(0, 0, 1, 1), gfx::Rect(0, 0, 1, 1)); + AddTextureQuad(frame.get(), 999); + AddTransferableResource(frame.get(), 999); + AddTextureQuad(frame.get(), 555); + AddTransferableResource(frame.get(), 555); + delegated_->SetFrameData(frame.Pass()); + + // But then we immediately stop using 999. + frame = CreateFrameData(gfx::Rect(0, 0, 1, 1), gfx::Rect(0, 0, 1, 1)); + AddTextureQuad(frame.get(), 555); + delegated_->SetFrameData(frame.Pass()); + break; + case 2: + // The unused resource should be returned. + delegated_->TakeUnusedResourcesForChildCompositor(&resources); + EXPECT_EQ(1u, resources.size()); + EXPECT_EQ(999, resources[0].id); + + endTest(); + break; + } + } + + virtual void treeActivatedOnThread(LayerTreeHostImpl* host_impl) OVERRIDE { + if (host_impl->activeTree()->source_frame_number() != 1) + return; + + LayerImpl* root_impl = host_impl->activeTree()->RootLayer(); + FakeDelegatedRendererLayerImpl* delegated_impl = + static_cast<FakeDelegatedRendererLayerImpl*>(root_impl->children()[0]); + + const ResourceProvider::ResourceIdMap& map = + host_impl->resourceProvider()->getChildToParentMap( + delegated_impl->ChildId()); + + // The layer only held on to the resource that was used. + EXPECT_EQ(1u, map.size()); + EXPECT_EQ(1u, map.count(555)); + + EXPECT_EQ(1u, delegated_impl->Resources().size()); + EXPECT_EQ(1u, delegated_impl->Resources().count(map.find(555)->second)); + } + + virtual void afterTest() OVERRIDE {} +}; + +SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostDelegatedTestDontLeakResource) + +class LayerTreeHostDelegatedTestResourceSentToParent + : public LayerTreeHostDelegatedTestCaseSingleDelegatedLayer { + public: + virtual void beginTest() OVERRIDE { + // Prevent drawing with resources that are sent to the grandparent. + m_layerTreeHost->setViewportSize(gfx::Size(10, 10), gfx::Size()); + postSetNeedsCommitToMainThread(); + } + + virtual void didCommit() OVERRIDE { + scoped_ptr<DelegatedFrameData> frame; + TransferableResourceArray resources; + + int next_source_frame_number = m_layerTreeHost->commitNumber(); + switch (next_source_frame_number) { + case 1: + // This frame includes two resources in it. + frame = CreateFrameData(gfx::Rect(0, 0, 1, 1), gfx::Rect(0, 0, 1, 1)); + AddTextureQuad(frame.get(), 999); + AddTransferableResource(frame.get(), 999); + AddTextureQuad(frame.get(), 555); + AddTransferableResource(frame.get(), 555); + delegated_->SetFrameData(frame.Pass()); + break; + case 2: + delegated_->TakeUnusedResourcesForChildCompositor(&resources); + EXPECT_EQ(0u, resources.size()); + + // 999 is in use in the grandparent compositor, generate a frame without + // it present. + frame = CreateFrameData(gfx::Rect(0, 0, 1, 1), gfx::Rect(0, 0, 1, 1)); + AddTextureQuad(frame.get(), 555); + delegated_->SetFrameData(frame.Pass()); + break; + case 3: + // Since 999 is in the grandparent it is not returned. + delegated_->TakeUnusedResourcesForChildCompositor(&resources); + EXPECT_EQ(0u, resources.size()); + + m_layerTreeHost->setNeedsCommit(); + break; + case 4: + // 999 was returned from the grandparent and could be released. + delegated_->TakeUnusedResourcesForChildCompositor(&resources); + EXPECT_EQ(1u, resources.size()); + EXPECT_EQ(999, resources[0].id); + + endTest(); + break; + } + } + + virtual void treeActivatedOnThread(LayerTreeHostImpl* host_impl) OVERRIDE { + if (host_impl->activeTree()->source_frame_number() < 1) + return; + + LayerImpl* root_impl = host_impl->activeTree()->RootLayer(); + FakeDelegatedRendererLayerImpl* delegated_impl = + static_cast<FakeDelegatedRendererLayerImpl*>(root_impl->children()[0]); + + const ResourceProvider::ResourceIdMap& map = + host_impl->resourceProvider()->getChildToParentMap( + delegated_impl->ChildId()); + + switch (host_impl->activeTree()->source_frame_number()) { + case 1: { + EXPECT_EQ(2u, map.size()); + EXPECT_EQ(1u, map.count(999)); + EXPECT_EQ(1u, map.count(555)); + + EXPECT_EQ(2u, delegated_impl->Resources().size()); + EXPECT_EQ(1u, delegated_impl->Resources().count(map.find(999)->second)); + EXPECT_EQ(1u, delegated_impl->Resources().count(map.find(555)->second)); + + // The 999 resource is sent to a grandparent compositor. + ResourceProvider::ResourceIdArray resources_for_parent; + resources_for_parent.push_back(map.find(999)->second); + TransferableResourceArray transferable_resources; + host_impl->resourceProvider()->prepareSendToParent( + resources_for_parent, &transferable_resources); + break; + } + case 2: { + EXPECT_EQ(2u, map.size()); + EXPECT_EQ(1u, map.count(999)); + EXPECT_EQ(1u, map.count(555)); + + /// 999 is in the parent, so not held by delegated renderer layer. + EXPECT_EQ(1u, delegated_impl->Resources().size()); + EXPECT_EQ(1u, delegated_impl->Resources().count(map.find(555)->second)); + + // Receive 999 back from the grandparent. + TransferableResource resource; + resource.id = map.find(999)->second; + TransferableResourceArray transferable_resources; + transferable_resources.push_back(resource); + host_impl->resourceProvider()->receiveFromParent( + transferable_resources); + break; + } + case 3: + // 999 should be released. + EXPECT_EQ(1u, map.size()); + EXPECT_EQ(1u, map.count(555)); + + EXPECT_EQ(1u, delegated_impl->Resources().size()); + EXPECT_EQ(1u, delegated_impl->Resources().count(map.find(555)->second)); + } + } + + virtual void afterTest() OVERRIDE {} +}; + +SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostDelegatedTestResourceSentToParent) + +class LayerTreeHostDelegatedTestCommitWithoutTake + : public LayerTreeHostDelegatedTestCaseSingleDelegatedLayer { + public: + virtual void beginTest() OVERRIDE { + // Prevent drawing with resources that are sent to the grandparent. + m_layerTreeHost->setViewportSize(gfx::Size(10, 10), gfx::Size()); + postSetNeedsCommitToMainThread(); + } + + virtual void didCommit() OVERRIDE { + scoped_ptr<DelegatedFrameData> frame; + TransferableResourceArray resources; + + int next_source_frame_number = m_layerTreeHost->commitNumber(); + switch (next_source_frame_number) { + case 1: + frame = CreateFrameData(gfx::Rect(0, 0, 1, 1), gfx::Rect(0, 0, 1, 1)); + AddTextureQuad(frame.get(), 999); + AddTransferableResource(frame.get(), 999); + AddTextureQuad(frame.get(), 555); + AddTransferableResource(frame.get(), 555); + AddTextureQuad(frame.get(), 444); + AddTransferableResource(frame.get(), 444); + delegated_->SetFrameData(frame.Pass()); + break; + case 2: + delegated_->TakeUnusedResourcesForChildCompositor(&resources); + EXPECT_EQ(0u, resources.size()); + + // Stop using 999 and 444 in this frame and commit. + frame = CreateFrameData(gfx::Rect(0, 0, 1, 1), gfx::Rect(0, 0, 1, 1)); + AddTextureQuad(frame.get(), 555); + delegated_->SetFrameData(frame.Pass()); + break; + case 3: + // Don't take resources here, but set a new frame that uses 999 again. + frame = CreateFrameData(gfx::Rect(0, 0, 1, 1), gfx::Rect(0, 0, 1, 1)); + AddTextureQuad(frame.get(), 999); + AddTextureQuad(frame.get(), 555); + delegated_->SetFrameData(frame.Pass()); + break; + case 4: + // 999 and 555 are in use, but 444 should be returned now. + delegated_->TakeUnusedResourcesForChildCompositor(&resources); + EXPECT_EQ(1u, resources.size()); + EXPECT_EQ(444, resources[0].id); + + endTest(); + break; + } + } + + virtual void treeActivatedOnThread(LayerTreeHostImpl* host_impl) OVERRIDE { + if (host_impl->activeTree()->source_frame_number() < 1) + return; + + LayerImpl* root_impl = host_impl->activeTree()->RootLayer(); + FakeDelegatedRendererLayerImpl* delegated_impl = + static_cast<FakeDelegatedRendererLayerImpl*>(root_impl->children()[0]); + + const ResourceProvider::ResourceIdMap& map = + host_impl->resourceProvider()->getChildToParentMap( + delegated_impl->ChildId()); + + switch (host_impl->activeTree()->source_frame_number()) { + case 1: + EXPECT_EQ(3u, map.size()); + EXPECT_EQ(1u, map.count(999)); + EXPECT_EQ(1u, map.count(555)); + EXPECT_EQ(1u, map.count(444)); + + EXPECT_EQ(3u, delegated_impl->Resources().size()); + EXPECT_EQ(1u, delegated_impl->Resources().count(map.find(999)->second)); + EXPECT_EQ(1u, delegated_impl->Resources().count(map.find(555)->second)); + EXPECT_EQ(1u, delegated_impl->Resources().count(map.find(444)->second)); + break; + case 2: + EXPECT_EQ(1u, map.size()); + EXPECT_EQ(1u, map.count(555)); + + EXPECT_EQ(1u, delegated_impl->Resources().size()); + EXPECT_EQ(1u, delegated_impl->Resources().count(map.find(555)->second)); + break; + case 3: + EXPECT_EQ(2u, map.size()); + EXPECT_EQ(1u, map.count(999)); + EXPECT_EQ(1u, map.count(555)); + + EXPECT_EQ(2u, delegated_impl->Resources().size()); + EXPECT_EQ(1u, delegated_impl->Resources().count(map.find(999)->second)); + EXPECT_EQ(1u, delegated_impl->Resources().count(map.find(555)->second)); + } + } + + virtual void afterTest() OVERRIDE {} +}; + +SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostDelegatedTestCommitWithoutTake) + } // namespace } // namespace cc |