Index: cc/layer_tree_host_unittest_context.cc |
diff --git a/cc/layer_tree_host_unittest_context.cc b/cc/layer_tree_host_unittest_context.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..06ca8e3c3cd13143870da9900f90945b562e98bb |
--- /dev/null |
+++ b/cc/layer_tree_host_unittest_context.cc |
@@ -0,0 +1,758 @@ |
+// Copyright 2012 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/layer_tree_host.h" |
+ |
+#include "base/basictypes.h" |
+#include "cc/content_layer.h" |
+#include "cc/delegated_renderer_layer.h" |
+#include "cc/delegated_renderer_layer_impl.h" |
+#include "cc/heads_up_display_layer.h" |
+#include "cc/io_surface_layer.h" |
+#include "cc/layer_impl.h" |
+#include "cc/layer_tree_host_impl.h" |
+#include "cc/layer_tree_impl.h" |
+#include "cc/scrollbar_layer.h" |
+#include "cc/single_thread_proxy.h" |
+#include "cc/test/fake_content_layer.h" |
+#include "cc/test/fake_content_layer_client.h" |
+#include "cc/test/fake_content_layer_impl.h" |
+#include "cc/test/fake_output_surface.h" |
+#include "cc/test/fake_scrollbar_theme_painter.h" |
+#include "cc/test/fake_video_frame.h" |
+#include "cc/test/fake_video_frame_provider.h" |
+#include "cc/test/fake_web_graphics_context_3d.h" |
+#include "cc/test/fake_web_scrollbar.h" |
+#include "cc/test/fake_web_scrollbar_theme_geometry.h" |
+#include "cc/test/layer_tree_test_common.h" |
+#include "cc/test/render_pass_test_common.h" |
+#include "cc/texture_layer.h" |
+#include "cc/video_layer.h" |
+#include "cc/video_layer_impl.h" |
+#include "media/base/media.h" |
+ |
+using media::VideoFrame; |
+using WebKit::WebGraphicsContext3D; |
+ |
+namespace cc { |
+namespace { |
+ |
+// These tests deal with losing the 3d graphics context. |
+class LayerTreeHostContextTest : public ThreadedTest { |
+ public: |
+ LayerTreeHostContextTest() |
+ : ThreadedTest(), |
+ context3d_(NULL), |
+ times_to_fail_create_(0), |
+ times_to_create_and_lose_(0), |
+ times_to_lose_during_commit_(0), |
+ times_to_repeat_loss_(0), |
+ times_to_fail_recreate_(0) { |
+ media::InitializeMediaLibraryForTesting(); |
+ } |
+ |
+ void LoseContext() { |
+ context3d_->loseContextCHROMIUM(); |
+ context3d_ = NULL; |
+ } |
+ |
+ virtual scoped_ptr<FakeWebGraphicsContext3D> CreateContext3d() { |
+ return FakeWebGraphicsContext3D::Create(); |
+ } |
+ |
+ virtual scoped_ptr<OutputSurface> createOutputSurface() OVERRIDE { |
+ if (times_to_fail_create_) { |
+ --times_to_fail_create_; |
+ return scoped_ptr<OutputSurface>(); |
+ } |
+ |
+ scoped_ptr<FakeWebGraphicsContext3D> context3d = CreateContext3d(); |
+ context3d_ = context3d.get(); |
+ |
+ if (times_to_create_and_lose_) { |
+ --times_to_create_and_lose_; |
+ // Make the context get lost during reinitialization. |
+ // The number of times MakeCurrent succeeds is not important, and |
+ // can be changed if needed to make this pass with future changes. |
+ context3d_->set_times_make_current_succeeds(2); |
+ } |
+ |
+ return FakeOutputSurface::Create3d( |
+ context3d.PassAs<WebGraphicsContext3D>()).PassAs<OutputSurface>(); |
+ } |
+ |
+ virtual void commitCompleteOnThread(LayerTreeHostImpl *host_impl) OVERRIDE { |
+ if (!times_to_lose_during_commit_) |
+ return; |
+ --times_to_lose_during_commit_; |
+ LoseContext(); |
+ |
+ times_to_create_and_lose_ = times_to_repeat_loss_; |
+ times_to_repeat_loss_ = 0; |
+ times_to_fail_create_ = times_to_fail_recreate_; |
+ times_to_fail_recreate_ = 0; |
+ } |
+ |
+ protected: |
+ FakeWebGraphicsContext3D* context3d_; |
+ int times_to_fail_create_; |
+ int times_to_create_and_lose_; |
+ int times_to_lose_during_commit_; |
+ int times_to_repeat_loss_; |
+ int times_to_fail_recreate_; |
+}; |
+ |
+class LayerTreeHostContextTestLostContextSucceeds : |
+ public LayerTreeHostContextTest { |
+ public: |
+ LayerTreeHostContextTestLostContextSucceeds() |
+ : LayerTreeHostContextTest(), |
+ test_case_(0), |
+ num_losses_(0) { |
+ } |
+ |
+ virtual void beginTest() OVERRIDE { |
+ postSetNeedsCommitToMainThread(); |
+ } |
+ |
+ virtual void didRecreateOutputSurface(bool succeeded) OVERRIDE { |
+ EXPECT_TRUE(succeeded); |
+ ++num_losses_; |
+ } |
+ |
+ virtual void afterTest() OVERRIDE { |
+ EXPECT_EQ(3, test_case_); |
+ EXPECT_EQ(3, num_losses_); |
+ } |
+ |
+ bool SourceFrameHasContextLoss(int source_frame) const { |
+ return source_frame % 2 == 1; |
+ } |
+ |
+ virtual void didCommitAndDrawFrame() OVERRIDE { |
+ // If the last frame had a context loss, then we'll commit again to |
+ // recover. |
+ if (SourceFrameHasContextLoss(m_layerTreeHost->commitNumber()) - 1) |
+ return; |
+ |
+ if (NextTestCase()) |
+ m_layerTreeHost->setNeedsCommit(); |
+ else |
+ endTest(); |
+ } |
+ |
+ bool NextTestCase() { |
+ static const TestCase kTests[] = { |
+ // Losing the context and failing to recreate it (or losing it again |
+ // immediately) a small number of times should succeed. |
+ { 1, // times_to_lose_during_commit |
+ 0, // times_to_repeat_loss |
+ 0, // times_to_fail_recreate |
+ }, |
+ { 1, |
+ 3, // times_to_repeat_loss |
+ 0, // times_to_fail_recreate |
+ }, |
+ { 1, |
+ 0, // times_to_repeat_loss |
+ 3, // times_to_fail_recreate |
+ }, |
+ }; |
+ |
+ if (test_case_ >= arraysize(kTests)) |
+ return false; |
+ |
+ times_to_lose_during_commit_ = |
+ kTests[test_case_].times_to_lose_during_commit; |
+ times_to_repeat_loss_ = kTests[test_case_].times_to_repeat_loss; |
+ times_to_fail_recreate_ = kTests[test_case_].times_to_fail_recreate; |
+ ++test_case_; |
+ return true; |
+ } |
+ |
+ struct TestCase { |
+ int times_to_lose_during_commit; |
+ int times_to_repeat_loss; |
+ int times_to_fail_recreate; |
+ }; |
+ |
+ private: |
+ size_t test_case_; |
+ int num_losses_; |
+}; |
+ |
+SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostContextTestLostContextSucceeds) |
+ |
+template<bool kUseSurface> |
jamesr
2013/01/03 22:59:07
Why the template? Code inside a TEST_F body is a
|
+class LayerTreeHostContextTestLostContextSucceedsWithContent : |
+ public LayerTreeHostContextTestLostContextSucceeds { |
+ public: |
+ |
+ LayerTreeHostContextTestLostContextSucceedsWithContent() |
+ : LayerTreeHostContextTestLostContextSucceeds() { |
+ } |
+ |
+ virtual void setupTree() OVERRIDE { |
+ scoped_refptr<Layer> root_ = Layer::create(); |
+ root_->setBounds(gfx::Size(10, 10)); |
+ root_->setAnchorPoint(gfx::PointF()); |
+ root_->setIsDrawable(true); |
+ |
+ scoped_refptr<FakeContentLayer> content_ = |
+ FakeContentLayer::Create(&client_); |
+ content_->setBounds(gfx::Size(10, 10)); |
+ content_->setAnchorPoint(gfx::PointF()); |
+ content_->setIsDrawable(true); |
+ if (kUseSurface) |
+ content_->setForceRenderSurface(true); |
+ root_->addChild(content_); |
+ |
+ m_layerTreeHost->setRootLayer(root_); |
+ LayerTreeHostContextTest::setupTree(); |
+ } |
+ |
+ virtual void drawLayersOnThread(LayerTreeHostImpl* host_impl) { |
+ FakeContentLayerImpl* content_impl = static_cast<FakeContentLayerImpl*>( |
+ host_impl->rootLayer()->children()[0]); |
+ // Even though the context was lost, we should have a resource. The |
+ // FakeWebGraphicsContext3D ensures that this resource is created with |
+ // the active context. |
+ EXPECT_TRUE(content_impl->HaveResourceForTileAt(0, 0)); |
+ } |
+ |
+ protected: |
+ FakeContentLayerClient client_; |
+ scoped_refptr<Layer> root_; |
+ scoped_refptr<ContentLayer> content_; |
+}; |
+ |
+class LayerTreeHostContextTestLostContextSucceedsWithContent_NoSurface |
+ : public LayerTreeHostContextTestLostContextSucceedsWithContent<false> {}; |
+ |
+SINGLE_AND_MULTI_THREAD_TEST_F( |
+ LayerTreeHostContextTestLostContextSucceedsWithContent_NoSurface) |
+ |
+class LayerTreeHostContextTestLostContextSucceedsWithContent_WithSurface |
+ : public LayerTreeHostContextTestLostContextSucceedsWithContent<true> {}; |
+ |
+SINGLE_AND_MULTI_THREAD_TEST_F( |
+ LayerTreeHostContextTestLostContextSucceedsWithContent_WithSurface) |
+ |
+template<int kTimesToRepeatLoss, int kTimesToFailRecreate> |
+class LayerTreeHostContextTestLostContextFails : |
+ public LayerTreeHostContextTest { |
+ public: |
+ LayerTreeHostContextTestLostContextFails() |
+ : LayerTreeHostContextTest(), |
+ num_commits_(0) { |
+ times_to_lose_during_commit_ = 1; |
+ times_to_repeat_loss_ = kTimesToRepeatLoss; |
+ times_to_fail_recreate_ = kTimesToFailRecreate; |
+ } |
+ |
+ virtual void beginTest() OVERRIDE { |
+ postSetNeedsCommitToMainThread(); |
+ } |
+ |
+ virtual void didRecreateOutputSurface(bool succeeded) OVERRIDE { |
+ EXPECT_FALSE(succeeded); |
+ endTest(); |
+ } |
+ |
+ virtual void commitCompleteOnThread(LayerTreeHostImpl* host_impl) OVERRIDE { |
+ LayerTreeHostContextTest::commitCompleteOnThread(host_impl); |
+ |
+ ++num_commits_; |
+ if (num_commits_ == 1) { |
+ // When the context is ok, we should have these things. |
+ EXPECT_TRUE(host_impl->outputSurface()); |
+ EXPECT_TRUE(host_impl->renderer()); |
+ EXPECT_TRUE(host_impl->resourceProvider()); |
+ return; |
+ } |
+ |
+ // When context recreation fails we shouldn't be left with any of them. |
+ EXPECT_FALSE(host_impl->outputSurface()); |
+ EXPECT_FALSE(host_impl->renderer()); |
+ EXPECT_FALSE(host_impl->resourceProvider()); |
+ } |
+ |
+ virtual void afterTest() OVERRIDE {} |
+ |
+ private: |
+ int num_commits_; |
+}; |
+ |
+class LayerTreeHostContextTestLostContextFails_RepeatLoss100 |
+ : public LayerTreeHostContextTestLostContextFails<100, 0> {}; |
+ |
+SINGLE_AND_MULTI_THREAD_TEST_F( |
+ LayerTreeHostContextTestLostContextFails_RepeatLoss100) |
+ |
+class LayerTreeHostContextTestLostContextFails_FailRecreate100 |
+ : public LayerTreeHostContextTestLostContextFails<0, 100> {}; |
+ |
+SINGLE_AND_MULTI_THREAD_TEST_F( |
+ LayerTreeHostContextTestLostContextFails_FailRecreate100) |
+ |
+class LayerTreeHostContextTestFinishAllRenderingAfterLoss : |
+ public LayerTreeHostContextTest { |
+ public: |
+ virtual void beginTest() OVERRIDE { |
+ // Lose the context until the compositor gives up on it. |
+ times_to_lose_during_commit_ = 1; |
+ times_to_repeat_loss_ = 10; |
+ postSetNeedsCommitToMainThread(); |
+ } |
+ |
+ virtual void didRecreateOutputSurface(bool succeeded) OVERRIDE { |
+ EXPECT_FALSE(succeeded); |
+ m_layerTreeHost->finishAllRendering(); |
+ endTest(); |
+ } |
+ |
+ virtual void afterTest() OVERRIDE {} |
+}; |
+ |
+SINGLE_AND_MULTI_THREAD_TEST_F( |
+ LayerTreeHostContextTestFinishAllRenderingAfterLoss) |
+ |
+template<bool kLoseAfterEvict> |
+class LayerTreeHostContextTestLostContextAndEvictTextures : |
+ public LayerTreeHostContextTest { |
+ public: |
+ LayerTreeHostContextTestLostContextAndEvictTextures() |
+ : LayerTreeHostContextTest(), |
+ layer_(FakeContentLayer::Create(&client_)), |
+ impl_host_(0), |
+ num_commits_(0) { |
+ } |
+ |
+ virtual void setupTree() OVERRIDE { |
+ layer_->setBounds(gfx::Size(10, 20)); |
+ m_layerTreeHost->setRootLayer(layer_); |
+ LayerTreeHostContextTest::setupTree(); |
+ } |
+ |
+ virtual void beginTest() OVERRIDE { |
+ postSetNeedsCommitToMainThread(); |
+ } |
+ |
+ void PostEvictTextures() { |
+ if (implThread()) { |
+ implThread()->postTask( |
+ base::Bind( |
+ &LayerTreeHostContextTestLostContextAndEvictTextures:: |
+ EvictTexturesOnImplThread, |
+ base::Unretained(this))); |
+ } else { |
+ DebugScopedSetImplThread impl(proxy()); |
+ EvictTexturesOnImplThread(); |
+ } |
+ } |
+ |
+ void EvictTexturesOnImplThread() { |
+ impl_host_->enforceManagedMemoryPolicy(ManagedMemoryPolicy(0)); |
+ if (kLoseAfterEvict) |
+ LoseContext(); |
+ } |
+ |
+ virtual void didCommitAndDrawFrame() OVERRIDE { |
+ if (num_commits_ > 1) |
+ return; |
+ EXPECT_TRUE(layer_->HaveBackingAt(0, 0)); |
+ PostEvictTextures(); |
+ } |
+ |
+ virtual void commitCompleteOnThread(LayerTreeHostImpl* impl) OVERRIDE { |
+ if (num_commits_ > 1) |
+ return; |
+ ++num_commits_; |
+ if (!kLoseAfterEvict) |
+ LoseContext(); |
+ impl_host_ = impl; |
+ } |
+ |
+ virtual void didRecreateOutputSurface(bool succeeded) OVERRIDE { |
+ EXPECT_TRUE(succeeded); |
+ endTest(); |
+ } |
+ |
+ virtual void afterTest() OVERRIDE {} |
+ |
+ private: |
+ FakeContentLayerClient client_; |
+ scoped_refptr<FakeContentLayer> layer_; |
+ LayerTreeHostImpl* impl_host_; |
+ int num_commits_; |
+}; |
+ |
+class LayerTreeHostContextTestLostContextAndEvictTextures_LoseAfterEvict |
+ : public LayerTreeHostContextTestLostContextAndEvictTextures<true> {}; |
+ |
+SINGLE_AND_MULTI_THREAD_TEST_F( |
+ LayerTreeHostContextTestLostContextAndEvictTextures_LoseAfterEvict); |
+ |
+class LayerTreeHostContextTestLostContextAndEvictTextures_LoseBeforeEvict |
+ : public LayerTreeHostContextTestLostContextAndEvictTextures<false> {}; |
+ |
+SINGLE_AND_MULTI_THREAD_TEST_F( |
+ LayerTreeHostContextTestLostContextAndEvictTextures_LoseBeforeEvict); |
+ |
+class LayerTreeHostContextTestLostContextWhileUpdatingResources : |
+ public LayerTreeHostContextTest { |
+ public: |
+ LayerTreeHostContextTestLostContextWhileUpdatingResources() |
+ : parent_(FakeContentLayer::Create(&client_)), |
+ num_children_(50), |
+ times_to_lose_on_end_query_(3) { |
+ } |
+ |
+ virtual scoped_ptr<FakeWebGraphicsContext3D> CreateContext3d() { |
+ scoped_ptr<FakeWebGraphicsContext3D> context = |
+ LayerTreeHostContextTest::CreateContext3d(); |
+ if (times_to_lose_on_end_query_) { |
+ --times_to_lose_on_end_query_; |
+ context->set_times_end_query_succeeds(5); |
+ } |
+ return context.Pass(); |
+ } |
+ |
+ virtual void setupTree() { |
+ parent_->setBounds(gfx::Size(num_children_, 1)); |
+ |
+ for (int i = 0; i < num_children_; i++) { |
+ scoped_refptr<FakeContentLayer> child = |
+ FakeContentLayer::Create(&client_); |
+ child->setPosition(gfx::PointF(i, 0.f)); |
+ child->setBounds(gfx::Size(1, 1)); |
+ parent_->addChild(child); |
+ } |
+ |
+ m_layerTreeHost->setRootLayer(parent_); |
+ LayerTreeHostContextTest::setupTree(); |
+ } |
+ |
+ virtual void beginTest() { |
+ postSetNeedsCommitToMainThread(); |
+ } |
+ |
+ virtual void commitCompleteOnThread(LayerTreeHostImpl* impl) { |
+ endTest(); |
+ } |
+ |
+ virtual void didRecreateOutputSurface(bool succeeded) OVERRIDE { |
+ EXPECT_TRUE(succeeded); |
+ } |
+ |
+ virtual void afterTest() { |
+ EXPECT_EQ(0, times_to_lose_on_end_query_); |
+ } |
+ |
+ private: |
+ FakeContentLayerClient client_; |
+ scoped_refptr<FakeContentLayer> parent_; |
+ int num_children_; |
+ int times_to_lose_on_end_query_; |
+}; |
+ |
+SINGLE_AND_MULTI_THREAD_TEST_F( |
+ LayerTreeHostContextTestLostContextWhileUpdatingResources) |
+ |
+class LayerTreeHostContextTestLayersNotified : |
+ public LayerTreeHostContextTest { |
+ public: |
+ LayerTreeHostContextTestLayersNotified() |
+ : LayerTreeHostContextTest(), |
+ num_commits_(0) { |
+ } |
+ |
+ virtual void setupTree() OVERRIDE { |
+ root_ = FakeContentLayer::Create(&client_); |
+ child_ = FakeContentLayer::Create(&client_); |
+ grandchild_ = FakeContentLayer::Create(&client_); |
+ |
+ root_->addChild(child_); |
+ child_->addChild(grandchild_); |
+ |
+ m_layerTreeHost->setRootLayer(root_); |
+ LayerTreeHostContextTest::setupTree(); |
+ } |
+ |
+ virtual void beginTest() OVERRIDE { |
+ postSetNeedsCommitToMainThread(); |
+ } |
+ |
+ virtual void commitCompleteOnThread(LayerTreeHostImpl* host_impl) OVERRIDE { |
+ FakeContentLayerImpl* root = static_cast<FakeContentLayerImpl*>( |
+ host_impl->rootLayer()); |
+ FakeContentLayerImpl* child = static_cast<FakeContentLayerImpl*>( |
+ root->children()[0]); |
+ FakeContentLayerImpl* grandchild = static_cast<FakeContentLayerImpl*>( |
+ child->children()[0]); |
+ |
+ ++num_commits_; |
+ switch (num_commits_) { |
+ case 1: |
+ EXPECT_EQ(0u, root->lost_output_surface_count()); |
+ EXPECT_EQ(0u, child->lost_output_surface_count()); |
+ EXPECT_EQ(0u, grandchild->lost_output_surface_count()); |
+ // Lose the context and struggle to recreate it. |
+ LoseContext(); |
+ times_to_fail_create_ = 1; |
+ break; |
+ case 2: |
+ EXPECT_EQ(1u, root->lost_output_surface_count()); |
+ EXPECT_EQ(1u, child->lost_output_surface_count()); |
+ EXPECT_EQ(1u, grandchild->lost_output_surface_count()); |
+ // Lose the context and again during recreate. |
+ LoseContext(); |
+ times_to_create_and_lose_ = 1; |
+ break; |
+ case 3: |
+ EXPECT_EQ(3u, root->lost_output_surface_count()); |
+ EXPECT_EQ(3u, child->lost_output_surface_count()); |
+ EXPECT_EQ(3u, grandchild->lost_output_surface_count()); |
+ endTest(); |
+ break; |
+ default: |
+ NOTREACHED(); |
+ } |
+ } |
+ |
+ virtual void afterTest() OVERRIDE {} |
+ |
+ private: |
+ int num_commits_; |
+ |
+ FakeContentLayerClient client_; |
+ scoped_refptr<FakeContentLayer> root_; |
+ scoped_refptr<FakeContentLayer> child_; |
+ scoped_refptr<FakeContentLayer> grandchild_; |
+}; |
+ |
+SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostContextTestLayersNotified) |
+ |
+class LayerTreeHostContextTestDontUseLostResources : |
+ public LayerTreeHostContextTest { |
+ public: |
+ virtual void setupTree() OVERRIDE { |
+ context3d_->set_have_extension_io_surface(true); |
+ context3d_->set_have_extension_egl_image(true); |
+ |
+ scoped_refptr<Layer> root_ = Layer::create(); |
+ root_->setBounds(gfx::Size(10, 10)); |
+ root_->setAnchorPoint(gfx::PointF()); |
+ root_->setIsDrawable(true); |
+ |
+ scoped_refptr<DelegatedRendererLayer> delegated_ = |
+ DelegatedRendererLayer::create(); |
+ delegated_->setBounds(gfx::Size(10, 10)); |
+ delegated_->setAnchorPoint(gfx::PointF()); |
+ delegated_->setIsDrawable(true); |
+ root_->addChild(delegated_); |
+ |
+ scoped_refptr<ContentLayer> content_ = ContentLayer::create(&client_); |
+ content_->setBounds(gfx::Size(10, 10)); |
+ content_->setAnchorPoint(gfx::PointF()); |
+ content_->setIsDrawable(true); |
+ root_->addChild(content_); |
+ |
+ scoped_refptr<TextureLayer> texture_ = TextureLayer::create(NULL); |
+ texture_->setBounds(gfx::Size(10, 10)); |
+ texture_->setAnchorPoint(gfx::PointF()); |
+ texture_->setTextureId(FakeWebGraphicsContext3D::kExternalTextureId); |
+ texture_->setIsDrawable(true); |
+ root_->addChild(texture_); |
+ |
+ scoped_refptr<ContentLayer> mask_ = ContentLayer::create(&client_); |
+ mask_->setBounds(gfx::Size(10, 10)); |
+ mask_->setAnchorPoint(gfx::PointF()); |
+ |
+ scoped_refptr<ContentLayer> content_with_mask_ = |
+ ContentLayer::create(&client_); |
+ content_with_mask_->setBounds(gfx::Size(10, 10)); |
+ content_with_mask_->setAnchorPoint(gfx::PointF()); |
+ content_with_mask_->setIsDrawable(true); |
+ content_with_mask_->setMaskLayer(mask_.get()); |
+ root_->addChild(content_with_mask_); |
+ |
+ VideoLayerImpl::FrameUnwrapper unwrapper = |
+ base::Bind(FakeVideoFrame::ToVideoFrame); |
+ |
+ scoped_refptr<VideoLayer> video_color_ = VideoLayer::create( |
+ &color_frame_provider_, unwrapper); |
+ video_color_->setBounds(gfx::Size(10, 10)); |
+ video_color_->setAnchorPoint(gfx::PointF()); |
+ video_color_->setIsDrawable(true); |
+ root_->addChild(video_color_); |
+ |
+ scoped_refptr<VideoLayer> video_hw_ = VideoLayer::create( |
+ &hw_frame_provider_, unwrapper); |
+ video_hw_->setBounds(gfx::Size(10, 10)); |
+ video_hw_->setAnchorPoint(gfx::PointF()); |
+ video_hw_->setIsDrawable(true); |
+ root_->addChild(video_hw_); |
+ |
+ scoped_refptr<VideoLayer> video_scaled_hw_ = VideoLayer::create( |
+ &scaled_hw_frame_provider_, unwrapper); |
+ video_scaled_hw_->setBounds(gfx::Size(10, 10)); |
+ video_scaled_hw_->setAnchorPoint(gfx::PointF()); |
+ video_scaled_hw_->setIsDrawable(true); |
+ root_->addChild(video_scaled_hw_); |
+ |
+ scoped_refptr<IOSurfaceLayer> io_surface_ = IOSurfaceLayer::create(); |
+ io_surface_->setBounds(gfx::Size(10, 10)); |
+ io_surface_->setAnchorPoint(gfx::PointF()); |
+ io_surface_->setIsDrawable(true); |
+ io_surface_->setIOSurfaceProperties(1, gfx::Size(10, 10)); |
+ root_->addChild(io_surface_); |
+ |
+ scoped_refptr<HeadsUpDisplayLayer> hud_ = HeadsUpDisplayLayer::create(); |
+ hud_->setBounds(gfx::Size(10, 10)); |
+ hud_->setAnchorPoint(gfx::PointF()); |
+ hud_->setIsDrawable(true); |
+ root_->addChild(hud_); |
+ // Enable the hud. |
+ LayerTreeDebugState debug_state; |
+ debug_state.showFPSCounter = true; |
+ m_layerTreeHost->setDebugState(debug_state); |
+ |
+ bool paint_scrollbar = true; |
+ bool has_thumb = true; |
+ scoped_refptr<ScrollbarLayer> scrollbar_ = ScrollbarLayer::create( |
+ FakeWebScrollbar::create().PassAs<WebKit::WebScrollbar>(), |
+ FakeScrollbarThemePainter::Create(paint_scrollbar) |
+ .PassAs<ScrollbarThemePainter>(), |
+ FakeWebScrollbarThemeGeometry::create(has_thumb) |
+ .PassAs<WebKit::WebScrollbarThemeGeometry>(), |
+ content_->id()); |
+ scrollbar_->setBounds(gfx::Size(10, 10)); |
+ scrollbar_->setAnchorPoint(gfx::PointF()); |
+ scrollbar_->setIsDrawable(true); |
+ root_->addChild(scrollbar_); |
+ |
+ m_layerTreeHost->setRootLayer(root_); |
+ LayerTreeHostContextTest::setupTree(); |
+ } |
+ |
+ virtual void beginTest() OVERRIDE { |
+ postSetNeedsCommitToMainThread(); |
+ } |
+ |
+ virtual void commitCompleteOnThread(LayerTreeHostImpl* host_impl) OVERRIDE { |
+ ResourceProvider* resource_provider = host_impl->resourceProvider(); |
+ |
+ if (host_impl->activeTree()->source_frame_number() == 0) { |
+ // Set up impl resources on the first commit. |
+ |
+ scoped_ptr<TestRenderPass> pass_for_quad = TestRenderPass::Create(); |
+ pass_for_quad->SetNew( |
+ // AppendOneOfEveryQuadType() makes a RenderPass quad with this id. |
+ RenderPass::Id(1, 1), |
+ gfx::Rect(0, 0, 10, 10), |
+ gfx::Rect(0, 0, 10, 10), |
+ gfx::Transform()); |
+ |
+ scoped_ptr<TestRenderPass> pass = TestRenderPass::Create(); |
+ pass->SetNew( |
+ RenderPass::Id(2, 1), |
+ gfx::Rect(0, 0, 10, 10), |
+ gfx::Rect(0, 0, 10, 10), |
+ gfx::Transform()); |
+ pass->AppendOneOfEveryQuadType(resource_provider); |
+ |
+ ScopedPtrVector<RenderPass> pass_list; |
+ pass_list.append(pass_for_quad.PassAs<RenderPass>()); |
+ pass_list.append(pass.PassAs<RenderPass>()); |
+ |
+ // First child is the delegated layer. |
+ DelegatedRendererLayerImpl* delegated_impl = |
+ static_cast<DelegatedRendererLayerImpl*>( |
+ host_impl->rootLayer()->children()[0]); |
+ delegated_impl->setRenderPasses(pass_list); |
+ EXPECT_TRUE(pass_list.isEmpty()); |
+ |
+ color_video_frame_ = make_scoped_ptr(new FakeVideoFrame( |
+ VideoFrame::CreateColorFrame( |
+ gfx::Size(4, 4), 0x80, 0x80, 0x80, base::TimeDelta()))); |
+ hw_video_frame_ = make_scoped_ptr(new FakeVideoFrame( |
+ VideoFrame::WrapNativeTexture( |
+ resource_provider->graphicsContext3D()->createTexture(), |
+ GL_TEXTURE_2D, |
+ gfx::Size(4, 4), gfx::Rect(0, 0, 4, 4), gfx::Size(4, 4), |
+ base::TimeDelta(), |
+ VideoFrame::ReadPixelsCB(), |
+ base::Closure()))); |
+ scaled_hw_video_frame_ = make_scoped_ptr(new FakeVideoFrame( |
+ VideoFrame::WrapNativeTexture( |
+ resource_provider->graphicsContext3D()->createTexture(), |
+ GL_TEXTURE_2D, |
+ gfx::Size(4, 4), gfx::Rect(0, 0, 3, 2), gfx::Size(4, 4), |
+ base::TimeDelta(), |
+ VideoFrame::ReadPixelsCB(), |
+ base::Closure()))); |
+ |
+ color_frame_provider_.set_frame(color_video_frame_.get()); |
+ hw_frame_provider_.set_frame(hw_video_frame_.get()); |
+ scaled_hw_frame_provider_.set_frame(scaled_hw_video_frame_.get()); |
+ return; |
+ } |
+ |
+ if (host_impl->activeTree()->source_frame_number() == 3) { |
+ // On the third commit we're recovering from context loss. Hardware |
+ // video frames should not be reused by the VideoFrameProvider, but |
+ // software frames can be. |
+ hw_frame_provider_.set_frame(NULL); |
+ scaled_hw_frame_provider_.set_frame(NULL); |
+ } |
+ } |
+ |
+ virtual bool prepareToDrawOnThread(LayerTreeHostImpl* host_impl) { |
+ if (host_impl->activeTree()->source_frame_number() == 2) { |
+ // Lose the context during draw on the second commit. This will cause |
+ // a third commit to recover. |
+ if (context3d_) |
+ context3d_->set_times_bind_texture_succeeds(4); |
+ } |
+ return true; |
+ } |
+ |
+ virtual void didCommitAndDrawFrame() OVERRIDE { |
+ // End the test once we know the 3nd frame drew. |
+ if (m_layerTreeHost->commitNumber() == 4) |
+ endTest(); |
+ } |
+ |
+ virtual void afterTest() OVERRIDE {} |
+ |
+ private: |
+ FakeContentLayerClient client_; |
+ |
+ scoped_refptr<Layer> root_; |
+ scoped_refptr<DelegatedRendererLayer> delegated_; |
+ scoped_refptr<ContentLayer> content_; |
+ scoped_refptr<TextureLayer> texture_; |
+ scoped_refptr<ContentLayer> mask_; |
+ scoped_refptr<ContentLayer> content_with_mask_; |
+ scoped_refptr<VideoLayer> video_color_; |
+ scoped_refptr<VideoLayer> video_hw_; |
+ scoped_refptr<VideoLayer> video_scaled_hw_; |
+ scoped_refptr<IOSurfaceLayer> io_surface_; |
+ scoped_refptr<HeadsUpDisplayLayer> hud_; |
+ scoped_refptr<ScrollbarLayer> scrollbar_; |
+ |
+ scoped_ptr<FakeVideoFrame> color_video_frame_; |
+ scoped_ptr<FakeVideoFrame> hw_video_frame_; |
+ scoped_ptr<FakeVideoFrame> scaled_hw_video_frame_; |
+ |
+ FakeVideoFrameProvider color_frame_provider_; |
+ FakeVideoFrameProvider hw_frame_provider_; |
+ FakeVideoFrameProvider scaled_hw_frame_provider_; |
+}; |
+ |
+SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostContextTestDontUseLostResources) |
+ |
+} // namespace |
+} // namespace cc |