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 d2246a504dcb3ab7fff34dccd44124115437d192..6833947d5cafc2a9fcb8b933a8e1925cc84de9ed 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_compositor_(0) { |
SynchronousCompositorFactory::SetInstance(this); |
} |
@@ -137,16 +138,20 @@ class SynchronousCompositorFactoryImpl : public SynchronousCompositorFactory { |
virtual scoped_refptr<cc::ContextProvider> |
GetOffscreenContextProviderForMainThread() OVERRIDE { |
- if (!offscreen_context_for_main_thread_.get() || |
- offscreen_context_for_main_thread_->DestroyedOnMainThread()) { |
+ bool can_create_context = CanCreateMainThreadContext(); |
+ if (can_create_context && |
+ (!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; |
- } |
+ } |
+ |
+ if (!can_create_context || |
+ (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; |
} |
return offscreen_context_for_main_thread_; |
} |
@@ -159,7 +164,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_); |
no sievers
2013/09/04 22:27:09
Does this also need to check if we actually have a
boliu
2013/09/04 23:05:57
Aha, yes, I did give this some thought. cc should
|
if (!offscreen_context_for_compositor_thread_.get() || |
offscreen_context_for_compositor_thread_->DestroyedOnMainThread()) { |
offscreen_context_for_compositor_thread_ = |
@@ -178,19 +183,62 @@ class SynchronousCompositorFactoryImpl : public SynchronousCompositorFactory { |
.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_; |
+ |
+ base::Lock num_hardware_compositor_lock_; |
+ unsigned int num_hardware_compositor_; |
no sievers
2013/09/04 22:27:09
nit: num_hardware_compositors
boliu
2013/09/04 23:05:57
Done.
|
}; |
+void SynchronousCompositorFactoryImpl::CompositorInitializedHardwareDraw( |
+ SynchronousCompositorImpl* compositor) { |
+ base::AutoLock lock(num_hardware_compositor_lock_); |
+ num_hardware_compositor_++; |
+} |
+ |
+void SynchronousCompositorFactoryImpl::CompositorReleasedHardwareDraw( |
+ SynchronousCompositorImpl* compositor) { |
+ bool should_release_resources = false; |
+ { |
+ base::AutoLock lock(num_hardware_compositor_lock_); |
+ DCHECK_GT(num_hardware_compositor_, 0u); |
+ num_hardware_compositor_--; |
+ should_release_resources = num_hardware_compositor_ == 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_compositor_ > 0; |
+} |
+ |
base::LazyInstance<SynchronousCompositorFactoryImpl>::Leaky g_factory = |
LAZY_INSTANCE_INITIALIZER; |
@@ -241,15 +289,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( |