Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "content/browser/android/in_process/synchronous_compositor_impl.h" | 5 #include "content/browser/android/in_process/synchronous_compositor_impl.h" |
| 6 | 6 |
| 7 #include "base/lazy_instance.h" | 7 #include "base/lazy_instance.h" |
| 8 #include "base/message_loop/message_loop.h" | 8 #include "base/message_loop/message_loop.h" |
| 9 #include "base/synchronization/lock.h" | 9 #include "base/synchronization/lock.h" |
| 10 #include "cc/input/input_handler.h" | 10 #include "cc/input/input_handler.h" |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 69 | 69 |
| 70 scoped_refptr<cc::ContextProvider> context_provider_; | 70 scoped_refptr<cc::ContextProvider> context_provider_; |
| 71 gpu::GLInProcessContext* gl_in_process_context_; | 71 gpu::GLInProcessContext* gl_in_process_context_; |
| 72 | 72 |
| 73 DISALLOW_COPY_AND_ASSIGN(VideoContextProvider); | 73 DISALLOW_COPY_AND_ASSIGN(VideoContextProvider); |
| 74 }; | 74 }; |
| 75 | 75 |
| 76 class SynchronousCompositorFactoryImpl : public SynchronousCompositorFactory { | 76 class SynchronousCompositorFactoryImpl : public SynchronousCompositorFactory { |
| 77 public: | 77 public: |
| 78 SynchronousCompositorFactoryImpl() | 78 SynchronousCompositorFactoryImpl() |
| 79 : wrapped_gl_context_for_main_thread_(NULL) { | 79 : wrapped_gl_context_for_main_thread_(NULL), |
| 80 num_hardware_compositor_(0) { | |
| 80 SynchronousCompositorFactory::SetInstance(this); | 81 SynchronousCompositorFactory::SetInstance(this); |
| 81 } | 82 } |
| 82 | 83 |
| 83 // SynchronousCompositorFactory | 84 // SynchronousCompositorFactory |
| 84 virtual scoped_refptr<base::MessageLoopProxy> | 85 virtual scoped_refptr<base::MessageLoopProxy> |
| 85 GetCompositorMessageLoop() OVERRIDE { | 86 GetCompositorMessageLoop() OVERRIDE { |
| 86 return BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI); | 87 return BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI); |
| 87 } | 88 } |
| 88 | 89 |
| 89 virtual scoped_ptr<cc::OutputSurface> CreateOutputSurface( | 90 virtual scoped_ptr<cc::OutputSurface> CreateOutputSurface( |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 130 if (!context.get()) | 131 if (!context.get()) |
| 131 return scoped_ptr<WebGraphicsContext3DInProcessCommandBufferImpl>(); | 132 return scoped_ptr<WebGraphicsContext3DInProcessCommandBufferImpl>(); |
| 132 | 133 |
| 133 return scoped_ptr<WebGraphicsContext3DInProcessCommandBufferImpl>( | 134 return scoped_ptr<WebGraphicsContext3DInProcessCommandBufferImpl>( |
| 134 WebGraphicsContext3DInProcessCommandBufferImpl::WrapContext( | 135 WebGraphicsContext3DInProcessCommandBufferImpl::WrapContext( |
| 135 context.Pass(), attributes)); | 136 context.Pass(), attributes)); |
| 136 } | 137 } |
| 137 | 138 |
| 138 virtual scoped_refptr<cc::ContextProvider> | 139 virtual scoped_refptr<cc::ContextProvider> |
| 139 GetOffscreenContextProviderForMainThread() OVERRIDE { | 140 GetOffscreenContextProviderForMainThread() OVERRIDE { |
| 140 if (!offscreen_context_for_main_thread_.get() || | 141 bool can_create_context = CanCreateMainThreadContext(); |
| 141 offscreen_context_for_main_thread_->DestroyedOnMainThread()) { | 142 if (can_create_context && |
| 143 (!offscreen_context_for_main_thread_.get() || | |
| 144 offscreen_context_for_main_thread_->DestroyedOnMainThread())) { | |
| 142 offscreen_context_for_main_thread_ = | 145 offscreen_context_for_main_thread_ = |
| 143 webkit::gpu::ContextProviderInProcess::Create( | 146 webkit::gpu::ContextProviderInProcess::Create( |
| 144 CreateOffscreenContext()); | 147 CreateOffscreenContext()); |
| 145 if (offscreen_context_for_main_thread_.get() && | 148 } |
| 146 !offscreen_context_for_main_thread_->BindToCurrentThread()) { | 149 |
| 147 offscreen_context_for_main_thread_ = NULL; | 150 if (!can_create_context || |
| 148 wrapped_gl_context_for_main_thread_ = NULL; | 151 (offscreen_context_for_main_thread_.get() && |
| 149 } | 152 !offscreen_context_for_main_thread_->BindToCurrentThread())) { |
| 153 offscreen_context_for_main_thread_ = NULL; | |
| 154 wrapped_gl_context_for_main_thread_ = NULL; | |
| 150 } | 155 } |
| 151 return offscreen_context_for_main_thread_; | 156 return offscreen_context_for_main_thread_; |
| 152 } | 157 } |
| 153 | 158 |
| 154 // This is called on both renderer main thread (offscreen context creation | 159 // This is called on both renderer main thread (offscreen context creation |
| 155 // path shared between cross-process and in-process platforms) and renderer | 160 // path shared between cross-process and in-process platforms) and renderer |
| 156 // compositor impl thread (InitializeHwDraw) in order to support Android | 161 // compositor impl thread (InitializeHwDraw) in order to support Android |
| 157 // WebView synchronously enable and disable hardware mode multiple times in | 162 // WebView synchronously enable and disable hardware mode multiple times in |
| 158 // the same task. This is ok because in-process WGC3D creation may happen on | 163 // the same task. This is ok because in-process WGC3D creation may happen on |
| 159 // any thread and is lightweight. | 164 // any thread and is lightweight. |
| 160 virtual scoped_refptr<cc::ContextProvider> | 165 virtual scoped_refptr<cc::ContextProvider> |
| 161 GetOffscreenContextProviderForCompositorThread() OVERRIDE { | 166 GetOffscreenContextProviderForCompositorThread() OVERRIDE { |
| 162 base::AutoLock lock(offscreen_context_for_compositor_thread_creation_lock_); | 167 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
| |
| 163 if (!offscreen_context_for_compositor_thread_.get() || | 168 if (!offscreen_context_for_compositor_thread_.get() || |
| 164 offscreen_context_for_compositor_thread_->DestroyedOnMainThread()) { | 169 offscreen_context_for_compositor_thread_->DestroyedOnMainThread()) { |
| 165 offscreen_context_for_compositor_thread_ = | 170 offscreen_context_for_compositor_thread_ = |
| 166 webkit::gpu::ContextProviderInProcess::CreateOffscreen(); | 171 webkit::gpu::ContextProviderInProcess::CreateOffscreen(); |
| 167 } | 172 } |
| 168 return offscreen_context_for_compositor_thread_; | 173 return offscreen_context_for_compositor_thread_; |
| 169 } | 174 } |
| 170 | 175 |
| 171 virtual scoped_ptr<StreamTextureFactory> CreateStreamTextureFactory( | 176 virtual scoped_ptr<StreamTextureFactory> CreateStreamTextureFactory( |
| 172 int view_id) OVERRIDE { | 177 int view_id) OVERRIDE { |
| 173 scoped_refptr<VideoContextProvider> context_provider = | 178 scoped_refptr<VideoContextProvider> context_provider = |
| 174 new VideoContextProvider(offscreen_context_for_main_thread_, | 179 new VideoContextProvider(offscreen_context_for_main_thread_, |
| 175 wrapped_gl_context_for_main_thread_); | 180 wrapped_gl_context_for_main_thread_); |
| 176 return make_scoped_ptr(new StreamTextureFactorySynchronousImpl( | 181 return make_scoped_ptr(new StreamTextureFactorySynchronousImpl( |
| 177 context_provider.get(), view_id)) | 182 context_provider.get(), view_id)) |
| 178 .PassAs<StreamTextureFactory>(); | 183 .PassAs<StreamTextureFactory>(); |
| 179 } | 184 } |
| 180 | 185 |
| 186 void CompositorInitializedHardwareDraw(SynchronousCompositorImpl* compositor); | |
| 187 void CompositorReleasedHardwareDraw(SynchronousCompositorImpl* compositor); | |
| 188 | |
| 181 private: | 189 private: |
| 190 void ReleaseGlobalHardwareResources(); | |
| 191 bool CanCreateMainThreadContext(); | |
| 192 | |
| 182 SynchronousInputEventFilter synchronous_input_event_filter_; | 193 SynchronousInputEventFilter synchronous_input_event_filter_; |
| 183 | 194 |
| 184 // Only guards construction of |offscreen_context_for_compositor_thread_|, | 195 // Only guards construction and destruction of |
| 185 // not usage. | 196 // |offscreen_context_for_compositor_thread_|, not usage. |
| 186 base::Lock offscreen_context_for_compositor_thread_creation_lock_; | 197 base::Lock offscreen_context_for_compositor_thread_lock_; |
| 187 scoped_refptr<cc::ContextProvider> offscreen_context_for_main_thread_; | 198 scoped_refptr<cc::ContextProvider> offscreen_context_for_main_thread_; |
| 188 // This is a pointer to the context owned by | 199 // This is a pointer to the context owned by |
| 189 // |offscreen_context_for_main_thread_|. | 200 // |offscreen_context_for_main_thread_|. |
| 190 gpu::GLInProcessContext* wrapped_gl_context_for_main_thread_; | 201 gpu::GLInProcessContext* wrapped_gl_context_for_main_thread_; |
| 191 scoped_refptr<cc::ContextProvider> offscreen_context_for_compositor_thread_; | 202 scoped_refptr<cc::ContextProvider> offscreen_context_for_compositor_thread_; |
| 203 | |
| 204 base::Lock num_hardware_compositor_lock_; | |
| 205 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.
| |
| 192 }; | 206 }; |
| 193 | 207 |
| 208 void SynchronousCompositorFactoryImpl::CompositorInitializedHardwareDraw( | |
| 209 SynchronousCompositorImpl* compositor) { | |
| 210 base::AutoLock lock(num_hardware_compositor_lock_); | |
| 211 num_hardware_compositor_++; | |
| 212 } | |
| 213 | |
| 214 void SynchronousCompositorFactoryImpl::CompositorReleasedHardwareDraw( | |
| 215 SynchronousCompositorImpl* compositor) { | |
| 216 bool should_release_resources = false; | |
| 217 { | |
| 218 base::AutoLock lock(num_hardware_compositor_lock_); | |
| 219 DCHECK_GT(num_hardware_compositor_, 0u); | |
| 220 num_hardware_compositor_--; | |
| 221 should_release_resources = num_hardware_compositor_ == 0u; | |
| 222 } | |
| 223 if (should_release_resources) | |
| 224 ReleaseGlobalHardwareResources(); | |
| 225 } | |
| 226 | |
| 227 void SynchronousCompositorFactoryImpl::ReleaseGlobalHardwareResources() { | |
| 228 { | |
| 229 base::AutoLock lock(offscreen_context_for_compositor_thread_lock_); | |
| 230 offscreen_context_for_compositor_thread_ = NULL; | |
| 231 } | |
| 232 | |
| 233 // TODO(boliu): Properly clean up command buffer server of main thread | |
| 234 // context here. | |
| 235 } | |
| 236 | |
| 237 bool SynchronousCompositorFactoryImpl::CanCreateMainThreadContext() { | |
| 238 base::AutoLock lock(num_hardware_compositor_lock_); | |
| 239 return num_hardware_compositor_ > 0; | |
| 240 } | |
| 241 | |
| 194 base::LazyInstance<SynchronousCompositorFactoryImpl>::Leaky g_factory = | 242 base::LazyInstance<SynchronousCompositorFactoryImpl>::Leaky g_factory = |
| 195 LAZY_INSTANCE_INITIALIZER; | 243 LAZY_INSTANCE_INITIALIZER; |
| 196 | 244 |
| 197 } // namespace | 245 } // namespace |
| 198 | 246 |
| 199 DEFINE_WEB_CONTENTS_USER_DATA_KEY(SynchronousCompositorImpl); | 247 DEFINE_WEB_CONTENTS_USER_DATA_KEY(SynchronousCompositorImpl); |
| 200 | 248 |
| 201 // static | 249 // static |
| 202 SynchronousCompositorImpl* SynchronousCompositorImpl::FromID(int process_id, | 250 SynchronousCompositorImpl* SynchronousCompositorImpl::FromID(int process_id, |
| 203 int routing_id) { | 251 int routing_id) { |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 234 void SynchronousCompositorImpl::SetClient( | 282 void SynchronousCompositorImpl::SetClient( |
| 235 SynchronousCompositorClient* compositor_client) { | 283 SynchronousCompositorClient* compositor_client) { |
| 236 DCHECK(CalledOnValidThread()); | 284 DCHECK(CalledOnValidThread()); |
| 237 compositor_client_ = compositor_client; | 285 compositor_client_ = compositor_client; |
| 238 } | 286 } |
| 239 | 287 |
| 240 bool SynchronousCompositorImpl::InitializeHwDraw( | 288 bool SynchronousCompositorImpl::InitializeHwDraw( |
| 241 scoped_refptr<gfx::GLSurface> surface) { | 289 scoped_refptr<gfx::GLSurface> surface) { |
| 242 DCHECK(CalledOnValidThread()); | 290 DCHECK(CalledOnValidThread()); |
| 243 DCHECK(output_surface_); | 291 DCHECK(output_surface_); |
| 244 return output_surface_->InitializeHwDraw( | 292 bool success = output_surface_->InitializeHwDraw( |
| 245 surface, | 293 surface, |
| 246 g_factory.Get().GetOffscreenContextProviderForCompositorThread()); | 294 g_factory.Get().GetOffscreenContextProviderForCompositorThread()); |
| 295 if (success) | |
| 296 g_factory.Get().CompositorInitializedHardwareDraw(this); | |
| 297 return success; | |
| 247 } | 298 } |
| 248 | 299 |
| 249 void SynchronousCompositorImpl::ReleaseHwDraw() { | 300 void SynchronousCompositorImpl::ReleaseHwDraw() { |
| 250 DCHECK(CalledOnValidThread()); | 301 DCHECK(CalledOnValidThread()); |
| 251 DCHECK(output_surface_); | 302 DCHECK(output_surface_); |
| 252 return output_surface_->ReleaseHwDraw(); | 303 output_surface_->ReleaseHwDraw(); |
| 304 g_factory.Get().CompositorReleasedHardwareDraw(this); | |
| 253 } | 305 } |
| 254 | 306 |
| 255 bool SynchronousCompositorImpl::DemandDrawHw( | 307 bool SynchronousCompositorImpl::DemandDrawHw( |
| 256 gfx::Size surface_size, | 308 gfx::Size surface_size, |
| 257 const gfx::Transform& transform, | 309 const gfx::Transform& transform, |
| 258 gfx::Rect viewport, | 310 gfx::Rect viewport, |
| 259 gfx::Rect clip, | 311 gfx::Rect clip, |
| 260 bool stencil_enabled) { | 312 bool stencil_enabled) { |
| 261 DCHECK(CalledOnValidThread()); | 313 DCHECK(CalledOnValidThread()); |
| 262 DCHECK(output_surface_); | 314 DCHECK(output_surface_); |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 383 g_factory.Get(); // Ensure it's initialized. | 435 g_factory.Get(); // Ensure it's initialized. |
| 384 SynchronousCompositorImpl::CreateForWebContents(contents); | 436 SynchronousCompositorImpl::CreateForWebContents(contents); |
| 385 } | 437 } |
| 386 if (SynchronousCompositorImpl* instance = | 438 if (SynchronousCompositorImpl* instance = |
| 387 SynchronousCompositorImpl::FromWebContents(contents)) { | 439 SynchronousCompositorImpl::FromWebContents(contents)) { |
| 388 instance->SetClient(client); | 440 instance->SetClient(client); |
| 389 } | 441 } |
| 390 } | 442 } |
| 391 | 443 |
| 392 } // namespace content | 444 } // namespace content |
| OLD | NEW |