diff options
Diffstat (limited to 'chromium/cc/trees/layer_tree_host_unittest_delegated.cc')
-rw-r--r-- | chromium/cc/trees/layer_tree_host_unittest_delegated.cc | 712 |
1 files changed, 543 insertions, 169 deletions
diff --git a/chromium/cc/trees/layer_tree_host_unittest_delegated.cc b/chromium/cc/trees/layer_tree_host_unittest_delegated.cc index d48931328af..012f6f82fdf 100644 --- a/chromium/cc/trees/layer_tree_host_unittest_delegated.cc +++ b/chromium/cc/trees/layer_tree_host_unittest_delegated.cc @@ -4,25 +4,73 @@ #include "cc/trees/layer_tree_host.h" +#include <algorithm> + #include "base/bind.h" +#include "base/location.h" +#include "base/synchronization/waitable_event.h" +#include "base/threading/thread.h" +#include "base/time/time.h" #include "cc/layers/delegated_renderer_layer.h" #include "cc/layers/delegated_renderer_layer_client.h" #include "cc/layers/delegated_renderer_layer_impl.h" #include "cc/output/compositor_frame.h" #include "cc/output/compositor_frame_ack.h" #include "cc/output/delegated_frame_data.h" +#include "cc/quads/render_pass_draw_quad.h" #include "cc/quads/shared_quad_state.h" #include "cc/quads/texture_draw_quad.h" +#include "cc/resources/returned_resource.h" #include "cc/test/fake_delegated_renderer_layer.h" #include "cc/test/fake_delegated_renderer_layer_impl.h" #include "cc/test/fake_output_surface.h" #include "cc/test/layer_tree_test.h" #include "cc/trees/layer_tree_impl.h" #include "gpu/GLES2/gl2extchromium.h" +#include "third_party/WebKit/public/platform/WebGraphicsContext3D.h" namespace cc { namespace { +bool ReturnedResourceLower(const ReturnedResource& a, + const ReturnedResource& b) { + return a.id < b.id; +} + +// Tests if the list of resources matches an expectation, modulo the order. +bool ResourcesMatch(ReturnedResourceArray actual, + unsigned* expected, + size_t expected_count) { + std::sort(actual.begin(), actual.end(), ReturnedResourceLower); + std::sort(expected, expected + expected_count); + size_t actual_index = 0; + + // for each element of the expected array, count off one of the actual array + // (after checking it matches). + for (size_t expected_index = 0; expected_index < expected_count; + ++expected_index) { + EXPECT_LT(actual_index, actual.size()); + if (actual_index >= actual.size()) + return false; + EXPECT_EQ(actual[actual_index].id, expected[expected_index]); + if (actual[actual_index].id != expected[expected_index]) + return false; + EXPECT_GT(actual[actual_index].count, 0); + if (actual[actual_index].count <= 0) { + return false; + } else { + --actual[actual_index].count; + if (actual[actual_index].count == 0) + ++actual_index; + } + } + EXPECT_EQ(actual_index, actual.size()); + return actual_index == actual.size(); +} + +#define EXPECT_RESOURCES(expected, actual) \ + EXPECT_TRUE(ResourcesMatch(actual, expected, arraysize(expected))); + // These tests deal with delegated renderer layers. class LayerTreeHostDelegatedTest : public LayerTreeTest { protected: @@ -108,6 +156,39 @@ class LayerTreeHostDelegatedTest : public LayerTreeTest { frame->render_pass_list[0]->quad_list.push_back(quad.PassAs<DrawQuad>()); } + void AddRenderPass(DelegatedFrameData* frame, + RenderPass::Id id, + gfx::Rect output_rect, + gfx::Rect damage_rect, + const FilterOperations& filters, + const FilterOperations& background_filters) { + for (size_t i = 0; i < frame->render_pass_list.size(); ++i) + DCHECK(id != frame->render_pass_list[i]->id); + + scoped_ptr<RenderPass> pass(RenderPass::Create()); + pass->SetNew(id, + output_rect, + damage_rect, + gfx::Transform()); + frame->render_pass_list.push_back(pass.Pass()); + + scoped_ptr<SharedQuadState> sqs = SharedQuadState::Create(); + scoped_ptr<RenderPassDrawQuad> quad = RenderPassDrawQuad::Create(); + + quad->SetNew(sqs.get(), + output_rect, + id, + false, // is_replica + 0, // mask_resource_id + damage_rect, + gfx::Rect(0, 0, 1, 1), // mask_uv_rect + filters, + skia::RefPtr<SkImageFilter>(), + background_filters); + frame->render_pass_list[0]->shared_quad_state_list.push_back(sqs.Pass()); + frame->render_pass_list[0]->quad_list.push_back(quad.PassAs<DrawQuad>()); + } + scoped_ptr<DelegatedFrameData> CreateEmptyFrameData() { scoped_ptr<DelegatedFrameData> frame(new DelegatedFrameData); return frame.Pass(); @@ -158,7 +239,8 @@ class LayerTreeHostDelegatedTest : public LayerTreeTest { CompositorFrameAck ack; for (size_t i = 0; i < resources_to_return.size(); ++i) output_surface()->ReturnResource(resources_to_return[i], &ack); - host_impl->OnSwapBuffersComplete(&ack); + host_impl->ReclaimResources(&ack); + host_impl->OnSwapBuffersComplete(); } }; @@ -246,8 +328,8 @@ class LayerTreeHostDelegatedTestCreateChildId FakeDelegatedRendererLayerImpl* delegated_impl = static_cast<FakeDelegatedRendererLayerImpl*>(root_impl->children()[0]); - WebKit::WebGraphicsContext3D* context = - host_impl->resource_provider()->GraphicsContext3D(); + ContextProvider* context_provider = + host_impl->output_surface()->context_provider(); ++num_activates_; switch (num_activates_) { @@ -255,8 +337,9 @@ class LayerTreeHostDelegatedTestCreateChildId EXPECT_TRUE(delegated_impl->ChildId()); EXPECT_FALSE(did_reset_child_id_); - context->loseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB, - GL_INNOCENT_CONTEXT_RESET_ARB); + context_provider->Context3d()->loseContextCHROMIUM( + GL_GUILTY_CONTEXT_RESET_ARB, + GL_INNOCENT_CONTEXT_RESET_ARB); break; case 3: EXPECT_TRUE(delegated_impl->ChildId()); @@ -291,6 +374,131 @@ class LayerTreeHostDelegatedTestCreateChildId SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostDelegatedTestCreateChildId); +class LayerTreeHostDelegatedTestOffscreenContext_NoFilters + : public LayerTreeHostDelegatedTestCaseSingleDelegatedLayer { + protected: + virtual void BeginTest() OVERRIDE { + scoped_ptr<DelegatedFrameData> frame = + CreateFrameData(gfx::Rect(0, 0, 1, 1), + gfx::Rect(0, 0, 1, 1)); + delegated_->SetFrameData(frame.Pass()); + + PostSetNeedsCommitToMainThread(); + } + + virtual void DrawLayersOnThread(LayerTreeHostImpl* host_impl) OVERRIDE { + EXPECT_FALSE(host_impl->offscreen_context_provider()); + EndTest(); + } + + virtual void AfterTest() OVERRIDE {} +}; + +SINGLE_AND_MULTI_THREAD_TEST_F( + LayerTreeHostDelegatedTestOffscreenContext_NoFilters); + +class LayerTreeHostDelegatedTestOffscreenContext_Filters + : public LayerTreeHostDelegatedTestCaseSingleDelegatedLayer { + protected: + virtual void BeginTest() OVERRIDE { + scoped_ptr<DelegatedFrameData> frame = + CreateFrameData(gfx::Rect(0, 0, 1, 1), + gfx::Rect(0, 0, 1, 1)); + + FilterOperations filters; + filters.Append(FilterOperation::CreateGrayscaleFilter(0.5f)); + AddRenderPass(frame.get(), + RenderPass::Id(2, 1), + gfx::Rect(0, 0, 1, 1), + gfx::Rect(0, 0, 1, 1), + filters, + FilterOperations()); + delegated_->SetFrameData(frame.Pass()); + + PostSetNeedsCommitToMainThread(); + } + + virtual void DrawLayersOnThread(LayerTreeHostImpl* host_impl) OVERRIDE { + bool expect_context = !delegating_renderer(); + EXPECT_EQ(expect_context, !!host_impl->offscreen_context_provider()); + EndTest(); + } + + virtual void AfterTest() OVERRIDE {} +}; + +SINGLE_AND_MULTI_THREAD_TEST_F( + LayerTreeHostDelegatedTestOffscreenContext_Filters); + +class LayerTreeHostDelegatedTestOffscreenContext_BackgroundFilters + : public LayerTreeHostDelegatedTestCaseSingleDelegatedLayer { + protected: + virtual void BeginTest() OVERRIDE { + scoped_ptr<DelegatedFrameData> frame = + CreateFrameData(gfx::Rect(0, 0, 1, 1), + gfx::Rect(0, 0, 1, 1)); + + FilterOperations filters; + filters.Append(FilterOperation::CreateGrayscaleFilter(0.5f)); + AddRenderPass(frame.get(), + RenderPass::Id(2, 1), + gfx::Rect(0, 0, 1, 1), + gfx::Rect(0, 0, 1, 1), + FilterOperations(), + filters); + delegated_->SetFrameData(frame.Pass()); + + PostSetNeedsCommitToMainThread(); + } + + virtual void DrawLayersOnThread(LayerTreeHostImpl* host_impl) OVERRIDE { + bool expect_context = !delegating_renderer(); + EXPECT_EQ(expect_context, !!host_impl->offscreen_context_provider()); + EndTest(); + } + + virtual void AfterTest() OVERRIDE {} +}; + +SINGLE_AND_MULTI_THREAD_TEST_F( + LayerTreeHostDelegatedTestOffscreenContext_BackgroundFilters); + +class LayerTreeHostDelegatedTestOffscreenContext_Filters_AddedToTree + : public LayerTreeHostDelegatedTestCaseSingleDelegatedLayer { + protected: + virtual void BeginTest() OVERRIDE { + scoped_ptr<DelegatedFrameData> frame = + CreateFrameData(gfx::Rect(0, 0, 1, 1), + gfx::Rect(0, 0, 1, 1)); + + FilterOperations filters; + filters.Append(FilterOperation::CreateGrayscaleFilter(0.5f)); + AddRenderPass(frame.get(), + RenderPass::Id(2, 1), + gfx::Rect(0, 0, 1, 1), + gfx::Rect(0, 0, 1, 1), + filters, + FilterOperations()); + + delegated_->RemoveFromParent(); + delegated_->SetFrameData(frame.Pass()); + layer_tree_host()->root_layer()->AddChild(delegated_); + + PostSetNeedsCommitToMainThread(); + } + + virtual void DrawLayersOnThread(LayerTreeHostImpl* host_impl) OVERRIDE { + bool expect_context = !delegating_renderer(); + EXPECT_EQ(expect_context, !!host_impl->offscreen_context_provider()); + EndTest(); + } + + virtual void AfterTest() OVERRIDE {} +}; + +SINGLE_AND_MULTI_THREAD_TEST_F( + LayerTreeHostDelegatedTestOffscreenContext_Filters_AddedToTree); + class LayerTreeHostDelegatedTestLayerUsesFrameDamage : public LayerTreeHostDelegatedTestCaseSingleDelegatedLayer { public: @@ -377,6 +585,28 @@ class LayerTreeHostDelegatedTestLayerUsesFrameDamage // Should create zero damage. layer_tree_host()->SetNeedsCommit(); break; + case 16: + // Moving the layer out of the tree and back in will damage the whole + // impl layer. + delegated_->RemoveFromParent(); + layer_tree_host()->root_layer()->AddChild(delegated_); + break; + case 17: + // Make a larger frame with lots of damage. Then a frame smaller than + // the first frame's damage. The entire layer should be damaged, but + // nothing more. + delegated_->SetFrameData(CreateFrameData(gfx::Rect(0, 0, 10, 10), + gfx::Rect(0, 0, 10, 10))); + delegated_->SetFrameData(CreateFrameData(gfx::Rect(0, 0, 5, 5), + gfx::Rect(1, 1, 2, 2))); + break; + case 18: + // Make a frame with lots of damage. Then replace it with an empty + // frame. The entire layer should be damaged, but nothing more. + delegated_->SetFrameData(CreateFrameData(gfx::Rect(0, 0, 10, 10), + gfx::Rect(0, 0, 10, 10))); + delegated_->SetFrameData(CreateEmptyFrameData()); + break; } first_draw_for_source_frame_ = true; } @@ -462,6 +692,18 @@ class LayerTreeHostDelegatedTestLayerUsesFrameDamage case 15: EXPECT_EQ(gfx::RectF(0.f, 0.f, 0.f, 0.f).ToString(), damage_rect.ToString()); + break; + case 16: + EXPECT_EQ(gfx::RectF(0.f, 0.f, 6.f, 6.f).ToString(), + damage_rect.ToString()); + break; + case 17: + EXPECT_EQ(gfx::RectF(0.f, 0.f, 6.f, 6.f).ToString(), + damage_rect.ToString()); + break; + case 18: + EXPECT_EQ(gfx::RectF(0.f, 0.f, 6.f, 6.f).ToString(), + damage_rect.ToString()); EndTest(); break; } @@ -492,10 +734,20 @@ class LayerTreeHostDelegatedTestMergeResources scoped_ptr<DelegatedFrameData> frame2 = CreateFrameData(gfx::Rect(0, 0, 1, 1), gfx::Rect(0, 0, 1, 1)); AddTextureQuad(frame2.get(), 999); + AddTransferableResource(frame2.get(), 999); AddTextureQuad(frame2.get(), 555); AddTransferableResource(frame2.get(), 555); delegated_->SetFrameData(frame2.Pass()); + // The resource 999 from frame1 is returned since it is still on the main + // thread. + ReturnedResourceArray returned_resources; + delegated_->TakeUnusedResourcesForChildCompositor(&returned_resources); + { + unsigned expected[] = {999}; + EXPECT_RESOURCES(expected, returned_resources); + } + PostSetNeedsCommitToMainThread(); } @@ -514,8 +766,8 @@ class LayerTreeHostDelegatedTestMergeResources 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)); + EXPECT_EQ(1u, delegated_impl->Resources().count(999)); + EXPECT_EQ(1u, delegated_impl->Resources().count(555)); EndTest(); } @@ -585,7 +837,7 @@ class LayerTreeHostDelegatedTestReturnUnusedResources virtual void DidCommitAndDrawFrame() OVERRIDE { scoped_ptr<DelegatedFrameData> frame; - TransferableResourceArray resources; + ReturnedResourceArray resources; int next_source_frame_number = layer_tree_host()->source_frame_number(); switch (next_source_frame_number) { @@ -599,11 +851,6 @@ class LayerTreeHostDelegatedTestReturnUnusedResources delegated_->SetFrameData(frame.Pass()); break; case 2: - // Retrieve unused resources to the main thread. - // TODO(danakj): Shouldn't need to commit to get resources. - layer_tree_host()->SetNeedsCommit(); - return; - case 3: // All of the resources are in use. delegated_->TakeUnusedResourcesForChildCompositor(&resources); EXPECT_EQ(0u, resources.size()); @@ -611,47 +858,42 @@ class LayerTreeHostDelegatedTestReturnUnusedResources // Keep using 999 but stop using 555. 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(), 444); AddTransferableResource(frame.get(), 444); delegated_->SetFrameData(frame.Pass()); break; - case 4: - // Retrieve unused resources to the main thread. - // TODO(danakj): Shouldn't need to commit to get resources. - layer_tree_host()->SetNeedsCommit(); - return; - case 5: + case 3: // 555 is no longer in use. delegated_->TakeUnusedResourcesForChildCompositor(&resources); - EXPECT_EQ(1u, resources.size()); - EXPECT_EQ(555u, resources[0].id); + { + unsigned expected[] = {555}; + EXPECT_RESOURCES(expected, resources); + } // Stop using any resources. frame = CreateFrameData(gfx::Rect(0, 0, 1, 1), gfx::Rect(0, 0, 1, 1)); delegated_->SetFrameData(frame.Pass()); break; - case 6: + case 4: // Postpone collecting resources for a frame. They should still be there // the next frame. layer_tree_host()->SetNeedsCommit(); return; - case 7: - // 444 and 999 are no longer in use. + case 5: + // 444 and 999 are no longer in use. We sent two refs to 999, so we + // should get two back. delegated_->TakeUnusedResourcesForChildCompositor(&resources); - EXPECT_EQ(2u, resources.size()); - if (resources[0].id == 999) { - EXPECT_EQ(999u, resources[0].id); - EXPECT_EQ(444u, resources[1].id); - } else { - EXPECT_EQ(444u, resources[0].id); - EXPECT_EQ(999u, resources[1].id); + { + unsigned expected[] = {444, 999, 999}; + EXPECT_RESOURCES(expected, resources); } EndTest(); break; } // Resource are never immediately released. - TransferableResourceArray empty_resources; + ReturnedResourceArray empty_resources; delegated_->TakeUnusedResourcesForChildCompositor(&empty_resources); EXPECT_TRUE(empty_resources.empty()); } @@ -676,7 +918,7 @@ class LayerTreeHostDelegatedTestReusedResources virtual void DidCommitAndDrawFrame() OVERRIDE { scoped_ptr<DelegatedFrameData> frame; - TransferableResourceArray resources; + ReturnedResourceArray resources; int next_source_frame_number = layer_tree_host()->source_frame_number(); switch (next_source_frame_number) { @@ -692,11 +934,6 @@ class LayerTreeHostDelegatedTestReusedResources delegated_->SetFrameData(frame.Pass()); break; case 2: - // Retrieve unused resources to the main thread. - // TODO(danakj): Shouldn't need to commit to get resources. - layer_tree_host()->SetNeedsCommit(); - return; - case 3: // All of the resources are in use. delegated_->TakeUnusedResourcesForChildCompositor(&resources); EXPECT_EQ(0u, resources.size()); @@ -704,6 +941,7 @@ class LayerTreeHostDelegatedTestReusedResources // Keep using 999 but stop using 555 and 444. frame = CreateFrameData(gfx::Rect(0, 0, 1, 1), gfx::Rect(0, 0, 1, 1)); AddTextureQuad(frame.get(), 999); + AddTransferableResource(frame.get(), 999); delegated_->SetFrameData(frame.Pass()); // Resource are not immediately released. @@ -713,19 +951,19 @@ class LayerTreeHostDelegatedTestReusedResources // Now using 555 and 444 again, but not 999. frame = CreateFrameData(gfx::Rect(0, 0, 1, 1), gfx::Rect(0, 0, 1, 1)); AddTextureQuad(frame.get(), 555); + AddTransferableResource(frame.get(), 555); AddTextureQuad(frame.get(), 444); + AddTransferableResource(frame.get(), 444); delegated_->SetFrameData(frame.Pass()); break; - case 4: - // Retrieve unused resources to the main thread. - // TODO(danakj): Shouldn't need to commit to get resources. - layer_tree_host()->SetNeedsCommit(); - return; - case 5: - // The 999 resource is the only unused one. + case 3: + // The 999 resource is the only unused one. Two references were sent, so + // two should be returned. delegated_->TakeUnusedResourcesForChildCompositor(&resources); - EXPECT_EQ(1u, resources.size()); - EXPECT_EQ(999u, resources[0].id); + { + unsigned expected[] = {999, 999}; + EXPECT_RESOURCES(expected, resources); + } EndTest(); break; } @@ -750,7 +988,7 @@ class LayerTreeHostDelegatedTestFrameBeforeAck virtual void DidCommitAndDrawFrame() OVERRIDE { scoped_ptr<DelegatedFrameData> frame; - TransferableResourceArray resources; + ReturnedResourceArray resources; int next_source_frame_number = layer_tree_host()->source_frame_number(); switch (next_source_frame_number) { @@ -766,11 +1004,6 @@ class LayerTreeHostDelegatedTestFrameBeforeAck delegated_->SetFrameData(frame.Pass()); break; case 2: - // Retrieve unused resources to the main thread. - // TODO(danakj): Shouldn't need to commit to get resources. - layer_tree_host()->SetNeedsCommit(); - return; - case 3: // All of the resources are in use. delegated_->TakeUnusedResourcesForChildCompositor(&resources); EXPECT_EQ(0u, resources.size()); @@ -778,6 +1011,7 @@ class LayerTreeHostDelegatedTestFrameBeforeAck // Keep using 999 but stop using 555 and 444. frame = CreateFrameData(gfx::Rect(0, 0, 1, 1), gfx::Rect(0, 0, 1, 1)); AddTextureQuad(frame.get(), 999); + AddTransferableResource(frame.get(), 999); delegated_->SetFrameData(frame.Pass()); // Resource are not immediately released. @@ -786,24 +1020,15 @@ class LayerTreeHostDelegatedTestFrameBeforeAck // The parent compositor (this one) does a commit. break; - case 4: - // Retrieve unused resources to the main thread. - // TODO(danakj): Shouldn't need to commit to get resources. - layer_tree_host()->SetNeedsCommit(); - return; - case 5: + case 3: delegated_->TakeUnusedResourcesForChildCompositor(&resources); - EXPECT_EQ(2u, resources.size()); - if (resources[0].id == 555) { - EXPECT_EQ(555u, resources[0].id); - EXPECT_EQ(444u, resources[1].id); - } else { - EXPECT_EQ(444u, resources[0].id); - EXPECT_EQ(555u, resources[1].id); + { + unsigned expected[] = {444, 555}; + EXPECT_RESOURCES(expected, resources); } - // The child compositor sends a frame before receiving an for the - // second frame. It uses 999, 444, and 555 again. + // The child compositor sends a frame referring to resources not in the + // frame. frame = CreateFrameData(gfx::Rect(0, 0, 1, 1), gfx::Rect(0, 0, 1, 1)); AddTextureQuad(frame.get(), 999); AddTextureQuad(frame.get(), 555); @@ -814,7 +1039,7 @@ class LayerTreeHostDelegatedTestFrameBeforeAck } virtual void DidActivateTreeOnThread(LayerTreeHostImpl* host_impl) OVERRIDE { - if (host_impl->active_tree()->source_frame_number() != 5) + if (host_impl->active_tree()->source_frame_number() != 3) return; LayerImpl* root_impl = host_impl->active_tree()->root_layer(); @@ -832,7 +1057,7 @@ class LayerTreeHostDelegatedTestFrameBeforeAck EXPECT_EQ(1u, map.count(999)); EXPECT_EQ(1u, delegated_impl->Resources().size()); - EXPECT_EQ(1u, delegated_impl->Resources().count(map.find(999)->second)); + EXPECT_EQ(1u, delegated_impl->Resources().count(999)); const RenderPass* pass = delegated_impl->RenderPassesInDrawOrder()[0]; EXPECT_EQ(1u, pass->quad_list.size()); @@ -862,7 +1087,7 @@ class LayerTreeHostDelegatedTestFrameBeforeTakeResources virtual void DidCommitAndDrawFrame() OVERRIDE { scoped_ptr<DelegatedFrameData> frame; - TransferableResourceArray resources; + ReturnedResourceArray resources; int next_source_frame_number = layer_tree_host()->source_frame_number(); switch (next_source_frame_number) { @@ -878,11 +1103,6 @@ class LayerTreeHostDelegatedTestFrameBeforeTakeResources delegated_->SetFrameData(frame.Pass()); break; case 2: - // Retrieve unused resources to the main thread. - // TODO(danakj): Shouldn't need to commit to get resources. - layer_tree_host()->SetNeedsCommit(); - return; - case 3: // All of the resources are in use. delegated_->TakeUnusedResourcesForChildCompositor(&resources); EXPECT_EQ(0u, resources.size()); @@ -890,6 +1110,7 @@ class LayerTreeHostDelegatedTestFrameBeforeTakeResources // Keep using 999 but stop using 555 and 444. frame = CreateFrameData(gfx::Rect(0, 0, 1, 1), gfx::Rect(0, 0, 1, 1)); AddTextureQuad(frame.get(), 999); + AddTransferableResource(frame.get(), 999); delegated_->SetFrameData(frame.Pass()); // Resource are not immediately released. @@ -898,31 +1119,28 @@ class LayerTreeHostDelegatedTestFrameBeforeTakeResources // The parent compositor (this one) does a commit. break; - case 4: - // Retrieve unused resources to the main thread. - // TODO(danakj): Shouldn't need to commit to get resources. - layer_tree_host()->SetNeedsCommit(); - return; - case 5: + case 3: // The child compositor sends a frame before taking resources back // from the previous commit. This frame makes use of the resources 555 // and 444, which were just released during commit. 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()); - // The resources are used by the new frame so are not returned. + // The resources are used by the new frame but are returned anyway since + // we passed them again. delegated_->TakeUnusedResourcesForChildCompositor(&resources); - EXPECT_EQ(0u, resources.size()); + { + unsigned expected[] = {444, 555}; + EXPECT_RESOURCES(expected, resources); + } break; - case 6: - // Retrieve unused resources to the main thread. - // TODO(danakj): Shouldn't need to commit to get resources. - layer_tree_host()->SetNeedsCommit(); - return; - case 7: + case 4: delegated_->TakeUnusedResourcesForChildCompositor(&resources); EXPECT_EQ(0u, resources.size()); EndTest(); @@ -931,7 +1149,7 @@ class LayerTreeHostDelegatedTestFrameBeforeTakeResources } virtual void DidActivateTreeOnThread(LayerTreeHostImpl* host_impl) OVERRIDE { - if (host_impl->active_tree()->source_frame_number() != 5) + if (host_impl->active_tree()->source_frame_number() != 3) return; LayerImpl* root_impl = host_impl->active_tree()->root_layer(); @@ -950,9 +1168,9 @@ class LayerTreeHostDelegatedTestFrameBeforeTakeResources 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)); + EXPECT_EQ(1u, delegated_impl->Resources().count(999)); + EXPECT_EQ(1u, delegated_impl->Resources().count(555)); + EXPECT_EQ(1u, delegated_impl->Resources().count(444)); const RenderPass* pass = delegated_impl->RenderPassesInDrawOrder()[0]; EXPECT_EQ(3u, pass->quad_list.size()); @@ -987,7 +1205,7 @@ class LayerTreeHostDelegatedTestBadFrame virtual void DidCommitAndDrawFrame() OVERRIDE { scoped_ptr<DelegatedFrameData> frame; - TransferableResourceArray resources; + ReturnedResourceArray resources; int next_source_frame_number = layer_tree_host()->source_frame_number(); switch (next_source_frame_number) { @@ -1001,11 +1219,6 @@ class LayerTreeHostDelegatedTestBadFrame delegated_->SetFrameData(frame.Pass()); break; case 2: - // Retrieve unused resources to the main thread. - // TODO(danakj): Shouldn't need to commit to get resources. - layer_tree_host()->SetNeedsCommit(); - return; - case 3: // All of the resources are in use. delegated_->TakeUnusedResourcesForChildCompositor(&resources); EXPECT_EQ(0u, resources.size()); @@ -1024,32 +1237,26 @@ class LayerTreeHostDelegatedTestBadFrame // The parent compositor (this one) does a commit. break; - case 4: - // Retrieve unused resources to the main thread. - // TODO(danakj): Shouldn't need to commit to get resources. - layer_tree_host()->SetNeedsCommit(); - return; - case 5: + case 3: // The bad frame's resource is given back to the child compositor. delegated_->TakeUnusedResourcesForChildCompositor(&resources); - EXPECT_EQ(1u, resources.size()); - EXPECT_EQ(444u, resources[0].id); + { + unsigned expected[] = {444}; + EXPECT_RESOURCES(expected, resources); + } // Now send a good frame with 999 again. frame = CreateFrameData(gfx::Rect(0, 0, 1, 1), gfx::Rect(0, 0, 1, 1)); AddTextureQuad(frame.get(), 999); delegated_->SetFrameData(frame.Pass()); break; - case 6: - // Retrieve unused resources to the main thread. - // TODO(danakj): Shouldn't need to commit to get resources. - layer_tree_host()->SetNeedsCommit(); - return; - case 7: + case 4: // The unused 555 from the last good frame is now released. delegated_->TakeUnusedResourcesForChildCompositor(&resources); - EXPECT_EQ(1u, resources.size()); - EXPECT_EQ(555u, resources[0].id); + { + unsigned expected[] = {555}; + EXPECT_RESOURCES(expected, resources); + } EndTest(); break; @@ -1080,8 +1287,8 @@ class LayerTreeHostDelegatedTestBadFrame 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)); + EXPECT_EQ(1u, delegated_impl->Resources().count(999)); + EXPECT_EQ(1u, delegated_impl->Resources().count(555)); const RenderPass* pass = delegated_impl->RenderPassesInDrawOrder()[0]; EXPECT_EQ(2u, pass->quad_list.size()); @@ -1093,15 +1300,15 @@ class LayerTreeHostDelegatedTestBadFrame EXPECT_EQ(map.find(555)->second, quad2->resource_id); break; } - case 3: { + case 2: { // 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(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(999)); + EXPECT_EQ(1u, delegated_impl->Resources().count(555)); // The bad frame is dropped though, we still have the frame with 999 and // 555 in it. @@ -1115,20 +1322,13 @@ class LayerTreeHostDelegatedTestBadFrame EXPECT_EQ(map.find(555)->second, quad2->resource_id); break; } - case 5: - // Resources given to our parent compositor will be returned now, but - // the DelegatedRendererLayerImpl doesn't know about it until the next - // commit. - // TODO(danakj): Shouldn't need a commit to return resources to the - // DelegatedRendererLayerImpl or to the main thread. - break; - case 6: { + case 3: { // We have the new good frame with just 999 in it. EXPECT_EQ(1u, map.size()); EXPECT_EQ(1u, map.count(999)); EXPECT_EQ(1u, delegated_impl->Resources().size()); - EXPECT_EQ(1u, delegated_impl->Resources().count(map.find(999)->second)); + EXPECT_EQ(1u, delegated_impl->Resources().count(999)); const RenderPass* pass = delegated_impl->RenderPassesInDrawOrder()[0]; EXPECT_EQ(1u, pass->quad_list.size()); @@ -1154,7 +1354,7 @@ class LayerTreeHostDelegatedTestUnnamedResource virtual void DidCommit() OVERRIDE { scoped_ptr<DelegatedFrameData> frame; - TransferableResourceArray resources; + ReturnedResourceArray resources; int next_source_frame_number = layer_tree_host()->source_frame_number(); switch (next_source_frame_number) { @@ -1169,8 +1369,10 @@ class LayerTreeHostDelegatedTestUnnamedResource case 2: // The unused resource should be returned. delegated_->TakeUnusedResourcesForChildCompositor(&resources); - EXPECT_EQ(1u, resources.size()); - EXPECT_EQ(999u, resources[0].id); + { + unsigned expected[] = {999}; + EXPECT_RESOURCES(expected, resources); + } EndTest(); break; @@ -1194,7 +1396,7 @@ class LayerTreeHostDelegatedTestUnnamedResource EXPECT_EQ(1u, map.count(555)); EXPECT_EQ(1u, delegated_impl->Resources().size()); - EXPECT_EQ(1u, delegated_impl->Resources().count(map.find(555)->second)); + EXPECT_EQ(1u, delegated_impl->Resources().count(555)); } virtual void AfterTest() OVERRIDE {} @@ -1209,9 +1411,9 @@ class LayerTreeHostDelegatedTestDontLeakResource PostSetNeedsCommitToMainThread(); } - virtual void DidCommit() OVERRIDE { + virtual void DidCommitAndDrawFrame() OVERRIDE { scoped_ptr<DelegatedFrameData> frame; - TransferableResourceArray resources; + ReturnedResourceArray resources; int next_source_frame_number = layer_tree_host()->source_frame_number(); switch (next_source_frame_number) { @@ -1227,14 +1429,29 @@ class LayerTreeHostDelegatedTestDontLeakResource // 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); + AddTransferableResource(frame.get(), 555); delegated_->SetFrameData(frame.Pass()); break; case 2: - // The unused resource should be returned. + // The unused resources should be returned. 555 is still used, but it's + // returned once to account for the first frame. delegated_->TakeUnusedResourcesForChildCompositor(&resources); - EXPECT_EQ(1u, resources.size()); - EXPECT_EQ(999u, resources[0].id); - + { + unsigned expected[] = {555, 999}; + EXPECT_RESOURCES(expected, resources); + } + // Send a frame with no resources in it. + frame = CreateFrameData(gfx::Rect(0, 0, 1, 1), gfx::Rect(0, 0, 1, 1)); + delegated_->SetFrameData(frame.Pass()); + break; + case 3: + // The now unused resource 555 should be returned. + resources.clear(); + delegated_->TakeUnusedResourcesForChildCompositor(&resources); + { + unsigned expected[] = {555}; + EXPECT_RESOURCES(expected, resources); + } EndTest(); break; } @@ -1257,7 +1474,12 @@ class LayerTreeHostDelegatedTestDontLeakResource EXPECT_EQ(1u, map.count(555)); EXPECT_EQ(1u, delegated_impl->Resources().size()); - EXPECT_EQ(1u, delegated_impl->Resources().count(map.find(555)->second)); + EXPECT_EQ(1u, delegated_impl->Resources().count(555)); + } + + virtual void SwapBuffersOnThread(LayerTreeHostImpl* host_impl, + bool result) OVERRIDE { + ReturnUnusedResourcesFromParent(host_impl); } virtual void AfterTest() OVERRIDE {} @@ -1270,7 +1492,7 @@ class LayerTreeHostDelegatedTestResourceSentToParent public: virtual void DidCommitAndDrawFrame() OVERRIDE { scoped_ptr<DelegatedFrameData> frame; - TransferableResourceArray resources; + ReturnedResourceArray resources; int next_source_frame_number = layer_tree_host()->source_frame_number(); switch (next_source_frame_number) { @@ -1291,6 +1513,7 @@ class LayerTreeHostDelegatedTestResourceSentToParent // it present. frame = CreateFrameData(gfx::Rect(0, 0, 1, 1), gfx::Rect(0, 0, 1, 1)); AddTextureQuad(frame.get(), 555); + AddTransferableResource(frame.get(), 555); delegated_->SetFrameData(frame.Pass()); break; case 3: @@ -1299,18 +1522,46 @@ class LayerTreeHostDelegatedTestResourceSentToParent EXPECT_EQ(0u, resources.size()); // The impl side will get back the resource at some point. - // TODO(danakj): The test should work without this. - layer_tree_host()->SetNeedsCommit(); + ImplThreadTaskRunner()->PostTask(FROM_HERE, + receive_resource_on_thread_); break; - case 4: - // 999 was returned from the grandparent and could be released. - delegated_->TakeUnusedResourcesForChildCompositor(&resources); - EXPECT_EQ(1u, resources.size()); - EXPECT_EQ(999u, resources[0].id); + } + } - EndTest(); - break; + void ReceiveResourceOnThread(LayerTreeHostImpl* host_impl) { + LayerImpl* root_impl = host_impl->active_tree()->root_layer(); + FakeDelegatedRendererLayerImpl* delegated_impl = + static_cast<FakeDelegatedRendererLayerImpl*>(root_impl->children()[0]); + + const ResourceProvider::ResourceIdMap& map = + host_impl->resource_provider()->GetChildToParentMap( + delegated_impl->ChildId()); + + // Receive 999 back from the grandparent. + CompositorFrameAck ack; + output_surface()->ReturnResource(map.find(999)->second, &ack); + host_impl->ReclaimResources(&ack); + host_impl->OnSwapBuffersComplete(); + + // And then it should be released by the DelegatedRendererLayer. + MainThreadTaskRunner()->PostTask( + FROM_HERE, + base::Bind(&LayerTreeHostDelegatedTestResourceSentToParent:: + DidReceiveResourceOnMainThread, + base::Unretained(this))); + } + + void DidReceiveResourceOnMainThread() { + ReturnedResourceArray resources; + + // 999 was returned from the grandparent and could be released. + delegated_->TakeUnusedResourcesForChildCompositor(&resources); + { + unsigned expected[] = {999}; + EXPECT_RESOURCES(expected, resources); } + + EndTest(); } virtual void DidActivateTreeOnThread(LayerTreeHostImpl* host_impl) OVERRIDE { @@ -1332,8 +1583,8 @@ class LayerTreeHostDelegatedTestResourceSentToParent 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)); + EXPECT_EQ(1u, delegated_impl->Resources().count(999)); + EXPECT_EQ(1u, delegated_impl->Resources().count(555)); // The 999 resource will be sent to a grandparent compositor. break; @@ -1345,12 +1596,13 @@ class LayerTreeHostDelegatedTestResourceSentToParent // 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)); + EXPECT_EQ(1u, delegated_impl->Resources().count(555)); - // Receive 999 back from the grandparent. - CompositorFrameAck ack; - output_surface()->ReturnResource(map.find(999)->second, &ack); - host_impl->OnSwapBuffersComplete(&ack); + receive_resource_on_thread_ = + base::Bind(&LayerTreeHostDelegatedTestResourceSentToParent:: + ReceiveResourceOnThread, + base::Unretained(this), + host_impl); break; } case 3: @@ -1366,7 +1618,7 @@ class LayerTreeHostDelegatedTestResourceSentToParent virtual void AfterTest() OVERRIDE {} - TransferableResource resource_in_grandparent; + base::Closure receive_resource_on_thread_; }; SINGLE_AND_MULTI_THREAD_DELEGATING_RENDERER_TEST_F( @@ -1383,7 +1635,7 @@ class LayerTreeHostDelegatedTestCommitWithoutTake virtual void DidCommit() OVERRIDE { scoped_ptr<DelegatedFrameData> frame; - TransferableResourceArray resources; + ReturnedResourceArray resources; int next_source_frame_number = layer_tree_host()->source_frame_number(); switch (next_source_frame_number) { @@ -1404,20 +1656,40 @@ class LayerTreeHostDelegatedTestCommitWithoutTake // 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); + AddTransferableResource(frame.get(), 555); delegated_->SetFrameData(frame.Pass()); + // 999 and 444 will be returned for frame 1, but not 555 since it's in + // the current frame. 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); + AddTransferableResource(frame.get(), 999); AddTextureQuad(frame.get(), 555); + AddTransferableResource(frame.get(), 555); delegated_->SetFrameData(frame.Pass()); break; case 4: - // 999 and 555 are in use, but 444 should be returned now. + // 555 from frame 1 and 2 isn't returned since it's still in use. 999 + // from frame 1 is returned though. delegated_->TakeUnusedResourcesForChildCompositor(&resources); - EXPECT_EQ(1u, resources.size()); - EXPECT_EQ(444u, resources[0].id); + { + unsigned expected[] = {444, 999}; + EXPECT_RESOURCES(expected, resources); + } + + frame = CreateFrameData(gfx::Rect(0, 0, 1, 1), gfx::Rect(0, 0, 1, 1)); + delegated_->SetFrameData(frame.Pass()); + // 555 will be returned 3 times for frames 1 2 and 3, and 999 will be + // returned once for frame 3. + break; + case 5: + delegated_->TakeUnusedResourcesForChildCompositor(&resources); + { + unsigned expected[] = {555, 555, 555, 999}; + EXPECT_RESOURCES(expected, resources); + } EndTest(); break; @@ -1444,16 +1716,16 @@ class LayerTreeHostDelegatedTestCommitWithoutTake 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)); + EXPECT_EQ(1u, delegated_impl->Resources().count(999)); + EXPECT_EQ(1u, delegated_impl->Resources().count(555)); + EXPECT_EQ(1u, delegated_impl->Resources().count(444)); 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)); + EXPECT_EQ(1u, delegated_impl->Resources().count(555)); break; case 3: EXPECT_EQ(2u, map.size()); @@ -1461,8 +1733,8 @@ class LayerTreeHostDelegatedTestCommitWithoutTake 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)); + EXPECT_EQ(1u, delegated_impl->Resources().count(999)); + EXPECT_EQ(1u, delegated_impl->Resources().count(555)); } } @@ -1471,5 +1743,107 @@ class LayerTreeHostDelegatedTestCommitWithoutTake SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostDelegatedTestCommitWithoutTake); +class DelegatedFrameIsActivatedDuringCommit + : public LayerTreeHostDelegatedTestCaseSingleDelegatedLayer { + protected: + DelegatedFrameIsActivatedDuringCommit() + : wait_thread_("WAIT"), + wait_event_(false, false) { + wait_thread_.Start(); + } + + virtual void BeginTest() OVERRIDE { + activate_count_ = 0; + + scoped_ptr<DelegatedFrameData> frame = + CreateFrameData(gfx::Rect(0, 0, 1, 1), gfx::Rect(0, 0, 1, 1)); + AddTextureQuad(frame.get(), 999); + AddTransferableResource(frame.get(), 999); + delegated_->SetFrameData(frame.Pass()); + + PostSetNeedsCommitToMainThread(); + } + + virtual void WillActivateTreeOnThread(LayerTreeHostImpl* impl) OVERRIDE { + // Slow down activation so the main thread DidCommit() will run if + // not blocked. + wait_thread_.message_loop()->PostDelayedTask( + FROM_HERE, + base::Bind(&base::WaitableEvent::Signal, + base::Unretained(&wait_event_)), + base::TimeDelta::FromMilliseconds(10)); + wait_event_.Wait(); + + base::AutoLock lock(activate_lock_); + ++activate_count_; + } + + virtual void DidActivateTreeOnThread(LayerTreeHostImpl* impl) OVERRIDE { + // The main thread is awake now, and will run DidCommit() immediately. + // Run DidActivate() afterwards by posting it now. + proxy()->MainThreadTaskRunner()->PostTask( + FROM_HERE, + base::Bind(&DelegatedFrameIsActivatedDuringCommit::DidActivate, + base::Unretained(this))); + } + + void DidActivate() { + base::AutoLock lock(activate_lock_); + switch (activate_count_) { + case 1: { + // The first frame has been activated. Set a new frame, and + // expect the next commit to finish *after* it is activated. + scoped_ptr<DelegatedFrameData> frame = + CreateFrameData(gfx::Rect(0, 0, 1, 1), gfx::Rect(0, 0, 1, 1)); + AddTextureQuad(frame.get(), 555); + AddTransferableResource(frame.get(), 555); + delegated_->SetFrameData(frame.Pass()); + // So this commit number should complete after the second activate. + EXPECT_EQ(1, layer_tree_host()->source_frame_number()); + break; + } + case 2: + // The second frame has been activated. Remove the layer from + // the tree to cause another commit/activation. The commit should + // finish *after* the layer is removed from the active tree. + delegated_->RemoveFromParent(); + // So this commit number should complete after the third activate. + EXPECT_EQ(2, layer_tree_host()->source_frame_number()); + break; + case 3: + EndTest(); + break; + } + } + + virtual void DidCommit() OVERRIDE { + switch (layer_tree_host()->source_frame_number()) { + case 2: { + // The activate for the 2nd frame should have happened before now. + base::AutoLock lock(activate_lock_); + EXPECT_EQ(2, activate_count_); + break; + } + case 3: { + // The activate to remove the layer should have happened before now. + base::AutoLock lock(activate_lock_); + EXPECT_EQ(3, activate_count_); + break; + } + } + } + + + virtual void AfterTest() OVERRIDE {} + + base::Thread wait_thread_; + base::WaitableEvent wait_event_; + base::Lock activate_lock_; + int activate_count_; +}; + +SINGLE_AND_MULTI_THREAD_TEST_F( + DelegatedFrameIsActivatedDuringCommit); + } // namespace } // namespace cc |