| // Copyright 2013 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "cc/trees/layer_tree_host.h" |
| |
| #include <algorithm> |
| |
| #include "base/bind.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: |
| scoped_ptr<DelegatedFrameData> CreateFrameData(gfx::Rect root_output_rect, |
| gfx::Rect root_damage_rect) { |
| scoped_ptr<DelegatedFrameData> frame(new DelegatedFrameData); |
| |
| scoped_ptr<RenderPass> root_pass(RenderPass::Create()); |
| root_pass->SetNew(RenderPass::Id(1, 1), |
| root_output_rect, |
| root_damage_rect, |
| gfx::Transform()); |
| frame->render_pass_list.push_back(root_pass.Pass()); |
| return frame.Pass(); |
| } |
| |
| scoped_ptr<DelegatedFrameData> CreateInvalidFrameData( |
| gfx::Rect root_output_rect, |
| gfx::Rect root_damage_rect) { |
| scoped_ptr<DelegatedFrameData> frame(new DelegatedFrameData); |
| |
| scoped_ptr<RenderPass> root_pass(RenderPass::Create()); |
| root_pass->SetNew(RenderPass::Id(1, 1), |
| root_output_rect, |
| root_damage_rect, |
| gfx::Transform()); |
| |
| scoped_ptr<SharedQuadState> shared_quad_state = SharedQuadState::Create(); |
| |
| gfx::Rect rect = root_output_rect; |
| gfx::Rect opaque_rect = root_output_rect; |
| // An invalid resource id! The resource isn't part of the frame. |
| unsigned resource_id = 5; |
| bool premultiplied_alpha = false; |
| gfx::PointF uv_top_left = gfx::PointF(0.f, 0.f); |
| gfx::PointF uv_bottom_right = gfx::PointF(1.f, 1.f); |
| SkColor background_color = 0; |
| float vertex_opacity[4] = {1.f, 1.f, 1.f, 1.f}; |
| bool flipped = false; |
| |
| scoped_ptr<TextureDrawQuad> invalid_draw_quad = TextureDrawQuad::Create(); |
| invalid_draw_quad->SetNew(shared_quad_state.get(), |
| rect, |
| opaque_rect, |
| resource_id, |
| premultiplied_alpha, |
| uv_top_left, |
| uv_bottom_right, |
| background_color, |
| vertex_opacity, |
| flipped); |
| root_pass->quad_list.push_back(invalid_draw_quad.PassAs<DrawQuad>()); |
| |
| root_pass->shared_quad_state_list.push_back(shared_quad_state.Pass()); |
| |
| frame->render_pass_list.push_back(root_pass.Pass()); |
| return frame.Pass(); |
| } |
| |
| void AddTransferableResource(DelegatedFrameData* frame, |
| ResourceProvider::ResourceId resource_id) { |
| TransferableResource resource; |
| resource.id = resource_id; |
| frame->resource_list.push_back(resource); |
| } |
| |
| void AddTextureQuad(DelegatedFrameData* frame, |
| ResourceProvider::ResourceId resource_id) { |
| scoped_ptr<SharedQuadState> sqs = SharedQuadState::Create(); |
| scoped_ptr<TextureDrawQuad> quad = TextureDrawQuad::Create(); |
| float vertex_opacity[4] = { 1.f, 1.f, 1.f, 1.f }; |
| quad->SetNew(sqs.get(), |
| gfx::Rect(0, 0, 10, 10), |
| gfx::Rect(0, 0, 10, 10), |
| resource_id, |
| false, |
| gfx::PointF(0.f, 0.f), |
| gfx::PointF(1.f, 1.f), |
| SK_ColorTRANSPARENT, |
| vertex_opacity, |
| false); |
| 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>()); |
| } |
| |
| 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(); |
| } |
| |
| |
| static ResourceProvider::ResourceId AppendResourceId( |
| std::vector<ResourceProvider::ResourceId>* resources_in_last_sent_frame, |
| ResourceProvider::ResourceId resource_id) { |
| resources_in_last_sent_frame->push_back(resource_id); |
| return resource_id; |
| } |
| |
| void ReturnUnusedResourcesFromParent(LayerTreeHostImpl* host_impl) { |
| DelegatedFrameData* delegated_frame_data = |
| output_surface()->last_sent_frame().delegated_frame_data.get(); |
| if (!delegated_frame_data) |
| return; |
| |
| std::vector<ResourceProvider::ResourceId> resources_in_last_sent_frame; |
| for (size_t i = 0; i < delegated_frame_data->render_pass_list.size(); ++i) { |
| RenderPass* pass = delegated_frame_data->render_pass_list.at(i); |
| for (size_t j = 0; j < pass->quad_list.size(); ++j) { |
| DrawQuad* quad = pass->quad_list[j]; |
| quad->IterateResources(base::Bind(&AppendResourceId, |
| &resources_in_last_sent_frame)); |
| } |
| } |
| |
| std::vector<ResourceProvider::ResourceId> resources_to_return; |
| |
| const TransferableResourceArray& resources_held_by_parent = |
| output_surface()->resources_held_by_parent(); |
| for (size_t i = 0; i < resources_held_by_parent.size(); ++i) { |
| ResourceProvider::ResourceId resource_in_parent = |
| resources_held_by_parent[i].id; |
| bool resource_in_parent_is_not_part_of_frame = |
| std::find(resources_in_last_sent_frame.begin(), |
| resources_in_last_sent_frame.end(), |
| resource_in_parent) == resources_in_last_sent_frame.end(); |
| if (resource_in_parent_is_not_part_of_frame) |
| resources_to_return.push_back(resource_in_parent); |
| } |
| |
| if (resources_to_return.empty()) |
| return; |
| |
| 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); |
| } |
| }; |
| |
| class LayerTreeHostDelegatedTestCaseSingleDelegatedLayer |
| : public LayerTreeHostDelegatedTest, |
| public DelegatedRendererLayerClient { |
| public: |
| virtual void SetupTree() OVERRIDE { |
| root_ = Layer::Create(); |
| root_->SetAnchorPoint(gfx::PointF()); |
| root_->SetBounds(gfx::Size(10, 10)); |
| |
| delegated_ = FakeDelegatedRendererLayer::Create(this); |
| delegated_->SetAnchorPoint(gfx::PointF()); |
| delegated_->SetBounds(gfx::Size(10, 10)); |
| delegated_->SetIsDrawable(true); |
| |
| root_->AddChild(delegated_); |
| layer_tree_host()->SetRootLayer(root_); |
| LayerTreeHostDelegatedTest::SetupTree(); |
| } |
| |
| virtual void BeginTest() OVERRIDE { |
| PostSetNeedsCommitToMainThread(); |
| } |
| |
| virtual void AfterTest() OVERRIDE {} |
| |
| virtual void DidCommitFrameData() OVERRIDE {} |
| |
| protected: |
| scoped_refptr<Layer> root_; |
| scoped_refptr<DelegatedRendererLayer> delegated_; |
| }; |
| |
| class LayerTreeHostDelegatedTestClientDidCommitCallback |
| : public LayerTreeHostDelegatedTestCaseSingleDelegatedLayer { |
| public: |
| LayerTreeHostDelegatedTestClientDidCommitCallback() |
| : LayerTreeHostDelegatedTestCaseSingleDelegatedLayer(), |
| num_did_commit_frame_data_(0) {} |
| |
| virtual void DidCommit() OVERRIDE { |
| if (TestEnded()) |
| return; |
| |
| EXPECT_EQ(1, num_did_commit_frame_data_); |
| EndTest(); |
| } |
| |
| virtual void BeginTest() OVERRIDE { |
| delegated_->SetFrameData(CreateFrameData(gfx::Rect(0, 0, 1, 1), |
| gfx::Rect(0, 0, 1, 1))); |
| PostSetNeedsCommitToMainThread(); |
| } |
| |
| virtual void DidCommitFrameData() OVERRIDE { |
| num_did_commit_frame_data_++; |
| } |
| |
| protected: |
| int num_did_commit_frame_data_; |
| }; |
| |
| SINGLE_AND_MULTI_THREAD_TEST_F( |
| LayerTreeHostDelegatedTestClientDidCommitCallback); |
| |
| class LayerTreeHostDelegatedTestCreateChildId |
| : public LayerTreeHostDelegatedTestCaseSingleDelegatedLayer { |
| public: |
| LayerTreeHostDelegatedTestCreateChildId() |
| : LayerTreeHostDelegatedTestCaseSingleDelegatedLayer(), |
| num_activates_(0), |
| did_reset_child_id_(false) {} |
| |
| virtual void DidCommit() OVERRIDE { |
| if (TestEnded()) |
| return; |
| delegated_->SetFrameData(CreateFrameData(gfx::Rect(0, 0, 1, 1), |
| gfx::Rect(0, 0, 1, 1))); |
| } |
| |
| virtual void DidActivateTreeOnThread(LayerTreeHostImpl* host_impl) OVERRIDE { |
| LayerImpl* root_impl = host_impl->active_tree()->root_layer(); |
| FakeDelegatedRendererLayerImpl* delegated_impl = |
| static_cast<FakeDelegatedRendererLayerImpl*>(root_impl->children()[0]); |
| |
| ContextProvider* context_provider = |
| host_impl->output_surface()->context_provider(); |
| |
| ++num_activates_; |
| switch (num_activates_) { |
| case 2: |
| EXPECT_TRUE(delegated_impl->ChildId()); |
| EXPECT_FALSE(did_reset_child_id_); |
| |
| context_provider->Context3d()->loseContextCHROMIUM( |
| GL_GUILTY_CONTEXT_RESET_ARB, |
| GL_INNOCENT_CONTEXT_RESET_ARB); |
| break; |
| case 3: |
| EXPECT_TRUE(delegated_impl->ChildId()); |
| EXPECT_TRUE(did_reset_child_id_); |
| EndTest(); |
| break; |
| } |
| } |
| |
| virtual void InitializedRendererOnThread(LayerTreeHostImpl* host_impl, |
| bool success) OVERRIDE { |
| EXPECT_TRUE(success); |
| |
| if (num_activates_ < 2) |
| return; |
| |
| LayerImpl* root_impl = host_impl->active_tree()->root_layer(); |
| FakeDelegatedRendererLayerImpl* delegated_impl = |
| static_cast<FakeDelegatedRendererLayerImpl*>(root_impl->children()[0]); |
| |
| EXPECT_EQ(2, num_activates_); |
| EXPECT_FALSE(delegated_impl->ChildId()); |
| did_reset_child_id_ = true; |
| } |
| |
| virtual void AfterTest() OVERRIDE {} |
| |
| protected: |
| int num_activates_; |
| bool did_reset_child_id_; |
| }; |
| |
| 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: |
| LayerTreeHostDelegatedTestLayerUsesFrameDamage() |
| : LayerTreeHostDelegatedTestCaseSingleDelegatedLayer(), |
| first_draw_for_source_frame_(true) {} |
| |
| virtual void DidCommit() OVERRIDE { |
| int next_source_frame_number = layer_tree_host()->source_frame_number(); |
| switch (next_source_frame_number) { |
| case 1: |
| // The first time the layer gets a frame the whole layer should be |
| // damaged. |
| delegated_->SetFrameData(CreateFrameData(gfx::Rect(0, 0, 1, 1), |
| gfx::Rect(0, 0, 1, 1))); |
| break; |
| case 2: |
| // Should create a total amount of gfx::Rect(2, 2, 10, 6) damage. |
| // The frame size is 20x20 while the layer is 10x10, so this should |
| // produce a gfx::Rect(1, 1, 5, 3) damage rect. |
| delegated_->SetFrameData(CreateFrameData(gfx::Rect(0, 0, 20, 20), |
| gfx::Rect(2, 2, 5, 5))); |
| delegated_->SetFrameData(CreateFrameData(gfx::Rect(0, 0, 20, 20), |
| gfx::Rect(7, 2, 5, 6))); |
| break; |
| case 3: |
| // Should create zero damage. |
| layer_tree_host()->SetNeedsCommit(); |
| break; |
| case 4: |
| // Should damage the full viewport. |
| delegated_->SetBounds(gfx::Size(2, 2)); |
| break; |
| case 5: |
| // Should create zero damage. |
| layer_tree_host()->SetNeedsCommit(); |
| break; |
| case 6: |
| // Should damage the full layer. |
| delegated_->SetBounds(gfx::Size(6, 6)); |
| delegated_->SetFrameData(CreateFrameData(gfx::Rect(0, 0, 5, 5), |
| gfx::Rect(1, 1, 2, 2))); |
| break; |
| case 7: |
| // Should create zero damage. |
| layer_tree_host()->SetNeedsCommit(); |
| break; |
| case 8: |
| // Should damage the full layer. |
| delegated_->SetDisplaySize(gfx::Size(10, 10)); |
| break; |
| case 9: |
| // Should create zero damage. |
| layer_tree_host()->SetNeedsCommit(); |
| break; |
| case 10: |
| // Setting an empty frame should damage the whole layer the |
| // first time. |
| delegated_->SetFrameData(CreateEmptyFrameData()); |
| break; |
| case 11: |
| // Setting an empty frame shouldn't damage anything after the |
| // first time. |
| delegated_->SetFrameData(CreateEmptyFrameData()); |
| break; |
| case 12: |
| // Having valid content to display agains should damage the whole layer. |
| delegated_->SetFrameData(CreateFrameData(gfx::Rect(0, 0, 10, 10), |
| gfx::Rect(5, 5, 1, 1))); |
| break; |
| case 13: |
| // An invalid frame isn't used, so it should not cause damage. |
| delegated_->SetFrameData(CreateInvalidFrameData(gfx::Rect(0, 0, 10, 10), |
| gfx::Rect(5, 5, 1, 1))); |
| break; |
| case 14: |
| // Should create gfx::Rect(1, 1, 2, 2) of damage. The frame size is |
| // 5x5 and the display size is now set to 10x10, so this should result |
| // in a gfx::Rect(2, 2, 4, 4) damage rect. |
| delegated_->SetFrameData(CreateFrameData(gfx::Rect(0, 0, 5, 5), |
| gfx::Rect(1, 1, 2, 2))); |
| break; |
| case 15: |
| // Should create zero damage. |
| layer_tree_host()->SetNeedsCommit(); |
| break; |
| } |
| first_draw_for_source_frame_ = true; |
| } |
| |
| virtual bool PrepareToDrawOnThread(LayerTreeHostImpl* host_impl, |
| LayerTreeHostImpl::FrameData* frame, |
| bool result) OVERRIDE { |
| EXPECT_TRUE(result); |
| |
| if (!first_draw_for_source_frame_) |
| return result; |
| |
| gfx::RectF damage_rect; |
| if (!frame->has_no_damage) { |
| damage_rect = frame->render_passes.back()->damage_rect; |
| } else { |
| // If there is no damage, then we have no render passes to send. |
| EXPECT_TRUE(frame->render_passes.empty()); |
| } |
| |
| switch (host_impl->active_tree()->source_frame_number()) { |
| case 0: |
| // First frame is damaged because of viewport resize. |
| EXPECT_EQ(gfx::RectF(0.f, 0.f, 10.f, 10.f).ToString(), |
| damage_rect.ToString()); |
| break; |
| case 1: |
| EXPECT_EQ(gfx::RectF(0.f, 0.f, 10.f, 10.f).ToString(), |
| damage_rect.ToString()); |
| break; |
| case 2: |
| EXPECT_EQ(gfx::RectF(1.f, 1.f, 5.f, 3.f).ToString(), |
| damage_rect.ToString()); |
| break; |
| case 3: |
| EXPECT_EQ(gfx::RectF(0.f, 0.f, 0.f, 0.f).ToString(), |
| damage_rect.ToString()); |
| break; |
| case 4: |
| EXPECT_EQ(gfx::RectF(0.f, 0.f, 10.f, 10.f).ToString(), |
| damage_rect.ToString()); |
| break; |
| case 5: |
| EXPECT_EQ(gfx::RectF(0.f, 0.f, 0.f, 0.f).ToString(), |
| damage_rect.ToString()); |
| break; |
| case 6: |
| EXPECT_EQ(gfx::RectF(0.f, 0.f, 6.f, 6.f).ToString(), |
| damage_rect.ToString()); |
| break; |
| case 7: |
| EXPECT_EQ(gfx::RectF(0.f, 0.f, 0.f, 0.f).ToString(), |
| damage_rect.ToString()); |
| break; |
| case 8: |
| EXPECT_EQ(gfx::RectF(0.f, 0.f, 6.f, 6.f).ToString(), |
| damage_rect.ToString()); |
| break; |
| case 9: |
| EXPECT_EQ(gfx::RectF(0.f, 0.f, 0.f, 0.f).ToString(), |
| damage_rect.ToString()); |
| break; |
| case 10: |
| EXPECT_EQ(gfx::RectF(0.f, 0.f, 6.f, 6.f).ToString(), |
| damage_rect.ToString()); |
| break; |
| case 11: |
| EXPECT_EQ(gfx::RectF(0.f, 0.f, 0.f, 0.f).ToString(), |
| damage_rect.ToString()); |
| break; |
| case 12: |
| EXPECT_EQ(gfx::RectF(0.f, 0.f, 6.f, 6.f).ToString(), |
| damage_rect.ToString()); |
| break; |
| case 13: |
| EXPECT_EQ(gfx::RectF(0.f, 0.f, 0.f, 0.f).ToString(), |
| damage_rect.ToString()); |
| break; |
| case 14: |
| EXPECT_EQ(gfx::RectF(2.f, 2.f, 4.f, 4.f).ToString(), |
| damage_rect.ToString()); |
| break; |
| case 15: |
| EXPECT_EQ(gfx::RectF(0.f, 0.f, 0.f, 0.f).ToString(), |
| damage_rect.ToString()); |
| EndTest(); |
| break; |
| } |
| |
| return result; |
| } |
| |
| protected: |
| bool first_draw_for_source_frame_; |
| }; |
| |
| SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostDelegatedTestLayerUsesFrameDamage); |
| |
| class LayerTreeHostDelegatedTestMergeResources |
| : public LayerTreeHostDelegatedTestCaseSingleDelegatedLayer { |
| public: |
| virtual void BeginTest() OVERRIDE { |
| // Push two frames to the delegated renderer layer with no commit between. |
| |
| // The first frame has resource 999. |
| scoped_ptr<DelegatedFrameData> frame1 = |
| CreateFrameData(gfx::Rect(0, 0, 1, 1), gfx::Rect(0, 0, 1, 1)); |
| AddTextureQuad(frame1.get(), 999); |
| AddTransferableResource(frame1.get(), 999); |
| delegated_->SetFrameData(frame1.Pass()); |
| |
| // The second frame uses resource 999 still, but also adds 555. |
| 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(); |
| } |
| |
| virtual void DidActivateTreeOnThread(LayerTreeHostImpl* host_impl) OVERRIDE { |
| 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()); |
| |
| // Both frames' resources should be in the parent's resource provider. |
| 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)); |
| |
| EndTest(); |
| } |
| |
| virtual void AfterTest() OVERRIDE {} |
| }; |
| |
| SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostDelegatedTestMergeResources); |
| |
| class LayerTreeHostDelegatedTestRemapResourcesInQuads |
| : public LayerTreeHostDelegatedTestCaseSingleDelegatedLayer { |
| public: |
| virtual void BeginTest() OVERRIDE { |
| // Generate a frame with two resources in it. |
| 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); |
| AddTextureQuad(frame.get(), 555); |
| AddTransferableResource(frame.get(), 555); |
| delegated_->SetFrameData(frame.Pass()); |
| |
| PostSetNeedsCommitToMainThread(); |
| } |
| |
| virtual void DidActivateTreeOnThread(LayerTreeHostImpl* host_impl) OVERRIDE { |
| 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()); |
| |
| // The frame's resource should be in the parent's resource provider. |
| EXPECT_EQ(2u, map.size()); |
| EXPECT_EQ(1u, map.count(999)); |
| EXPECT_EQ(1u, map.count(555)); |
| |
| ResourceProvider::ResourceId parent_resource_id1 = map.find(999)->second; |
| EXPECT_NE(parent_resource_id1, 999u); |
| ResourceProvider::ResourceId parent_resource_id2 = map.find(555)->second; |
| EXPECT_NE(parent_resource_id2, 555u); |
| |
| // The resources in the quads should be remapped to the parent's namespace. |
| const TextureDrawQuad* quad1 = TextureDrawQuad::MaterialCast( |
| delegated_impl->RenderPassesInDrawOrder()[0]->quad_list[0]); |
| EXPECT_EQ(parent_resource_id1, quad1->resource_id); |
| const TextureDrawQuad* quad2 = TextureDrawQuad::MaterialCast( |
| delegated_impl->RenderPassesInDrawOrder()[0]->quad_list[1]); |
| EXPECT_EQ(parent_resource_id2, quad2->resource_id); |
| |
| EndTest(); |
| } |
| |
| virtual void AfterTest() OVERRIDE {} |
| }; |
| |
| SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostDelegatedTestRemapResourcesInQuads); |
| |
| class LayerTreeHostDelegatedTestReturnUnusedResources |
| : public LayerTreeHostDelegatedTestCaseSingleDelegatedLayer { |
| public: |
| virtual void BeginTest() OVERRIDE { |
| PostSetNeedsCommitToMainThread(); |
| } |
| |
| virtual void DidCommitAndDrawFrame() OVERRIDE { |
| scoped_ptr<DelegatedFrameData> frame; |
| ReturnedResourceArray resources; |
| |
| int next_source_frame_number = layer_tree_host()->source_frame_number(); |
| switch (next_source_frame_number) { |
| case 1: |
| // Generate a frame with 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: |
| // 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()); |
| |
| // 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); |
| 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: |
| // 555 is no longer in use. |
| delegated_->TakeUnusedResourcesForChildCompositor(&resources); |
| { |
| 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: |
| // 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. |
| delegated_->TakeUnusedResourcesForChildCompositor(&resources); |
| { |
| unsigned expected[] = {444, 999}; |
| EXPECT_RESOURCES(expected, resources); |
| } |
| EndTest(); |
| break; |
| } |
| |
| // Resource are never immediately released. |
| ReturnedResourceArray empty_resources; |
| delegated_->TakeUnusedResourcesForChildCompositor(&empty_resources); |
| EXPECT_TRUE(empty_resources.empty()); |
| } |
| |
| virtual void SwapBuffersOnThread(LayerTreeHostImpl* host_impl, |
| bool result) OVERRIDE { |
| ReturnUnusedResourcesFromParent(host_impl); |
| } |
| |
| virtual void AfterTest() OVERRIDE {} |
| }; |
| |
| SINGLE_AND_MULTI_THREAD_TEST_F( |
| LayerTreeHostDelegatedTestReturnUnusedResources); |
| |
| class LayerTreeHostDelegatedTestReusedResources |
| : public LayerTreeHostDelegatedTestCaseSingleDelegatedLayer { |
| public: |
| virtual void BeginTest() OVERRIDE { |
| PostSetNeedsCommitToMainThread(); |
| } |
| |
| virtual void DidCommitAndDrawFrame() OVERRIDE { |
| scoped_ptr<DelegatedFrameData> frame; |
| ReturnedResourceArray resources; |
| |
| int next_source_frame_number = layer_tree_host()->source_frame_number(); |
| switch (next_source_frame_number) { |
| case 1: |
| // Generate a frame with some 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); |
| AddTextureQuad(frame.get(), 444); |
| AddTransferableResource(frame.get(), 444); |
| 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()); |
| |
| // 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); |
| delegated_->SetFrameData(frame.Pass()); |
| |
| // Resource are not immediately released. |
| delegated_->TakeUnusedResourcesForChildCompositor(&resources); |
| EXPECT_EQ(0u, resources.size()); |
| |
| // 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); |
| AddTextureQuad(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. |
| delegated_->TakeUnusedResourcesForChildCompositor(&resources); |
| { |
| unsigned expected[] = {999}; |
| EXPECT_RESOURCES(expected, resources); |
| } |
| EndTest(); |
| break; |
| } |
| } |
| |
| virtual void SwapBuffersOnThread(LayerTreeHostImpl* host_impl, |
| bool result) OVERRIDE { |
| ReturnUnusedResourcesFromParent(host_impl); |
| } |
| |
| virtual void AfterTest() OVERRIDE {} |
| }; |
| |
| SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostDelegatedTestReusedResources); |
| |
| class LayerTreeHostDelegatedTestFrameBeforeAck |
| : public LayerTreeHostDelegatedTestCaseSingleDelegatedLayer { |
| public: |
| virtual void BeginTest() OVERRIDE { |
| PostSetNeedsCommitToMainThread(); |
| } |
| |
| virtual void DidCommitAndDrawFrame() OVERRIDE { |
| scoped_ptr<DelegatedFrameData> frame; |
| ReturnedResourceArray resources; |
| |
| int next_source_frame_number = layer_tree_host()->source_frame_number(); |
| switch (next_source_frame_number) { |
| case 1: |
| // Generate a frame with some 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); |
| AddTextureQuad(frame.get(), 444); |
| AddTransferableResource(frame.get(), 444); |
| 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()); |
| |
| // 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); |
| delegated_->SetFrameData(frame.Pass()); |
| |
| // Resource are not immediately released. |
| delegated_->TakeUnusedResourcesForChildCompositor(&resources); |
| EXPECT_EQ(0u, resources.size()); |
| |
| // 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: |
| delegated_->TakeUnusedResourcesForChildCompositor(&resources); |
| { |
| 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. |
| frame = CreateFrameData(gfx::Rect(0, 0, 1, 1), gfx::Rect(0, 0, 1, 1)); |
| AddTextureQuad(frame.get(), 999); |
| AddTextureQuad(frame.get(), 555); |
| AddTextureQuad(frame.get(), 444); |
| delegated_->SetFrameData(frame.Pass()); |
| break; |
| } |
| } |
| |
| virtual void DidActivateTreeOnThread(LayerTreeHostImpl* host_impl) OVERRIDE { |
| if (host_impl->active_tree()->source_frame_number() != 5) |
| return; |
| |
| 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()); |
| |
| // 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()); |
| EXPECT_EQ(1u, map.count(999)); |
| |
| EXPECT_EQ(1u, delegated_impl->Resources().size()); |
| EXPECT_EQ(1u, delegated_impl->Resources().count(map.find(999)->second)); |
| |
| const RenderPass* pass = delegated_impl->RenderPassesInDrawOrder()[0]; |
| EXPECT_EQ(1u, pass->quad_list.size()); |
| const TextureDrawQuad* quad = TextureDrawQuad::MaterialCast( |
| pass->quad_list[0]); |
| EXPECT_EQ(map.find(999)->second, quad->resource_id); |
| |
| EndTest(); |
| } |
| |
| virtual void SwapBuffersOnThread(LayerTreeHostImpl* host_impl, |
| bool result) OVERRIDE { |
| ReturnUnusedResourcesFromParent(host_impl); |
| } |
| |
| virtual void AfterTest() OVERRIDE {} |
| }; |
| |
| SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostDelegatedTestFrameBeforeAck); |
| |
| class LayerTreeHostDelegatedTestFrameBeforeTakeResources |
| : public LayerTreeHostDelegatedTestCaseSingleDelegatedLayer { |
| public: |
| virtual void BeginTest() OVERRIDE { |
| PostSetNeedsCommitToMainThread(); |
| } |
| |
| virtual void DidCommitAndDrawFrame() OVERRIDE { |
| scoped_ptr<DelegatedFrameData> frame; |
| ReturnedResourceArray resources; |
| |
| int next_source_frame_number = layer_tree_host()->source_frame_number(); |
| switch (next_source_frame_number) { |
| case 1: |
| // Generate a frame with some 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); |
| AddTextureQuad(frame.get(), 444); |
| AddTransferableResource(frame.get(), 444); |
| 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()); |
| |
| // 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. |
| delegated_->TakeUnusedResourcesForChildCompositor(&resources); |
| EXPECT_EQ(0u, resources.size()); |
| |
| // 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: |
| // 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 but are returned anyway since |
| // we passed them again. |
| delegated_->TakeUnusedResourcesForChildCompositor(&resources); |
| { |
| 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: |
| delegated_->TakeUnusedResourcesForChildCompositor(&resources); |
| EXPECT_EQ(0u, resources.size()); |
| EndTest(); |
| break; |
| } |
| } |
| |
| virtual void DidActivateTreeOnThread(LayerTreeHostImpl* host_impl) OVERRIDE { |
| if (host_impl->active_tree()->source_frame_number() != 5) |
| return; |
| |
| 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()); |
| |
| // 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(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(3u, pass->quad_list.size()); |
| const TextureDrawQuad* quad1 = TextureDrawQuad::MaterialCast( |
| pass->quad_list[0]); |
| 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 SwapBuffersOnThread(LayerTreeHostImpl* host_impl, |
| bool result) OVERRIDE { |
| ReturnUnusedResourcesFromParent(host_impl); |
| } |
| |
| virtual void AfterTest() OVERRIDE {} |
| }; |
| |
| SINGLE_AND_MULTI_THREAD_TEST_F( |
| LayerTreeHostDelegatedTestFrameBeforeTakeResources); |
| |
| class LayerTreeHostDelegatedTestBadFrame |
| : public LayerTreeHostDelegatedTestCaseSingleDelegatedLayer { |
| public: |
| virtual void BeginTest() OVERRIDE { |
| PostSetNeedsCommitToMainThread(); |
| } |
| |
| virtual void DidCommitAndDrawFrame() OVERRIDE { |
| scoped_ptr<DelegatedFrameData> frame; |
| ReturnedResourceArray resources; |
| |
| int next_source_frame_number = layer_tree_host()->source_frame_number(); |
| switch (next_source_frame_number) { |
| case 1: |
| // Generate a frame with some 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: |
| // 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()); |
| |
| // Generate a bad frame with a resource the layer doesn't have. The |
| // 885 and 775 resources are unknown, while ownership of the legit 444 |
| // resource is passed in here. The bad frame does not use any of the |
| // previous resources, 999 or 555. |
| // A bad quad is present both before and after the good quad. |
| frame = CreateFrameData(gfx::Rect(0, 0, 1, 1), gfx::Rect(0, 0, 1, 1)); |
| AddTextureQuad(frame.get(), 885); |
| AddTextureQuad(frame.get(), 444); |
| AddTransferableResource(frame.get(), 444); |
| AddTextureQuad(frame.get(), 775); |
| delegated_->SetFrameData(frame.Pass()); |
| |
| // 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: |
| // The bad frame's resource is given back to the child compositor. |
| delegated_->TakeUnusedResourcesForChildCompositor(&resources); |
| { |
| 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: |
| // The unused 555 from the last good frame is now released. |
| delegated_->TakeUnusedResourcesForChildCompositor(&resources); |
| { |
| unsigned expected[] = {555}; |
| EXPECT_RESOURCES(expected, resources); |
| } |
| |
| EndTest(); |
| break; |
| } |
| } |
| |
| virtual void SwapBuffersOnThread(LayerTreeHostImpl* host_impl, |
| bool result) OVERRIDE { |
| if (host_impl->active_tree()->source_frame_number() < 1) |
| return; |
| |
| ReturnUnusedResourcesFromParent(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()); |
| |
| switch (host_impl->active_tree()->source_frame_number()) { |
| case 1: { |
| // We have the first good frame with just 990 and 555 in it. |
| // layer. |
| 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)); |
| |
| const RenderPass* pass = delegated_impl->RenderPassesInDrawOrder()[0]; |
| EXPECT_EQ(2u, pass->quad_list.size()); |
| const TextureDrawQuad* quad1 = TextureDrawQuad::MaterialCast( |
| pass->quad_list[0]); |
| 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); |
| break; |
| } |
| case 3: { |
| // 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)); |
| |
| // The bad frame is dropped though, we still have the frame with 999 and |
| // 555 in it. |
| const RenderPass* pass = delegated_impl->RenderPassesInDrawOrder()[0]; |
| EXPECT_EQ(2u, pass->quad_list.size()); |
| const TextureDrawQuad* quad1 = TextureDrawQuad::MaterialCast( |
| pass->quad_list[0]); |
| 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); |
| 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: { |
| // 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)); |
| |
| const RenderPass* pass = delegated_impl->RenderPassesInDrawOrder()[0]; |
| EXPECT_EQ(1u, pass->quad_list.size()); |
| const TextureDrawQuad* quad1 = TextureDrawQuad::MaterialCast( |
| pass->quad_list[0]); |
| EXPECT_EQ(map.find(999)->second, quad1->resource_id); |
| break; |
| } |
| } |
| } |
| |
| virtual void AfterTest() OVERRIDE {} |
| }; |
| |
| 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; |
| ReturnedResourceArray resources; |
| |
| int next_source_frame_number = layer_tree_host()->source_frame_number(); |
| 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); |
| { |
| unsigned expected[] = {999}; |
| EXPECT_RESOURCES(expected, resources); |
| } |
| |
| EndTest(); |
| break; |
| } |
| } |
| |
| virtual void DidActivateTreeOnThread(LayerTreeHostImpl* host_impl) OVERRIDE { |
| if (host_impl->active_tree()->source_frame_number() != 1) |
| return; |
| |
| 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()); |
| |
| // 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; |
| ReturnedResourceArray resources; |
| |
| int next_source_frame_number = layer_tree_host()->source_frame_number(); |
| 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); |
| AddTransferableResource(frame.get(), 555); |
| delegated_->SetFrameData(frame.Pass()); |
| break; |
| case 2: |
| // The unused resources should be returned. 555 is still used, but it's |
| // returned once to account for the first frame. |
| delegated_->TakeUnusedResourcesForChildCompositor(&resources); |
| { |
| 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 impl side will get back the resource at some point. |
| // TODO(piman): The test should work without this. |
| layer_tree_host()->SetNeedsCommit(); |
| break; |
| case 4: |
| // The now unused resource 555 should be returned. |
| resources.clear(); |
| delegated_->TakeUnusedResourcesForChildCompositor(&resources); |
| { |
| unsigned expected[] = {555}; |
| EXPECT_RESOURCES(expected, resources); |
| } |
| EndTest(); |
| break; |
| } |
| } |
| |
| virtual void DidActivateTreeOnThread(LayerTreeHostImpl* host_impl) OVERRIDE { |
| if (host_impl->active_tree()->source_frame_number() != 1) |
| return; |
| |
| 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()); |
| |
| // 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 SwapBuffersOnThread(LayerTreeHostImpl* host_impl, |
| bool result) OVERRIDE { |
| ReturnUnusedResourcesFromParent(host_impl); |
| } |
| |
| virtual void AfterTest() OVERRIDE {} |
| }; |
| |
| SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostDelegatedTestDontLeakResource); |
| |
| class LayerTreeHostDelegatedTestResourceSentToParent |
| : public LayerTreeHostDelegatedTestCaseSingleDelegatedLayer { |
| public: |
| virtual void DidCommitAndDrawFrame() OVERRIDE { |
| scoped_ptr<DelegatedFrameData> frame; |
| ReturnedResourceArray resources; |
| |
| int next_source_frame_number = layer_tree_host()->source_frame_number(); |
| 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()); |
| |
| // The impl side will get back the resource at some point. |
| // TODO(danakj): The test should work without this. |
| layer_tree_host()->SetNeedsCommit(); |
| break; |
| case 4: |
| // 999 was returned from the grandparent and could be released. |
| delegated_->TakeUnusedResourcesForChildCompositor(&resources); |
| { |
| unsigned expected[] = {999}; |
| EXPECT_RESOURCES(expected, resources); |
| } |
| |
| EndTest(); |
| break; |
| } |
| } |
| |
| virtual void DidActivateTreeOnThread(LayerTreeHostImpl* host_impl) OVERRIDE { |
| if (host_impl->active_tree()->source_frame_number() < 1) |
| return; |
| |
| 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()); |
| |
| switch (host_impl->active_tree()->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 will be sent to a grandparent compositor. |
| 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. |
| CompositorFrameAck ack; |
| output_surface()->ReturnResource(map.find(999)->second, &ack); |
| host_impl->OnSwapBuffersComplete(&ack); |
| 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)); |
| break; |
| } |
| } |
| |
| virtual void AfterTest() OVERRIDE {} |
| |
| TransferableResource resource_in_grandparent; |
| }; |
| |
| SINGLE_AND_MULTI_THREAD_DELEGATING_RENDERER_TEST_F( |
| LayerTreeHostDelegatedTestResourceSentToParent); |
| |
| class LayerTreeHostDelegatedTestCommitWithoutTake |
| : public LayerTreeHostDelegatedTestCaseSingleDelegatedLayer { |
| public: |
| virtual void BeginTest() OVERRIDE { |
| // Prevent drawing with resources that are sent to the grandparent. |
| layer_tree_host()->SetViewportSize(gfx::Size()); |
| PostSetNeedsCommitToMainThread(); |
| } |
| |
| virtual void DidCommit() OVERRIDE { |
| scoped_ptr<DelegatedFrameData> frame; |
| ReturnedResourceArray resources; |
| |
| int next_source_frame_number = layer_tree_host()->source_frame_number(); |
| 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); |
| 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: |
| // 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); |
| { |
| 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; |
| } |
| } |
| |
| virtual void DidActivateTreeOnThread(LayerTreeHostImpl* host_impl) OVERRIDE { |
| if (host_impl->active_tree()->source_frame_number() < 1) |
| return; |
| |
| 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()); |
| |
| switch (host_impl->active_tree()->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); |
| |
| 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 |