| Index: content/browser/android/in_process/synchronous_compositor_impl.cc
|
| diff --git a/content/browser/android/in_process/synchronous_compositor_impl.cc b/content/browser/android/in_process/synchronous_compositor_impl.cc
|
| index 67590eb03cc30339e5ef1e02ebdab8d78f25372e..3f7132108b6640e8434aa10dd60f7d9ff2c01616 100644
|
| --- a/content/browser/android/in_process/synchronous_compositor_impl.cc
|
| +++ b/content/browser/android/in_process/synchronous_compositor_impl.cc
|
| @@ -76,7 +76,8 @@ class VideoContextProvider
|
| class SynchronousCompositorFactoryImpl : public SynchronousCompositorFactory {
|
| public:
|
| SynchronousCompositorFactoryImpl()
|
| - : wrapped_gl_context_for_main_thread_(NULL) {
|
| + : wrapped_gl_context_for_main_thread_(NULL),
|
| + num_hardware_compositors_(0) {
|
| SynchronousCompositorFactory::SetInstance(this);
|
| }
|
|
|
| @@ -135,16 +136,24 @@ class SynchronousCompositorFactoryImpl : public SynchronousCompositorFactory {
|
|
|
| virtual scoped_refptr<cc::ContextProvider>
|
| GetOffscreenContextProviderForMainThread() OVERRIDE {
|
| - if (!offscreen_context_for_main_thread_.get() ||
|
| - offscreen_context_for_main_thread_->DestroyedOnMainThread()) {
|
| + // This check only guarantees the main thread context is created after
|
| + // a compositor did successfully initialize hardware draw in the past.
|
| + // In particular this does not guarantee that the main thread context
|
| + // will fail creation when all compositors release hardware draw.
|
| + bool failed = !CanCreateMainThreadContext();
|
| + if (!failed &&
|
| + (!offscreen_context_for_main_thread_.get() ||
|
| + offscreen_context_for_main_thread_->DestroyedOnMainThread())) {
|
| offscreen_context_for_main_thread_ =
|
| webkit::gpu::ContextProviderInProcess::Create(
|
| CreateOffscreenContext());
|
| - if (offscreen_context_for_main_thread_.get() &&
|
| - !offscreen_context_for_main_thread_->BindToCurrentThread()) {
|
| - offscreen_context_for_main_thread_ = NULL;
|
| - wrapped_gl_context_for_main_thread_ = NULL;
|
| - }
|
| + failed = !offscreen_context_for_main_thread_.get() ||
|
| + !offscreen_context_for_main_thread_->BindToCurrentThread();
|
| + }
|
| +
|
| + if (failed) {
|
| + offscreen_context_for_main_thread_ = NULL;
|
| + wrapped_gl_context_for_main_thread_ = NULL;
|
| }
|
| return offscreen_context_for_main_thread_;
|
| }
|
| @@ -157,7 +166,7 @@ class SynchronousCompositorFactoryImpl : public SynchronousCompositorFactory {
|
| // any thread and is lightweight.
|
| virtual scoped_refptr<cc::ContextProvider>
|
| GetOffscreenContextProviderForCompositorThread() OVERRIDE {
|
| - base::AutoLock lock(offscreen_context_for_compositor_thread_creation_lock_);
|
| + base::AutoLock lock(offscreen_context_for_compositor_thread_lock_);
|
| if (!offscreen_context_for_compositor_thread_.get() ||
|
| offscreen_context_for_compositor_thread_->DestroyedOnMainThread()) {
|
| offscreen_context_for_compositor_thread_ =
|
| @@ -168,27 +177,75 @@ class SynchronousCompositorFactoryImpl : public SynchronousCompositorFactory {
|
|
|
| virtual scoped_ptr<StreamTextureFactory> CreateStreamTextureFactory(
|
| int view_id) OVERRIDE {
|
| - scoped_refptr<VideoContextProvider> context_provider =
|
| - new VideoContextProvider(offscreen_context_for_main_thread_,
|
| - wrapped_gl_context_for_main_thread_);
|
| + scoped_refptr<VideoContextProvider> context_provider;
|
| + if (CanCreateMainThreadContext()) {
|
| + context_provider =
|
| + new VideoContextProvider(offscreen_context_for_main_thread_,
|
| + wrapped_gl_context_for_main_thread_);
|
| + }
|
| return make_scoped_ptr(new StreamTextureFactorySynchronousImpl(
|
| context_provider.get(), view_id))
|
| .PassAs<StreamTextureFactory>();
|
| }
|
|
|
| + void CompositorInitializedHardwareDraw(SynchronousCompositorImpl* compositor);
|
| + void CompositorReleasedHardwareDraw(SynchronousCompositorImpl* compositor);
|
| +
|
| private:
|
| + void ReleaseGlobalHardwareResources();
|
| + bool CanCreateMainThreadContext();
|
| +
|
| SynchronousInputEventFilter synchronous_input_event_filter_;
|
|
|
| - // Only guards construction of |offscreen_context_for_compositor_thread_|,
|
| - // not usage.
|
| - base::Lock offscreen_context_for_compositor_thread_creation_lock_;
|
| + // Only guards construction and destruction of
|
| + // |offscreen_context_for_compositor_thread_|, not usage.
|
| + base::Lock offscreen_context_for_compositor_thread_lock_;
|
| scoped_refptr<cc::ContextProvider> offscreen_context_for_main_thread_;
|
| // This is a pointer to the context owned by
|
| // |offscreen_context_for_main_thread_|.
|
| gpu::GLInProcessContext* wrapped_gl_context_for_main_thread_;
|
| scoped_refptr<cc::ContextProvider> offscreen_context_for_compositor_thread_;
|
| +
|
| + // |num_hardware_compositor_lock_| is updated on UI thread only but can be
|
| + // read on renderer main thread.
|
| + base::Lock num_hardware_compositor_lock_;
|
| + unsigned int num_hardware_compositors_;
|
| };
|
|
|
| +void SynchronousCompositorFactoryImpl::CompositorInitializedHardwareDraw(
|
| + SynchronousCompositorImpl* compositor) {
|
| + base::AutoLock lock(num_hardware_compositor_lock_);
|
| + num_hardware_compositors_++;
|
| +}
|
| +
|
| +void SynchronousCompositorFactoryImpl::CompositorReleasedHardwareDraw(
|
| + SynchronousCompositorImpl* compositor) {
|
| + bool should_release_resources = false;
|
| + {
|
| + base::AutoLock lock(num_hardware_compositor_lock_);
|
| + DCHECK_GT(num_hardware_compositors_, 0u);
|
| + num_hardware_compositors_--;
|
| + should_release_resources = num_hardware_compositors_ == 0u;
|
| + }
|
| + if (should_release_resources)
|
| + ReleaseGlobalHardwareResources();
|
| +}
|
| +
|
| +void SynchronousCompositorFactoryImpl::ReleaseGlobalHardwareResources() {
|
| + {
|
| + base::AutoLock lock(offscreen_context_for_compositor_thread_lock_);
|
| + offscreen_context_for_compositor_thread_ = NULL;
|
| + }
|
| +
|
| + // TODO(boliu): Properly clean up command buffer server of main thread
|
| + // context here.
|
| +}
|
| +
|
| +bool SynchronousCompositorFactoryImpl::CanCreateMainThreadContext() {
|
| + base::AutoLock lock(num_hardware_compositor_lock_);
|
| + return num_hardware_compositors_ > 0;
|
| +}
|
| +
|
| base::LazyInstance<SynchronousCompositorFactoryImpl>::Leaky g_factory =
|
| LAZY_INSTANCE_INITIALIZER;
|
|
|
| @@ -239,15 +296,19 @@ bool SynchronousCompositorImpl::InitializeHwDraw(
|
| scoped_refptr<gfx::GLSurface> surface) {
|
| DCHECK(CalledOnValidThread());
|
| DCHECK(output_surface_);
|
| - return output_surface_->InitializeHwDraw(
|
| + bool success = output_surface_->InitializeHwDraw(
|
| surface,
|
| g_factory.Get().GetOffscreenContextProviderForCompositorThread());
|
| + if (success)
|
| + g_factory.Get().CompositorInitializedHardwareDraw(this);
|
| + return success;
|
| }
|
|
|
| void SynchronousCompositorImpl::ReleaseHwDraw() {
|
| DCHECK(CalledOnValidThread());
|
| DCHECK(output_surface_);
|
| - return output_surface_->ReleaseHwDraw();
|
| + output_surface_->ReleaseHwDraw();
|
| + g_factory.Get().CompositorReleasedHardwareDraw(this);
|
| }
|
|
|
| bool SynchronousCompositorImpl::DemandDrawHw(
|
|
|