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" |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
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 if (pending_ui_) | 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 | |
57 // schedule another requestDrawGL on the UI thread. | |
58 if (pending_ui_ || state->has_queued_functor_on_ui_) | |
55 return false; | 59 return false; |
56 pending_ui_ = state; | 60 pending_ui_ = state; |
57 return true; | 61 return true; |
58 } | 62 } |
59 | 63 |
60 void RequestDrawGLTracker::ResetPending() { | 64 void RequestDrawGLTracker::ResetPending() { |
61 base::AutoLock lock(lock_); | 65 base::AutoLock lock(lock_); |
62 pending_non_ui_ = NULL; | 66 pending_non_ui_ = NULL; |
63 pending_ui_ = NULL; | 67 pending_ui_ = NULL; |
64 } | 68 } |
65 | 69 |
66 } // namespace internal | 70 } // namespace internal |
67 | 71 |
68 namespace { | 72 namespace { |
69 | 73 |
70 base::LazyInstance<internal::RequestDrawGLTracker> g_request_draw_gl_tracker = | 74 base::LazyInstance<internal::RequestDrawGLTracker> g_request_draw_gl_tracker = |
71 LAZY_INSTANCE_INITIALIZER; | 75 LAZY_INSTANCE_INITIALIZER; |
72 | 76 |
73 } | 77 } |
74 | 78 |
75 SharedRendererState::SharedRendererState( | 79 SharedRendererState::SharedRendererState( |
76 const scoped_refptr<base::SingleThreadTaskRunner>& ui_loop, | 80 const scoped_refptr<base::SingleThreadTaskRunner>& ui_loop, |
77 BrowserViewRenderer* browser_view_renderer) | 81 BrowserViewRenderer* browser_view_renderer) |
78 : ui_loop_(ui_loop), | 82 : ui_loop_(ui_loop), |
79 browser_view_renderer_(browser_view_renderer), | 83 browser_view_renderer_(browser_view_renderer), |
84 has_queued_functor_on_ui_(false), | |
80 renderer_manager_key_(GLViewRendererManager::GetInstance()->NullKey()), | 85 renderer_manager_key_(GLViewRendererManager::GetInstance()->NullKey()), |
81 force_commit_(false), | 86 force_commit_(false), |
82 inside_hardware_release_(false), | 87 inside_hardware_release_(false), |
83 needs_force_invalidate_on_next_draw_gl_(false), | 88 needs_force_invalidate_on_next_draw_gl_(false), |
84 weak_factory_on_ui_thread_(this) { | 89 weak_factory_on_ui_thread_(this) { |
85 DCHECK(ui_loop_->BelongsToCurrentThread()); | 90 DCHECK(ui_loop_->BelongsToCurrentThread()); |
86 DCHECK(browser_view_renderer_); | 91 DCHECK(browser_view_renderer_); |
87 ui_thread_weak_ptr_ = weak_factory_on_ui_thread_.GetWeakPtr(); | 92 ui_thread_weak_ptr_ = weak_factory_on_ui_thread_.GetWeakPtr(); |
88 ResetRequestDrawGLCallback(); | 93 ResetRequestDrawGLCallback(); |
89 } | 94 } |
(...skipping 15 matching lines...) Expand all Loading... | |
105 { | 110 { |
106 base::AutoLock lock(lock_); | 111 base::AutoLock lock(lock_); |
107 callback = request_draw_gl_closure_; | 112 callback = request_draw_gl_closure_; |
108 } | 113 } |
109 ui_loop_->PostTask(FROM_HERE, callback); | 114 ui_loop_->PostTask(FROM_HERE, callback); |
110 } | 115 } |
111 } | 116 } |
112 | 117 |
113 void SharedRendererState::DidDrawGLProcess() { | 118 void SharedRendererState::DidDrawGLProcess() { |
114 g_request_draw_gl_tracker.Get().ResetPending(); | 119 g_request_draw_gl_tracker.Get().ResetPending(); |
120 has_queued_functor_on_ui_ = false; | |
115 } | 121 } |
116 | 122 |
117 void SharedRendererState::ResetRequestDrawGLCallback() { | 123 void SharedRendererState::ResetRequestDrawGLCallback() { |
118 DCHECK(ui_loop_->BelongsToCurrentThread()); | 124 DCHECK(ui_loop_->BelongsToCurrentThread()); |
119 base::AutoLock lock(lock_); | 125 base::AutoLock lock(lock_); |
120 request_draw_gl_cancelable_closure_.Reset(base::Bind( | 126 request_draw_gl_cancelable_closure_.Reset(base::Bind( |
121 &SharedRendererState::ClientRequestDrawGLOnUI, base::Unretained(this))); | 127 &SharedRendererState::ClientRequestDrawGLOnUI, base::Unretained(this))); |
122 request_draw_gl_closure_ = request_draw_gl_cancelable_closure_.callback(); | 128 request_draw_gl_closure_ = request_draw_gl_cancelable_closure_.callback(); |
123 } | 129 } |
124 | 130 |
125 void SharedRendererState::ClientRequestDrawGLOnUI() { | 131 void SharedRendererState::ClientRequestDrawGLOnUI() { |
126 DCHECK(ui_loop_->BelongsToCurrentThread()); | 132 DCHECK(ui_loop_->BelongsToCurrentThread()); |
127 ResetRequestDrawGLCallback(); | 133 ResetRequestDrawGLCallback(); |
134 has_queued_functor_on_ui_ = true; | |
128 if (!browser_view_renderer_->RequestDrawGL(false)) { | 135 if (!browser_view_renderer_->RequestDrawGL(false)) { |
129 g_request_draw_gl_tracker.Get().ResetPending(); | 136 g_request_draw_gl_tracker.Get().ResetPending(); |
130 LOG(ERROR) << "Failed to request GL process. Deadlock likely"; | 137 LOG(ERROR) << "Failed to request GL process. Deadlock likely"; |
131 } | 138 } |
132 } | 139 } |
133 | 140 |
134 void SharedRendererState::UpdateParentDrawConstraintsOnUI() { | 141 void SharedRendererState::UpdateParentDrawConstraintsOnUI() { |
135 DCHECK(ui_loop_->BelongsToCurrentThread()); | 142 DCHECK(ui_loop_->BelongsToCurrentThread()); |
136 browser_view_renderer_->UpdateParentDrawConstraints(); | 143 browser_view_renderer_->UpdateParentDrawConstraints(); |
137 } | 144 } |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
252 resources->swap(returned_resources_); | 259 resources->swap(returned_resources_); |
253 } | 260 } |
254 | 261 |
255 bool SharedRendererState::ReturnedResourcesEmptyOnUI() const { | 262 bool SharedRendererState::ReturnedResourcesEmptyOnUI() const { |
256 base::AutoLock lock(lock_); | 263 base::AutoLock lock(lock_); |
257 return returned_resources_.empty(); | 264 return returned_resources_.empty(); |
258 } | 265 } |
259 | 266 |
260 void SharedRendererState::DrawGL(AwDrawGLInfo* draw_info) { | 267 void SharedRendererState::DrawGL(AwDrawGLInfo* draw_info) { |
261 TRACE_EVENT0("android_webview", "DrawFunctor"); | 268 TRACE_EVENT0("android_webview", "DrawFunctor"); |
269 // kModeProcessNoContext should never happen because we tear down hardware | |
270 // in onTrimMemory. However that guarantee is maintained outside of chromium | |
271 // code. Not notifying shared state in kModeProcessNoContext can lead to | |
272 // immediate deadlock, which is slightly more catastrophic than leaks or | |
273 // corruption. | |
274 if (draw_info->mode == AwDrawGLInfo::kModeProcess || | |
boliu
2014/12/13 01:03:15
nit: put it after the kModeSync check
hush (inactive)
2014/12/13 01:17:23
Done.
| |
275 draw_info->mode == AwDrawGLInfo::kModeProcessNoContext) { | |
276 DidDrawGLProcess(); | |
277 } | |
278 | |
262 if (draw_info->mode == AwDrawGLInfo::kModeSync) { | 279 if (draw_info->mode == AwDrawGLInfo::kModeSync) { |
263 TRACE_EVENT_INSTANT0("android_webview", "kModeSync", | 280 TRACE_EVENT_INSTANT0("android_webview", "kModeSync", |
264 TRACE_EVENT_SCOPE_THREAD); | 281 TRACE_EVENT_SCOPE_THREAD); |
265 if (hardware_renderer_) | 282 if (hardware_renderer_) |
266 hardware_renderer_->CommitFrame(); | 283 hardware_renderer_->CommitFrame(); |
267 return; | 284 return; |
268 } | 285 } |
269 | 286 |
270 { | 287 { |
271 GLViewRendererManager* manager = GLViewRendererManager::GetInstance(); | 288 GLViewRendererManager* manager = GLViewRendererManager::GetInstance(); |
272 base::AutoLock lock(lock_); | 289 base::AutoLock lock(lock_); |
273 if (renderer_manager_key_ != manager->NullKey()) { | 290 if (renderer_manager_key_ != manager->NullKey()) { |
274 manager->DidDrawGL(renderer_manager_key_); | 291 manager->DidDrawGL(renderer_manager_key_); |
275 } | 292 } |
276 } | 293 } |
277 | 294 |
278 ScopedAppGLStateRestore state_restore( | 295 ScopedAppGLStateRestore state_restore( |
279 draw_info->mode == AwDrawGLInfo::kModeDraw | 296 draw_info->mode == AwDrawGLInfo::kModeDraw |
280 ? ScopedAppGLStateRestore::MODE_DRAW | 297 ? ScopedAppGLStateRestore::MODE_DRAW |
281 : ScopedAppGLStateRestore::MODE_RESOURCE_MANAGEMENT); | 298 : ScopedAppGLStateRestore::MODE_RESOURCE_MANAGEMENT); |
282 ScopedAllowGL allow_gl; | 299 ScopedAllowGL allow_gl; |
283 | 300 |
284 if (draw_info->mode == AwDrawGLInfo::kModeProcessNoContext) { | 301 if (draw_info->mode == AwDrawGLInfo::kModeProcessNoContext) { |
285 LOG(ERROR) << "Received unexpected kModeProcessNoContext"; | 302 LOG(ERROR) << "Received unexpected kModeProcessNoContext"; |
286 } | 303 } |
287 | 304 |
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()) { | 305 if (IsInsideHardwareRelease()) { |
299 hardware_renderer_.reset(); | 306 hardware_renderer_.reset(); |
300 // Flush the idle queue in tear down. | 307 // Flush the idle queue in tear down. |
301 DeferredGpuCommandService::GetInstance()->PerformAllIdleWork(); | 308 DeferredGpuCommandService::GetInstance()->PerformAllIdleWork(); |
302 return; | 309 return; |
303 } | 310 } |
304 | 311 |
305 if (draw_info->mode != AwDrawGLInfo::kModeDraw) { | 312 if (draw_info->mode != AwDrawGLInfo::kModeDraw) { |
306 if (draw_info->mode == AwDrawGLInfo::kModeProcess) { | 313 if (draw_info->mode == AwDrawGLInfo::kModeProcess) { |
307 DeferredGpuCommandService::GetInstance()->PerformIdleWork(true); | 314 DeferredGpuCommandService::GetInstance()->PerformIdleWork(true); |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
371 : shared_renderer_state_(shared_renderer_state) { | 378 : shared_renderer_state_(shared_renderer_state) { |
372 DCHECK(!shared_renderer_state_->IsInsideHardwareRelease()); | 379 DCHECK(!shared_renderer_state_->IsInsideHardwareRelease()); |
373 shared_renderer_state_->SetInsideHardwareRelease(true); | 380 shared_renderer_state_->SetInsideHardwareRelease(true); |
374 } | 381 } |
375 | 382 |
376 SharedRendererState::InsideHardwareReleaseReset::~InsideHardwareReleaseReset() { | 383 SharedRendererState::InsideHardwareReleaseReset::~InsideHardwareReleaseReset() { |
377 shared_renderer_state_->SetInsideHardwareRelease(false); | 384 shared_renderer_state_->SetInsideHardwareRelease(false); |
378 } | 385 } |
379 | 386 |
380 } // namespace android_webview | 387 } // namespace android_webview |
OLD | NEW |