cc: Don't crash on a GL texture given to TextureLayer when in software

BUG=230257

Review URL: https://chromiumcodereview.appspot.com/18560007

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@210139 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/cc/layers/texture_layer_impl.cc b/cc/layers/texture_layer_impl.cc
index c5258cf..ce5251d5 100644
--- a/cc/layers/texture_layer_impl.cc
+++ b/cc/layers/texture_layer_impl.cc
@@ -67,12 +67,30 @@
   if (draw_mode == DRAW_MODE_RESOURCELESS_SOFTWARE)
     return false;
 
-  if (!uses_mailbox_ && texture_id_) {
+  if (uses_mailbox_) {
+    if (own_mailbox_) {
+      DCHECK(!external_texture_resource_);
+      if ((draw_mode == DRAW_MODE_HARDWARE && texture_mailbox_.IsTexture()) ||
+          (draw_mode == DRAW_MODE_SOFTWARE &&
+           texture_mailbox_.IsSharedMemory())) {
+        // TODO(piman): for shm mailboxes in HW mode, we could upload into a
+        // resource here.
+        external_texture_resource_ =
+            resource_provider->CreateResourceFromTextureMailbox(
+                texture_mailbox_);
+        DCHECK(external_texture_resource_);
+      }
+      if (external_texture_resource_)
+        own_mailbox_ = false;
+    }
+  } else if (texture_id_) {
     DCHECK(!external_texture_resource_);
-    external_texture_resource_ =
-        resource_provider->CreateResourceFromExternalTexture(
-            GL_TEXTURE_2D,
-            texture_id_);
+    if (draw_mode == DRAW_MODE_HARDWARE) {
+      external_texture_resource_ =
+          resource_provider->CreateResourceFromExternalTexture(
+              GL_TEXTURE_2D,
+              texture_id_);
+    }
   }
   return external_texture_resource_ &&
          LayerImpl::WillDraw(draw_mode, resource_provider);
@@ -136,18 +154,6 @@
   return true;
 }
 
-void TextureLayerImpl::DidBecomeActive() {
-  if (!own_mailbox_)
-    return;
-  DCHECK(!external_texture_resource_);
-  ResourceProvider* resource_provider = layer_tree_impl()->resource_provider();
-  if (texture_mailbox_.IsValid()) {
-    external_texture_resource_ =
-        resource_provider->CreateResourceFromTextureMailbox(texture_mailbox_);
-  }
-  own_mailbox_ = false;
-}
-
 void TextureLayerImpl::FreeTextureMailbox() {
   if (!uses_mailbox_)
     return;
diff --git a/cc/layers/texture_layer_impl.h b/cc/layers/texture_layer_impl.h
index b23498e..63a9c0f3 100644
--- a/cc/layers/texture_layer_impl.h
+++ b/cc/layers/texture_layer_impl.h
@@ -34,8 +34,6 @@
 
   virtual void DidLoseOutputSurface() OVERRIDE;
 
-  virtual void DidBecomeActive() OVERRIDE;
-
   unsigned texture_id() const { return texture_id_; }
   void set_texture_id(unsigned id) { texture_id_ = id; }
   void set_premultiplied_alpha(bool premultiplied_alpha) {
diff --git a/cc/layers/texture_layer_unittest.cc b/cc/layers/texture_layer_unittest.cc
index ee4f469..39c0836 100644
--- a/cc/layers/texture_layer_unittest.cc
+++ b/cc/layers/texture_layer_unittest.cc
@@ -465,6 +465,14 @@
     EXPECT_TRUE(host_impl_.InitializeRenderer(CreateFakeOutputSurface()));
   }
 
+  bool WillDraw(TextureLayerImpl* layer, DrawMode mode) {
+    bool will_draw = layer->WillDraw(
+        mode, host_impl_.active_tree()->resource_provider());
+    if (will_draw)
+      layer->DidDraw(host_impl_.active_tree()->resource_provider());
+    return will_draw;
+  }
+
   CommonMailboxObjects test_data_;
   FakeLayerTreeHostClient fake_client_;
 };
