diff options
author | fischman@chromium.org <fischman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-08-13 21:21:38 +0000 |
---|---|---|
committer | fischman@chromium.org <fischman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-08-13 21:21:38 +0000 |
commit | fe476b031d96e1cc92321c57e2da967fa510407d (patch) | |
tree | 0933634e9c20e0e2191779f2ad428851e0a11f1d /content/renderer | |
parent | 86204ea37bde1eaa82df380e02cae07da5f0f28d (diff) | |
download | chromium_src-fe476b031d96e1cc92321c57e2da967fa510407d.zip chromium_src-fe476b031d96e1cc92321c57e2da967fa510407d.tar.gz chromium_src-fe476b031d96e1cc92321c57e2da967fa510407d.tar.bz2 |
Fix lifecycle-vs-threads of GpuVDAContext3D.
This context3d is meant to be created on the render thread but can only be
dereferenced on the compositor thread. Before this CL this was violated as
RenderThreadImpl::GetGpuVDAContext3D() checked for context loss to decide
whether to recreate the context. Now context loss proactively notifies the
render thread, instead.
BUG=142047
Review URL: https://chromiumcodereview.appspot.com/10832264
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@151352 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content/renderer')
-rw-r--r-- | content/renderer/media/renderer_gpu_video_decoder_factories.cc | 19 | ||||
-rw-r--r-- | content/renderer/media/renderer_gpu_video_decoder_factories.h | 7 | ||||
-rw-r--r-- | content/renderer/render_thread_impl.cc | 44 | ||||
-rw-r--r-- | content/renderer/render_thread_impl.h | 9 | ||||
-rw-r--r-- | content/renderer/render_view_impl.cc | 4 |
5 files changed, 55 insertions, 28 deletions
diff --git a/content/renderer/media/renderer_gpu_video_decoder_factories.cc b/content/renderer/media/renderer_gpu_video_decoder_factories.cc index a64ddbd..9fa05b3 100644 --- a/content/renderer/media/renderer_gpu_video_decoder_factories.cc +++ b/content/renderer/media/renderer_gpu_video_decoder_factories.cc @@ -19,14 +19,11 @@ RendererGpuVideoDecoderFactories::~RendererGpuVideoDecoderFactories() {} RendererGpuVideoDecoderFactories::RendererGpuVideoDecoderFactories( GpuChannelHost* gpu_channel_host, const scoped_refptr<base::MessageLoopProxy>& message_loop, - const base::WeakPtr<WebGraphicsContext3DCommandBufferImpl>& context) + WebGraphicsContext3DCommandBufferImpl* context) : message_loop_(message_loop), - gpu_channel_host_(gpu_channel_host), - context_(context) { - DCHECK(context_); - context_->DetachFromThread(); + gpu_channel_host_(gpu_channel_host) { if (message_loop_->BelongsToCurrentThread()) { - AsyncGetContext(NULL); + AsyncGetContext(context, NULL); return; } // Threaded compositor requires us to wait for the context to be acquired. @@ -36,12 +33,20 @@ RendererGpuVideoDecoderFactories::RendererGpuVideoDecoderFactories( // Unretained to avoid ref/deref'ing |*this|, which is not yet stored in a // scoped_refptr. Safe because the Wait() below keeps us alive until this // task completes. - base::Unretained(this), &waiter)); + base::Unretained(this), + // OK to pass raw because the pointee is only deleted on the compositor + // thread, and only as the result of a PostTask from the render thread + // which can only happen after this function returns, so our PostTask will + // run first. + context, + &waiter)); waiter.Wait(); } void RendererGpuVideoDecoderFactories::AsyncGetContext( + WebGraphicsContext3DCommandBufferImpl* context, base::WaitableEvent* waiter) { + context_ = context->AsWeakPtr(); if (context_) context_->makeContextCurrent(); if (waiter) diff --git a/content/renderer/media/renderer_gpu_video_decoder_factories.h b/content/renderer/media/renderer_gpu_video_decoder_factories.h index 89efa54..a9b27e3 100644 --- a/content/renderer/media/renderer_gpu_video_decoder_factories.h +++ b/content/renderer/media/renderer_gpu_video_decoder_factories.h @@ -32,12 +32,12 @@ class WaitableEvent; class CONTENT_EXPORT RendererGpuVideoDecoderFactories : public media::GpuVideoDecoder::Factories { public: - // Takes a ref on |gpu_channel_host| and tests |context| for NULL before each + // Takes a ref on |gpu_channel_host| and tests |context| for loss before each // use. RendererGpuVideoDecoderFactories( GpuChannelHost* gpu_channel_host, const scoped_refptr<base::MessageLoopProxy>& message_loop, - const base::WeakPtr<WebGraphicsContext3DCommandBufferImpl>& wgc3dcbi); + WebGraphicsContext3DCommandBufferImpl* wgc3dcbi); virtual media::VideoDecodeAccelerator* CreateVideoDecodeAccelerator( media::VideoCodecProfile profile, @@ -58,7 +58,8 @@ class CONTENT_EXPORT RendererGpuVideoDecoderFactories private: // Helper for the constructor to acquire the ContentGLContext on the // compositor thread (when it is enabled). - void AsyncGetContext(base::WaitableEvent* waiter); + void AsyncGetContext(WebGraphicsContext3DCommandBufferImpl* context, + base::WaitableEvent* waiter); // Async versions of the public methods. They use output parameters instead // of return values and each takes a WaitableEvent* param to signal completion diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc index 35ab4ec..c33a671 100644 --- a/content/renderer/render_thread_impl.cc +++ b/content/renderer/render_thread_impl.cc @@ -173,6 +173,17 @@ static void AddHistogramSample(void* hist, int sample) { histogram->Add(sample); } +class RenderThreadImpl::GpuVDAContextLostCallback + : public WebKit::WebGraphicsContext3D::WebGraphicsContextLostCallback { + public: + GpuVDAContextLostCallback() {} + virtual ~GpuVDAContextLostCallback() {} + virtual void onContextLost() { + ChildThread::current()->message_loop()->PostTask(FROM_HERE, base::Bind( + &RenderThreadImpl::OnGpuVDAContextLoss)); + } +}; + RenderThreadImpl* RenderThreadImpl::current() { return lazy_tls.Pointer()->Get(); } @@ -262,6 +273,8 @@ void RenderThreadImpl::Init() { WebKit::WebCompositor::setPartialSwapEnabled( command_line.HasSwitch(switches::kEnablePartialSwap)); + context_lost_cb_.reset(new GpuVDAContextLostCallback()); + // Note that under Linux, the media library will normally already have // been initialized by the Zygote before this instance became a Renderer. FilePath media_path; @@ -746,27 +759,30 @@ void RenderThreadImpl::PostponeIdleNotification() { idle_notifications_to_skip_ = 2; } -base::WeakPtr<WebGraphicsContext3DCommandBufferImpl> -RenderThreadImpl::GetGpuVDAContext3D() { - // If we already handed out a pointer to a context and it's been lost, create - // a new one. - if (gpu_vda_context3d_.get() && gpu_vda_context3d_->isContextLost()) { - if (compositor_thread()) { - compositor_thread()->GetWebThread()->message_loop()->DeleteSoon( - FROM_HERE, gpu_vda_context3d_.release()); - } else { - gpu_vda_context3d_.reset(); - } +/* static */ +void RenderThreadImpl::OnGpuVDAContextLoss() { + RenderThreadImpl* self = RenderThreadImpl::current(); + DCHECK(self); + if (!self->gpu_vda_context3d_.get()) + return; + if (self->compositor_thread()) { + self->compositor_thread()->GetWebThread()->message_loop()->DeleteSoon( + FROM_HERE, self->gpu_vda_context3d_.release()); + } else { + self->gpu_vda_context3d_.reset(); } +} + +WebGraphicsContext3DCommandBufferImpl* +RenderThreadImpl::GetGpuVDAContext3D() { if (!gpu_vda_context3d_.get()) { gpu_vda_context3d_.reset( WebGraphicsContext3DCommandBufferImpl::CreateOffscreenContext( this, WebKit::WebGraphicsContext3D::Attributes(), GURL("chrome://gpu/RenderThreadImpl::GetGpuVDAContext3D"))); + gpu_vda_context3d_->setContextLostCallback(context_lost_cb_.get()); } - if (!gpu_vda_context3d_.get()) - return base::WeakPtr<WebGraphicsContext3DCommandBufferImpl>(); - return gpu_vda_context3d_->AsWeakPtr(); + return gpu_vda_context3d_.get(); } content::AudioRendererMixerManager* diff --git a/content/renderer/render_thread_impl.h b/content/renderer/render_thread_impl.h index 5ffdda1..dfcdb65 100644 --- a/content/renderer/render_thread_impl.h +++ b/content/renderer/render_thread_impl.h @@ -218,9 +218,12 @@ class CONTENT_EXPORT RenderThreadImpl : public content::RenderThread, // Returns a graphics context shared among all // RendererGpuVideoDecoderFactories, or NULL on error. Context remains owned // by this class and must be null-tested before each use to detect context - // loss. The returned WeakPtr<> is only valid on the compositor thread when + // loss. The returned context is only valid on the compositor thread when // threaded compositing is enabled. - base::WeakPtr<WebGraphicsContext3DCommandBufferImpl> GetGpuVDAContext3D(); + WebGraphicsContext3DCommandBufferImpl* GetGpuVDAContext3D(); + + // Handle loss of the shared GpuVDAContext3D context above. + static void OnGpuVDAContextLoss(); // AudioRendererMixerManager instance which manages renderer side mixer // instances shared based on configured audio parameters. Lazily created on @@ -299,6 +302,8 @@ class CONTENT_EXPORT RenderThreadImpl : public content::RenderThread, ObserverList<content::RenderProcessObserver> observers_; + class GpuVDAContextLostCallback; + scoped_ptr<GpuVDAContextLostCallback> context_lost_cb_; scoped_ptr<WebGraphicsContext3DCommandBufferImpl> gpu_vda_context3d_; scoped_ptr<content::AudioRendererMixerManager> audio_renderer_mixer_manager_; diff --git a/content/renderer/render_view_impl.cc b/content/renderer/render_view_impl.cc index fb0c230..f2c7716e 100644 --- a/content/renderer/render_view_impl.cc +++ b/content/renderer/render_view_impl.cc @@ -2423,10 +2423,10 @@ WebMediaPlayer* RenderViewImpl::createMediaPlayer( #endif use_accelerated_video_decode &= !CommandLine::ForCurrentProcess()->HasSwitch( switches::kDisableAcceleratedVideoDecode); - base::WeakPtr<WebGraphicsContext3DCommandBufferImpl> context3d = + WebGraphicsContext3DCommandBufferImpl* context3d = use_accelerated_video_decode ? RenderThreadImpl::current()->GetGpuVDAContext3D() : - base::WeakPtr<WebGraphicsContext3DCommandBufferImpl>(); + NULL; if (context3d) { scoped_refptr<base::MessageLoopProxy> factories_loop = RenderThreadImpl::current()->compositor_thread() ? |