diff options
author | danakj@chromium.org <danakj@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-09-17 01:24:16 +0000 |
---|---|---|
committer | danakj@chromium.org <danakj@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-09-17 01:24:16 +0000 |
commit | 9260757f9dd8de119450e6cc351dda15df17cf8d (patch) | |
tree | 1aa791088cd401d42e714c1b102635e7e4caf480 /cc | |
parent | 0ceda8a5374cf90e636134835d41c3194c52b0bc (diff) | |
download | chromium_src-9260757f9dd8de119450e6cc351dda15df17cf8d.zip chromium_src-9260757f9dd8de119450e6cc351dda15df17cf8d.tar.gz chromium_src-9260757f9dd8de119450e6cc351dda15df17cf8d.tar.bz2 |
cc: Move TextureMailbox::ReleaseCallback to SingleReleaseCallback.
This moves the release callback out of the TextureMailbox so that we
can use it for other resource types than just texture mailboxes.
While doing this, we make a SingleReleaseCallback class that is
held in a scoped_ptr. This class DCHECKs that the callback is run
before it is destroyed, and ensures clear ownership semantics as
you must Pass() the callback around.
No change in behaviour, covered by existing tests.
R=piman
BUG=263069
Review URL: https://chromiumcodereview.appspot.com/23648014
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@223500 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'cc')
30 files changed, 471 insertions, 286 deletions
@@ -314,6 +314,7 @@ 'resources/raster_mode.h', 'resources/raster_worker_pool.cc', 'resources/raster_worker_pool.h', + 'resources/release_callback.h', 'resources/resource.cc', 'resources/resource.h', 'resources/resource_pool.cc', @@ -331,6 +332,8 @@ 'resources/scoped_resource.h', 'resources/scoped_ui_resource.cc', 'resources/scoped_ui_resource.h', + 'resources/single_release_callback.cc', + 'resources/single_release_callback.h', 'resources/skpicture_content_layer_updater.cc', 'resources/skpicture_content_layer_updater.h', 'resources/sync_point_helper.cc', diff --git a/cc/layers/texture_layer.cc b/cc/layers/texture_layer.cc index d4a1314..340526e 100644 --- a/cc/layers/texture_layer.cc +++ b/cc/layers/texture_layer.cc @@ -5,10 +5,12 @@ #include "cc/layers/texture_layer.h" #include "base/bind.h" +#include "base/callback_helpers.h" #include "base/location.h" #include "base/synchronization/lock.h" #include "cc/layers/texture_layer_client.h" #include "cc/layers/texture_layer_impl.h" +#include "cc/resources/single_release_callback.h" #include "cc/trees/blocking_task_runner.h" #include "cc/trees/layer_tree_host.h" #include "third_party/WebKit/public/platform/WebGraphicsContext3D.h" @@ -51,7 +53,7 @@ void TextureLayer::ClearClient() { layer_tree_host()->StopRateLimiter(client_->Context3d()); client_ = NULL; if (uses_mailbox_) - SetTextureMailbox(TextureMailbox()); + SetTextureMailbox(TextureMailbox(), scoped_ptr<SingleReleaseCallback>()); else SetTextureId(0); } @@ -130,13 +132,17 @@ void TextureLayer::SetTextureId(unsigned id) { SetNextCommitWaitsForActivation(); } -void TextureLayer::SetTextureMailbox(const TextureMailbox& mailbox) { +void TextureLayer::SetTextureMailbox( + const TextureMailbox& mailbox, + scoped_ptr<SingleReleaseCallback> release_callback) { DCHECK(uses_mailbox_); DCHECK(!mailbox.IsValid() || !holder_ref_ || !mailbox.Equals(holder_ref_->holder()->mailbox())); + DCHECK_EQ(mailbox.IsValid(), !!release_callback); + // If we never commited the mailbox, we need to release it here. if (mailbox.IsValid()) - holder_ref_ = MailboxHolder::Create(mailbox); + holder_ref_ = MailboxHolder::Create(mailbox, release_callback.Pass()); else holder_ref_.reset(); needs_set_mailbox_ = true; @@ -198,9 +204,12 @@ bool TextureLayer::Update(ResourceUpdateQueue* queue, if (client_) { if (uses_mailbox_) { TextureMailbox mailbox; + scoped_ptr<SingleReleaseCallback> release_callback; if (client_->PrepareTextureMailbox( - &mailbox, layer_tree_host()->UsingSharedMemoryResources())) { - SetTextureMailbox(mailbox); + &mailbox, + &release_callback, + layer_tree_host()->UsingSharedMemoryResources())) { + SetTextureMailbox(mailbox, release_callback.Pass()); updated = true; } } else { @@ -235,13 +244,13 @@ void TextureLayer::PushPropertiesTo(LayerImpl* layer) { texture_layer->set_blend_background_color(blend_background_color_); if (uses_mailbox_ && needs_set_mailbox_) { TextureMailbox texture_mailbox; + scoped_ptr<SingleReleaseCallback> release_callback; if (holder_ref_) { MailboxHolder* holder = holder_ref_->holder(); - TextureMailbox::ReleaseCallback callback = - holder->GetCallbackForImplThread(); - texture_mailbox = holder->mailbox().CopyWithNewCallback(callback); + texture_mailbox = holder->mailbox(); + release_callback = holder->GetCallbackForImplThread(); } - texture_layer->SetTextureMailbox(texture_mailbox); + texture_layer->SetTextureMailbox(texture_mailbox, release_callback.Pass()); needs_set_mailbox_ = false; } else { texture_layer->set_texture_id(texture_id_); @@ -273,10 +282,13 @@ TextureLayer::MailboxHolder::MainThreadReference::~MainThreadReference() { holder_->InternalRelease(); } -TextureLayer::MailboxHolder::MailboxHolder(const TextureMailbox& mailbox) +TextureLayer::MailboxHolder::MailboxHolder( + const TextureMailbox& mailbox, + scoped_ptr<SingleReleaseCallback> release_callback) : message_loop_(BlockingTaskRunner::current()), internal_references_(0), mailbox_(mailbox), + release_callback_(release_callback.Pass()), sync_point_(mailbox.sync_point()), is_lost_(false) { } @@ -286,9 +298,11 @@ TextureLayer::MailboxHolder::~MailboxHolder() { } scoped_ptr<TextureLayer::MailboxHolder::MainThreadReference> -TextureLayer::MailboxHolder::Create(const TextureMailbox& mailbox) { +TextureLayer::MailboxHolder::Create( + const TextureMailbox& mailbox, + scoped_ptr<SingleReleaseCallback> release_callback) { return scoped_ptr<MainThreadReference>(new MainThreadReference( - new MailboxHolder(mailbox))); + new MailboxHolder(mailbox, release_callback.Pass()))); } void TextureLayer::MailboxHolder::Return(unsigned sync_point, bool is_lost) { @@ -297,13 +311,14 @@ void TextureLayer::MailboxHolder::Return(unsigned sync_point, bool is_lost) { is_lost_ = is_lost; } -TextureMailbox::ReleaseCallback +scoped_ptr<SingleReleaseCallback> TextureLayer::MailboxHolder::GetCallbackForImplThread() { // We can't call GetCallbackForImplThread if we released the main thread // reference. DCHECK_GT(internal_references_, 0u); InternalAddRef(); - return base::Bind(&MailboxHolder::ReturnAndReleaseOnImplThread, this); + return SingleReleaseCallback::Create( + base::Bind(&MailboxHolder::ReturnAndReleaseOnImplThread, this)); } void TextureLayer::MailboxHolder::InternalAddRef() { @@ -313,8 +328,9 @@ void TextureLayer::MailboxHolder::InternalAddRef() { void TextureLayer::MailboxHolder::InternalRelease() { DCHECK(message_loop_->BelongsToCurrentThread()); if (!--internal_references_) { - mailbox_.RunReleaseCallback(sync_point_, is_lost_); - DCHECK(mailbox_.callback().is_null()); + release_callback_->Run(sync_point_, is_lost_); + mailbox_ = TextureMailbox(); + release_callback_.reset(); } } diff --git a/cc/layers/texture_layer.h b/cc/layers/texture_layer.h index cb34cf5..5fb214c 100644 --- a/cc/layers/texture_layer.h +++ b/cc/layers/texture_layer.h @@ -17,6 +17,7 @@ namespace WebKit { class WebGraphicsContext3D; } namespace cc { class BlockingTaskRunner; +class SingleReleaseCallback; class TextureLayerClient; // A Layer containing a the rendered output of a plugin instance. @@ -41,20 +42,22 @@ class CC_EXPORT TextureLayer : public Layer { // Gets a ReleaseCallback that can be called from another thread. Note: the // caller must ensure the callback is called. - TextureMailbox::ReleaseCallback GetCallbackForImplThread(); + scoped_ptr<SingleReleaseCallback> GetCallbackForImplThread(); protected: friend class TextureLayer; // Protected visiblity so only TextureLayer and unit tests can create these. static scoped_ptr<MainThreadReference> Create( - const TextureMailbox& mailbox); + const TextureMailbox& mailbox, + scoped_ptr<SingleReleaseCallback> release_callback); virtual ~MailboxHolder(); private: friend class base::RefCountedThreadSafe<MailboxHolder>; friend class MainThreadReference; - explicit MailboxHolder(const TextureMailbox& mailbox); + explicit MailboxHolder(const TextureMailbox& mailbox, + scoped_ptr<SingleReleaseCallback> release_callback); void InternalAddRef(); void InternalRelease(); @@ -67,6 +70,7 @@ class CC_EXPORT TextureLayer : public Layer { // during commit where the main thread is blocked. unsigned internal_references_; TextureMailbox mailbox_; + scoped_ptr<SingleReleaseCallback> release_callback_; // This lock guards the sync_point_ and is_lost_ fields because they can be // accessed on both the impl and main thread. We do this to ensure that the @@ -125,7 +129,8 @@ class CC_EXPORT TextureLayer : public Layer { // Code path for plugins which supply their own mailbox. bool uses_mailbox() const { return uses_mailbox_; } - void SetTextureMailbox(const TextureMailbox& mailbox); + void SetTextureMailbox(const TextureMailbox& mailbox, + scoped_ptr<SingleReleaseCallback> release_callback); void WillModifyTexture(); diff --git a/cc/layers/texture_layer_client.h b/cc/layers/texture_layer_client.h index 73d34b3..187b12f 100644 --- a/cc/layers/texture_layer_client.h +++ b/cc/layers/texture_layer_client.h @@ -5,6 +5,8 @@ #ifndef CC_LAYERS_TEXTURE_LAYER_CLIENT_H_ #define CC_LAYERS_TEXTURE_LAYER_CLIENT_H_ +#include "cc/resources/single_release_callback.h" + namespace WebKit { class WebGraphicsContext3D; } namespace cc { @@ -24,8 +26,10 @@ class TextureLayerClient { // Returns true and provides a mailbox if a new frame is available. // Returns false if no new data is available // and the old mailbox is to be reused. - virtual bool PrepareTextureMailbox(TextureMailbox* mailbox, - bool use_shared_memory) = 0; + virtual bool PrepareTextureMailbox( + TextureMailbox* mailbox, + scoped_ptr<SingleReleaseCallback>* release_callback, + bool use_shared_memory) = 0; protected: virtual ~TextureLayerClient() {} diff --git a/cc/layers/texture_layer_impl.cc b/cc/layers/texture_layer_impl.cc index 851bf9a..413708d 100644 --- a/cc/layers/texture_layer_impl.cc +++ b/cc/layers/texture_layer_impl.cc @@ -4,12 +4,15 @@ #include "cc/layers/texture_layer_impl.h" +#include <vector> + #include "base/strings/stringprintf.h" #include "cc/layers/quad_sink.h" #include "cc/output/renderer.h" #include "cc/quads/texture_draw_quad.h" #include "cc/resources/platform_color.h" #include "cc/resources/scoped_resource.h" +#include "cc/resources/single_release_callback.h" #include "cc/trees/layer_tree_impl.h" namespace cc { @@ -36,10 +39,14 @@ TextureLayerImpl::TextureLayerImpl(LayerTreeImpl* tree_impl, TextureLayerImpl::~TextureLayerImpl() { FreeTextureMailbox(); } -void TextureLayerImpl::SetTextureMailbox(const TextureMailbox& mailbox) { +void TextureLayerImpl::SetTextureMailbox( + const TextureMailbox& mailbox, + scoped_ptr<SingleReleaseCallback> release_callback) { DCHECK(uses_mailbox_); + DCHECK_EQ(mailbox.IsValid(), !!release_callback); FreeTextureMailbox(); texture_mailbox_ = mailbox; + release_callback_ = release_callback.Pass(); own_mailbox_ = true; valid_texture_copy_ = false; } @@ -60,7 +67,8 @@ void TextureLayerImpl::PushPropertiesTo(LayerImpl* layer) { texture_layer->set_vertex_opacity(vertex_opacity_); texture_layer->set_premultiplied_alpha(premultiplied_alpha_); if (uses_mailbox_ && own_mailbox_) { - texture_layer->SetTextureMailbox(texture_mailbox_); + texture_layer->SetTextureMailbox(texture_mailbox_, + release_callback_.Pass()); own_mailbox_ = false; } else { texture_layer->set_texture_id(texture_id_); @@ -80,7 +88,8 @@ bool TextureLayerImpl::WillDraw(DrawMode draw_mode, texture_mailbox_.IsSharedMemory())) { external_texture_resource_ = resource_provider->CreateResourceFromTextureMailbox( - texture_mailbox_); + texture_mailbox_, + release_callback_.Pass()); DCHECK(external_texture_resource_); texture_copy_.reset(); valid_texture_copy_ = false; @@ -229,7 +238,10 @@ void TextureLayerImpl::FreeTextureMailbox() { return; if (own_mailbox_) { DCHECK(!external_texture_resource_); - texture_mailbox_.RunReleaseCallback(texture_mailbox_.sync_point(), false); + if (release_callback_) + release_callback_->Run(texture_mailbox_.sync_point(), false); + texture_mailbox_ = TextureMailbox(); + release_callback_.reset(); } else if (external_texture_resource_) { DCHECK(!own_mailbox_); ResourceProvider* resource_provider = diff --git a/cc/layers/texture_layer_impl.h b/cc/layers/texture_layer_impl.h index f857206..90c2692 100644 --- a/cc/layers/texture_layer_impl.h +++ b/cc/layers/texture_layer_impl.h @@ -12,6 +12,7 @@ #include "cc/layers/layer_impl.h" namespace cc { +class SingleReleaseCallback; class ScopedResource; class CC_EXPORT TextureLayerImpl : public LayerImpl { @@ -61,7 +62,8 @@ class CC_EXPORT TextureLayerImpl : public LayerImpl { virtual bool CanClipSelf() const OVERRIDE; - void SetTextureMailbox(const TextureMailbox& mailbox); + void SetTextureMailbox(const TextureMailbox& mailbox, + scoped_ptr<SingleReleaseCallback> release_callback); private: TextureLayerImpl(LayerTreeImpl* tree_impl, int id, bool uses_mailbox); @@ -81,6 +83,7 @@ class CC_EXPORT TextureLayerImpl : public LayerImpl { scoped_ptr<ScopedResource> texture_copy_; TextureMailbox texture_mailbox_; + scoped_ptr<SingleReleaseCallback> release_callback_; bool uses_mailbox_; bool own_mailbox_; bool valid_texture_copy_; diff --git a/cc/layers/texture_layer_unittest.cc b/cc/layers/texture_layer_unittest.cc index cf13ebe..3126ddb 100644 --- a/cc/layers/texture_layer_unittest.cc +++ b/cc/layers/texture_layer_unittest.cc @@ -255,9 +255,12 @@ class FakeTextureLayerClient : public TextureLayerClient { return context_.get(); } - virtual bool PrepareTextureMailbox(TextureMailbox* mailbox, - bool use_shared_memory) OVERRIDE { + virtual bool PrepareTextureMailbox( + TextureMailbox* mailbox, + scoped_ptr<SingleReleaseCallback>* release_callback, + bool use_shared_memory) OVERRIDE { *mailbox = TextureMailbox(); + *release_callback = scoped_ptr<SingleReleaseCallback>(); return true; } @@ -340,25 +343,25 @@ struct CommonMailboxObjects { mailbox_name2_); gpu::Mailbox m1; m1.SetName(reinterpret_cast<const int8*>(mailbox_name1_.data())); - mailbox1_ = TextureMailbox(m1, release_mailbox1_, sync_point1_); + mailbox1_ = TextureMailbox(m1, sync_point1_); gpu::Mailbox m2; m2.SetName(reinterpret_cast<const int8*>(mailbox_name2_.data())); - mailbox2_ = TextureMailbox(m2, release_mailbox2_, sync_point2_); + mailbox2_ = TextureMailbox(m2, sync_point2_); gfx::Size size(128, 128); EXPECT_TRUE(shared_memory_->CreateAndMapAnonymous(4 * size.GetArea())); release_mailbox3_ = base::Bind(&MockMailboxCallback::Release2, base::Unretained(&mock_callback_), shared_memory_.get()); - mailbox3_ = TextureMailbox(shared_memory_.get(), size, release_mailbox3_); + mailbox3_ = TextureMailbox(shared_memory_.get(), size); } std::string mailbox_name1_; std::string mailbox_name2_; MockMailboxCallback mock_callback_; - TextureMailbox::ReleaseCallback release_mailbox1_; - TextureMailbox::ReleaseCallback release_mailbox2_; - TextureMailbox::ReleaseCallback release_mailbox3_; + ReleaseCallback release_mailbox1_; + ReleaseCallback release_mailbox2_; + ReleaseCallback release_mailbox3_; TextureMailbox mailbox1_; TextureMailbox mailbox2_; TextureMailbox mailbox3_; @@ -400,7 +403,9 @@ TEST_F(TextureLayerWithMailboxTest, ReplaceMailboxOnMainThreadBeforeCommit) { EXPECT_CALL(*layer_tree_host_, AcquireLayerTextures()).Times(0); EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1)); - test_layer->SetTextureMailbox(test_data_.mailbox1_); + test_layer->SetTextureMailbox( + test_data_.mailbox1_, + SingleReleaseCallback::Create(test_data_.release_mailbox1_)); Mock::VerifyAndClearExpectations(layer_tree_host_.get()); EXPECT_CALL(*layer_tree_host_, AcquireLayerTextures()).Times(0); @@ -410,7 +415,9 @@ TEST_F(TextureLayerWithMailboxTest, ReplaceMailboxOnMainThreadBeforeCommit) { test_data_.sync_point1_, false)) .Times(1); - test_layer->SetTextureMailbox(test_data_.mailbox2_); + test_layer->SetTextureMailbox( + test_data_.mailbox2_, + SingleReleaseCallback::Create(test_data_.release_mailbox2_)); Mock::VerifyAndClearExpectations(layer_tree_host_.get()); Mock::VerifyAndClearExpectations(&test_data_.mock_callback_); @@ -421,13 +428,16 @@ TEST_F(TextureLayerWithMailboxTest, ReplaceMailboxOnMainThreadBeforeCommit) { test_data_.sync_point2_, false)) .Times(1); - test_layer->SetTextureMailbox(TextureMailbox()); + test_layer->SetTextureMailbox(TextureMailbox(), + scoped_ptr<SingleReleaseCallback>()); Mock::VerifyAndClearExpectations(layer_tree_host_.get()); Mock::VerifyAndClearExpectations(&test_data_.mock_callback_); EXPECT_CALL(*layer_tree_host_, AcquireLayerTextures()).Times(0); EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1)); - test_layer->SetTextureMailbox(test_data_.mailbox3_); + test_layer->SetTextureMailbox( + test_data_.mailbox3_, + SingleReleaseCallback::Create(test_data_.release_mailbox3_)); Mock::VerifyAndClearExpectations(layer_tree_host_.get()); Mock::VerifyAndClearExpectations(&test_data_.mock_callback_); @@ -437,13 +447,16 @@ TEST_F(TextureLayerWithMailboxTest, ReplaceMailboxOnMainThreadBeforeCommit) { Release2(test_data_.shared_memory_.get(), 0, false)) .Times(1); - test_layer->SetTextureMailbox(TextureMailbox()); + test_layer->SetTextureMailbox(TextureMailbox(), + scoped_ptr<SingleReleaseCallback>()); Mock::VerifyAndClearExpectations(layer_tree_host_.get()); Mock::VerifyAndClearExpectations(&test_data_.mock_callback_); // Test destructor. EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1)); - test_layer->SetTextureMailbox(test_data_.mailbox1_); + test_layer->SetTextureMailbox( + test_data_.mailbox1_, + SingleReleaseCallback::Create(test_data_.release_mailbox1_)); } class TextureLayerMailboxHolderTest : public TextureLayerTest { @@ -465,14 +478,15 @@ class TextureLayerMailboxHolderTest : public TextureLayerTest { void CreateMainRef() { main_ref_ = TestMailboxHolder::Create( - test_data_.mailbox1_).Pass(); + test_data_.mailbox1_, + SingleReleaseCallback::Create(test_data_.release_mailbox1_)).Pass(); } void ReleaseMainRef() { main_ref_.reset(); } - void CreateImplRef(TextureMailbox::ReleaseCallback* impl_ref) { + void CreateImplRef(scoped_ptr<SingleReleaseCallback>* impl_ref) { *impl_ref = main_ref_->holder()->GetCallbackForImplThread(); } @@ -505,7 +519,7 @@ TEST_F(TextureLayerMailboxHolderTest, TwoCompositors_BothReleaseThenMain) { // The texture layer is attached to compositor1, and passes a reference to its // impl tree. - TextureMailbox::ReleaseCallback compositor1; + scoped_ptr<SingleReleaseCallback> compositor1; main_thread_.message_loop()->PostTask( FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef, @@ -514,7 +528,7 @@ TEST_F(TextureLayerMailboxHolderTest, TwoCompositors_BothReleaseThenMain) { // Then the texture layer is removed and attached to compositor2, and passes a // reference to its impl tree. - TextureMailbox::ReleaseCallback compositor2; + scoped_ptr<SingleReleaseCallback> compositor2; main_thread_.message_loop()->PostTask( FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef, @@ -526,8 +540,8 @@ TEST_F(TextureLayerMailboxHolderTest, TwoCompositors_BothReleaseThenMain) { // The compositors both destroy their impl trees before the main thread layer // is destroyed. - compositor1.Run(100, false); - compositor2.Run(200, false); + compositor1->Run(100, false); + compositor2->Run(200, false); Wait(main_thread_); @@ -560,7 +574,7 @@ TEST_F(TextureLayerMailboxHolderTest, TwoCompositors_MainReleaseBetween) { // The texture layer is attached to compositor1, and passes a reference to its // impl tree. - TextureMailbox::ReleaseCallback compositor1; + scoped_ptr<SingleReleaseCallback> compositor1; main_thread_.message_loop()->PostTask( FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef, @@ -569,7 +583,7 @@ TEST_F(TextureLayerMailboxHolderTest, TwoCompositors_MainReleaseBetween) { // Then the texture layer is removed and attached to compositor2, and passes a // reference to its impl tree. - TextureMailbox::ReleaseCallback compositor2; + scoped_ptr<SingleReleaseCallback> compositor2; main_thread_.message_loop()->PostTask( FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef, @@ -580,7 +594,7 @@ TEST_F(TextureLayerMailboxHolderTest, TwoCompositors_MainReleaseBetween) { Mock::VerifyAndClearExpectations(&test_data_.mock_callback_); // One compositor destroys their impl tree. - compositor1.Run(100, false); + compositor1->Run(100, false); // Then the main thread reference is destroyed. main_thread_.message_loop()->PostTask( @@ -598,7 +612,7 @@ TEST_F(TextureLayerMailboxHolderTest, TwoCompositors_MainReleaseBetween) { EXPECT_CALL(test_data_.mock_callback_, Release(test_data_.mailbox_name1_, 200, true)).Times(1); - compositor2.Run(200, true); + compositor2->Run(200, true); Wait(main_thread_); Mock::VerifyAndClearExpectations(&test_data_.mock_callback_); } @@ -616,7 +630,7 @@ TEST_F(TextureLayerMailboxHolderTest, TwoCompositors_MainReleasedFirst) { // The texture layer is attached to compositor1, and passes a reference to its // impl tree. - TextureMailbox::ReleaseCallback compositor1; + scoped_ptr<SingleReleaseCallback> compositor1; main_thread_.message_loop()->PostTask( FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef, @@ -625,7 +639,7 @@ TEST_F(TextureLayerMailboxHolderTest, TwoCompositors_MainReleasedFirst) { // Then the texture layer is removed and attached to compositor2, and passes a // reference to its impl tree. - TextureMailbox::ReleaseCallback compositor2; + scoped_ptr<SingleReleaseCallback> compositor2; main_thread_.message_loop()->PostTask( FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef, @@ -642,7 +656,7 @@ TEST_F(TextureLayerMailboxHolderTest, TwoCompositors_MainReleasedFirst) { base::Unretained(this))); // One compositor destroys their impl tree. - compositor2.Run(200, false); + compositor2->Run(200, false); Wait(main_thread_); @@ -654,7 +668,7 @@ TEST_F(TextureLayerMailboxHolderTest, TwoCompositors_MainReleasedFirst) { EXPECT_CALL(test_data_.mock_callback_, Release(test_data_.mailbox_name1_, 100, true)).Times(1); - compositor1.Run(100, true); + compositor1->Run(100, true); Wait(main_thread_); Mock::VerifyAndClearExpectations(&test_data_.mock_callback_); } @@ -672,7 +686,7 @@ TEST_F(TextureLayerMailboxHolderTest, TwoCompositors_SecondImplRefShortcut) { // The texture layer is attached to compositor1, and passes a reference to its // impl tree. - TextureMailbox::ReleaseCallback compositor1; + scoped_ptr<SingleReleaseCallback> compositor1; main_thread_.message_loop()->PostTask( FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef, @@ -681,7 +695,7 @@ TEST_F(TextureLayerMailboxHolderTest, TwoCompositors_SecondImplRefShortcut) { // Then the texture layer is removed and attached to compositor2, and passes a // reference to its impl tree. - TextureMailbox::ReleaseCallback compositor2; + scoped_ptr<SingleReleaseCallback> compositor2; main_thread_.message_loop()->PostTask( FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef, @@ -719,7 +733,7 @@ TEST_F(TextureLayerMailboxHolderTest, TwoCompositors_SecondImplRefShortcut) { // Before the main thread capturing starts, one compositor destroys their // impl reference. Since capturing did not start, this gets post-tasked to // the main thread. - compositor1.Run(100, false); + compositor1->Run(100, false); // Start capturing on the main thread. begin_capture.Signal(); @@ -730,7 +744,7 @@ TEST_F(TextureLayerMailboxHolderTest, TwoCompositors_SecondImplRefShortcut) { // released before compositor1, whose reference will be released later when // the post-task is serviced. But since it was destroyed _on the impl thread_ // last, its sync point values should be used. - compositor2.Run(200, true); + compositor2->Run(200, true); stop_capture.Signal(); Wait(main_thread_); @@ -753,12 +767,12 @@ class TextureLayerImplWithMailboxThreadedCallback : public LayerTreeTest { void SetMailbox(char mailbox_char) { EXPECT_EQ(true, main_thread_.CalledOnValidThread()); - TextureMailbox mailbox( - std::string(64, mailbox_char), + TextureMailbox mailbox(std::string(64, mailbox_char)); + scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create( base::Bind( &TextureLayerImplWithMailboxThreadedCallback::ReleaseCallback, base::Unretained(this))); - layer_->SetTextureMailbox(mailbox); + layer_->SetTextureMailbox(mailbox, callback.Pass()); } virtual void BeginTest() OVERRIDE { @@ -808,7 +822,8 @@ class TextureLayerImplWithMailboxThreadedCallback : public LayerTreeTest { EXPECT_EQ(3, callback_count_); // Case #4: release mailbox that was committed but never drawn. The // old mailbox should be released during the next commit. - layer_->SetTextureMailbox(TextureMailbox()); + layer_->SetTextureMailbox(TextureMailbox(), + scoped_ptr<SingleReleaseCallback>()); break; case 4: if (layer_tree_host()->settings().impl_side_painting) { @@ -847,7 +862,8 @@ class TextureLayerImplWithMailboxThreadedCallback : public LayerTreeTest { case 8: EXPECT_EQ(4, callback_count_); // Resetting the mailbox will call the callback now. - layer_->SetTextureMailbox(TextureMailbox()); + layer_->SetTextureMailbox(TextureMailbox(), + scoped_ptr<SingleReleaseCallback>()); EXPECT_EQ(5, callback_count_); EndTest(); break; @@ -908,8 +924,10 @@ class TextureLayerNoMailboxIsActivatedDuringCommit : public LayerTreeTest, virtual WebKit::WebGraphicsContext3D* Context3d() OVERRIDE { return OffscreenContextProviderForMainThread()->Context3d(); } - virtual bool PrepareTextureMailbox(TextureMailbox* mailbox, - bool use_shared_memory) OVERRIDE { + virtual bool PrepareTextureMailbox( + TextureMailbox* mailbox, + scoped_ptr<SingleReleaseCallback>* release_callback, + bool use_shared_memory) OVERRIDE { return false; } @@ -1003,11 +1021,11 @@ class TextureLayerMailboxIsActivatedDuringCommit : public LayerTreeTest { static void ReleaseCallback(unsigned sync_point, bool lost_resource) {} void SetMailbox(char mailbox_char) { - TextureMailbox mailbox( - std::string(64, mailbox_char), + TextureMailbox mailbox(std::string(64, mailbox_char)); + scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create( base::Bind( &TextureLayerMailboxIsActivatedDuringCommit::ReleaseCallback)); - layer_->SetTextureMailbox(mailbox); + layer_->SetTextureMailbox(mailbox, callback.Pass()); } virtual void BeginTest() OVERRIDE { @@ -1148,14 +1166,17 @@ TEST_F(TextureLayerImplWithMailboxTest, TestWillDraw) { { scoped_ptr<TextureLayerImpl> impl_layer = TextureLayerImpl::Create(host_impl_.active_tree(), 1, true); - impl_layer->SetTextureMailbox(test_data_.mailbox1_); + impl_layer->SetTextureMailbox( + test_data_.mailbox1_, + SingleReleaseCallback::Create(test_data_.release_mailbox1_)); 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(TextureMailbox()); + impl_layer->SetTextureMailbox(TextureMailbox(), + scoped_ptr<SingleReleaseCallback>()); EXPECT_FALSE(WillDraw(impl_layer.get(), DRAW_MODE_HARDWARE)); } @@ -1163,7 +1184,9 @@ TEST_F(TextureLayerImplWithMailboxTest, TestWillDraw) { // Software resource. scoped_ptr<TextureLayerImpl> impl_layer = TextureLayerImpl::Create(host_impl_.active_tree(), 1, true); - impl_layer->SetTextureMailbox(test_data_.mailbox3_); + impl_layer->SetTextureMailbox( + test_data_.mailbox3_, + SingleReleaseCallback::Create(test_data_.release_mailbox3_)); EXPECT_TRUE(WillDraw(impl_layer.get(), DRAW_MODE_HARDWARE)); } @@ -1189,14 +1212,17 @@ TEST_F(TextureLayerImplWithMailboxTest, TestWillDraw) { { scoped_ptr<TextureLayerImpl> impl_layer = TextureLayerImpl::Create(host_impl_.active_tree(), 1, true); - impl_layer->SetTextureMailbox(test_data_.mailbox1_); + impl_layer->SetTextureMailbox( + test_data_.mailbox1_, + SingleReleaseCallback::Create(test_data_.release_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()); + impl_layer->SetTextureMailbox(TextureMailbox(), + scoped_ptr<SingleReleaseCallback>()); EXPECT_FALSE(WillDraw(impl_layer.get(), DRAW_MODE_SOFTWARE)); } @@ -1204,7 +1230,9 @@ TEST_F(TextureLayerImplWithMailboxTest, TestWillDraw) { // Software resource. scoped_ptr<TextureLayerImpl> impl_layer = TextureLayerImpl::Create(host_impl_.active_tree(), 1, true); - impl_layer->SetTextureMailbox(test_data_.mailbox3_); + impl_layer->SetTextureMailbox( + test_data_.mailbox3_, + SingleReleaseCallback::Create(test_data_.release_mailbox3_)); EXPECT_TRUE(WillDraw(impl_layer.get(), DRAW_MODE_SOFTWARE)); } @@ -1230,7 +1258,9 @@ TEST_F(TextureLayerImplWithMailboxTest, TestWillDraw) { { scoped_ptr<TextureLayerImpl> impl_layer = TextureLayerImpl::Create(host_impl_.active_tree(), 1, true); - impl_layer->SetTextureMailbox(test_data_.mailbox1_); + impl_layer->SetTextureMailbox( + test_data_.mailbox1_, + SingleReleaseCallback::Create(test_data_.release_mailbox1_)); EXPECT_FALSE(WillDraw(impl_layer.get(), DRAW_MODE_RESOURCELESS_SOFTWARE)); } @@ -1256,7 +1286,9 @@ TEST_F(TextureLayerImplWithMailboxTest, TestImplLayerCallbacks) { pending_layer->CreateLayerImpl(host_impl_.active_tree())); ASSERT_TRUE(active_layer); - pending_layer->SetTextureMailbox(test_data_.mailbox1_); + pending_layer->SetTextureMailbox( + test_data_.mailbox1_, + SingleReleaseCallback::Create(test_data_.release_mailbox1_)); // Test multiple commits without an activation. EXPECT_CALL(test_data_.mock_callback_, @@ -1264,7 +1296,9 @@ TEST_F(TextureLayerImplWithMailboxTest, TestImplLayerCallbacks) { test_data_.sync_point1_, false)) .Times(1); - pending_layer->SetTextureMailbox(test_data_.mailbox2_); + pending_layer->SetTextureMailbox( + test_data_.mailbox2_, + SingleReleaseCallback::Create(test_data_.release_mailbox2_)); Mock::VerifyAndClearExpectations(&test_data_.mock_callback_); // Test callback after activation. @@ -1272,7 +1306,9 @@ TEST_F(TextureLayerImplWithMailboxTest, TestImplLayerCallbacks) { active_layer->DidBecomeActive(); EXPECT_CALL(test_data_.mock_callback_, Release(_, _, _)).Times(0); - pending_layer->SetTextureMailbox(test_data_.mailbox1_); + pending_layer->SetTextureMailbox( + test_data_.mailbox1_, + SingleReleaseCallback::Create(test_data_.release_mailbox1_)); Mock::VerifyAndClearExpectations(&test_data_.mock_callback_); EXPECT_CALL(test_data_.mock_callback_, @@ -1286,7 +1322,8 @@ TEST_F(TextureLayerImplWithMailboxTest, TestImplLayerCallbacks) { EXPECT_CALL(test_data_.mock_callback_, Release(test_data_.mailbox_name1_, _, false)) .Times(1); - pending_layer->SetTextureMailbox(TextureMailbox()); + pending_layer->SetTextureMailbox(TextureMailbox(), + scoped_ptr<SingleReleaseCallback>()); pending_layer->PushPropertiesTo(active_layer.get()); active_layer->DidBecomeActive(); Mock::VerifyAndClearExpectations(&test_data_.mock_callback_); @@ -1297,7 +1334,9 @@ TEST_F(TextureLayerImplWithMailboxTest, TestImplLayerCallbacks) { test_data_.sync_point1_, false)) .Times(1); - pending_layer->SetTextureMailbox(test_data_.mailbox1_); + pending_layer->SetTextureMailbox( + test_data_.mailbox1_, + SingleReleaseCallback::Create(test_data_.release_mailbox1_)); } TEST_F(TextureLayerImplWithMailboxTest, @@ -1309,18 +1348,23 @@ TEST_F(TextureLayerImplWithMailboxTest, EXPECT_CALL(test_data_.mock_callback_, Release(test_data_.mailbox_name1_, _, false)) .Times(1); - impl_layer->SetTextureMailbox(test_data_.mailbox1_); + impl_layer->SetTextureMailbox( + test_data_.mailbox1_, + SingleReleaseCallback::Create(test_data_.release_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()); - impl_layer->SetTextureMailbox(TextureMailbox()); + impl_layer->SetTextureMailbox(TextureMailbox(), + scoped_ptr<SingleReleaseCallback>()); } TEST_F(TextureLayerImplWithMailboxTest, TestCallbackOnInUseResource) { ResourceProvider* provider = host_impl_.active_tree()->resource_provider(); ResourceProvider::ResourceId id = - provider->CreateResourceFromTextureMailbox(test_data_.mailbox1_); + provider->CreateResourceFromTextureMailbox( + test_data_.mailbox1_, + SingleReleaseCallback::Create(test_data_.release_mailbox1_)); provider->AllocateForTesting(id); // Transfer some resources to the parent. @@ -1371,7 +1415,9 @@ class TextureLayerClientTest } virtual bool PrepareTextureMailbox( - cc::TextureMailbox* mailbox, bool use_shared_memory) OVERRIDE { + TextureMailbox* mailbox, + scoped_ptr<SingleReleaseCallback>* release_callback, + bool use_shared_memory) OVERRIDE { return false; } @@ -1487,7 +1533,9 @@ class TextureLayerChangeInvisibleTest // TextureLayerClient implementation. virtual bool PrepareTextureMailbox( - cc::TextureMailbox* mailbox, bool use_shared_memory) OVERRIDE { + cc::TextureMailbox* mailbox, + scoped_ptr<SingleReleaseCallback>* release_callback, + bool use_shared_memory) OVERRIDE { return false; } @@ -1661,19 +1709,21 @@ class TextureLayerChangeInvisibleMailboxTest // TextureLayerClient implementation. virtual bool PrepareTextureMailbox( - cc::TextureMailbox* mailbox, bool use_shared_memory) OVERRIDE { + cc::TextureMailbox* mailbox, + scoped_ptr<SingleReleaseCallback>* release_callback, + bool use_shared_memory) OVERRIDE { ++prepare_called_; if (!mailbox_changed_) return false; *mailbox = mailbox_; + *release_callback = SingleReleaseCallback::Create( + base::Bind(&TextureLayerChangeInvisibleMailboxTest::MailboxReleased, + base::Unretained(this))); return true; } TextureMailbox MakeMailbox(char name) { - return TextureMailbox( - std::string(64, name), - base::Bind(&TextureLayerChangeInvisibleMailboxTest::MailboxReleased, - base::Unretained(this))); + return TextureMailbox(std::string(64, name)); } void MailboxReleased(unsigned sync_point, bool lost_resource) { @@ -1819,7 +1869,9 @@ class TextureLayerLostContextTest } virtual bool PrepareTextureMailbox( - cc::TextureMailbox* mailbox, bool use_shared_memory) OVERRIDE { + TextureMailbox* mailbox, + scoped_ptr<SingleReleaseCallback>* release_callback, + bool use_shared_memory) OVERRIDE { return false; } @@ -1880,12 +1932,12 @@ class TextureLayerWithMailboxMainThreadDeleted : public LayerTreeTest { void SetMailbox(char mailbox_char) { EXPECT_EQ(true, main_thread_.CalledOnValidThread()); - TextureMailbox mailbox( - std::string(64, mailbox_char), + TextureMailbox mailbox(std::string(64, mailbox_char)); + scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create( base::Bind( &TextureLayerWithMailboxMainThreadDeleted::ReleaseCallback, base::Unretained(this))); - layer_->SetTextureMailbox(mailbox); + layer_->SetTextureMailbox(mailbox, callback.Pass()); } virtual void SetupTree() OVERRIDE { @@ -1952,12 +2004,12 @@ class TextureLayerWithMailboxImplThreadDeleted : public LayerTreeTest { void SetMailbox(char mailbox_char) { EXPECT_EQ(true, main_thread_.CalledOnValidThread()); - TextureMailbox mailbox( - std::string(64, mailbox_char), + TextureMailbox mailbox(std::string(64, mailbox_char)); + scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create( base::Bind( &TextureLayerWithMailboxImplThreadDeleted::ReleaseCallback, base::Unretained(this))); - layer_->SetTextureMailbox(mailbox); + layer_->SetTextureMailbox(mailbox, callback.Pass()); } virtual void SetupTree() OVERRIDE { diff --git a/cc/layers/video_layer_impl.cc b/cc/layers/video_layer_impl.cc index 4328067..28e470e 100644 --- a/cc/layers/video_layer_impl.cc +++ b/cc/layers/video_layer_impl.cc @@ -13,6 +13,7 @@ #include "cc/quads/texture_draw_quad.h" #include "cc/quads/yuv_video_draw_quad.h" #include "cc/resources/resource_provider.h" +#include "cc/resources/single_release_callback.h" #include "cc/trees/layer_tree_impl.h" #include "cc/trees/proxy.h" #include "media/base/video_frame.h" @@ -111,10 +112,13 @@ bool VideoLayerImpl::WillDraw(DrawMode draw_mode, return true; } + DCHECK_EQ(external_resources.mailboxes.size(), + external_resources.release_callbacks.size()); for (size_t i = 0; i < external_resources.mailboxes.size(); ++i) { - frame_resources_.push_back( - resource_provider->CreateResourceFromTextureMailbox( - external_resources.mailboxes[i])); + unsigned resource_id = resource_provider->CreateResourceFromTextureMailbox( + external_resources.mailboxes[i], + SingleReleaseCallback::Create(external_resources.release_callbacks[i])); + frame_resources_.push_back(resource_id); } return true; diff --git a/cc/layers/video_layer_impl.h b/cc/layers/video_layer_impl.h index b071871..b4df141 100644 --- a/cc/layers/video_layer_impl.h +++ b/cc/layers/video_layer_impl.h @@ -9,6 +9,7 @@ #include "cc/base/cc_export.h" #include "cc/layers/layer_impl.h" +#include "cc/resources/release_callback.h" #include "cc/resources/video_resource_updater.h" namespace media { @@ -59,7 +60,8 @@ class CC_EXPORT VideoLayerImpl : public LayerImpl { // TODO(danakj): Remove these, hide software path inside ResourceProvider and // ExternalResource (aka TextureMailbox) classes. std::vector<unsigned> software_resources_; - TextureMailbox::ReleaseCallback software_release_callback_; + // Called once for each software resource. + ReleaseCallback software_release_callback_; DISALLOW_COPY_AND_ASSIGN(VideoLayerImpl); }; diff --git a/cc/output/copy_output_request.cc b/cc/output/copy_output_request.cc index 995c3f4..6163d5d 100644 --- a/cc/output/copy_output_request.cc +++ b/cc/output/copy_output_request.cc @@ -8,6 +8,7 @@ #include "base/callback_helpers.h" #include "base/logging.h" #include "cc/output/copy_output_result.h" +#include "cc/resources/single_release_callback.h" #include "cc/resources/texture_mailbox.h" #include "third_party/skia/include/core/SkBitmap.h" @@ -40,11 +41,13 @@ void CopyOutputRequest::SendBitmapResult(scoped_ptr<SkBitmap> bitmap) { SendResult(CopyOutputResult::CreateBitmapResult(bitmap.Pass()).Pass()); } -void CopyOutputRequest::SendTextureResult(gfx::Size size, - scoped_ptr<TextureMailbox> texture) { - DCHECK(texture->IsTexture()); - SendResult(CopyOutputResult::CreateTextureResult(size, - texture.Pass()).Pass()); +void CopyOutputRequest::SendTextureResult( + gfx::Size size, + const TextureMailbox& texture_mailbox, + scoped_ptr<SingleReleaseCallback> release_callback) { + DCHECK(texture_mailbox.IsTexture()); + SendResult(CopyOutputResult::CreateTextureResult( + size, texture_mailbox, release_callback.Pass())); } } // namespace cc diff --git a/cc/output/copy_output_request.h b/cc/output/copy_output_request.h index 3f4d925..c4a9248 100644 --- a/cc/output/copy_output_request.h +++ b/cc/output/copy_output_request.h @@ -14,6 +14,7 @@ class SkBitmap; namespace cc { class CopyOutputResult; +class SingleReleaseCallback; class TextureMailbox; class CC_EXPORT CopyOutputRequest { @@ -61,7 +62,8 @@ class CC_EXPORT CopyOutputRequest { void SendEmptyResult(); void SendBitmapResult(scoped_ptr<SkBitmap> bitmap); void SendTextureResult(gfx::Size size, - scoped_ptr<TextureMailbox> texture_mailbox); + const TextureMailbox& texture_mailbox, + scoped_ptr<SingleReleaseCallback> release_callback); void SendResult(scoped_ptr<CopyOutputResult> result); diff --git a/cc/output/copy_output_result.cc b/cc/output/copy_output_result.cc index 55213cd..1831fba 100644 --- a/cc/output/copy_output_result.cc +++ b/cc/output/copy_output_result.cc @@ -5,6 +5,7 @@ #include "cc/output/copy_output_result.h" #include "base/logging.h" +#include "cc/resources/single_release_callback.h" #include "cc/resources/texture_mailbox.h" #include "third_party/skia/include/core/SkBitmap.h" @@ -18,25 +19,32 @@ CopyOutputResult::CopyOutputResult(scoped_ptr<SkBitmap> bitmap) DCHECK(bitmap_); } -CopyOutputResult::CopyOutputResult(gfx::Size size, - scoped_ptr<TextureMailbox> texture_mailbox) +CopyOutputResult::CopyOutputResult( + gfx::Size size, + const TextureMailbox& texture_mailbox, + scoped_ptr<SingleReleaseCallback> release_callback) : size_(size), - texture_mailbox_(texture_mailbox.Pass()) { - DCHECK(texture_mailbox_); - DCHECK(texture_mailbox_->IsTexture()); + texture_mailbox_(texture_mailbox), + release_callback_(release_callback.Pass()) { + DCHECK(texture_mailbox_.IsTexture()); } CopyOutputResult::~CopyOutputResult() { - if (texture_mailbox_) - texture_mailbox_->RunReleaseCallback(0, false); + if (release_callback_) + release_callback_->Run(0, false); } scoped_ptr<SkBitmap> CopyOutputResult::TakeBitmap() { return bitmap_.Pass(); } -scoped_ptr<TextureMailbox> CopyOutputResult::TakeTexture() { - return texture_mailbox_.Pass(); +void CopyOutputResult::TakeTexture( + TextureMailbox* texture_mailbox, + scoped_ptr<SingleReleaseCallback>* release_callback) { + *texture_mailbox = texture_mailbox_; + *release_callback = release_callback_.Pass(); + + texture_mailbox_ = TextureMailbox(); } } // namespace cc diff --git a/cc/output/copy_output_result.h b/cc/output/copy_output_result.h index 04cf2c6..c2f011d 100644 --- a/cc/output/copy_output_result.h +++ b/cc/output/copy_output_result.h @@ -7,11 +7,13 @@ #include "base/memory/scoped_ptr.h" #include "cc/base/cc_export.h" +#include "cc/resources/texture_mailbox.h" #include "ui/gfx/size.h" class SkBitmap; namespace cc { +class SingleReleaseCallback; class TextureMailbox; class CC_EXPORT CopyOutputResult { @@ -25,29 +27,34 @@ class CC_EXPORT CopyOutputResult { } static scoped_ptr<CopyOutputResult> CreateTextureResult( gfx::Size size, - scoped_ptr<TextureMailbox> texture_mailbox) { - return make_scoped_ptr(new CopyOutputResult(size, texture_mailbox.Pass())); + const TextureMailbox& texture_mailbox, + scoped_ptr<SingleReleaseCallback> release_callback) { + return make_scoped_ptr( + new CopyOutputResult(size, texture_mailbox, release_callback.Pass())); } ~CopyOutputResult(); bool IsEmpty() const { return !HasBitmap() && !HasTexture(); } bool HasBitmap() const { return !!bitmap_; } - bool HasTexture() const { return !!texture_mailbox_; } + bool HasTexture() const { return texture_mailbox_.IsValid(); } gfx::Size size() const { return size_; } scoped_ptr<SkBitmap> TakeBitmap(); - scoped_ptr<TextureMailbox> TakeTexture(); + void TakeTexture(TextureMailbox* texture_mailbox, + scoped_ptr<SingleReleaseCallback>* release_callback); private: CopyOutputResult(); explicit CopyOutputResult(scoped_ptr<SkBitmap> bitmap); explicit CopyOutputResult(gfx::Size size, - scoped_ptr<TextureMailbox> texture_mailbox); + const TextureMailbox& texture_mailbox, + scoped_ptr<SingleReleaseCallback> release_callback); gfx::Size size_; scoped_ptr<SkBitmap> bitmap_; - scoped_ptr<TextureMailbox> texture_mailbox_; + TextureMailbox texture_mailbox_; + scoped_ptr<SingleReleaseCallback> release_callback_; }; } // namespace cc diff --git a/cc/output/gl_renderer.cc b/cc/output/gl_renderer.cc index 0b56c9d..074d603 100644 --- a/cc/output/gl_renderer.cc +++ b/cc/output/gl_renderer.cc @@ -2221,13 +2221,13 @@ void GLRenderer::GetFramebufferPixelsAsync( GL_TEXTURE_2D, mailbox.name)); GLC(context_, context_->bindTexture(GL_TEXTURE_2D, 0)); sync_point = context_->insertSyncPoint(); - scoped_ptr<TextureMailbox> texture_mailbox = make_scoped_ptr( - new TextureMailbox(mailbox, - texture_mailbox_deleter_->GetReleaseCallback( - output_surface_->context_provider(), texture_id), - GL_TEXTURE_2D, - sync_point)); - request->SendTextureResult(window_rect.size(), texture_mailbox.Pass()); + TextureMailbox texture_mailbox(mailbox, GL_TEXTURE_2D, sync_point); + scoped_ptr<SingleReleaseCallback> release_callback = + texture_mailbox_deleter_->GetReleaseCallback( + output_surface_->context_provider(), texture_id); + request->SendTextureResult(window_rect.size(), + texture_mailbox, + release_callback.Pass()); return; } diff --git a/cc/resources/release_callback.h b/cc/resources/release_callback.h new file mode 100644 index 0000000..9433f7f --- /dev/null +++ b/cc/resources/release_callback.h @@ -0,0 +1,17 @@ +// Copyright 2013 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. + +#ifndef CC_RESOURCES_RELEASE_CALLBACK_H_ +#define CC_RESOURCES_RELEASE_CALLBACK_H_ + +#include "base/callback.h" + +namespace cc { + +typedef base::Callback<void(unsigned sync_point, bool is_lost)> + ReleaseCallback; + +} // namespace cc + +#endif // CC_RESOURCES_RELEASE_CALLBACK_H_ diff --git a/cc/resources/resource_provider.cc b/cc/resources/resource_provider.cc index 5c8d39c..017c2e9 100644 --- a/cc/resources/resource_provider.cc +++ b/cc/resources/resource_provider.cc @@ -312,7 +312,8 @@ ResourceProvider::CreateResourceFromExternalTexture( } ResourceProvider::ResourceId ResourceProvider::CreateResourceFromTextureMailbox( - const TextureMailbox& mailbox) { + const TextureMailbox& mailbox, + scoped_ptr<SingleReleaseCallback> release_callback) { DCHECK(thread_checker_.CalledOnValidThread()); // Just store the information. Mailbox will be consumed in LockForRead(). ResourceId id = next_id_++; @@ -332,6 +333,9 @@ ResourceProvider::ResourceId ResourceProvider::CreateResourceFromTextureMailbox( resource.external = true; resource.allocated = true; resource.mailbox = mailbox; + resource.release_callback = + base::Bind(&SingleReleaseCallback::Run, + base::Owned(release_callback.release())); return id; } @@ -400,7 +404,7 @@ void ResourceProvider::DeleteResourceInternal(ResourceMap::iterator it, resource->pixels = NULL; } } - resource->mailbox.RunReleaseCallback(sync_point, lost_resource); + resource->release_callback.Run(sync_point, lost_resource); } if (resource->pixels) delete[] resource->pixels; @@ -963,9 +967,8 @@ void ResourceProvider::ReceiveReturnsFromParent( if (it->sync_point) GLC(context3d, context3d->waitSyncPoint(it->sync_point)); } else { - resource->mailbox = TextureMailbox(resource->mailbox.name(), - resource->mailbox.callback(), - it->sync_point); + resource->mailbox = + TextureMailbox(resource->mailbox.name(), it->sync_point); } if (resource->marked_for_deletion) DeleteResourceInternal(map_iterator, Normal); diff --git a/cc/resources/resource_provider.h b/cc/resources/resource_provider.h index 8b4b01b..88ff274 100644 --- a/cc/resources/resource_provider.h +++ b/cc/resources/resource_provider.h @@ -18,6 +18,8 @@ #include "cc/base/cc_export.h" #include "cc/output/context_provider.h" #include "cc/output/output_surface.h" +#include "cc/resources/release_callback.h" +#include "cc/resources/single_release_callback.h" #include "cc/resources/texture_mailbox.h" #include "cc/resources/transferable_resource.h" #include "third_party/khronos/GLES2/gl2.h" @@ -103,7 +105,9 @@ class CC_EXPORT ResourceProvider { unsigned texture_id); // Wraps an external texture mailbox into a GL resource. - ResourceId CreateResourceFromTextureMailbox(const TextureMailbox& mailbox); + ResourceId CreateResourceFromTextureMailbox( + const TextureMailbox& mailbox, + scoped_ptr<SingleReleaseCallback> release_callback); void DeleteResource(ResourceId id); @@ -354,6 +358,7 @@ class CC_EXPORT ResourceProvider { // Query used to determine when asynchronous set pixels complete. unsigned gl_upload_query_id; TextureMailbox mailbox; + ReleaseCallback release_callback; uint8_t* pixels; uint8_t* pixel_buffer; int lock_for_read_count; diff --git a/cc/resources/resource_provider_unittest.cc b/cc/resources/resource_provider_unittest.cc index afb2330..abdd78e 100644 --- a/cc/resources/resource_provider_unittest.cc +++ b/cc/resources/resource_provider_unittest.cc @@ -14,6 +14,7 @@ #include "cc/debug/test_web_graphics_context_3d.h" #include "cc/output/output_surface.h" #include "cc/resources/returned_resource.h" +#include "cc/resources/single_release_callback.h" #include "cc/test/fake_output_surface.h" #include "cc/test/fake_output_surface_client.h" #include "gpu/GLES2/gl2extchromium.h" @@ -918,11 +919,12 @@ TEST_P(ResourceProviderTest, TransferMailboxResources) { unsigned release_sync_point = 0; bool lost_resource = false; - TextureMailbox::ReleaseCallback callback = + ReleaseCallback callback = base::Bind(ReleaseTextureMailbox, &release_sync_point, &lost_resource); ResourceProvider::ResourceId resource = resource_provider_->CreateResourceFromTextureMailbox( - TextureMailbox(mailbox, callback, sync_point)); + TextureMailbox(mailbox, sync_point), + SingleReleaseCallback::Create(callback)); EXPECT_EQ(1, context()->texture_count()); EXPECT_EQ(0u, release_sync_point); { @@ -968,7 +970,8 @@ TEST_P(ResourceProviderTest, TransferMailboxResources) { EXPECT_LT(0u, sync_point); release_sync_point = 0; resource = resource_provider_->CreateResourceFromTextureMailbox( - TextureMailbox(mailbox, callback, sync_point)); + TextureMailbox(mailbox, sync_point), + SingleReleaseCallback::Create(callback)); EXPECT_EQ(1, context()->texture_count()); EXPECT_EQ(0u, release_sync_point); { @@ -1030,10 +1033,11 @@ TEST_P(ResourceProviderTest, Shutdown) { unsigned release_sync_point = 0; bool lost_resource = false; - TextureMailbox::ReleaseCallback callback = - base::Bind(ReleaseTextureMailbox, &release_sync_point, &lost_resource); + scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create( + base::Bind(ReleaseTextureMailbox, &release_sync_point, &lost_resource)); resource_provider_->CreateResourceFromTextureMailbox( - TextureMailbox(mailbox, callback, sync_point)); + TextureMailbox(mailbox, sync_point), + callback.Pass()); EXPECT_EQ(0u, release_sync_point); EXPECT_FALSE(lost_resource); @@ -1069,10 +1073,11 @@ TEST_P(ResourceProviderTest, ShutdownSharedMemory) { CreateAndFillSharedMemory(size, 0)); bool release_called = false; - TextureMailbox::ReleaseCallback callback = - base::Bind(ReleaseSharedMemoryCallback, &release_called); + scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create( + base::Bind(ReleaseSharedMemoryCallback, &release_called)); resource_provider_->CreateResourceFromTextureMailbox( - TextureMailbox(shared_memory.get(), size, callback)); + TextureMailbox(shared_memory.get(), size), + callback.Pass()); resource_provider_.reset(); @@ -1094,11 +1099,12 @@ TEST_P(ResourceProviderTest, ShutdownWithExportedResource) { unsigned release_sync_point = 0; bool lost_resource = false; - TextureMailbox::ReleaseCallback callback = - base::Bind(ReleaseTextureMailbox, &release_sync_point, &lost_resource); + scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create( + base::Bind(ReleaseTextureMailbox, &release_sync_point, &lost_resource)); ResourceProvider::ResourceId resource = resource_provider_->CreateResourceFromTextureMailbox( - TextureMailbox(mailbox, callback, sync_point)); + TextureMailbox(mailbox, sync_point), + callback.Pass()); // Transfer the resource, so we can't release it properly on shutdown. ResourceProvider::ResourceIdArray resource_ids_to_transfer; @@ -1131,10 +1137,11 @@ TEST_P(ResourceProviderTest, LostContext) { unsigned release_sync_point = 0; bool lost_resource = false; - TextureMailbox::ReleaseCallback callback = - base::Bind(ReleaseTextureMailbox, &release_sync_point, &lost_resource); + scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create( + base::Bind(ReleaseTextureMailbox, &release_sync_point, &lost_resource)); resource_provider_->CreateResourceFromTextureMailbox( - TextureMailbox(mailbox, callback, sync_point)); + TextureMailbox(mailbox, sync_point), + callback.Pass()); EXPECT_EQ(0u, release_sync_point); EXPECT_FALSE(lost_resource); @@ -1341,11 +1348,13 @@ TEST_P(ResourceProviderTest, TextureMailbox_SharedMemory) { scoped_ptr<ResourceProvider> resource_provider( ResourceProvider::Create(output_surface.get(), 0)); - TextureMailbox::ReleaseCallback callback = base::Bind(&EmptyReleaseCallback); - TextureMailbox mailbox(shared_memory.get(), size, callback); + scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create( + base::Bind(&EmptyReleaseCallback)); + TextureMailbox mailbox(shared_memory.get(), size); ResourceProvider::ResourceId id = - resource_provider->CreateResourceFromTextureMailbox(mailbox); + resource_provider->CreateResourceFromTextureMailbox( + mailbox, callback.Pass()); EXPECT_NE(0u, id); { @@ -1386,14 +1395,14 @@ TEST_P(ResourceProviderTest, TextureMailbox_GLTexture2D) { gpu::Mailbox gpu_mailbox; memcpy(gpu_mailbox.name, "Hello world", strlen("Hello world") + 1); - TextureMailbox::ReleaseCallback callback = base::Bind(&EmptyReleaseCallback); + scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create( + base::Bind(&EmptyReleaseCallback)); - TextureMailbox mailbox(gpu_mailbox, - callback, - sync_point); + TextureMailbox mailbox(gpu_mailbox, sync_point); ResourceProvider::ResourceId id = - resource_provider->CreateResourceFromTextureMailbox(mailbox); + resource_provider->CreateResourceFromTextureMailbox( + mailbox, callback.Pass()); EXPECT_NE(0u, id); Mock::VerifyAndClearExpectations(context); @@ -1450,15 +1459,14 @@ TEST_P(ResourceProviderTest, TextureMailbox_GLTextureExternalOES) { gpu::Mailbox gpu_mailbox; memcpy(gpu_mailbox.name, "Hello world", strlen("Hello world") + 1); - TextureMailbox::ReleaseCallback callback = base::Bind(&EmptyReleaseCallback); + scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create( + base::Bind(&EmptyReleaseCallback)); - TextureMailbox mailbox(gpu_mailbox, - callback, - target, - sync_point); + TextureMailbox mailbox(gpu_mailbox, target, sync_point); ResourceProvider::ResourceId id = - resource_provider->CreateResourceFromTextureMailbox(mailbox); + resource_provider->CreateResourceFromTextureMailbox( + mailbox, callback.Pass()); EXPECT_NE(0u, id); Mock::VerifyAndClearExpectations(context); diff --git a/cc/resources/single_release_callback.cc b/cc/resources/single_release_callback.cc new file mode 100644 index 0000000..9c6b9de --- /dev/null +++ b/cc/resources/single_release_callback.cc @@ -0,0 +1,29 @@ +// Copyright 2013 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/resources/single_release_callback.h" + +#include "base/callback_helpers.h" +#include "base/logging.h" + +namespace cc { + +SingleReleaseCallback::SingleReleaseCallback(const ReleaseCallback& callback) + : has_been_run_(false), callback_(callback) { + DCHECK(!callback_.is_null()) + << "Use a NULL SingleReleaseCallback for an empty callback."; +} + +SingleReleaseCallback::~SingleReleaseCallback() { + DCHECK(callback_.is_null() || has_been_run_) + << "SingleReleaseCallback was never run."; +} + +void SingleReleaseCallback::Run(unsigned sync_point, bool is_lost) { + DCHECK(!has_been_run_) << "SingleReleaseCallback was run more than once."; + has_been_run_ = true; + callback_.Run(sync_point, is_lost); +} + +} // namespace cc diff --git a/cc/resources/single_release_callback.h b/cc/resources/single_release_callback.h new file mode 100644 index 0000000..fe1a3ba --- /dev/null +++ b/cc/resources/single_release_callback.h @@ -0,0 +1,33 @@ +// Copyright 2013 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. + +#ifndef CC_RESOURCES_SINGLE_RELEASE_CALLBACK_H_ +#define CC_RESOURCES_SINGLE_RELEASE_CALLBACK_H_ + +#include "base/memory/scoped_ptr.h" +#include "cc/base/cc_export.h" +#include "cc/resources/release_callback.h" + +namespace cc { + +class CC_EXPORT SingleReleaseCallback { + public: + static scoped_ptr<SingleReleaseCallback> Create(const ReleaseCallback& cb) { + return make_scoped_ptr(new SingleReleaseCallback(cb)); + } + + ~SingleReleaseCallback(); + + void Run(unsigned sync_point, bool is_lost); + + private: + explicit SingleReleaseCallback(const ReleaseCallback& callback); + + bool has_been_run_; + ReleaseCallback callback_; +}; + +} // namespace cc + +#endif // CC_RESOURCES_SINGLE_RELEASE_CALLBACK_H_ diff --git a/cc/resources/texture_mailbox.cc b/cc/resources/texture_mailbox.cc index 2a8f570..149d56c 100644 --- a/cc/resources/texture_mailbox.cc +++ b/cc/resources/texture_mailbox.cc @@ -4,7 +4,6 @@ #include "cc/resources/texture_mailbox.h" -#include "base/callback_helpers.h" #include "base/logging.h" #include "third_party/khronos/GLES2/gl2.h" @@ -16,69 +15,48 @@ TextureMailbox::TextureMailbox() shared_memory_(NULL) { } -TextureMailbox::TextureMailbox( - const std::string& mailbox_name, - const ReleaseCallback& callback) - : callback_(callback), - target_(GL_TEXTURE_2D), +TextureMailbox::TextureMailbox(const std::string& mailbox_name) + : target_(GL_TEXTURE_2D), sync_point_(0), shared_memory_(NULL) { - DCHECK(mailbox_name.empty() == callback.is_null()); if (!mailbox_name.empty()) { CHECK(mailbox_name.size() == sizeof(name_.name)); name_.SetName(reinterpret_cast<const int8*>(mailbox_name.data())); } } -TextureMailbox::TextureMailbox( - const gpu::Mailbox& mailbox_name, - const ReleaseCallback& callback) - : callback_(callback), - target_(GL_TEXTURE_2D), +TextureMailbox::TextureMailbox(const gpu::Mailbox& mailbox_name) + : target_(GL_TEXTURE_2D), sync_point_(0), shared_memory_(NULL) { - DCHECK(mailbox_name.IsZero() == callback.is_null()); name_.SetName(mailbox_name.name); } -TextureMailbox::TextureMailbox( - const gpu::Mailbox& mailbox_name, - const ReleaseCallback& callback, - unsigned sync_point) - : callback_(callback), - target_(GL_TEXTURE_2D), +TextureMailbox::TextureMailbox(const gpu::Mailbox& mailbox_name, + unsigned sync_point) + : target_(GL_TEXTURE_2D), sync_point_(sync_point), shared_memory_(NULL) { - DCHECK(mailbox_name.IsZero() == callback.is_null()); name_.SetName(mailbox_name.name); } -TextureMailbox::TextureMailbox( - const gpu::Mailbox& mailbox_name, - const ReleaseCallback& callback, - unsigned texture_target, - unsigned sync_point) - : callback_(callback), - target_(texture_target), +TextureMailbox::TextureMailbox(const gpu::Mailbox& mailbox_name, + unsigned texture_target, + unsigned sync_point) + : target_(texture_target), sync_point_(sync_point), shared_memory_(NULL) { - DCHECK(mailbox_name.IsZero() == callback.is_null()); name_.SetName(mailbox_name.name); } -TextureMailbox::TextureMailbox( - base::SharedMemory* shared_memory, - gfx::Size size, - const ReleaseCallback& callback) - : callback_(callback), - target_(GL_TEXTURE_2D), +TextureMailbox::TextureMailbox(base::SharedMemory* shared_memory, + gfx::Size size) + : target_(GL_TEXTURE_2D), sync_point_(0), shared_memory_(shared_memory), - shared_memory_size_(size) { -} + shared_memory_size_(size) {} -TextureMailbox::~TextureMailbox() { -} +TextureMailbox::~TextureMailbox() {} bool TextureMailbox::Equals(const TextureMailbox& other) const { if (other.IsTexture()) @@ -103,19 +81,6 @@ void TextureMailbox::SetName(const gpu::Mailbox& name) { name_ = name; } -void TextureMailbox::RunReleaseCallback(unsigned sync_point, - bool lost_resource) { - if (!callback_.is_null()) - base::ResetAndReturn(&callback_).Run(sync_point, lost_resource); -} - -TextureMailbox TextureMailbox::CopyWithNewCallback( - const ReleaseCallback& callback) const { - TextureMailbox result(*this); - result.callback_ = callback; - return result; -} - size_t TextureMailbox::shared_memory_size_in_bytes() const { return 4 * shared_memory_size_.GetArea(); } diff --git a/cc/resources/texture_mailbox.h b/cc/resources/texture_mailbox.h index 9490939..a9b021b 100644 --- a/cc/resources/texture_mailbox.h +++ b/cc/resources/texture_mailbox.h @@ -19,23 +19,16 @@ namespace cc { // can hold a shared memory resource as well as a texture mailbox. class CC_EXPORT TextureMailbox { public: - typedef base::Callback<void(unsigned sync_point, - bool lost_resource)> ReleaseCallback; TextureMailbox(); - TextureMailbox(const std::string& mailbox_name, - const ReleaseCallback& callback); + explicit TextureMailbox(const std::string& mailbox_name); + explicit TextureMailbox(const gpu::Mailbox& mailbox_name); TextureMailbox(const gpu::Mailbox& mailbox_name, - const ReleaseCallback& callback); - TextureMailbox(const gpu::Mailbox& mailbox_name, - const ReleaseCallback& callback, unsigned sync_point); TextureMailbox(const gpu::Mailbox& mailbox_name, - const ReleaseCallback& callback, unsigned texture_target, unsigned sync_point); TextureMailbox(base::SharedMemory* shared_memory, - gfx::Size size, - const ReleaseCallback& callback); + gfx::Size size); ~TextureMailbox(); @@ -61,16 +54,8 @@ class CC_EXPORT TextureMailbox { // storing a TextureMailbox in ResourceProvider. Then we can remove this. void SetName(const gpu::Mailbox& name); - // TODO(danakj): ReleaseCallback should be a separate scoped_ptr outside this - // class to avoid silently adding references to the callback's internals. - void RunReleaseCallback(unsigned sync_point, bool lost_resource); - - TextureMailbox CopyWithNewCallback(const ReleaseCallback& callback) const; - const ReleaseCallback& callback() const { return callback_; } - private: gpu::Mailbox name_; - ReleaseCallback callback_; unsigned target_; unsigned sync_point_; base::SharedMemory* shared_memory_; diff --git a/cc/resources/texture_mailbox_deleter.cc b/cc/resources/texture_mailbox_deleter.cc index ed611e4..ae6df17 100644 --- a/cc/resources/texture_mailbox_deleter.cc +++ b/cc/resources/texture_mailbox_deleter.cc @@ -9,6 +9,7 @@ #include "base/memory/weak_ptr.h" #include "base/message_loop/message_loop_proxy.h" #include "cc/output/context_provider.h" +#include "cc/resources/single_release_callback.h" #include "third_party/WebKit/public/platform/WebGraphicsContext3D.h" namespace cc { @@ -25,7 +26,7 @@ static void DeleteTextureOnImplThread( static void PostTaskFromMainToImplThread( scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner, - TextureMailbox::ReleaseCallback run_impl_callback, + ReleaseCallback run_impl_callback, unsigned sync_point, bool is_lost) { // This posts the task to RunDeleteTextureOnImplThread(). @@ -40,43 +41,45 @@ TextureMailboxDeleter::~TextureMailboxDeleter() { impl_callbacks_.at(i)->Run(0, true); } -TextureMailbox::ReleaseCallback TextureMailboxDeleter::GetReleaseCallback( +scoped_ptr<SingleReleaseCallback> TextureMailboxDeleter::GetReleaseCallback( const scoped_refptr<ContextProvider>& context_provider, unsigned texture_id) { // This callback owns a reference on the |context_provider|. It must be // destroyed on the impl thread. Upon destruction of this class, the // callback must immediately be destroyed. - scoped_ptr<TextureMailbox::ReleaseCallback> impl_callback( - new TextureMailbox::ReleaseCallback(base::Bind( - &DeleteTextureOnImplThread, context_provider, texture_id))); + scoped_ptr<SingleReleaseCallback> impl_callback = + SingleReleaseCallback::Create(base::Bind(&DeleteTextureOnImplThread, + context_provider, + texture_id)); impl_callbacks_.push_back(impl_callback.Pass()); // The raw pointer to the impl-side callback is valid as long as this // class is alive. So we guard it with a WeakPtr. - TextureMailbox::ReleaseCallback run_impl_callback = + ReleaseCallback run_impl_callback( base::Bind(&TextureMailboxDeleter::RunDeleteTextureOnImplThread, weak_ptr_factory_.GetWeakPtr(), - impl_callbacks_.back()); + impl_callbacks_.back())); // Provide a callback for the main thread that posts back to the impl // thread. - TextureMailbox::ReleaseCallback main_callback = - base::Bind(&PostTaskFromMainToImplThread, - base::MessageLoopProxy::current(), - run_impl_callback); + scoped_ptr<SingleReleaseCallback> main_callback = + SingleReleaseCallback::Create(base::Bind( + &PostTaskFromMainToImplThread, + base::MessageLoopProxy::current(), + run_impl_callback)); - return main_callback; + return main_callback.Pass(); } void TextureMailboxDeleter::RunDeleteTextureOnImplThread( - TextureMailbox::ReleaseCallback* impl_callback, + SingleReleaseCallback* impl_callback, unsigned sync_point, bool is_lost) { for (size_t i = 0; i < impl_callbacks_.size(); ++i) { - if (impl_callbacks_.at(i)->Equals(*impl_callback)) { + if (impl_callbacks_.at(i) == impl_callback) { // Run the callback, then destroy it here on the impl thread. - impl_callback->Run(sync_point, is_lost); + impl_callbacks_.at(i)->Run(sync_point, is_lost); impl_callbacks_.erase(impl_callbacks_.begin() + i); return; } diff --git a/cc/resources/texture_mailbox_deleter.h b/cc/resources/texture_mailbox_deleter.h index 608dd7a..072dcab 100644 --- a/cc/resources/texture_mailbox_deleter.h +++ b/cc/resources/texture_mailbox_deleter.h @@ -8,10 +8,10 @@ #include "base/memory/weak_ptr.h" #include "cc/base/cc_export.h" #include "cc/base/scoped_ptr_vector.h" -#include "cc/resources/texture_mailbox.h" namespace cc { class ContextProvider; +class SingleReleaseCallback; class CC_EXPORT TextureMailboxDeleter { public: @@ -25,7 +25,7 @@ class CC_EXPORT TextureMailboxDeleter { // due to the compositor shutting down, then the ReleaseCallback will // become a no-op and the texture will be deleted immediately on the // impl thread, along with dropping the reference to the ContextProvider. - TextureMailbox::ReleaseCallback GetReleaseCallback( + scoped_ptr<SingleReleaseCallback> GetReleaseCallback( const scoped_refptr<ContextProvider>& context_provider, unsigned texture_id); @@ -33,12 +33,12 @@ class CC_EXPORT TextureMailboxDeleter { // Runs the |impl_callback| to delete the texture and removes the callback // from the |impl_callbacks_| list. void RunDeleteTextureOnImplThread( - TextureMailbox::ReleaseCallback* impl_callback, + SingleReleaseCallback* impl_callback, unsigned sync_point, bool is_lost); base::WeakPtrFactory<TextureMailboxDeleter> weak_ptr_factory_; - ScopedPtrVector<TextureMailbox::ReleaseCallback> impl_callbacks_; + ScopedPtrVector<SingleReleaseCallback> impl_callbacks_; }; } // namespace cc diff --git a/cc/resources/texture_mailbox_deleter_unittest.cc b/cc/resources/texture_mailbox_deleter_unittest.cc index e08984e..a6ec48e 100644 --- a/cc/resources/texture_mailbox_deleter_unittest.cc +++ b/cc/resources/texture_mailbox_deleter_unittest.cc @@ -6,6 +6,7 @@ #include "cc/debug/test_context_provider.h" #include "cc/debug/test_web_graphics_context_3d.h" +#include "cc/resources/single_release_callback.h" #include "testing/gtest/include/gtest/gtest.h" namespace cc { @@ -23,8 +24,8 @@ TEST(TextureMailboxDeleterTest, Destroy) { EXPECT_TRUE(context_provider->HasOneRef()); EXPECT_EQ(1u, context_provider->TestContext3d()->NumTextures()); - TextureMailbox::ReleaseCallback cb = - deleter->GetReleaseCallback(context_provider, texture_id); + scoped_ptr<SingleReleaseCallback> cb = + deleter->GetReleaseCallback(context_provider, texture_id).Pass(); EXPECT_FALSE(context_provider->HasOneRef()); EXPECT_EQ(1u, context_provider->TestContext3d()->NumTextures()); @@ -33,6 +34,10 @@ TEST(TextureMailboxDeleterTest, Destroy) { deleter.reset(); EXPECT_TRUE(context_provider->HasOneRef()); EXPECT_EQ(0u, context_provider->TestContext3d()->NumTextures()); + + // Run the scoped release callback before destroying it, but it won't do + // anything. + cb->Run(0, false); } } // namespace diff --git a/cc/resources/video_resource_updater.cc b/cc/resources/video_resource_updater.cc index f278c59..d07ff35 100644 --- a/cc/resources/video_resource_updater.cc +++ b/cc/resources/video_resource_updater.cc @@ -271,13 +271,12 @@ VideoFrameExternalResources VideoResourceUpdater::CreateForSoftwarePlanes( plane_resources[0].resource_format, gpu::Mailbox() }; - TextureMailbox::ReleaseCallback callback_to_free_resource = - base::Bind(&RecycleResource, - AsWeakPtr(), - recycle_data); + external_resources.software_resources.push_back( plane_resources[0].resource_id); - external_resources.software_release_callback = callback_to_free_resource; + external_resources.software_release_callback = + base::Bind(&RecycleResource, AsWeakPtr(), recycle_data); + external_resources.type = VideoFrameExternalResources::SOFTWARE_RESOURCE; return external_resources; @@ -307,13 +306,11 @@ VideoFrameExternalResources VideoResourceUpdater::CreateForSoftwarePlanes( plane_resources[i].resource_format, plane_resources[i].mailbox }; - TextureMailbox::ReleaseCallback callback_to_free_resource = - base::Bind(&RecycleResource, - AsWeakPtr(), - recycle_data); + external_resources.mailboxes.push_back( - TextureMailbox(plane_resources[i].mailbox, - callback_to_free_resource)); + TextureMailbox(plane_resources[i].mailbox)); + external_resources.release_callbacks.push_back( + base::Bind(&RecycleResource, AsWeakPtr(), recycle_data)); } external_resources.type = VideoFrameExternalResources::YUV_RESOURCE; @@ -358,14 +355,12 @@ VideoFrameExternalResources VideoResourceUpdater::CreateForHardwarePlanes( scoped_refptr<media::VideoFrame::MailboxHolder> mailbox_holder = video_frame->texture_mailbox(); - TextureMailbox::ReleaseCallback callback_to_return_resource = - base::Bind(&ReturnTexture, mailbox_holder); - external_resources.mailboxes.push_back( TextureMailbox(mailbox_holder->mailbox(), - callback_to_return_resource, video_frame->texture_target(), mailbox_holder->sync_point())); + external_resources.release_callbacks.push_back( + base::Bind(&ReturnTexture, mailbox_holder)); return external_resources; } diff --git a/cc/resources/video_resource_updater.h b/cc/resources/video_resource_updater.h index cf71cfa..d0e9f9c 100644 --- a/cc/resources/video_resource_updater.h +++ b/cc/resources/video_resource_updater.h @@ -12,6 +12,7 @@ #include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" #include "cc/base/cc_export.h" +#include "cc/resources/release_callback.h" #include "cc/resources/texture_mailbox.h" #include "ui/gfx/size.h" @@ -48,10 +49,11 @@ class CC_EXPORT VideoFrameExternalResources { ResourceType type; std::vector<TextureMailbox> mailboxes; + std::vector<ReleaseCallback> release_callbacks; // TODO(danakj): Remove these too. std::vector<unsigned> software_resources; - TextureMailbox::ReleaseCallback software_release_callback; + ReleaseCallback software_release_callback; VideoFrameExternalResources(); ~VideoFrameExternalResources(); diff --git a/cc/test/layer_tree_pixel_test.cc b/cc/test/layer_tree_pixel_test.cc index 16d7187..1d38e64 100644 --- a/cc/test/layer_tree_pixel_test.cc +++ b/cc/test/layer_tree_pixel_test.cc @@ -125,8 +125,10 @@ scoped_refptr<SolidColorLayer> LayerTreePixelTest::CreateSolidColorLayer( void LayerTreePixelTest::EndTest() { // Drop TextureMailboxes on the main thread so that they can be cleaned up and // the pending callbacks will fire. - for (size_t i = 0; i < texture_layers_.size(); ++i) - texture_layers_[i]->SetTextureMailbox(TextureMailbox()); + for (size_t i = 0; i < texture_layers_.size(); ++i) { + texture_layers_[i]->SetTextureMailbox(TextureMailbox(), + scoped_ptr<SingleReleaseCallback>()); + } TryEndTest(); } @@ -174,7 +176,12 @@ scoped_refptr<TextureLayer> LayerTreePixelTest::CreateTextureLayer( layer->SetAnchorPoint(gfx::PointF()); layer->SetBounds(rect.size()); layer->SetPosition(rect.origin()); - layer->SetTextureMailbox(CopyBitmapToTextureMailboxAsTexture(bitmap)); + + TextureMailbox texture_mailbox; + scoped_ptr<SingleReleaseCallback> release_callback; + CopyBitmapToTextureMailboxAsTexture( + bitmap, &texture_mailbox, &release_callback); + layer->SetTextureMailbox(texture_mailbox, release_callback.Pass()); texture_layers_.push_back(layer); pending_texture_mailbox_callbacks_++; @@ -301,8 +308,10 @@ void LayerTreePixelTest::ReleaseTextureMailbox( TryEndTest(); } -TextureMailbox LayerTreePixelTest::CopyBitmapToTextureMailboxAsTexture( - const SkBitmap& bitmap) { +void LayerTreePixelTest::CopyBitmapToTextureMailboxAsTexture( + const SkBitmap& bitmap, + TextureMailbox* texture_mailbox, + scoped_ptr<SingleReleaseCallback>* release_callback) { DCHECK_GT(bitmap.width(), 0); DCHECK_GT(bitmap.height(), 0); @@ -364,13 +373,12 @@ TextureMailbox LayerTreePixelTest::CopyBitmapToTextureMailboxAsTexture( context3d->bindTexture(GL_TEXTURE_2D, 0); uint32 sync_point = context3d->insertSyncPoint(); - return TextureMailbox( - mailbox, + *texture_mailbox = TextureMailbox(mailbox, sync_point); + *release_callback = SingleReleaseCallback::Create( base::Bind(&LayerTreePixelTest::ReleaseTextureMailbox, base::Unretained(this), base::Passed(&context3d), - texture_id), - sync_point); + texture_id)); } } // namespace cc diff --git a/cc/test/layer_tree_pixel_test.h b/cc/test/layer_tree_pixel_test.h index 82fffb4..2fdf2a6 100644 --- a/cc/test/layer_tree_pixel_test.h +++ b/cc/test/layer_tree_pixel_test.h @@ -7,6 +7,7 @@ #include "base/files/file_path.h" #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" +#include "cc/resources/single_release_callback.h" #include "cc/test/layer_tree_test.h" #ifndef CC_TEST_LAYER_TREE_PIXEL_TEST_H_ @@ -75,7 +76,10 @@ class LayerTreePixelTest : public LayerTreeTest { gfx::Size size, const TextureMailbox& texture_mailbox); - TextureMailbox CopyBitmapToTextureMailboxAsTexture(const SkBitmap& bitmap); + void CopyBitmapToTextureMailboxAsTexture( + const SkBitmap& bitmap, + TextureMailbox* texture_mailbox, + scoped_ptr<SingleReleaseCallback>* release_callback); void ReleaseTextureMailbox( scoped_ptr<WebKit::WebGraphicsContext3D> context3d, diff --git a/cc/trees/layer_tree_host_pixeltest_readback.cc b/cc/trees/layer_tree_host_pixeltest_readback.cc index 1c8380b..28b80b9 100644 --- a/cc/trees/layer_tree_host_pixeltest_readback.cc +++ b/cc/trees/layer_tree_host_pixeltest_readback.cc @@ -58,13 +58,15 @@ class LayerTreeHostReadbackPixelTest : public LayerTreePixelTest { EXPECT_TRUE(proxy()->IsMainThread()); EXPECT_TRUE(result->HasTexture()); - scoped_ptr<TextureMailbox> texture_mailbox = result->TakeTexture().Pass(); - EXPECT_TRUE(texture_mailbox->IsValid()); - EXPECT_TRUE(texture_mailbox->IsTexture()); + TextureMailbox texture_mailbox; + scoped_ptr<SingleReleaseCallback> release_callback; + result->TakeTexture(&texture_mailbox, &release_callback); + EXPECT_TRUE(texture_mailbox.IsValid()); + EXPECT_TRUE(texture_mailbox.IsTexture()); scoped_ptr<SkBitmap> bitmap = - CopyTextureMailboxToBitmap(result->size(), *texture_mailbox); - texture_mailbox->RunReleaseCallback(0, false); + CopyTextureMailboxToBitmap(result->size(), texture_mailbox); + release_callback->Run(0, false); ReadbackResultAsBitmap(CopyOutputResult::CreateBitmapResult(bitmap.Pass())); } |