summaryrefslogtreecommitdiffstats
path: root/cc
diff options
context:
space:
mode:
authorpiman@chromium.org <piman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-03-29 02:27:54 +0000
committerpiman@chromium.org <piman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-03-29 02:27:54 +0000
commit97d519fbd5e9bf800444226b52593059ef0940dc (patch)
treebee7231a3045731852cd6bea920a56641794dd74 /cc
parent49ecc3ddbff6988b6614a70da44f56c1feb49308 (diff)
downloadchromium_src-97d519fbd5e9bf800444226b52593059ef0940dc.zip
chromium_src-97d519fbd5e9bf800444226b52593059ef0940dc.tar.gz
chromium_src-97d519fbd5e9bf800444226b52593059ef0940dc.tar.bz2
TextureLayer: clear texture id when clearing client.
This is to avoid having the impl side accessing a texture that's been deleted. BUG=224308 Review URL: https://chromiumcodereview.appspot.com/13126002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@191268 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'cc')
-rw-r--r--cc/layers/texture_layer.cc5
-rw-r--r--cc/layers/texture_layer.h2
-rw-r--r--cc/layers/texture_layer_unittest.cc112
3 files changed, 118 insertions, 1 deletions
diff --git a/cc/layers/texture_layer.cc b/cc/layers/texture_layer.cc
index acabc87..eb62c0d 100644
--- a/cc/layers/texture_layer.cc
+++ b/cc/layers/texture_layer.cc
@@ -64,6 +64,11 @@ TextureLayer::~TextureLayer() {
texture_mailbox_.RunReleaseCallback(texture_mailbox_.sync_point());
}
+void TextureLayer::ClearClient() {
+ client_ = NULL;
+ SetTextureId(0);
+}
+
scoped_ptr<LayerImpl> TextureLayer::CreateLayerImpl(LayerTreeImpl* tree_impl) {
return TextureLayerImpl::Create(tree_impl, id(), uses_mailbox_).
PassAs<LayerImpl>();
diff --git a/cc/layers/texture_layer.h b/cc/layers/texture_layer.h
index 1e7b31b..ad8d44f 100644
--- a/cc/layers/texture_layer.h
+++ b/cc/layers/texture_layer.h
@@ -29,7 +29,7 @@ class CC_EXPORT TextureLayer : public Layer {
// Used when mailbox names are specified instead of texture IDs.
static scoped_refptr<TextureLayer> CreateForMailbox();
- void ClearClient() { client_ = NULL; }
+ void ClearClient();
virtual scoped_ptr<LayerImpl> CreateLayerImpl(LayerTreeImpl* tree_impl)
OVERRIDE;
diff --git a/cc/layers/texture_layer_unittest.cc b/cc/layers/texture_layer_unittest.cc
index 6d20988..912eff9 100644
--- a/cc/layers/texture_layer_unittest.cc
+++ b/cc/layers/texture_layer_unittest.cc
@@ -8,6 +8,7 @@
#include "base/callback.h"
#include "cc/base/thread.h"
+#include "cc/layers/texture_layer_client.h"
#include "cc/layers/texture_layer_impl.h"
#include "cc/test/fake_impl_proxy.h"
#include "cc/test/fake_layer_tree_host_client.h"
@@ -474,5 +475,116 @@ TEST_F(TextureLayerImplWithMailboxTest, TestCallbackOnInUseResource) {
provider->ReceiveFromParent(list);
}
+// Check that ClearClient correctly clears the state so that the impl side
+// doesn't try to use a texture that could have been destroyed.
+class TextureLayerClientTest :
+ public LayerTreeTest,
+ public TextureLayerClient {
+ public:
+ TextureLayerClientTest()
+ : context_(NULL),
+ texture_(0),
+ commit_count_(0),
+ expected_used_textures_on_draw_(0),
+ expected_used_textures_on_commit_(0) {}
+
+ virtual scoped_ptr<OutputSurface> CreateOutputSurface() OVERRIDE {
+ scoped_ptr<TestWebGraphicsContext3D> context(
+ TestWebGraphicsContext3D::Create());
+ context_ = context.get();
+ texture_ = context->createTexture();
+ return FakeOutputSurface::Create3d(
+ context.PassAs<WebKit::WebGraphicsContext3D>()).PassAs<OutputSurface>();
+ }
+
+ virtual unsigned PrepareTexture(ResourceUpdateQueue* queue) {
+ return texture_;
+ }
+
+ virtual WebKit::WebGraphicsContext3D* Context3d() {
+ return context_;
+ }
+
+ virtual void SetupTree() OVERRIDE {
+ scoped_refptr<Layer> root = Layer::Create();
+ root->SetBounds(gfx::Size(10, 10));
+ root->SetAnchorPoint(gfx::PointF());
+ root->SetIsDrawable(true);
+
+ texture_layer_ = TextureLayer::Create(this);
+ texture_layer_->SetBounds(gfx::Size(10, 10));
+ texture_layer_->SetAnchorPoint(gfx::PointF());
+ texture_layer_->SetIsDrawable(true);
+ root->AddChild(texture_layer_);
+
+ layer_tree_host()->SetRootLayer(root);
+ LayerTreeTest::SetupTree();
+ {
+ base::AutoLock lock(lock_);
+ expected_used_textures_on_commit_ = 1;
+ }
+ }
+
+ virtual void BeginTest() OVERRIDE {
+ PostSetNeedsCommitToMainThread();
+ }
+
+ virtual void DidCommitAndDrawFrame() OVERRIDE {
+ ++commit_count_;
+ switch (commit_count_) {
+ case 1:
+ texture_layer_->ClearClient();
+ texture_layer_->SetNeedsDisplay();
+ {
+ base::AutoLock lock(lock_);
+ expected_used_textures_on_commit_ = 0;
+ }
+ texture_ = 0;
+ break;
+ case 2:
+ EndTest();
+ break;
+ default:
+ NOTREACHED();
+ break;
+ }
+ }
+
+ virtual void BeginCommitOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
+ base::AutoLock lock(lock_);
+ expected_used_textures_on_draw_ = expected_used_textures_on_commit_;
+ }
+
+ virtual bool PrepareToDrawOnThread(LayerTreeHostImpl* host_impl,
+ LayerTreeHostImpl::FrameData* frame_data,
+ bool result) OVERRIDE {
+ context_->ResetUsedTextures();
+ return true;
+ }
+
+ virtual void SwapBuffersOnThread(LayerTreeHostImpl* host_impl,
+ bool result) OVERRIDE {
+ ASSERT_TRUE(result);
+ EXPECT_EQ(expected_used_textures_on_draw_, context_->NumUsedTextures());
+ }
+
+ virtual void AfterTest() OVERRIDE {}
+
+ private:
+ scoped_refptr<TextureLayer> texture_layer_;
+ TestWebGraphicsContext3D* context_;
+ unsigned texture_;
+ int commit_count_;
+
+ // Used only on thread.
+ unsigned expected_used_textures_on_draw_;
+
+ // Used on either thread, protected by lock_.
+ base::Lock lock_;
+ unsigned expected_used_textures_on_commit_;
+};
+
+SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerClientTest);
+
} // namespace
} // namespace cc