diff options
author | piman@chromium.org <piman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-03-29 02:27:54 +0000 |
---|---|---|
committer | piman@chromium.org <piman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-03-29 02:27:54 +0000 |
commit | 97d519fbd5e9bf800444226b52593059ef0940dc (patch) | |
tree | bee7231a3045731852cd6bea920a56641794dd74 /cc | |
parent | 49ecc3ddbff6988b6614a70da44f56c1feb49308 (diff) | |
download | chromium_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.cc | 5 | ||||
-rw-r--r-- | cc/layers/texture_layer.h | 2 | ||||
-rw-r--r-- | cc/layers/texture_layer_unittest.cc | 112 |
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 |