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 "android_webview/browser/in_process_view_renderer.h" | 5 #include "android_webview/browser/in_process_view_renderer.h" |
6 | 6 |
7 #include <android/bitmap.h> | 7 #include <android/bitmap.h> |
8 | 8 |
9 #include "android_webview/browser/aw_gl_surface.h" | 9 #include "android_webview/browser/aw_gl_surface.h" |
10 #include "android_webview/browser/scoped_app_gl_state_restore.h" | 10 #include "android_webview/browser/scoped_app_gl_state_restore.h" |
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
166 DCHECK(!allow_gl); | 166 DCHECK(!allow_gl); |
167 allow_gl = true; | 167 allow_gl = true; |
168 } | 168 } |
169 | 169 |
170 ScopedAllowGL::~ScopedAllowGL() { | 170 ScopedAllowGL::~ScopedAllowGL() { |
171 allow_gl = false; | 171 allow_gl = false; |
172 } | 172 } |
173 | 173 |
174 bool ScopedAllowGL::allow_gl = false; | 174 bool ScopedAllowGL::allow_gl = false; |
175 | 175 |
176 base::LazyInstance<GLViewRendererManager>::Leaky g_view_renderer_manager; | 176 base::LazyInstance<GLViewRendererManager>::Leaky g_view_renderer_manager = |
| 177 LAZY_INSTANCE_INITIALIZER; |
177 | 178 |
178 void RequestProcessGLOnUIThread() { | 179 void RequestProcessGLOnUIThread() { |
179 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { | 180 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { |
180 BrowserThread::PostTask( | 181 BrowserThread::PostTask( |
181 BrowserThread::UI, FROM_HERE, base::Bind(&RequestProcessGLOnUIThread)); | 182 BrowserThread::UI, FROM_HERE, base::Bind(&RequestProcessGLOnUIThread)); |
182 return; | 183 return; |
183 } | 184 } |
184 | 185 |
185 InProcessViewRenderer* renderer = static_cast<InProcessViewRenderer*>( | 186 InProcessViewRenderer* renderer = static_cast<InProcessViewRenderer*>( |
186 g_view_renderer_manager.Get().GetMostRecentlyDrawn()); | 187 g_view_renderer_manager.Get().GetMostRecentlyDrawn()); |
187 if (!renderer || !renderer->RequestProcessGL()) { | 188 if (!renderer || !renderer->RequestProcessGL()) { |
188 LOG(ERROR) << "Failed to request GL process. Deadlock likely: " | 189 LOG(ERROR) << "Failed to request GL process. Deadlock likely: " |
189 << !!renderer; | 190 << !!renderer; |
190 } | 191 } |
191 } | 192 } |
192 | 193 |
193 } // namespace | 194 class DeferredGpuCommandService |
| 195 : public gpu::InProcessCommandBuffer::Service, |
| 196 public base::RefCountedThreadSafe<DeferredGpuCommandService> { |
| 197 public: |
| 198 DeferredGpuCommandService(); |
| 199 |
| 200 virtual void ScheduleTask(const base::Closure& task) OVERRIDE; |
| 201 virtual void ScheduleIdleWork(const base::Closure& task) OVERRIDE; |
| 202 virtual bool UseVirtualizedGLContexts() OVERRIDE; |
| 203 |
| 204 void RunTasks(); |
| 205 |
| 206 virtual void AddRef() const OVERRIDE { |
| 207 base::RefCountedThreadSafe<DeferredGpuCommandService>::AddRef(); |
| 208 } |
| 209 virtual void Release() const OVERRIDE { |
| 210 base::RefCountedThreadSafe<DeferredGpuCommandService>::Release(); |
| 211 } |
| 212 |
| 213 protected: |
| 214 virtual ~DeferredGpuCommandService(); |
| 215 friend class base::RefCountedThreadSafe<DeferredGpuCommandService>; |
| 216 |
| 217 private: |
| 218 base::Lock tasks_lock_; |
| 219 std::queue<base::Closure> tasks_; |
| 220 DISALLOW_COPY_AND_ASSIGN(DeferredGpuCommandService); |
| 221 }; |
| 222 |
| 223 DeferredGpuCommandService::DeferredGpuCommandService() {} |
| 224 |
| 225 DeferredGpuCommandService::~DeferredGpuCommandService() { |
| 226 base::AutoLock lock(tasks_lock_); |
| 227 DCHECK(tasks_.empty()); |
| 228 } |
194 | 229 |
195 // Called from different threads! | 230 // Called from different threads! |
196 static void ScheduleGpuWork() { | 231 void DeferredGpuCommandService::ScheduleTask(const base::Closure& task) { |
| 232 { |
| 233 base::AutoLock lock(tasks_lock_); |
| 234 tasks_.push(task); |
| 235 } |
197 if (ScopedAllowGL::IsAllowed()) { | 236 if (ScopedAllowGL::IsAllowed()) { |
198 gpu::InProcessCommandBuffer::ProcessGpuWorkOnCurrentThread(); | 237 RunTasks(); |
199 } else { | 238 } else { |
200 RequestProcessGLOnUIThread(); | 239 RequestProcessGLOnUIThread(); |
201 } | 240 } |
202 } | 241 } |
203 | 242 |
| 243 void DeferredGpuCommandService::ScheduleIdleWork( |
| 244 const base::Closure& callback) { |
| 245 // TODO(sievers): Should this do anything? |
| 246 } |
| 247 |
| 248 bool DeferredGpuCommandService::UseVirtualizedGLContexts() { return true; } |
| 249 |
| 250 void DeferredGpuCommandService::RunTasks() { |
| 251 bool has_more_tasks; |
| 252 { |
| 253 base::AutoLock lock(tasks_lock_); |
| 254 has_more_tasks = tasks_.size() > 0; |
| 255 } |
| 256 |
| 257 while (has_more_tasks) { |
| 258 base::Closure task; |
| 259 { |
| 260 base::AutoLock lock(tasks_lock_); |
| 261 task = tasks_.front(); |
| 262 tasks_.pop(); |
| 263 } |
| 264 task.Run(); |
| 265 { |
| 266 base::AutoLock lock(tasks_lock_); |
| 267 has_more_tasks = tasks_.size() > 0; |
| 268 } |
| 269 |
| 270 } |
| 271 } |
| 272 |
| 273 base::LazyInstance<scoped_refptr<DeferredGpuCommandService> > g_service = |
| 274 LAZY_INSTANCE_INITIALIZER; |
| 275 |
| 276 } // namespace |
| 277 |
204 // static | 278 // static |
205 void BrowserViewRenderer::SetAwDrawSWFunctionTable( | 279 void BrowserViewRenderer::SetAwDrawSWFunctionTable( |
206 AwDrawSWFunctionTable* table) { | 280 AwDrawSWFunctionTable* table) { |
207 g_sw_draw_functions = table; | 281 g_sw_draw_functions = table; |
208 gpu::InProcessCommandBuffer::SetScheduleCallback( | |
209 base::Bind(&ScheduleGpuWork)); | |
210 } | 282 } |
211 | 283 |
212 // static | 284 // static |
213 AwDrawSWFunctionTable* BrowserViewRenderer::GetAwDrawSWFunctionTable() { | 285 AwDrawSWFunctionTable* BrowserViewRenderer::GetAwDrawSWFunctionTable() { |
214 return g_sw_draw_functions; | 286 return g_sw_draw_functions; |
215 } | 287 } |
216 | 288 |
217 InProcessViewRenderer::InProcessViewRenderer( | 289 InProcessViewRenderer::InProcessViewRenderer( |
218 BrowserViewRenderer::Client* client, | 290 BrowserViewRenderer::Client* client, |
219 JavaHelper* java_helper, | 291 JavaHelper* java_helper, |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
344 // normal levels in the next DrawGL call. | 416 // normal levels in the next DrawGL call. |
345 content::SynchronousCompositorMemoryPolicy policy; | 417 content::SynchronousCompositorMemoryPolicy policy; |
346 policy.bytes_limit = 0; | 418 policy.bytes_limit = 0; |
347 policy.num_resources_limit = 0; | 419 policy.num_resources_limit = 0; |
348 if (memory_policy_ == policy) | 420 if (memory_policy_ == policy) |
349 return; | 421 return; |
350 | 422 |
351 TRACE_EVENT0("android_webview", "InProcessViewRenderer::TrimMemory"); | 423 TRACE_EVENT0("android_webview", "InProcessViewRenderer::TrimMemory"); |
352 ScopedAppGLStateRestore state_restore( | 424 ScopedAppGLStateRestore state_restore( |
353 ScopedAppGLStateRestore::MODE_RESOURCE_MANAGEMENT); | 425 ScopedAppGLStateRestore::MODE_RESOURCE_MANAGEMENT); |
354 gpu::InProcessCommandBuffer::ProcessGpuWorkOnCurrentThread(); | 426 g_service.Get()->RunTasks(); |
355 ScopedAllowGL allow_gl; | 427 ScopedAllowGL allow_gl; |
356 | 428 |
357 SetMemoryPolicy(policy); | 429 SetMemoryPolicy(policy); |
358 ForceFakeCompositeSW(); | 430 ForceFakeCompositeSW(); |
359 } | 431 } |
360 | 432 |
361 void InProcessViewRenderer::SetMemoryPolicy( | 433 void InProcessViewRenderer::SetMemoryPolicy( |
362 content::SynchronousCompositorMemoryPolicy& new_policy) { | 434 content::SynchronousCompositorMemoryPolicy& new_policy) { |
363 if (memory_policy_ == new_policy) | 435 if (memory_policy_ == new_policy) |
364 return; | 436 return; |
(...skipping 19 matching lines...) Expand all Loading... |
384 // thus return false here to clear to background color for this draw. | 456 // thus return false here to clear to background color for this draw. |
385 return compositor_ && client_->RequestDrawGL(java_canvas); | 457 return compositor_ && client_->RequestDrawGL(java_canvas); |
386 } | 458 } |
387 // Perform a software draw | 459 // Perform a software draw |
388 return DrawSWInternal(java_canvas, clip); | 460 return DrawSWInternal(java_canvas, clip); |
389 } | 461 } |
390 | 462 |
391 bool InProcessViewRenderer::InitializeHwDraw() { | 463 bool InProcessViewRenderer::InitializeHwDraw() { |
392 TRACE_EVENT0("android_webview", "InitializeHwDraw"); | 464 TRACE_EVENT0("android_webview", "InitializeHwDraw"); |
393 DCHECK(!gl_surface_); | 465 DCHECK(!gl_surface_); |
394 gl_surface_ = new AwGLSurface; | 466 gl_surface_ = new AwGLSurface; |
| 467 if (!g_service.Get()) { |
| 468 g_service.Get() = new DeferredGpuCommandService; |
| 469 content::SynchronousCompositor::SetGpuService(g_service.Get()); |
| 470 } |
395 hardware_failed_ = !compositor_->InitializeHwDraw(gl_surface_); | 471 hardware_failed_ = !compositor_->InitializeHwDraw(gl_surface_); |
396 hardware_initialized_ = true; | 472 hardware_initialized_ = true; |
397 | 473 |
398 if (hardware_failed_) | 474 if (hardware_failed_) |
399 gl_surface_ = NULL; | 475 gl_surface_ = NULL; |
400 | 476 |
401 return !hardware_failed_; | 477 return !hardware_failed_; |
402 } | 478 } |
403 | 479 |
404 void InProcessViewRenderer::DrawGL(AwDrawGLInfo* draw_info) { | 480 void InProcessViewRenderer::DrawGL(AwDrawGLInfo* draw_info) { |
405 TRACE_EVENT0("android_webview", "InProcessViewRenderer::DrawGL"); | 481 TRACE_EVENT0("android_webview", "InProcessViewRenderer::DrawGL"); |
406 | 482 |
407 manager_key_ = g_view_renderer_manager.Get().DidDrawGL(manager_key_, this); | 483 manager_key_ = g_view_renderer_manager.Get().DidDrawGL(manager_key_, this); |
408 | 484 |
409 // We need to watch if the current Android context has changed and enforce | 485 // We need to watch if the current Android context has changed and enforce |
410 // a clean-up in the compositor. | 486 // a clean-up in the compositor. |
411 EGLContext current_context = eglGetCurrentContext(); | 487 EGLContext current_context = eglGetCurrentContext(); |
412 if (!current_context) { | 488 if (!current_context) { |
413 TRACE_EVENT_INSTANT0( | 489 TRACE_EVENT_INSTANT0( |
414 "android_webview", "EarlyOut_NullEGLContext", TRACE_EVENT_SCOPE_THREAD); | 490 "android_webview", "EarlyOut_NullEGLContext", TRACE_EVENT_SCOPE_THREAD); |
415 return; | 491 return; |
416 } | 492 } |
417 | 493 |
418 ScopedAppGLStateRestore state_restore(ScopedAppGLStateRestore::MODE_DRAW); | 494 ScopedAppGLStateRestore state_restore(ScopedAppGLStateRestore::MODE_DRAW); |
419 gpu::InProcessCommandBuffer::ProcessGpuWorkOnCurrentThread(); | 495 if (g_service.Get()) |
| 496 g_service.Get()->RunTasks(); |
420 ScopedAllowGL allow_gl; | 497 ScopedAllowGL allow_gl; |
421 | 498 |
422 if (!attached_to_window_) { | 499 if (!attached_to_window_) { |
423 TRACE_EVENT_INSTANT0( | 500 TRACE_EVENT_INSTANT0( |
424 "android_webview", "EarlyOut_NotAttached", TRACE_EVENT_SCOPE_THREAD); | 501 "android_webview", "EarlyOut_NotAttached", TRACE_EVENT_SCOPE_THREAD); |
425 return; | 502 return; |
426 } | 503 } |
427 | 504 |
428 if (draw_info->mode == AwDrawGLInfo::kModeProcess) { | 505 if (draw_info->mode == AwDrawGLInfo::kModeProcess) { |
429 TRACE_EVENT_INSTANT0( | 506 TRACE_EVENT_INSTANT0( |
(...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
698 void InProcessViewRenderer::OnDetachedFromWindow() { | 775 void InProcessViewRenderer::OnDetachedFromWindow() { |
699 TRACE_EVENT0("android_webview", | 776 TRACE_EVENT0("android_webview", |
700 "InProcessViewRenderer::OnDetachedFromWindow"); | 777 "InProcessViewRenderer::OnDetachedFromWindow"); |
701 | 778 |
702 NoLongerExpectsDrawGL(); | 779 NoLongerExpectsDrawGL(); |
703 if (hardware_initialized_) { | 780 if (hardware_initialized_) { |
704 DCHECK(compositor_); | 781 DCHECK(compositor_); |
705 | 782 |
706 ScopedAppGLStateRestore state_restore( | 783 ScopedAppGLStateRestore state_restore( |
707 ScopedAppGLStateRestore::MODE_RESOURCE_MANAGEMENT); | 784 ScopedAppGLStateRestore::MODE_RESOURCE_MANAGEMENT); |
708 gpu::InProcessCommandBuffer::ProcessGpuWorkOnCurrentThread(); | 785 g_service.Get()->RunTasks(); |
709 ScopedAllowGL allow_gl; | 786 ScopedAllowGL allow_gl; |
710 compositor_->ReleaseHwDraw(); | 787 compositor_->ReleaseHwDraw(); |
711 hardware_initialized_ = false; | 788 hardware_initialized_ = false; |
712 } | 789 } |
713 | 790 |
714 gl_surface_ = NULL; | 791 gl_surface_ = NULL; |
715 attached_to_window_ = false; | 792 attached_to_window_ = false; |
716 } | 793 } |
717 | 794 |
718 bool InProcessViewRenderer::IsAttachedToWindow() { | 795 bool InProcessViewRenderer::IsAttachedToWindow() { |
(...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1016 base::StringAppendF(&str, | 1093 base::StringAppendF(&str, |
1017 "surface width height: [%d %d] ", | 1094 "surface width height: [%d %d] ", |
1018 draw_info->width, | 1095 draw_info->width, |
1019 draw_info->height); | 1096 draw_info->height); |
1020 base::StringAppendF(&str, "is_layer: %d ", draw_info->is_layer); | 1097 base::StringAppendF(&str, "is_layer: %d ", draw_info->is_layer); |
1021 } | 1098 } |
1022 return str; | 1099 return str; |
1023 } | 1100 } |
1024 | 1101 |
1025 } // namespace android_webview | 1102 } // namespace android_webview |
OLD | NEW |