1 // Copyright 2013 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "cc/resources/texture_mailbox_deleter.h" 6 7 #include "base/bind.h" 8 #include "base/location.h" 9 #include "base/memory/weak_ptr.h" 10 #include "base/message_loop/message_loop_proxy.h" 11 #include "cc/output/context_provider.h" 12 #include "cc/resources/single_release_callback.h" 13 #include "gpu/command_buffer/client/gles2_interface.h" 14 15 namespace cc { 16 17 static void DeleteTextureOnImplThread( 18 const scoped_refptr<ContextProvider>& context_provider, 19 unsigned texture_id, 20 unsigned sync_point, 21 bool is_lost) { 22 if (sync_point) 23 context_provider->ContextGL()->WaitSyncPointCHROMIUM(sync_point); 24 context_provider->ContextGL()->DeleteTextures(1, &texture_id); 25 } 26 27 static void PostTaskFromMainToImplThread( 28 scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner, 29 ReleaseCallback run_impl_callback, 30 unsigned sync_point, 31 bool is_lost) { 32 // This posts the task to RunDeleteTextureOnImplThread(). 33 impl_task_runner->PostTask( 34 FROM_HERE, base::Bind(run_impl_callback, sync_point, is_lost)); 35 } 36 37 TextureMailboxDeleter::TextureMailboxDeleter() : weak_ptr_factory_(this) {} 38 39 TextureMailboxDeleter::~TextureMailboxDeleter() { 40 for (size_t i = 0; i < impl_callbacks_.size(); ++i) 41 impl_callbacks_.at(i)->Run(0, true); 42 } 43 44 scoped_ptr<SingleReleaseCallback> TextureMailboxDeleter::GetReleaseCallback( 45 const scoped_refptr<ContextProvider>& context_provider, 46 unsigned texture_id) { 47 // This callback owns a reference on the |context_provider|. It must be 48 // destroyed on the impl thread. Upon destruction of this class, the 49 // callback must immediately be destroyed. 50 scoped_ptr<SingleReleaseCallback> impl_callback = 51 SingleReleaseCallback::Create(base::Bind(&DeleteTextureOnImplThread, 52 context_provider, 53 texture_id)); 54 55 impl_callbacks_.push_back(impl_callback.Pass()); 56 57 // The raw pointer to the impl-side callback is valid as long as this 58 // class is alive. So we guard it with a WeakPtr. 59 ReleaseCallback run_impl_callback( 60 base::Bind(&TextureMailboxDeleter::RunDeleteTextureOnImplThread, 61 weak_ptr_factory_.GetWeakPtr(), 62 impl_callbacks_.back())); 63 64 // Provide a callback for the main thread that posts back to the impl 65 // thread. 66 scoped_ptr<SingleReleaseCallback> main_callback = 67 SingleReleaseCallback::Create(base::Bind( 68 &PostTaskFromMainToImplThread, 69 base::MessageLoopProxy::current(), 70 run_impl_callback)); 71 72 return main_callback.Pass(); 73 } 74 75 void TextureMailboxDeleter::RunDeleteTextureOnImplThread( 76 SingleReleaseCallback* impl_callback, 77 unsigned sync_point, 78 bool is_lost) { 79 for (size_t i = 0; i < impl_callbacks_.size(); ++i) { 80 if (impl_callbacks_.at(i) == impl_callback) { 81 // Run the callback, then destroy it here on the impl thread. 82 impl_callbacks_.at(i)->Run(sync_point, is_lost); 83 impl_callbacks_.erase(impl_callbacks_.begin() + i); 84 return; 85 } 86 } 87 88 NOTREACHED() << "The Callback returned by GetDeleteCallback() was called " 89 << "more than once."; 90 } 91 92 } // namespace cc 93