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_compositors_(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 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
128 if (!context.get()) | 129 if (!context.get()) |
129 return scoped_ptr<WebGraphicsContext3DInProcessCommandBufferImpl>(); | 130 return scoped_ptr<WebGraphicsContext3DInProcessCommandBufferImpl>(); |
130 | 131 |
131 return scoped_ptr<WebGraphicsContext3DInProcessCommandBufferImpl>( | 132 return scoped_ptr<WebGraphicsContext3DInProcessCommandBufferImpl>( |
132 WebGraphicsContext3DInProcessCommandBufferImpl::WrapContext( | 133 WebGraphicsContext3DInProcessCommandBufferImpl::WrapContext( |
133 context.Pass(), attributes)); | 134 context.Pass(), attributes)); |
134 } | 135 } |
135 | 136 |
136 virtual scoped_refptr<cc::ContextProvider> | 137 virtual scoped_refptr<cc::ContextProvider> |
137 GetOffscreenContextProviderForMainThread() OVERRIDE { | 138 GetOffscreenContextProviderForMainThread() OVERRIDE { |
138 if (!offscreen_context_for_main_thread_.get() || | 139 // This check only guarantees the main thread context is created after |
139 offscreen_context_for_main_thread_->DestroyedOnMainThread()) { | 140 // a compositor did successfully initialize hardware draw in the past. |
| 141 // In particular this does not guarantee that the main thread context |
| 142 // will fail creation when all compositors release hardware draw. |
| 143 bool failed = !CanCreateMainThreadContext(); |
| 144 if (!failed && |
| 145 (!offscreen_context_for_main_thread_.get() || |
| 146 offscreen_context_for_main_thread_->DestroyedOnMainThread())) { |
140 offscreen_context_for_main_thread_ = | 147 offscreen_context_for_main_thread_ = |
141 webkit::gpu::ContextProviderInProcess::Create( | 148 webkit::gpu::ContextProviderInProcess::Create( |
142 CreateOffscreenContext()); | 149 CreateOffscreenContext()); |
143 if (offscreen_context_for_main_thread_.get() && | 150 failed = !offscreen_context_for_main_thread_.get() || |
144 !offscreen_context_for_main_thread_->BindToCurrentThread()) { | 151 !offscreen_context_for_main_thread_->BindToCurrentThread(); |
145 offscreen_context_for_main_thread_ = NULL; | 152 } |
146 wrapped_gl_context_for_main_thread_ = NULL; | 153 |
147 } | 154 if (failed) { |
| 155 offscreen_context_for_main_thread_ = NULL; |
| 156 wrapped_gl_context_for_main_thread_ = NULL; |
148 } | 157 } |
149 return offscreen_context_for_main_thread_; | 158 return offscreen_context_for_main_thread_; |
150 } | 159 } |
151 | 160 |
152 // This is called on both renderer main thread (offscreen context creation | 161 // This is called on both renderer main thread (offscreen context creation |
153 // path shared between cross-process and in-process platforms) and renderer | 162 // path shared between cross-process and in-process platforms) and renderer |
154 // compositor impl thread (InitializeHwDraw) in order to support Android | 163 // compositor impl thread (InitializeHwDraw) in order to support Android |
155 // WebView synchronously enable and disable hardware mode multiple times in | 164 // WebView synchronously enable and disable hardware mode multiple times in |
156 // the same task. This is ok because in-process WGC3D creation may happen on | 165 // the same task. This is ok because in-process WGC3D creation may happen on |
157 // any thread and is lightweight. | 166 // any thread and is lightweight. |
158 virtual scoped_refptr<cc::ContextProvider> | 167 virtual scoped_refptr<cc::ContextProvider> |
159 GetOffscreenContextProviderForCompositorThread() OVERRIDE { | 168 GetOffscreenContextProviderForCompositorThread() OVERRIDE { |
160 base::AutoLock lock(offscreen_context_for_compositor_thread_creation_lock_); | 169 base::AutoLock lock(offscreen_context_for_compositor_thread_lock_); |
161 if (!offscreen_context_for_compositor_thread_.get() || | 170 if (!offscreen_context_for_compositor_thread_.get() || |
162 offscreen_context_for_compositor_thread_->DestroyedOnMainThread()) { | 171 offscreen_context_for_compositor_thread_->DestroyedOnMainThread()) { |
163 offscreen_context_for_compositor_thread_ = | 172 offscreen_context_for_compositor_thread_ = |
164 webkit::gpu::ContextProviderInProcess::CreateOffscreen(); | 173 webkit::gpu::ContextProviderInProcess::CreateOffscreen(); |
165 } | 174 } |
166 return offscreen_context_for_compositor_thread_; | 175 return offscreen_context_for_compositor_thread_; |
167 } | 176 } |
168 | 177 |
169 virtual scoped_ptr<StreamTextureFactory> CreateStreamTextureFactory( | 178 virtual scoped_ptr<StreamTextureFactory> CreateStreamTextureFactory( |
170 int view_id) OVERRIDE { | 179 int view_id) OVERRIDE { |
171 scoped_refptr<VideoContextProvider> context_provider = | 180 scoped_refptr<VideoContextProvider> context_provider; |
172 new VideoContextProvider(offscreen_context_for_main_thread_, | 181 if (CanCreateMainThreadContext()) { |
173 wrapped_gl_context_for_main_thread_); | 182 context_provider = |
| 183 new VideoContextProvider(offscreen_context_for_main_thread_, |
| 184 wrapped_gl_context_for_main_thread_); |
| 185 } |
174 return make_scoped_ptr(new StreamTextureFactorySynchronousImpl( | 186 return make_scoped_ptr(new StreamTextureFactorySynchronousImpl( |
175 context_provider.get(), view_id)) | 187 context_provider.get(), view_id)) |
176 .PassAs<StreamTextureFactory>(); | 188 .PassAs<StreamTextureFactory>(); |
177 } | 189 } |
178 | 190 |
| 191 void CompositorInitializedHardwareDraw(SynchronousCompositorImpl* compositor); |
| 192 void CompositorReleasedHardwareDraw(SynchronousCompositorImpl* compositor); |
| 193 |
179 private: | 194 private: |
| 195 void ReleaseGlobalHardwareResources(); |
| 196 bool CanCreateMainThreadContext(); |
| 197 |
180 SynchronousInputEventFilter synchronous_input_event_filter_; | 198 SynchronousInputEventFilter synchronous_input_event_filter_; |
181 | 199 |
182 // Only guards construction of |offscreen_context_for_compositor_thread_|, | 200 // Only guards construction and destruction of |
183 // not usage. | 201 // |offscreen_context_for_compositor_thread_|, not usage. |
184 base::Lock offscreen_context_for_compositor_thread_creation_lock_; | 202 base::Lock offscreen_context_for_compositor_thread_lock_; |
185 scoped_refptr<cc::ContextProvider> offscreen_context_for_main_thread_; | 203 scoped_refptr<cc::ContextProvider> offscreen_context_for_main_thread_; |
186 // This is a pointer to the context owned by | 204 // This is a pointer to the context owned by |
187 // |offscreen_context_for_main_thread_|. | 205 // |offscreen_context_for_main_thread_|. |
188 gpu::GLInProcessContext* wrapped_gl_context_for_main_thread_; | 206 gpu::GLInProcessContext* wrapped_gl_context_for_main_thread_; |
189 scoped_refptr<cc::ContextProvider> offscreen_context_for_compositor_thread_; | 207 scoped_refptr<cc::ContextProvider> offscreen_context_for_compositor_thread_; |
| 208 |
| 209 // |num_hardware_compositor_lock_| is updated on UI thread only but can be |
| 210 // read on renderer main thread. |
| 211 base::Lock num_hardware_compositor_lock_; |
| 212 unsigned int num_hardware_compositors_; |
190 }; | 213 }; |
191 | 214 |
| 215 void SynchronousCompositorFactoryImpl::CompositorInitializedHardwareDraw( |
| 216 SynchronousCompositorImpl* compositor) { |
| 217 base::AutoLock lock(num_hardware_compositor_lock_); |
| 218 num_hardware_compositors_++; |
| 219 } |
| 220 |
| 221 void SynchronousCompositorFactoryImpl::CompositorReleasedHardwareDraw( |
| 222 SynchronousCompositorImpl* compositor) { |
| 223 bool should_release_resources = false; |
| 224 { |
| 225 base::AutoLock lock(num_hardware_compositor_lock_); |
| 226 DCHECK_GT(num_hardware_compositors_, 0u); |
| 227 num_hardware_compositors_--; |
| 228 should_release_resources = num_hardware_compositors_ == 0u; |
| 229 } |
| 230 if (should_release_resources) |
| 231 ReleaseGlobalHardwareResources(); |
| 232 } |
| 233 |
| 234 void SynchronousCompositorFactoryImpl::ReleaseGlobalHardwareResources() { |
| 235 { |
| 236 base::AutoLock lock(offscreen_context_for_compositor_thread_lock_); |
| 237 offscreen_context_for_compositor_thread_ = NULL; |
| 238 } |
| 239 |
| 240 // TODO(boliu): Properly clean up command buffer server of main thread |
| 241 // context here. |
| 242 } |
| 243 |
| 244 bool SynchronousCompositorFactoryImpl::CanCreateMainThreadContext() { |
| 245 base::AutoLock lock(num_hardware_compositor_lock_); |
| 246 return num_hardware_compositors_ > 0; |
| 247 } |
| 248 |
192 base::LazyInstance<SynchronousCompositorFactoryImpl>::Leaky g_factory = | 249 base::LazyInstance<SynchronousCompositorFactoryImpl>::Leaky g_factory = |
193 LAZY_INSTANCE_INITIALIZER; | 250 LAZY_INSTANCE_INITIALIZER; |
194 | 251 |
195 } // namespace | 252 } // namespace |
196 | 253 |
197 DEFINE_WEB_CONTENTS_USER_DATA_KEY(SynchronousCompositorImpl); | 254 DEFINE_WEB_CONTENTS_USER_DATA_KEY(SynchronousCompositorImpl); |
198 | 255 |
199 // static | 256 // static |
200 SynchronousCompositorImpl* SynchronousCompositorImpl::FromID(int process_id, | 257 SynchronousCompositorImpl* SynchronousCompositorImpl::FromID(int process_id, |
201 int routing_id) { | 258 int routing_id) { |
(...skipping 30 matching lines...) Expand all Loading... |
232 void SynchronousCompositorImpl::SetClient( | 289 void SynchronousCompositorImpl::SetClient( |
233 SynchronousCompositorClient* compositor_client) { | 290 SynchronousCompositorClient* compositor_client) { |
234 DCHECK(CalledOnValidThread()); | 291 DCHECK(CalledOnValidThread()); |
235 compositor_client_ = compositor_client; | 292 compositor_client_ = compositor_client; |
236 } | 293 } |
237 | 294 |
238 bool SynchronousCompositorImpl::InitializeHwDraw( | 295 bool SynchronousCompositorImpl::InitializeHwDraw( |
239 scoped_refptr<gfx::GLSurface> surface) { | 296 scoped_refptr<gfx::GLSurface> surface) { |
240 DCHECK(CalledOnValidThread()); | 297 DCHECK(CalledOnValidThread()); |
241 DCHECK(output_surface_); | 298 DCHECK(output_surface_); |
242 return output_surface_->InitializeHwDraw( | 299 bool success = output_surface_->InitializeHwDraw( |
243 surface, | 300 surface, |
244 g_factory.Get().GetOffscreenContextProviderForCompositorThread()); | 301 g_factory.Get().GetOffscreenContextProviderForCompositorThread()); |
| 302 if (success) |
| 303 g_factory.Get().CompositorInitializedHardwareDraw(this); |
| 304 return success; |
245 } | 305 } |
246 | 306 |
247 void SynchronousCompositorImpl::ReleaseHwDraw() { | 307 void SynchronousCompositorImpl::ReleaseHwDraw() { |
248 DCHECK(CalledOnValidThread()); | 308 DCHECK(CalledOnValidThread()); |
249 DCHECK(output_surface_); | 309 DCHECK(output_surface_); |
250 return output_surface_->ReleaseHwDraw(); | 310 output_surface_->ReleaseHwDraw(); |
| 311 g_factory.Get().CompositorReleasedHardwareDraw(this); |
251 } | 312 } |
252 | 313 |
253 bool SynchronousCompositorImpl::DemandDrawHw( | 314 bool SynchronousCompositorImpl::DemandDrawHw( |
254 gfx::Size surface_size, | 315 gfx::Size surface_size, |
255 const gfx::Transform& transform, | 316 const gfx::Transform& transform, |
256 gfx::Rect viewport, | 317 gfx::Rect viewport, |
257 gfx::Rect clip, | 318 gfx::Rect clip, |
258 bool stencil_enabled) { | 319 bool stencil_enabled) { |
259 DCHECK(CalledOnValidThread()); | 320 DCHECK(CalledOnValidThread()); |
260 DCHECK(output_surface_); | 321 DCHECK(output_surface_); |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
373 g_factory.Get(); // Ensure it's initialized. | 434 g_factory.Get(); // Ensure it's initialized. |
374 SynchronousCompositorImpl::CreateForWebContents(contents); | 435 SynchronousCompositorImpl::CreateForWebContents(contents); |
375 } | 436 } |
376 if (SynchronousCompositorImpl* instance = | 437 if (SynchronousCompositorImpl* instance = |
377 SynchronousCompositorImpl::FromWebContents(contents)) { | 438 SynchronousCompositorImpl::FromWebContents(contents)) { |
378 instance->SetClient(client); | 439 instance->SetClient(client); |
379 } | 440 } |
380 } | 441 } |
381 | 442 |
382 } // namespace content | 443 } // namespace content |
OLD | NEW |