Index: cc/trees/layer_tree_host_unittest_context.cc |
=================================================================== |
--- cc/trees/layer_tree_host_unittest_context.cc (revision 214824) |
+++ cc/trees/layer_tree_host_unittest_context.cc (working copy) |
@@ -24,6 +24,7 @@ |
#include "cc/test/fake_delegated_renderer_layer_impl.h" |
#include "cc/test/fake_layer_tree_host_client.h" |
#include "cc/test/fake_output_surface.h" |
+#include "cc/test/fake_scoped_ui_resource.h" |
#include "cc/test/fake_scrollbar.h" |
#include "cc/test/fake_scrollbar_layer.h" |
#include "cc/test/fake_video_frame_provider.h" |
@@ -1502,21 +1503,17 @@ |
LayerTreeHostContextTest::CommitCompleteOnThread(impl); |
++commits_; |
- size_t upload_count = scrollbar_layer_->last_update_full_upload_size() + |
- scrollbar_layer_->last_update_partial_upload_size(); |
switch (commits_) { |
case 1: |
// First (regular) update, we should upload 2 resources (thumb, and |
// backtrack). |
EXPECT_EQ(1, scrollbar_layer_->update_count()); |
- EXPECT_EQ(2u, upload_count); |
LoseContext(); |
break; |
case 2: |
// Second update, after the lost context, we should still upload 2 |
// resources even if the contents haven't changed. |
EXPECT_EQ(2, scrollbar_layer_->update_count()); |
- EXPECT_EQ(2u, upload_count); |
EndTest(); |
break; |
default: |
@@ -1603,5 +1600,279 @@ |
SINGLE_AND_MULTI_THREAD_TEST_F( |
LayerTreeHostTestCannotCreateIfCannotCreateOutputSurface); |
+class UIResourceLostTest : public LayerTreeHostContextTest { |
+ public: |
+ UIResourceLostTest() : time_step_(0) {} |
+ virtual void BeginTest() OVERRIDE { PostSetNeedsCommitToMainThread(); } |
+ virtual void AfterTest() OVERRIDE {} |
+ |
+ protected: |
+ int time_step_; |
+ scoped_ptr<FakeScopedUIResource> ui_resource_; |
+}; |
+ |
+// Losing context after an UI resource has been created. |
+class UIResourceLostAfterCommit : public UIResourceLostTest { |
+ public: |
+ virtual void CommitCompleteOnThread(LayerTreeHostImpl* impl) OVERRIDE { |
+ LayerTreeHostContextTest::CommitCompleteOnThread(impl); |
+ switch (time_step_) { |
+ case 0: |
+ ui_resource_ = FakeScopedUIResource::Create(layer_tree_host()); |
+ // Expects a valid UIResourceId. |
+ EXPECT_NE(0, ui_resource_->id()); |
+ PostSetNeedsCommitToMainThread(); |
+ break; |
+ case 1: |
+ // The resource should have been created on LTHI after the commit. |
+ if (!layer_tree_host()->settings().impl_side_painting) |
+ EXPECT_NE(0u, impl->ResourceIdForUIResource(ui_resource_->id())); |
+ PostSetNeedsCommitToMainThread(); |
+ break; |
+ case 2: |
+ LoseContext(); |
+ break; |
+ case 3: |
+ // The resources should have been recreated. The bitmap callback should |
+ // have been called once with the resource_lost flag set to true. |
+ EXPECT_EQ(1, ui_resource_->lost_resource_count); |
+ // Resource Id on the impl-side have been recreated as well. Note |
+ // that the same UIResourceId persists after the context lost. |
+ if (!layer_tree_host()->settings().impl_side_painting) |
+ EXPECT_NE(0u, impl->ResourceIdForUIResource(ui_resource_->id())); |
+ PostSetNeedsCommitToMainThread(); |
+ break; |
+ case 4: |
+ // Release resource before ending test. |
+ ui_resource_.reset(); |
+ EndTest(); |
+ break; |
+ } |
+ } |
+ |
+ virtual void DidActivateTreeOnThread(LayerTreeHostImpl* impl) OVERRIDE { |
+ LayerTreeHostContextTest::DidActivateTreeOnThread(impl); |
+ switch (time_step_) { |
+ case 1: |
+ if (layer_tree_host()->settings().impl_side_painting) |
+ EXPECT_NE(0u, impl->ResourceIdForUIResource(ui_resource_->id())); |
+ break; |
+ case 3: |
+ if (layer_tree_host()->settings().impl_side_painting) |
+ EXPECT_NE(0u, impl->ResourceIdForUIResource(ui_resource_->id())); |
+ break; |
+ } |
+ ++time_step_; |
+ } |
+}; |
+ |
+SINGLE_AND_MULTI_THREAD_TEST_F(UIResourceLostAfterCommit); |
+ |
+// Losing context before UI resource requests can be commited. Three sequences |
+// of creation/deletion are considered: |
+// 1. Create one resource -> Context Lost => Expect the resource to have been |
+// created. |
+// 2. Delete an exisiting resource (test_id0_) -> create a second resource |
+// (test_id1_) -> Context Lost => Expect the test_id0_ to be removed and |
+// test_id1_ to have been created. |
+// 3. Create one resource -> Delete that same resource -> Context Lost => Expect |
+// the resource to not exist in the manager. |
+class UIResourceLostBeforeCommit : public UIResourceLostTest { |
+ public: |
+ UIResourceLostBeforeCommit() |
+ : test_id0_(0), |
+ test_id1_(0) {} |
+ |
+ virtual void CommitCompleteOnThread(LayerTreeHostImpl* impl) OVERRIDE { |
+ LayerTreeHostContextTest::CommitCompleteOnThread(impl); |
+ switch (time_step_) { |
+ case 0: |
+ // Sequence 1: |
+ ui_resource_ = FakeScopedUIResource::Create(layer_tree_host()); |
+ LoseContext(); |
+ // Resource Id on the impl-side should no longer be valid after |
+ // context is lost. |
+ EXPECT_EQ(0u, impl->ResourceIdForUIResource(ui_resource_->id())); |
+ break; |
+ case 1: |
+ // The resources should have been recreated. |
+ EXPECT_EQ(2, ui_resource_->resource_create_count); |
+ // "resource lost" callback was called once for the resource in the |
+ // resource map. |
+ EXPECT_EQ(1, ui_resource_->lost_resource_count); |
+ // Resource Id on the impl-side have been recreated as well. Note |
+ // that the same UIResourceId persists after the context lost. |
+ if (!layer_tree_host()->settings().impl_side_painting) |
+ EXPECT_NE(0u, impl->ResourceIdForUIResource(ui_resource_->id())); |
+ PostSetNeedsCommitToMainThread(); |
+ break; |
+ case 2: |
+ // Sequence 2: |
+ // Currently one resource has been created. |
+ test_id0_ = ui_resource_->id(); |
+ // Delete this resource. |
+ ui_resource_.reset(); |
+ // Create another resource. |
+ ui_resource_ = FakeScopedUIResource::Create(layer_tree_host()); |
+ test_id1_ = ui_resource_->id(); |
+ // Sanity check that two resource creations return different ids. |
+ EXPECT_NE(test_id0_, test_id1_); |
+ // Lose the context before commit. |
+ LoseContext(); |
+ break; |
+ case 3: |
+ if (!layer_tree_host()->settings().impl_side_painting) { |
+ // The previous resource should have been deleted. |
+ EXPECT_EQ(0u, impl->ResourceIdForUIResource(test_id0_)); |
+ // The second resource should have been created. |
+ EXPECT_NE(0u, impl->ResourceIdForUIResource(test_id1_)); |
+ } |
+ |
+ // The second resource called the resource callback once and since the |
+ // context is lost, a "resource lost" callback was also issued. |
+ EXPECT_EQ(2, ui_resource_->resource_create_count); |
+ EXPECT_EQ(1, ui_resource_->lost_resource_count); |
+ // Clear the manager of resources. |
+ ui_resource_.reset(); |
+ PostSetNeedsCommitToMainThread(); |
+ break; |
+ case 4: |
+ // Sequence 3: |
+ ui_resource_ = FakeScopedUIResource::Create(layer_tree_host()); |
+ test_id0_ = ui_resource_->id(); |
+ // Sanity check the UIResourceId should not be 0. |
+ EXPECT_NE(0, test_id0_); |
+ // Usually ScopedUIResource are deleted from the manager in their |
+ // destructor (so usually ui_resource_.reset()). But here we need |
+ // ui_resource_ for the next step, so call DeleteUIResource directly. |
+ layer_tree_host()->DeleteUIResource(test_id0_); |
+ LoseContext(); |
+ break; |
+ case 5: |
+ // Expect the resource callback to have been called once. |
+ EXPECT_EQ(1, ui_resource_->resource_create_count); |
+ // No "resource lost" callbacks. |
+ EXPECT_EQ(0, ui_resource_->lost_resource_count); |
+ if (!layer_tree_host()->settings().impl_side_painting) { |
+ // The UI resource id should not be valid |
+ EXPECT_EQ(0u, impl->ResourceIdForUIResource(test_id0_)); |
+ } |
+ PostSetNeedsCommitToMainThread(); |
+ break; |
+ case 6: |
+ ui_resource_.reset(); |
+ EndTest(); |
+ break; |
+ } |
+ } |
+ |
+ virtual void DidActivateTreeOnThread(LayerTreeHostImpl* impl) OVERRIDE { |
+ LayerTreeHostContextTest::DidActivateTreeOnThread(impl); |
+ switch (time_step_) { |
+ case 1: |
+ if (layer_tree_host()->settings().impl_side_painting) |
+ EXPECT_NE(0u, impl->ResourceIdForUIResource(ui_resource_->id())); |
+ break; |
+ case 3: |
+ if (layer_tree_host()->settings().impl_side_painting) { |
+ EXPECT_EQ(0u, impl->ResourceIdForUIResource(test_id0_)); |
+ EXPECT_NE(0u, impl->ResourceIdForUIResource(test_id1_)); |
+ } |
+ break; |
+ case 5: |
+ if (layer_tree_host()->settings().impl_side_painting) |
+ EXPECT_EQ(0u, impl->ResourceIdForUIResource(test_id0_)); |
+ break; |
+ } |
+ ++time_step_; |
+ } |
+ |
+ private: |
+ UIResourceId test_id0_; |
+ UIResourceId test_id1_; |
+}; |
+ |
+SINGLE_AND_MULTI_THREAD_TEST_F(UIResourceLostBeforeCommit); |
+ |
+// Losing UI resource before the pending trees is activated but after the |
+// commit. Impl-side-painting only. |
+class UIResourceLostBeforeActivateTree : public UIResourceLostTest { |
+ virtual void CommitCompleteOnThread(LayerTreeHostImpl* impl) OVERRIDE { |
+ LayerTreeHostContextTest::CommitCompleteOnThread(impl); |
+ switch (time_step_) { |
+ case 0: |
+ ui_resource_ = FakeScopedUIResource::Create(layer_tree_host()); |
+ PostSetNeedsCommitToMainThread(); |
+ break; |
+ case 2: |
+ PostSetNeedsCommitToMainThread(); |
+ break; |
+ case 3: |
+ test_id_ = ui_resource_->id(); |
+ ui_resource_.reset(); |
+ PostSetNeedsCommitToMainThread(); |
+ break; |
+ case 4: |
+ PostSetNeedsCommitToMainThread(); |
+ break; |
+ case 5: |
+ EndTest(); |
+ break; |
+ } |
+ } |
+ |
+ virtual void WillActivateTreeOnThread(LayerTreeHostImpl* impl) OVERRIDE { |
+ switch (time_step_) { |
+ case 0: |
+ break; |
+ case 1: |
+ // The resource creation callback has been called. |
+ EXPECT_EQ(1, ui_resource_->resource_create_count); |
+ // The resource is not yet lost (sanity check). |
+ EXPECT_EQ(0, ui_resource_->lost_resource_count); |
+ // The resource should not have been created yet on the impl-side. |
+ EXPECT_EQ(0u, impl->ResourceIdForUIResource(ui_resource_->id())); |
+ LoseContext(); |
+ break; |
+ case 3: |
+ LoseContext(); |
+ break; |
+ } |
+ } |
+ |
+ virtual void DidActivateTreeOnThread(LayerTreeHostImpl* impl) OVERRIDE { |
+ LayerTreeHostContextTest::DidActivateTreeOnThread(impl); |
+ switch (time_step_) { |
+ case 1: |
+ // The pending requests on the impl-side should have been processed. |
+ EXPECT_NE(0u, impl->ResourceIdForUIResource(ui_resource_->id())); |
+ break; |
+ case 2: |
+ // The "lost resource" callback should have been called once. |
+ EXPECT_EQ(1, ui_resource_->lost_resource_count); |
+ break; |
+ case 4: |
+ // The resource is deleted and should not be in the manager. Use |
+ // test_id_ since ui_resource_ has been deleted. |
+ EXPECT_EQ(0u, impl->ResourceIdForUIResource(test_id_)); |
+ break; |
+ } |
+ ++time_step_; |
+ } |
+ |
+ private: |
+ UIResourceId test_id_; |
+}; |
+ |
+TEST_F(UIResourceLostBeforeActivateTree, |
+ RunMultiThread_DirectRenderer_ImplSidePaint) { |
+ RunTest(true, false, true); |
+} |
+ |
+TEST_F(UIResourceLostBeforeActivateTree, |
+ RunMultiThread_DelegatingRenderer_ImplSidePaint) { |
+ RunTest(true, true, true); |
+} |
+ |
} // namespace |
} // namespace cc |