OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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/shared_renderer_state.h" | 5 #include "android_webview/browser/shared_renderer_state.h" |
6 | 6 |
7 #include "android_webview/browser/browser_view_renderer.h" | 7 #include "android_webview/browser/browser_view_renderer.h" |
8 #include "android_webview/browser/deferred_gpu_command_service.h" | 8 #include "android_webview/browser/deferred_gpu_command_service.h" |
9 #include "android_webview/browser/hardware_renderer.h" | 9 #include "android_webview/browser/hardware_renderer.h" |
10 #include "android_webview/browser/scoped_app_gl_state_restore.h" | 10 #include "android_webview/browser/scoped_app_gl_state_restore.h" |
11 #include "android_webview/public/browser/draw_gl.h" | 11 #include "android_webview/public/browser/draw_gl.h" |
12 #include "base/bind.h" | 12 #include "base/bind.h" |
13 #include "base/debug/trace_event_argument.h" | 13 #include "base/debug/trace_event_argument.h" |
14 #include "base/lazy_instance.h" | 14 #include "base/lazy_instance.h" |
15 #include "base/location.h" | 15 #include "base/location.h" |
16 | 16 |
17 namespace android_webview { | 17 namespace android_webview { |
18 | 18 |
19 namespace internal { | 19 namespace internal { |
20 | 20 |
21 class RequestDrawGLTracker { | 21 class RequestDrawGLTracker { |
22 public: | 22 public: |
23 RequestDrawGLTracker(); | 23 RequestDrawGLTracker(); |
24 bool ShouldRequestOnNonUiThread(SharedRendererState* state); | 24 bool ShouldRequestOnNonUiThread(SharedRendererState* state); |
25 bool ShouldRequestOnUiThread(SharedRendererState* state); | 25 bool ShouldRequestOnUiThread(SharedRendererState* state); |
26 void DidRequestOnUiThread(); | |
27 void ResetPending(); | 26 void ResetPending(); |
| 27 void SetQueuedFunctorOnUi(SharedRendererState* state); |
28 | 28 |
29 private: | 29 private: |
30 base::Lock lock_; | 30 base::Lock lock_; |
31 SharedRendererState* pending_ui_; | 31 SharedRendererState* pending_ui_; |
32 SharedRendererState* pending_non_ui_; | 32 SharedRendererState* pending_non_ui_; |
33 }; | 33 }; |
34 | 34 |
35 RequestDrawGLTracker::RequestDrawGLTracker() | 35 RequestDrawGLTracker::RequestDrawGLTracker() |
36 : pending_ui_(NULL), pending_non_ui_(NULL) { | 36 : pending_ui_(NULL), pending_non_ui_(NULL) { |
37 } | 37 } |
38 | 38 |
39 bool RequestDrawGLTracker::ShouldRequestOnNonUiThread( | 39 bool RequestDrawGLTracker::ShouldRequestOnNonUiThread( |
40 SharedRendererState* state) { | 40 SharedRendererState* state) { |
41 base::AutoLock lock(lock_); | 41 base::AutoLock lock(lock_); |
42 if (pending_ui_ || pending_non_ui_) | 42 if (pending_ui_ || pending_non_ui_) |
43 return false; | 43 return false; |
44 pending_non_ui_ = state; | 44 pending_non_ui_ = state; |
45 return true; | 45 return true; |
46 } | 46 } |
47 | 47 |
48 bool RequestDrawGLTracker::ShouldRequestOnUiThread(SharedRendererState* state) { | 48 bool RequestDrawGLTracker::ShouldRequestOnUiThread(SharedRendererState* state) { |
49 base::AutoLock lock(lock_); | 49 base::AutoLock lock(lock_); |
50 if (pending_non_ui_) { | 50 if (pending_non_ui_) { |
51 pending_non_ui_->ResetRequestDrawGLCallback(); | 51 pending_non_ui_->ResetRequestDrawGLCallback(); |
52 pending_non_ui_ = NULL; | 52 pending_non_ui_ = NULL; |
53 } | 53 } |
| 54 // At this time, we could have already called RequestDrawGL on the UI thread, |
| 55 // but the corresponding GL mode process hasn't happened yet. In this case, |
| 56 // don't schedule another requestDrawGL on the UI thread. |
54 if (pending_ui_) | 57 if (pending_ui_) |
55 return false; | 58 return false; |
56 pending_ui_ = state; | 59 pending_ui_ = state; |
57 return true; | 60 return true; |
58 } | 61 } |
59 | 62 |
60 void RequestDrawGLTracker::ResetPending() { | 63 void RequestDrawGLTracker::ResetPending() { |
61 base::AutoLock lock(lock_); | 64 base::AutoLock lock(lock_); |
62 pending_non_ui_ = NULL; | 65 pending_non_ui_ = NULL; |
63 pending_ui_ = NULL; | 66 pending_ui_ = NULL; |
64 } | 67 } |
65 | 68 |
| 69 void RequestDrawGLTracker::SetQueuedFunctorOnUi(SharedRendererState* state) { |
| 70 base::AutoLock lock(lock_); |
| 71 DCHECK(state); |
| 72 DCHECK(pending_ui_ == state || pending_non_ui_ == state); |
| 73 pending_ui_ = state; |
| 74 pending_non_ui_ = NULL; |
| 75 } |
| 76 |
66 } // namespace internal | 77 } // namespace internal |
67 | 78 |
68 namespace { | 79 namespace { |
69 | 80 |
70 base::LazyInstance<internal::RequestDrawGLTracker> g_request_draw_gl_tracker = | 81 base::LazyInstance<internal::RequestDrawGLTracker> g_request_draw_gl_tracker = |
71 LAZY_INSTANCE_INITIALIZER; | 82 LAZY_INSTANCE_INITIALIZER; |
72 | 83 |
73 } | 84 } |
74 | 85 |
75 SharedRendererState::SharedRendererState( | 86 SharedRendererState::SharedRendererState( |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
118 DCHECK(ui_loop_->BelongsToCurrentThread()); | 129 DCHECK(ui_loop_->BelongsToCurrentThread()); |
119 base::AutoLock lock(lock_); | 130 base::AutoLock lock(lock_); |
120 request_draw_gl_cancelable_closure_.Reset(base::Bind( | 131 request_draw_gl_cancelable_closure_.Reset(base::Bind( |
121 &SharedRendererState::ClientRequestDrawGLOnUI, base::Unretained(this))); | 132 &SharedRendererState::ClientRequestDrawGLOnUI, base::Unretained(this))); |
122 request_draw_gl_closure_ = request_draw_gl_cancelable_closure_.callback(); | 133 request_draw_gl_closure_ = request_draw_gl_cancelable_closure_.callback(); |
123 } | 134 } |
124 | 135 |
125 void SharedRendererState::ClientRequestDrawGLOnUI() { | 136 void SharedRendererState::ClientRequestDrawGLOnUI() { |
126 DCHECK(ui_loop_->BelongsToCurrentThread()); | 137 DCHECK(ui_loop_->BelongsToCurrentThread()); |
127 ResetRequestDrawGLCallback(); | 138 ResetRequestDrawGLCallback(); |
| 139 g_request_draw_gl_tracker.Get().SetQueuedFunctorOnUi(this); |
128 if (!browser_view_renderer_->RequestDrawGL(false)) { | 140 if (!browser_view_renderer_->RequestDrawGL(false)) { |
129 g_request_draw_gl_tracker.Get().ResetPending(); | 141 g_request_draw_gl_tracker.Get().ResetPending(); |
130 LOG(ERROR) << "Failed to request GL process. Deadlock likely"; | 142 LOG(ERROR) << "Failed to request GL process. Deadlock likely"; |
131 } | 143 } |
132 } | 144 } |
133 | 145 |
134 void SharedRendererState::UpdateParentDrawConstraintsOnUI() { | 146 void SharedRendererState::UpdateParentDrawConstraintsOnUI() { |
135 DCHECK(ui_loop_->BelongsToCurrentThread()); | 147 DCHECK(ui_loop_->BelongsToCurrentThread()); |
136 browser_view_renderer_->UpdateParentDrawConstraints(); | 148 browser_view_renderer_->UpdateParentDrawConstraints(); |
137 } | 149 } |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
260 void SharedRendererState::DrawGL(AwDrawGLInfo* draw_info) { | 272 void SharedRendererState::DrawGL(AwDrawGLInfo* draw_info) { |
261 TRACE_EVENT0("android_webview", "DrawFunctor"); | 273 TRACE_EVENT0("android_webview", "DrawFunctor"); |
262 if (draw_info->mode == AwDrawGLInfo::kModeSync) { | 274 if (draw_info->mode == AwDrawGLInfo::kModeSync) { |
263 TRACE_EVENT_INSTANT0("android_webview", "kModeSync", | 275 TRACE_EVENT_INSTANT0("android_webview", "kModeSync", |
264 TRACE_EVENT_SCOPE_THREAD); | 276 TRACE_EVENT_SCOPE_THREAD); |
265 if (hardware_renderer_) | 277 if (hardware_renderer_) |
266 hardware_renderer_->CommitFrame(); | 278 hardware_renderer_->CommitFrame(); |
267 return; | 279 return; |
268 } | 280 } |
269 | 281 |
| 282 // kModeProcessNoContext should never happen because we tear down hardware |
| 283 // in onTrimMemory. However that guarantee is maintained outside of chromium |
| 284 // code. Not notifying shared state in kModeProcessNoContext can lead to |
| 285 // immediate deadlock, which is slightly more catastrophic than leaks or |
| 286 // corruption. |
| 287 if (draw_info->mode == AwDrawGLInfo::kModeProcess || |
| 288 draw_info->mode == AwDrawGLInfo::kModeProcessNoContext) { |
| 289 DidDrawGLProcess(); |
| 290 } |
| 291 |
270 { | 292 { |
271 GLViewRendererManager* manager = GLViewRendererManager::GetInstance(); | 293 GLViewRendererManager* manager = GLViewRendererManager::GetInstance(); |
272 base::AutoLock lock(lock_); | 294 base::AutoLock lock(lock_); |
273 if (renderer_manager_key_ != manager->NullKey()) { | 295 if (renderer_manager_key_ != manager->NullKey()) { |
274 manager->DidDrawGL(renderer_manager_key_); | 296 manager->DidDrawGL(renderer_manager_key_); |
275 } | 297 } |
276 } | 298 } |
277 | 299 |
278 ScopedAppGLStateRestore state_restore( | 300 ScopedAppGLStateRestore state_restore( |
279 draw_info->mode == AwDrawGLInfo::kModeDraw | 301 draw_info->mode == AwDrawGLInfo::kModeDraw |
280 ? ScopedAppGLStateRestore::MODE_DRAW | 302 ? ScopedAppGLStateRestore::MODE_DRAW |
281 : ScopedAppGLStateRestore::MODE_RESOURCE_MANAGEMENT); | 303 : ScopedAppGLStateRestore::MODE_RESOURCE_MANAGEMENT); |
282 ScopedAllowGL allow_gl; | 304 ScopedAllowGL allow_gl; |
283 | 305 |
284 if (draw_info->mode == AwDrawGLInfo::kModeProcessNoContext) { | 306 if (draw_info->mode == AwDrawGLInfo::kModeProcessNoContext) { |
285 LOG(ERROR) << "Received unexpected kModeProcessNoContext"; | 307 LOG(ERROR) << "Received unexpected kModeProcessNoContext"; |
286 } | 308 } |
287 | 309 |
288 // kModeProcessNoContext should never happen because we tear down hardware | |
289 // in onTrimMemory. However that guarantee is maintained outside of chromium | |
290 // code. Not notifying shared state in kModeProcessNoContext can lead to | |
291 // immediate deadlock, which is slightly more catastrophic than leaks or | |
292 // corruption. | |
293 if (draw_info->mode == AwDrawGLInfo::kModeProcess || | |
294 draw_info->mode == AwDrawGLInfo::kModeProcessNoContext) { | |
295 DidDrawGLProcess(); | |
296 } | |
297 | |
298 if (IsInsideHardwareRelease()) { | 310 if (IsInsideHardwareRelease()) { |
299 hardware_renderer_.reset(); | 311 hardware_renderer_.reset(); |
300 // Flush the idle queue in tear down. | 312 // Flush the idle queue in tear down. |
301 DeferredGpuCommandService::GetInstance()->PerformAllIdleWork(); | 313 DeferredGpuCommandService::GetInstance()->PerformAllIdleWork(); |
302 return; | 314 return; |
303 } | 315 } |
304 | 316 |
305 if (draw_info->mode != AwDrawGLInfo::kModeDraw) { | 317 if (draw_info->mode != AwDrawGLInfo::kModeDraw) { |
306 if (draw_info->mode == AwDrawGLInfo::kModeProcess) { | 318 if (draw_info->mode == AwDrawGLInfo::kModeProcess) { |
307 DeferredGpuCommandService::GetInstance()->PerformIdleWork(true); | 319 DeferredGpuCommandService::GetInstance()->PerformIdleWork(true); |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
371 : shared_renderer_state_(shared_renderer_state) { | 383 : shared_renderer_state_(shared_renderer_state) { |
372 DCHECK(!shared_renderer_state_->IsInsideHardwareRelease()); | 384 DCHECK(!shared_renderer_state_->IsInsideHardwareRelease()); |
373 shared_renderer_state_->SetInsideHardwareRelease(true); | 385 shared_renderer_state_->SetInsideHardwareRelease(true); |
374 } | 386 } |
375 | 387 |
376 SharedRendererState::InsideHardwareReleaseReset::~InsideHardwareReleaseReset() { | 388 SharedRendererState::InsideHardwareReleaseReset::~InsideHardwareReleaseReset() { |
377 shared_renderer_state_->SetInsideHardwareRelease(false); | 389 shared_renderer_state_->SetInsideHardwareRelease(false); |
378 } | 390 } |
379 | 391 |
380 } // namespace android_webview | 392 } // namespace android_webview |
OLD | NEW |