From 6b14423001656e1ed508e542552ca5c6e10209cb Mon Sep 17 00:00:00 2001 From: "danakj@chromium.org" Date: Tue, 30 Jul 2013 22:27:55 +0000 Subject: Allow ContextProvider impls to be used without subclassing. Currently the ContextProviderCommandBuffer is subclassed in every location it is used in order to implement the methods to create the context3d, and handle lost contexts. Instead, we can use base::Callback, and avoid subclassing these ContextProvider implementations everywhere => much less lines of code. Also, the subclasses implement methods such as "CreateOffscreenContext", so we would need a separate subclass for onscreen contexts, causing an explosion in the number of subclasses needed. Added thread-safety checks to the ContextProvider implementations while I was there. R=piman@chromium.org BUG=258625 Review URL: https://codereview.chromium.org/21128002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@214443 0039d316-1c4b-4281-b951-d872f2087c98 --- cc/output/context_provider.h | 9 +++ cc/test/fake_context_provider.cc | 42 +++++++++--- cc/test/fake_context_provider.h | 19 +++-- .../browser/aura/gpu_process_transport_factory.cc | 80 +++++++--------------- .../browser/aura/gpu_process_transport_factory.h | 43 ++---------- .../gpu/client/context_provider_command_buffer.cc | 49 +++++++++++-- .../gpu/client/context_provider_command_buffer.h | 24 ++++--- content/renderer/render_thread_impl.cc | 30 ++------ content/renderer/render_thread_impl.h | 6 +- .../context_provider_from_context_factory.cc | 5 ++ .../context_provider_from_context_factory.h | 1 + webkit/common/gpu/context_provider_in_process.cc | 35 ++++++++-- webkit/common/gpu/context_provider_in_process.h | 13 +++- 13 files changed, 189 insertions(+), 167 deletions(-) diff --git a/cc/output/context_provider.h b/cc/output/context_provider.h index 3b489c7..13b7df5 100644 --- a/cc/output/context_provider.h +++ b/cc/output/context_provider.h @@ -5,6 +5,7 @@ #ifndef CC_OUTPUT_CONTEXT_PROVIDER_H_ #define CC_OUTPUT_CONTEXT_PROVIDER_H_ +#include "base/callback.h" #include "base/memory/ref_counted.h" class GrContext; @@ -32,6 +33,14 @@ class ContextProvider : public base::RefCountedThreadSafe { // the context inside the provider is no longer valid. virtual bool DestroyedOnMainThread() = 0; + // Sets a callback to be called when the context is lost. This should be + // called from the same thread that the context is bound to. To avoid races, + // it should be called before BindToCurrentThread(), or VerifyContexts() + // should be called after setting the callback. + typedef base::Closure LostContextCallback; + virtual void SetLostContextCallback( + const LostContextCallback& lost_context_callback) = 0; + protected: friend class base::RefCountedThreadSafe; virtual ~ContextProvider() {} diff --git a/cc/test/fake_context_provider.cc b/cc/test/fake_context_provider.cc index e12f783..d49fa89 100644 --- a/cc/test/fake_context_provider.cc +++ b/cc/test/fake_context_provider.cc @@ -9,29 +9,38 @@ namespace cc { FakeContextProvider::FakeContextProvider() - : destroyed_(false) { + : bound_(false), + destroyed_(false) { + DCHECK(main_thread_checker_.CalledOnValidThread()); + context_thread_checker_.DetachFromThread(); } -FakeContextProvider::FakeContextProvider( - const CreateCallback& create_callback) - : create_callback_(create_callback), - bound_(false), - destroyed_(false) { +FakeContextProvider::~FakeContextProvider() { + DCHECK(main_thread_checker_.CalledOnValidThread() || + context_thread_checker_.CalledOnValidThread()); } -FakeContextProvider::~FakeContextProvider() {} +bool FakeContextProvider::InitializeOnMainThread( + const CreateCallback& create_callback) { + DCHECK(main_thread_checker_.CalledOnValidThread()); -bool FakeContextProvider::InitializeOnMainThread() { DCHECK(!context3d_); - - if (create_callback_.is_null()) + if (create_callback.is_null()) context3d_ = TestWebGraphicsContext3D::Create().Pass(); else - context3d_ = create_callback_.Run(); + context3d_ = create_callback.Run(); return context3d_; } bool FakeContextProvider::BindToCurrentThread() { + DCHECK(context3d_); + + // This is called on the thread the context will be used. + DCHECK(context_thread_checker_.CalledOnValidThread()); + + if (bound_) + return true; + bound_ = true; if (!context3d_->makeContextCurrent()) { base::AutoLock lock(destroyed_lock_); @@ -44,12 +53,14 @@ bool FakeContextProvider::BindToCurrentThread() { WebKit::WebGraphicsContext3D* FakeContextProvider::Context3d() { DCHECK(context3d_); DCHECK(bound_); + DCHECK(context_thread_checker_.CalledOnValidThread()); return context3d_.get(); } class GrContext* FakeContextProvider::GrContext() { DCHECK(context3d_); DCHECK(bound_); + DCHECK(context_thread_checker_.CalledOnValidThread()); // TODO(danakj): Make a fake GrContext. return NULL; @@ -58,6 +69,7 @@ class GrContext* FakeContextProvider::GrContext() { void FakeContextProvider::VerifyContexts() { DCHECK(context3d_); DCHECK(bound_); + DCHECK(context_thread_checker_.CalledOnValidThread()); if (context3d_->isContextLost()) { base::AutoLock lock(destroyed_lock_); @@ -66,8 +78,16 @@ void FakeContextProvider::VerifyContexts() { } bool FakeContextProvider::DestroyedOnMainThread() { + DCHECK(main_thread_checker_.CalledOnValidThread()); + base::AutoLock lock(destroyed_lock_); return destroyed_; } +void FakeContextProvider::SetLostContextCallback( + const LostContextCallback& cb) { + DCHECK(context_thread_checker_.CalledOnValidThread()); + NOTIMPLEMENTED(); +} + } // namespace cc diff --git a/cc/test/fake_context_provider.h b/cc/test/fake_context_provider.h index 9ab1abd..4a18e4a 100644 --- a/cc/test/fake_context_provider.h +++ b/cc/test/fake_context_provider.h @@ -8,6 +8,7 @@ #include "base/callback.h" #include "base/memory/scoped_ptr.h" #include "base/synchronization/lock.h" +#include "base/threading/thread_checker.h" #include "cc/output/context_provider.h" namespace cc { @@ -19,17 +20,13 @@ class FakeContextProvider : public cc::ContextProvider { CreateCallback; static scoped_refptr Create() { - scoped_refptr provider = new FakeContextProvider(); - if (!provider->InitializeOnMainThread()) - return NULL; - return provider; + return Create(CreateCallback()); } static scoped_refptr Create( const CreateCallback& create_callback) { - scoped_refptr provider = - new FakeContextProvider(create_callback); - if (!provider->InitializeOnMainThread()) + scoped_refptr provider = new FakeContextProvider; + if (!provider->InitializeOnMainThread(create_callback)) return NULL; return provider; } @@ -39,18 +36,20 @@ class FakeContextProvider : public cc::ContextProvider { virtual class GrContext* GrContext() OVERRIDE; virtual void VerifyContexts() OVERRIDE; virtual bool DestroyedOnMainThread() OVERRIDE; + virtual void SetLostContextCallback(const LostContextCallback& cb) OVERRIDE; protected: FakeContextProvider(); - explicit FakeContextProvider(const CreateCallback& create_callback); virtual ~FakeContextProvider(); - bool InitializeOnMainThread(); + bool InitializeOnMainThread(const CreateCallback& create_callback); - CreateCallback create_callback_; scoped_ptr context3d_; bool bound_; + base::ThreadChecker main_thread_checker_; + base::ThreadChecker context_thread_checker_; + base::Lock destroyed_lock_; bool destroyed_; }; diff --git a/content/browser/aura/gpu_process_transport_factory.cc b/content/browser/aura/gpu_process_transport_factory.cc index 0a4a8fa..6ac45f7 100644 --- a/content/browser/aura/gpu_process_transport_factory.cc +++ b/content/browser/aura/gpu_process_transport_factory.cc @@ -19,6 +19,7 @@ #include "content/browser/gpu/gpu_data_manager_impl.h" #include "content/browser/gpu/gpu_surface_tracker.h" #include "content/browser/renderer_host/render_widget_host_impl.h" +#include "content/common/gpu/client/context_provider_command_buffer.h" #include "content/common/gpu/client/gl_helper.h" #include "content/common/gpu/client/gpu_channel_host.h" #include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h" @@ -221,6 +222,9 @@ GpuProcessTransportFactory::GpuProcessTransportFactory() GpuProcessTransportFactory::~GpuProcessTransportFactory() { DCHECK(per_compositor_data_.empty()); + + // Make sure the lost context callback doesn't try to run during destruction. + callback_factory_.InvalidateWeakPtrs(); } scoped_ptr @@ -397,7 +401,15 @@ scoped_refptr GpuProcessTransportFactory::OffscreenContextProviderForMainThread() { if (!shared_contexts_main_thread_.get() || shared_contexts_main_thread_->DestroyedOnMainThread()) { - shared_contexts_main_thread_ = MainThreadContextProvider::Create(this); + shared_contexts_main_thread_ = ContextProviderCommandBuffer::Create( + base::Bind(&GpuProcessTransportFactory:: + CreateOffscreenCommandBufferContext, + base::Unretained(this))); + shared_contexts_main_thread_->SetLostContextCallback(base::Bind( + &GpuProcessTransportFactory:: + OnLostMainThreadSharedContextInsideCallback, + callback_factory_.GetWeakPtr())); + if (shared_contexts_main_thread_.get() && !shared_contexts_main_thread_->BindToCurrentThread()) shared_contexts_main_thread_ = NULL; @@ -409,8 +421,10 @@ scoped_refptr GpuProcessTransportFactory::OffscreenContextProviderForCompositorThread() { if (!shared_contexts_compositor_thread_.get() || shared_contexts_compositor_thread_->DestroyedOnMainThread()) { - shared_contexts_compositor_thread_ = - CompositorThreadContextProvider::Create(this); + shared_contexts_compositor_thread_ = ContextProviderCommandBuffer::Create( + base::Bind(&GpuProcessTransportFactory:: + CreateOffscreenCommandBufferContext, + base::Unretained(this))); } return shared_contexts_compositor_thread_; } @@ -480,64 +494,16 @@ GpuProcessTransportFactory::CreateContextCommon( return context.Pass(); } -// static -scoped_refptr -GpuProcessTransportFactory::MainThreadContextProvider::Create( - GpuProcessTransportFactory* factory) { - scoped_refptr provider = - new MainThreadContextProvider(factory); - if (!provider->InitializeOnMainThread()) - return NULL; - return provider; -} - -GpuProcessTransportFactory::MainThreadContextProvider:: - MainThreadContextProvider(GpuProcessTransportFactory* factory) - : factory_(factory) {} - -GpuProcessTransportFactory::MainThreadContextProvider:: - ~MainThreadContextProvider() {} - -scoped_ptr -GpuProcessTransportFactory::MainThreadContextProvider:: - CreateOffscreenContext3d() { - return factory_->CreateOffscreenCommandBufferContext(); +void GpuProcessTransportFactory::CreateSharedContextLazy() { + scoped_refptr provider = + OffscreenContextProviderForMainThread(); } -void GpuProcessTransportFactory::MainThreadContextProvider::OnLostContext() { +void GpuProcessTransportFactory::OnLostMainThreadSharedContextInsideCallback() { base::MessageLoop::current()->PostTask( FROM_HERE, base::Bind(&GpuProcessTransportFactory::OnLostMainThreadSharedContext, - factory_->callback_factory_.GetWeakPtr())); -} - -// static -scoped_refptr -GpuProcessTransportFactory::CompositorThreadContextProvider::Create( - GpuProcessTransportFactory* factory) { - scoped_refptr provider = - new CompositorThreadContextProvider(factory); - if (!provider->InitializeOnMainThread()) - return NULL; - return provider; -} - -GpuProcessTransportFactory::CompositorThreadContextProvider:: - CompositorThreadContextProvider(GpuProcessTransportFactory* factory) - : factory_(factory) {} - -GpuProcessTransportFactory::CompositorThreadContextProvider:: - ~CompositorThreadContextProvider() {} - -scoped_ptr -GpuProcessTransportFactory::CompositorThreadContextProvider:: - CreateOffscreenContext3d() { - return factory_->CreateOffscreenCommandBufferContext(); -} - -void GpuProcessTransportFactory::CreateSharedContextLazy() { - scoped_refptr provider = - OffscreenContextProviderForMainThread(); + callback_factory_.GetWeakPtr())); } void GpuProcessTransportFactory::OnLostMainThreadSharedContext() { @@ -545,7 +511,7 @@ void GpuProcessTransportFactory::OnLostMainThreadSharedContext() { // Keep old resources around while we call the observers, but ensure that // new resources are created if needed. - scoped_refptr old_contexts_main_thread = + scoped_refptr old_contexts_main_thread = shared_contexts_main_thread_; shared_contexts_main_thread_ = NULL; diff --git a/content/browser/aura/gpu_process_transport_factory.h b/content/browser/aura/gpu_process_transport_factory.h index 276316f..9e40b5c 100644 --- a/content/browser/aura/gpu_process_transport_factory.h +++ b/content/browser/aura/gpu_process_transport_factory.h @@ -13,13 +13,13 @@ #include "base/memory/weak_ptr.h" #include "base/observer_list.h" #include "content/browser/aura/image_transport_factory.h" -#include "content/common/gpu/client/context_provider_command_buffer.h" #include "ui/compositor/compositor.h" namespace content { class BrowserCompositorOutputSurface; class BrowserCompositorOutputSurfaceProxy; class CompositorSwapClient; +class ContextProviderCommandBuffer; class ReflectorImpl; class WebGraphicsContext3DCommandBufferImpl; class WebGraphicsContext3DSwapBuffersClient; @@ -79,50 +79,15 @@ class GpuProcessTransportFactory const base::WeakPtr& swap_client, int surface_id); - class MainThreadContextProvider : public ContextProviderCommandBuffer { - public: - static scoped_refptr Create( - GpuProcessTransportFactory* factory); - - protected: - explicit MainThreadContextProvider(GpuProcessTransportFactory* factory); - virtual ~MainThreadContextProvider(); - - // ContextProviderCommandBuffer implementation. - virtual scoped_ptr - CreateOffscreenContext3d() OVERRIDE; - virtual void OnLostContext() OVERRIDE; - - private: - GpuProcessTransportFactory* factory_; - }; - - class CompositorThreadContextProvider : public ContextProviderCommandBuffer { - public: - static scoped_refptr Create( - GpuProcessTransportFactory* factory); - - protected: - explicit CompositorThreadContextProvider( - GpuProcessTransportFactory* factory); - virtual ~CompositorThreadContextProvider(); - - // ContextProviderCommandBuffer implementation. - virtual scoped_ptr - CreateOffscreenContext3d() OVERRIDE; - - private: - GpuProcessTransportFactory* factory_; - }; - void CreateSharedContextLazy(); + void OnLostMainThreadSharedContextInsideCallback(); void OnLostMainThreadSharedContext(); typedef std::map PerCompositorDataMap; PerCompositorDataMap per_compositor_data_; - scoped_refptr shared_contexts_main_thread_; - scoped_refptr + scoped_refptr shared_contexts_main_thread_; + scoped_refptr shared_contexts_compositor_thread_; scoped_ptr gl_helper_; ObserverList observer_list_; diff --git a/content/common/gpu/client/context_provider_command_buffer.cc b/content/common/gpu/client/context_provider_command_buffer.cc index 6789116..96e75ad 100644 --- a/content/common/gpu/client/context_provider_command_buffer.cc +++ b/content/common/gpu/client/context_provider_command_buffer.cc @@ -4,6 +4,7 @@ #include "content/common/gpu/client/context_provider_command_buffer.h" +#include "base/callback_helpers.h" #include "webkit/common/gpu/grcontext_for_webgraphicscontext3d.h" namespace content { @@ -21,7 +22,7 @@ class ContextProviderCommandBuffer::LostContextCallbackProxy } virtual void onContextLost() { - provider_->OnLostContextInternal(); + provider_->OnLostContext(); } private: @@ -50,12 +51,26 @@ class ContextProviderCommandBuffer::MemoryAllocationCallbackProxy ContextProviderCommandBuffer* provider_; }; +scoped_refptr +ContextProviderCommandBuffer::Create(const CreateCallback& create_callback) { + scoped_refptr provider = + new ContextProviderCommandBuffer; + if (!provider->InitializeOnMainThread(create_callback)) + return NULL; + return provider; +} + ContextProviderCommandBuffer::ContextProviderCommandBuffer() : leak_on_destroy_(false), destroyed_(false) { + DCHECK(main_thread_checker_.CalledOnValidThread()); + context_thread_checker_.DetachFromThread(); } ContextProviderCommandBuffer::~ContextProviderCommandBuffer() { + DCHECK(main_thread_checker_.CalledOnValidThread() || + context_thread_checker_.CalledOnValidThread()); + base::AutoLock lock(main_thread_lock_); if (leak_on_destroy_) { WebGraphicsContext3DCommandBufferImpl* context3d ALLOW_UNUSED = @@ -65,15 +80,22 @@ ContextProviderCommandBuffer::~ContextProviderCommandBuffer() { } } -bool ContextProviderCommandBuffer::InitializeOnMainThread() { +bool ContextProviderCommandBuffer::InitializeOnMainThread( + const CreateCallback& create_callback) { + DCHECK(main_thread_checker_.CalledOnValidThread()); + DCHECK(!context3d_); - context3d_ = CreateOffscreenContext3d().Pass(); + DCHECK(!create_callback.is_null()); + context3d_ = create_callback.Run(); return !!context3d_; } bool ContextProviderCommandBuffer::BindToCurrentThread() { DCHECK(context3d_); + // This is called on the thread the context will be used. + DCHECK(context_thread_checker_.CalledOnValidThread()); + if (lost_context_callback_proxy_) return true; @@ -88,6 +110,7 @@ WebGraphicsContext3DCommandBufferImpl* ContextProviderCommandBuffer::Context3d() { DCHECK(context3d_); DCHECK(lost_context_callback_proxy_); // Is bound to thread. + DCHECK(context_thread_checker_.CalledOnValidThread()); return context3d_.get(); } @@ -95,6 +118,7 @@ ContextProviderCommandBuffer::Context3d() { class GrContext* ContextProviderCommandBuffer::GrContext() { DCHECK(context3d_); DCHECK(lost_context_callback_proxy_); // Is bound to thread. + DCHECK(context_thread_checker_.CalledOnValidThread()); if (gr_context_) return gr_context_->get(); @@ -109,28 +133,41 @@ class GrContext* ContextProviderCommandBuffer::GrContext() { void ContextProviderCommandBuffer::VerifyContexts() { DCHECK(context3d_); DCHECK(lost_context_callback_proxy_); // Is bound to thread. + DCHECK(context_thread_checker_.CalledOnValidThread()); if (context3d_->isContextLost()) - OnLostContextInternal(); + OnLostContext(); } -void ContextProviderCommandBuffer::OnLostContextInternal() { +void ContextProviderCommandBuffer::OnLostContext() { + DCHECK(context_thread_checker_.CalledOnValidThread()); { base::AutoLock lock(main_thread_lock_); if (destroyed_) return; destroyed_ = true; } - OnLostContext(); + if (!lost_context_callback_.is_null()) + base::ResetAndReturn(&lost_context_callback_).Run(); } bool ContextProviderCommandBuffer::DestroyedOnMainThread() { + DCHECK(main_thread_checker_.CalledOnValidThread()); + base::AutoLock lock(main_thread_lock_); return destroyed_; } +void ContextProviderCommandBuffer::SetLostContextCallback( + const LostContextCallback& lost_context_callback) { + DCHECK(context_thread_checker_.CalledOnValidThread()); + DCHECK(lost_context_callback_.is_null()); + lost_context_callback_ = lost_context_callback; +} + void ContextProviderCommandBuffer::OnMemoryAllocationChanged( bool nonzero_allocation) { + DCHECK(context_thread_checker_.CalledOnValidThread()); if (gr_context_) gr_context_->SetMemoryLimit(nonzero_allocation); } diff --git a/content/common/gpu/client/context_provider_command_buffer.h b/content/common/gpu/client/context_provider_command_buffer.h index acb9303..dd21499 100644 --- a/content/common/gpu/client/context_provider_command_buffer.h +++ b/content/common/gpu/client/context_provider_command_buffer.h @@ -7,6 +7,7 @@ #include "base/memory/scoped_ptr.h" #include "base/synchronization/lock.h" +#include "base/threading/thread_checker.h" #include "cc/output/context_provider.h" #include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h" @@ -22,11 +23,18 @@ namespace content { // WebGraphicsContext3DCommandBufferImpl context and a GrContext. class ContextProviderCommandBuffer : public cc::ContextProvider { public: + typedef base::Callback< + scoped_ptr(void)> CreateCallback; + static scoped_refptr Create( + const CreateCallback& create_callback); + virtual bool BindToCurrentThread() OVERRIDE; virtual WebGraphicsContext3DCommandBufferImpl* Context3d() OVERRIDE; virtual class GrContext* GrContext() OVERRIDE; virtual void VerifyContexts() OVERRIDE; virtual bool DestroyedOnMainThread() OVERRIDE; + virtual void SetLostContextCallback( + const LostContextCallback& lost_context_callback) OVERRIDE; void set_leak_on_destroy() { base::AutoLock lock(main_thread_lock_); @@ -39,20 +47,20 @@ class ContextProviderCommandBuffer : public cc::ContextProvider { // This must be called immedately after creating this object, and it should // be thrown away if this returns false. - bool InitializeOnMainThread(); - - // Subclass must provide an implementation to create an offscreen context. - virtual scoped_ptr - CreateOffscreenContext3d() = 0; + bool InitializeOnMainThread(const CreateCallback& create_callback); - void OnLostContextInternal(); - virtual void OnLostContext() {} - virtual void OnMemoryAllocationChanged(bool nonzero_allocation); + void OnLostContext(); + void OnMemoryAllocationChanged(bool nonzero_allocation); private: + base::ThreadChecker main_thread_checker_; + base::ThreadChecker context_thread_checker_; + scoped_ptr context3d_; scoped_ptr gr_context_; + LostContextCallback lost_context_callback_; + base::Lock main_thread_lock_; bool leak_on_destroy_; bool destroyed_; diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc index 7adc22f..8f656a0 100644 --- a/content/renderer/render_thread_impl.cc +++ b/content/renderer/render_thread_impl.cc @@ -250,28 +250,6 @@ class RenderThreadImpl::GpuVDAContextLostCallback scoped_refptr main_message_loop_; }; -class RenderThreadImpl::RendererContextProviderCommandBuffer - : public ContextProviderCommandBuffer { - public: - static scoped_refptr Create() { - scoped_refptr provider = - new RendererContextProviderCommandBuffer(); - if (!provider->InitializeOnMainThread()) - return NULL; - return provider; - } - - protected: - virtual ~RendererContextProviderCommandBuffer() {} - - virtual scoped_ptr - CreateOffscreenContext3d() OVERRIDE { - RenderThreadImpl* self = RenderThreadImpl::current(); - DCHECK(self); - return self->CreateOffscreenContext3d().Pass(); - } -}; - RenderThreadImpl::HistogramCustomizer::HistogramCustomizer() { custom_histograms_.insert("V8.MemoryExternalFragmentationTotal"); custom_histograms_.insert("V8.MemoryHeapSampleTotalCommitted"); @@ -977,7 +955,9 @@ RenderThreadImpl::OffscreenContextProviderForMainThread() { if (!shared_contexts_main_thread_.get() || shared_contexts_main_thread_->DestroyedOnMainThread()) { shared_contexts_main_thread_ = - RendererContextProviderCommandBuffer::Create(); + ContextProviderCommandBuffer::Create( + base::Bind(&RenderThreadImpl::CreateOffscreenContext3d, + base::Unretained(this))); if (shared_contexts_main_thread_.get() && !shared_contexts_main_thread_->BindToCurrentThread()) shared_contexts_main_thread_ = NULL; @@ -999,7 +979,9 @@ RenderThreadImpl::OffscreenContextProviderForCompositorThread() { if (!shared_contexts_compositor_thread_.get() || shared_contexts_compositor_thread_->DestroyedOnMainThread()) { shared_contexts_compositor_thread_ = - RendererContextProviderCommandBuffer::Create(); + ContextProviderCommandBuffer::Create( + base::Bind(&RenderThreadImpl::CreateOffscreenContext3d, + base::Unretained(this))); } return shared_contexts_compositor_thread_; } diff --git a/content/renderer/render_thread_impl.h b/content/renderer/render_thread_impl.h index 5b3dac0..a0bda15 100644 --- a/content/renderer/render_thread_impl.h +++ b/content/renderer/render_thread_impl.h @@ -467,10 +467,8 @@ class CONTENT_EXPORT RenderThreadImpl : public RenderThread, scoped_ptr input_handler_manager_; scoped_refptr compositor_output_surface_filter_; - class RendererContextProviderCommandBuffer; - scoped_refptr - shared_contexts_main_thread_; - scoped_refptr + scoped_refptr shared_contexts_main_thread_; + scoped_refptr shared_contexts_compositor_thread_; ObserverList observers_; diff --git a/ui/compositor/context_provider_from_context_factory.cc b/ui/compositor/context_provider_from_context_factory.cc index c6f7790..262998a 100644 --- a/ui/compositor/context_provider_from_context_factory.cc +++ b/ui/compositor/context_provider_from_context_factory.cc @@ -61,6 +61,11 @@ bool ContextProviderFromContextFactory::DestroyedOnMainThread() { return destroyed_; } +void ContextProviderFromContextFactory::SetLostContextCallback( + const LostContextCallback& cb) { + NOTIMPLEMENTED(); +} + bool ContextProviderFromContextFactory::InitializeOnMainThread() { if (context3d_) return true; diff --git a/ui/compositor/context_provider_from_context_factory.h b/ui/compositor/context_provider_from_context_factory.h index 9877ab3..57be7f4 100644 --- a/ui/compositor/context_provider_from_context_factory.h +++ b/ui/compositor/context_provider_from_context_factory.h @@ -24,6 +24,7 @@ class ContextProviderFromContextFactory virtual class GrContext* GrContext() OVERRIDE; virtual void VerifyContexts() OVERRIDE; virtual bool DestroyedOnMainThread() OVERRIDE; + virtual void SetLostContextCallback(const LostContextCallback& cb) OVERRIDE; protected: ContextProviderFromContextFactory(ContextFactory* factory); diff --git a/webkit/common/gpu/context_provider_in_process.cc b/webkit/common/gpu/context_provider_in_process.cc index 5daf360..e56da80 100644 --- a/webkit/common/gpu/context_provider_in_process.cc +++ b/webkit/common/gpu/context_provider_in_process.cc @@ -4,6 +4,7 @@ #include "webkit/common/gpu/context_provider_in_process.h" +#include "base/callback_helpers.h" #include "webkit/common/gpu/grcontext_for_webgraphicscontext3d.h" #include "webkit/common/gpu/webgraphicscontext3d_in_process_command_buffer_impl.h" @@ -23,7 +24,7 @@ class ContextProviderInProcess::LostContextCallbackProxy } virtual void onContextLost() { - provider_->OnLostContextInternal(); + provider_->OnLostContext(); } private: @@ -54,12 +55,18 @@ class ContextProviderInProcess::MemoryAllocationCallbackProxy ContextProviderInProcess::ContextProviderInProcess() : destroyed_(false) { + DCHECK(main_thread_checker_.CalledOnValidThread()); + context_thread_checker_.DetachFromThread(); } -ContextProviderInProcess::~ContextProviderInProcess() {} +ContextProviderInProcess::~ContextProviderInProcess() { + DCHECK(main_thread_checker_.CalledOnValidThread() || + context_thread_checker_.CalledOnValidThread()); +} bool ContextProviderInProcess::InitializeOnMainThread() { DCHECK(!context3d_); + DCHECK(main_thread_checker_.CalledOnValidThread()); WebKit::WebGraphicsContext3D::Attributes attributes; attributes.depth = false; @@ -79,6 +86,9 @@ bool ContextProviderInProcess::InitializeOnMainThread() { bool ContextProviderInProcess::BindToCurrentThread() { DCHECK(context3d_); + // This is called on the thread the context will be used. + DCHECK(context_thread_checker_.CalledOnValidThread()); + if (lost_context_callback_proxy_) return true; @@ -92,6 +102,7 @@ bool ContextProviderInProcess::BindToCurrentThread() { WebKit::WebGraphicsContext3D* ContextProviderInProcess::Context3d() { DCHECK(context3d_); DCHECK(lost_context_callback_proxy_); // Is bound to thread. + DCHECK(context_thread_checker_.CalledOnValidThread()); return context3d_.get(); } @@ -99,6 +110,7 @@ WebKit::WebGraphicsContext3D* ContextProviderInProcess::Context3d() { class GrContext* ContextProviderInProcess::GrContext() { DCHECK(context3d_); DCHECK(lost_context_callback_proxy_); // Is bound to thread. + DCHECK(context_thread_checker_.CalledOnValidThread()); if (gr_context_) return gr_context_->get(); @@ -113,28 +125,41 @@ class GrContext* ContextProviderInProcess::GrContext() { void ContextProviderInProcess::VerifyContexts() { DCHECK(context3d_); DCHECK(lost_context_callback_proxy_); // Is bound to thread. + DCHECK(context_thread_checker_.CalledOnValidThread()); if (context3d_->isContextLost()) - OnLostContextInternal(); + OnLostContext(); } -void ContextProviderInProcess::OnLostContextInternal() { +void ContextProviderInProcess::OnLostContext() { + DCHECK(context_thread_checker_.CalledOnValidThread()); { base::AutoLock lock(destroyed_lock_); if (destroyed_) return; destroyed_ = true; } - OnLostContext(); + if (!lost_context_callback_.is_null()) + base::ResetAndReturn(&lost_context_callback_).Run(); } bool ContextProviderInProcess::DestroyedOnMainThread() { + DCHECK(main_thread_checker_.CalledOnValidThread()); + base::AutoLock lock(destroyed_lock_); return destroyed_; } +void ContextProviderInProcess::SetLostContextCallback( + const LostContextCallback& lost_context_callback) { + DCHECK(context_thread_checker_.CalledOnValidThread()); + DCHECK(lost_context_callback_.is_null()); + lost_context_callback_ = lost_context_callback; +} + void ContextProviderInProcess::OnMemoryAllocationChanged( bool nonzero_allocation) { + DCHECK(context_thread_checker_.CalledOnValidThread()); if (gr_context_) gr_context_->SetMemoryLimit(nonzero_allocation); } diff --git a/webkit/common/gpu/context_provider_in_process.h b/webkit/common/gpu/context_provider_in_process.h index b87fc91..b427abe 100644 --- a/webkit/common/gpu/context_provider_in_process.h +++ b/webkit/common/gpu/context_provider_in_process.h @@ -8,6 +8,7 @@ #include "base/compiler_specific.h" #include "base/memory/scoped_ptr.h" #include "base/synchronization/lock.h" +#include "base/threading/thread_checker.h" #include "cc/output/context_provider.h" #include "webkit/common/gpu/webkit_gpu_export.h" @@ -35,6 +36,8 @@ class WEBKIT_GPU_EXPORT ContextProviderInProcess virtual class GrContext* GrContext() OVERRIDE; virtual void VerifyContexts() OVERRIDE; virtual bool DestroyedOnMainThread() OVERRIDE; + virtual void SetLostContextCallback( + const LostContextCallback& lost_context_callback) OVERRIDE; protected: ContextProviderInProcess(); @@ -42,14 +45,18 @@ class WEBKIT_GPU_EXPORT ContextProviderInProcess bool InitializeOnMainThread(); - void OnLostContextInternal(); - virtual void OnLostContext() {} - virtual void OnMemoryAllocationChanged(bool nonzero_allocation); + void OnLostContext(); + void OnMemoryAllocationChanged(bool nonzero_allocation); private: + base::ThreadChecker main_thread_checker_; + base::ThreadChecker context_thread_checker_; + scoped_ptr context3d_; scoped_ptr gr_context_; + LostContextCallback lost_context_callback_; + base::Lock destroyed_lock_; bool destroyed_; -- cgit v1.1