diff options
author | danakj@chromium.org <danakj@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-07-30 22:27:55 +0000 |
---|---|---|
committer | danakj@chromium.org <danakj@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-07-30 22:27:55 +0000 |
commit | 6b14423001656e1ed508e542552ca5c6e10209cb (patch) | |
tree | 9c451725609a61fda2729b55a2ed9a5a00616c8f | |
parent | f5de9e5bb9a33de6f7f103688167e30c4fece29c (diff) | |
download | chromium_src-6b14423001656e1ed508e542552ca5c6e10209cb.zip chromium_src-6b14423001656e1ed508e542552ca5c6e10209cb.tar.gz chromium_src-6b14423001656e1ed508e542552ca5c6e10209cb.tar.bz2 |
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
-rw-r--r-- | cc/output/context_provider.h | 9 | ||||
-rw-r--r-- | cc/test/fake_context_provider.cc | 42 | ||||
-rw-r--r-- | cc/test/fake_context_provider.h | 19 | ||||
-rw-r--r-- | content/browser/aura/gpu_process_transport_factory.cc | 80 | ||||
-rw-r--r-- | content/browser/aura/gpu_process_transport_factory.h | 43 | ||||
-rw-r--r-- | content/common/gpu/client/context_provider_command_buffer.cc | 49 | ||||
-rw-r--r-- | content/common/gpu/client/context_provider_command_buffer.h | 24 | ||||
-rw-r--r-- | content/renderer/render_thread_impl.cc | 30 | ||||
-rw-r--r-- | content/renderer/render_thread_impl.h | 6 | ||||
-rw-r--r-- | ui/compositor/context_provider_from_context_factory.cc | 5 | ||||
-rw-r--r-- | ui/compositor/context_provider_from_context_factory.h | 1 | ||||
-rw-r--r-- | webkit/common/gpu/context_provider_in_process.cc | 35 | ||||
-rw-r--r-- | 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<ContextProvider> { // 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<ContextProvider>; 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<FakeContextProvider> Create() { - scoped_refptr<FakeContextProvider> provider = new FakeContextProvider(); - if (!provider->InitializeOnMainThread()) - return NULL; - return provider; + return Create(CreateCallback()); } static scoped_refptr<FakeContextProvider> Create( const CreateCallback& create_callback) { - scoped_refptr<FakeContextProvider> provider = - new FakeContextProvider(create_callback); - if (!provider->InitializeOnMainThread()) + scoped_refptr<FakeContextProvider> 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<WebKit::WebGraphicsContext3D> 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<WebGraphicsContext3DCommandBufferImpl> @@ -397,7 +401,15 @@ scoped_refptr<cc::ContextProvider> 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<cc::ContextProvider> 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> -GpuProcessTransportFactory::MainThreadContextProvider::Create( - GpuProcessTransportFactory* factory) { - scoped_refptr<MainThreadContextProvider> provider = - new MainThreadContextProvider(factory); - if (!provider->InitializeOnMainThread()) - return NULL; - return provider; -} - -GpuProcessTransportFactory::MainThreadContextProvider:: - MainThreadContextProvider(GpuProcessTransportFactory* factory) - : factory_(factory) {} - -GpuProcessTransportFactory::MainThreadContextProvider:: - ~MainThreadContextProvider() {} - -scoped_ptr<WebGraphicsContext3DCommandBufferImpl> -GpuProcessTransportFactory::MainThreadContextProvider:: - CreateOffscreenContext3d() { - return factory_->CreateOffscreenCommandBufferContext(); +void GpuProcessTransportFactory::CreateSharedContextLazy() { + scoped_refptr<cc::ContextProvider> 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> -GpuProcessTransportFactory::CompositorThreadContextProvider::Create( - GpuProcessTransportFactory* factory) { - scoped_refptr<CompositorThreadContextProvider> provider = - new CompositorThreadContextProvider(factory); - if (!provider->InitializeOnMainThread()) - return NULL; - return provider; -} - -GpuProcessTransportFactory::CompositorThreadContextProvider:: - CompositorThreadContextProvider(GpuProcessTransportFactory* factory) - : factory_(factory) {} - -GpuProcessTransportFactory::CompositorThreadContextProvider:: - ~CompositorThreadContextProvider() {} - -scoped_ptr<WebGraphicsContext3DCommandBufferImpl> -GpuProcessTransportFactory::CompositorThreadContextProvider:: - CreateOffscreenContext3d() { - return factory_->CreateOffscreenCommandBufferContext(); -} - -void GpuProcessTransportFactory::CreateSharedContextLazy() { - scoped_refptr<cc::ContextProvider> 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<MainThreadContextProvider> old_contexts_main_thread = + scoped_refptr<ContextProviderCommandBuffer> 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<WebGraphicsContext3DSwapBuffersClient>& swap_client, int surface_id); - class MainThreadContextProvider : public ContextProviderCommandBuffer { - public: - static scoped_refptr<MainThreadContextProvider> Create( - GpuProcessTransportFactory* factory); - - protected: - explicit MainThreadContextProvider(GpuProcessTransportFactory* factory); - virtual ~MainThreadContextProvider(); - - // ContextProviderCommandBuffer implementation. - virtual scoped_ptr<WebGraphicsContext3DCommandBufferImpl> - CreateOffscreenContext3d() OVERRIDE; - virtual void OnLostContext() OVERRIDE; - - private: - GpuProcessTransportFactory* factory_; - }; - - class CompositorThreadContextProvider : public ContextProviderCommandBuffer { - public: - static scoped_refptr<CompositorThreadContextProvider> Create( - GpuProcessTransportFactory* factory); - - protected: - explicit CompositorThreadContextProvider( - GpuProcessTransportFactory* factory); - virtual ~CompositorThreadContextProvider(); - - // ContextProviderCommandBuffer implementation. - virtual scoped_ptr<WebGraphicsContext3DCommandBufferImpl> - CreateOffscreenContext3d() OVERRIDE; - - private: - GpuProcessTransportFactory* factory_; - }; - void CreateSharedContextLazy(); + void OnLostMainThreadSharedContextInsideCallback(); void OnLostMainThreadSharedContext(); typedef std::map<ui::Compositor*, PerCompositorData*> PerCompositorDataMap; PerCompositorDataMap per_compositor_data_; - scoped_refptr<MainThreadContextProvider> shared_contexts_main_thread_; - scoped_refptr<CompositorThreadContextProvider> + scoped_refptr<ContextProviderCommandBuffer> shared_contexts_main_thread_; + scoped_refptr<ContextProviderCommandBuffer> shared_contexts_compositor_thread_; scoped_ptr<GLHelper> gl_helper_; ObserverList<ImageTransportFactoryObserver> 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> +ContextProviderCommandBuffer::Create(const CreateCallback& create_callback) { + scoped_refptr<ContextProviderCommandBuffer> 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<WebGraphicsContext3DCommandBufferImpl>(void)> CreateCallback; + static scoped_refptr<ContextProviderCommandBuffer> 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<WebGraphicsContext3DCommandBufferImpl> - 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<WebGraphicsContext3DCommandBufferImpl> context3d_; scoped_ptr<webkit::gpu::GrContextForWebGraphicsContext3D> 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<base::MessageLoopProxy> main_message_loop_; }; -class RenderThreadImpl::RendererContextProviderCommandBuffer - : public ContextProviderCommandBuffer { - public: - static scoped_refptr<RendererContextProviderCommandBuffer> Create() { - scoped_refptr<RendererContextProviderCommandBuffer> provider = - new RendererContextProviderCommandBuffer(); - if (!provider->InitializeOnMainThread()) - return NULL; - return provider; - } - - protected: - virtual ~RendererContextProviderCommandBuffer() {} - - virtual scoped_ptr<WebGraphicsContext3DCommandBufferImpl> - 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<InputHandlerManager> input_handler_manager_; scoped_refptr<IPC::ForwardingMessageFilter> compositor_output_surface_filter_; - class RendererContextProviderCommandBuffer; - scoped_refptr<RendererContextProviderCommandBuffer> - shared_contexts_main_thread_; - scoped_refptr<RendererContextProviderCommandBuffer> + scoped_refptr<ContextProviderCommandBuffer> shared_contexts_main_thread_; + scoped_refptr<ContextProviderCommandBuffer> shared_contexts_compositor_thread_; ObserverList<RenderProcessObserver> 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<WebKit::WebGraphicsContext3D> context3d_; scoped_ptr<webkit::gpu::GrContextForWebGraphicsContext3D> gr_context_; + LostContextCallback lost_context_callback_; + base::Lock destroyed_lock_; bool destroyed_; |