@@ -472,23 +480,35 @@
 // Test conditions for results of TextureLayerImpl::WillDraw under
 // different configurations of different mailbox, texture_id, and draw_mode.
 TEST_F(TextureLayerImplWithMailboxTest, TestWillDraw) {
+  EXPECT_CALL(test_data_.mock_callback_,
+              Release(test_data_.mailbox_name1_,
+                      test_data_.sync_point1_,
+                      false))
+      .Times(AnyNumber());
+  EXPECT_CALL(test_data_.mock_callback_,
+              Release2(test_data_.shared_memory_.get(), 0, false))
+      .Times(AnyNumber());
   // Hardware mode.
   {
     scoped_ptr<TextureLayerImpl> impl_layer =
         TextureLayerImpl::Create(host_impl_.active_tree(), 1, true);
     impl_layer->SetTextureMailbox(test_data_.mailbox1_);
-    impl_layer->DidBecomeActive();
-    EXPECT_TRUE(impl_layer->WillDraw(
-        DRAW_MODE_HARDWARE, host_impl_.active_tree()->resource_provider()));
-    impl_layer->DidDraw(host_impl_.active_tree()->resource_provider());
+    EXPECT_TRUE(WillDraw(impl_layer.get(), DRAW_MODE_HARDWARE));
   }
 
   {
     scoped_ptr<TextureLayerImpl> impl_layer =
         TextureLayerImpl::Create(host_impl_.active_tree(), 1, true);
-    impl_layer->SetTextureMailbox(test_data_.mailbox1_);
-    EXPECT_FALSE(impl_layer->WillDraw(
-        DRAW_MODE_HARDWARE, host_impl_.active_tree()->resource_provider()));
+    impl_layer->SetTextureMailbox(TextureMailbox());
+    EXPECT_FALSE(WillDraw(impl_layer.get(), DRAW_MODE_HARDWARE));
+  }
+
+  {
+    // Software resource.
+    scoped_ptr<TextureLayerImpl> impl_layer =
+        TextureLayerImpl::Create(host_impl_.active_tree(), 1, true);
+    impl_layer->SetTextureMailbox(test_data_.mailbox3_);
+    EXPECT_FALSE(WillDraw(impl_layer.get(), DRAW_MODE_HARDWARE));
   }
 
   {
@@ -497,17 +517,53 @@
     unsigned texture =
         host_impl_.output_surface()->context3d()->createTexture();
     impl_layer->set_texture_id(texture);
-    EXPECT_TRUE(impl_layer->WillDraw(
-        DRAW_MODE_HARDWARE, host_impl_.active_tree()->resource_provider()));
-    impl_layer->DidDraw(host_impl_.active_tree()->resource_provider());
+    EXPECT_TRUE(WillDraw(impl_layer.get(), DRAW_MODE_HARDWARE));
   }
 
   {
     scoped_ptr<TextureLayerImpl> impl_layer =
         TextureLayerImpl::Create(host_impl_.active_tree(), 1, false);
     impl_layer->set_texture_id(0);
-    EXPECT_FALSE(impl_layer->WillDraw(
-        DRAW_MODE_HARDWARE, host_impl_.active_tree()->resource_provider()));
+    EXPECT_FALSE(WillDraw(impl_layer.get(), DRAW_MODE_HARDWARE));
+  }
+
+  // Software mode.
+  {
+    scoped_ptr<TextureLayerImpl> impl_layer =
+        TextureLayerImpl::Create(host_impl_.active_tree(), 1, true);
+    impl_layer->SetTextureMailbox(test_data_.mailbox1_);
+    EXPECT_FALSE(WillDraw(impl_layer.get(), DRAW_MODE_SOFTWARE));
+  }
+
+  {
+    scoped_ptr<TextureLayerImpl> impl_layer =
+        TextureLayerImpl::Create(host_impl_.active_tree(), 1, true);
+    impl_layer->SetTextureMailbox(TextureMailbox());
+    EXPECT_FALSE(WillDraw(impl_layer.get(), DRAW_MODE_SOFTWARE));
+  }
+
+  {
+    // Software resource.
+    scoped_ptr<TextureLayerImpl> impl_layer =
+        TextureLayerImpl::Create(host_impl_.active_tree(), 1, true);
+    impl_layer->SetTextureMailbox(test_data_.mailbox3_);
+    EXPECT_TRUE(WillDraw(impl_layer.get(), DRAW_MODE_SOFTWARE));
+  }
+
+  {
+    scoped_ptr<TextureLayerImpl> impl_layer =
+        TextureLayerImpl::Create(host_impl_.active_tree(), 1, false);
+    unsigned texture =
+        host_impl_.output_surface()->context3d()->createTexture();
+    impl_layer->set_texture_id(texture);
+    EXPECT_FALSE(WillDraw(impl_layer.get(), DRAW_MODE_SOFTWARE));
+  }
+
+  {
+    scoped_ptr<TextureLayerImpl> impl_layer =
+        TextureLayerImpl::Create(host_impl_.active_tree(), 1, false);
+    impl_layer->set_texture_id(0);
+    EXPECT_FALSE(WillDraw(impl_layer.get(), DRAW_MODE_SOFTWARE));
   }
 
   // Resourceless software mode.
@@ -515,10 +571,7 @@
     scoped_ptr<TextureLayerImpl> impl_layer =
         TextureLayerImpl::Create(host_impl_.active_tree(), 1, true);
     impl_layer->SetTextureMailbox(test_data_.mailbox1_);
-    impl_layer->DidBecomeActive();
-    EXPECT_FALSE(
-        impl_layer->WillDraw(DRAW_MODE_RESOURCELESS_SOFTWARE,
-                             host_impl_.active_tree()->resource_provider()));
+    EXPECT_FALSE(WillDraw(impl_layer.get(), DRAW_MODE_RESOURCELESS_SOFTWARE));
   }
 
   {
@@ -527,9 +580,7 @@
     unsigned texture =
         host_impl_.output_surface()->context3d()->createTexture();
     impl_layer->set_texture_id(texture);
-    EXPECT_FALSE(
-        impl_layer->WillDraw(DRAW_MODE_RESOURCELESS_SOFTWARE,
-                             host_impl_.active_tree()->resource_provider()));
+    EXPECT_FALSE(WillDraw(impl_layer.get(), DRAW_MODE_RESOURCELESS_SOFTWARE));
   }
 }
 
diff --git a/webkit/tools/layout_tests/test_expectations.txt b/webkit/tools/layout_tests/test_expectations.txt
index 4229c65..d2012336 100644
--- a/webkit/tools/layout_tests/test_expectations.txt
+++ b/webkit/tools/layout_tests/test_expectations.txt
@@ -30,3 +30,6 @@
 # src/third_party/WebKit/LayoutTests/TestExpectations . Right?)
 #
 # EVERYTHING BELOW THIS LINE WILL BE DELETED AT EVERY WEBKIT DEPS ROLL
+crbug.com/230257 virtual/softwarecompositing/plugins/webplugin-alpha.html [ ImageOnlyFailure ]
+crbug.com/230257 virtual/softwarecompositing/plugins/webplugin-no-alpha.html [ ImageOnlyFailure ]
+crbug.com/230257 virtual/softwarecompositing/plugins/webplugin-reflection.html [ ImageOnlyFailure ]