Chromium Code Reviews| 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/render_thread_manager.h" | 5 #include "android_webview/browser/render_thread_manager.h" |
| 6 | 6 |
| 7 #include <utility> | 7 #include <utility> |
| 8 | 8 |
| 9 #include "android_webview/browser/compositor_frame_producer.h" | 9 #include "android_webview/browser/compositor_frame_producer.h" |
| 10 #include "android_webview/browser/compositor_id.h" | 10 #include "android_webview/browser/compositor_id.h" |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 91 base::LazyInstance<internal::RequestInvokeGLTracker> | 91 base::LazyInstance<internal::RequestInvokeGLTracker> |
| 92 g_request_invoke_gl_tracker = LAZY_INSTANCE_INITIALIZER; | 92 g_request_invoke_gl_tracker = LAZY_INSTANCE_INITIALIZER; |
| 93 } | 93 } |
| 94 | 94 |
| 95 RenderThreadManager::RenderThreadManager( | 95 RenderThreadManager::RenderThreadManager( |
| 96 RenderThreadManagerClient* client, | 96 RenderThreadManagerClient* client, |
| 97 const scoped_refptr<base::SingleThreadTaskRunner>& ui_loop) | 97 const scoped_refptr<base::SingleThreadTaskRunner>& ui_loop) |
| 98 : ui_loop_(ui_loop), | 98 : ui_loop_(ui_loop), |
| 99 client_(client), | 99 client_(client), |
| 100 compositor_frame_producer_(nullptr), | 100 compositor_frame_producer_(nullptr), |
| 101 has_received_frame_(false), | |
| 101 renderer_manager_key_(GLViewRendererManager::GetInstance()->NullKey()), | 102 renderer_manager_key_(GLViewRendererManager::GetInstance()->NullKey()), |
| 102 hardware_renderer_has_frame_(false), | |
| 103 sync_on_draw_hardware_(base::CommandLine::ForCurrentProcess()->HasSwitch( | 103 sync_on_draw_hardware_(base::CommandLine::ForCurrentProcess()->HasSwitch( |
| 104 switches::kSyncOnDrawHardware)), | 104 switches::kSyncOnDrawHardware)), |
| 105 inside_hardware_release_(false), | 105 inside_hardware_release_(false), |
| 106 weak_factory_on_ui_thread_(this) { | 106 weak_factory_on_ui_thread_(this) { |
| 107 DCHECK(ui_loop_->BelongsToCurrentThread()); | 107 DCHECK(ui_loop_->BelongsToCurrentThread()); |
| 108 DCHECK(client_); | 108 DCHECK(client_); |
| 109 ui_thread_weak_ptr_ = weak_factory_on_ui_thread_.GetWeakPtr(); | 109 ui_thread_weak_ptr_ = weak_factory_on_ui_thread_.GetWeakPtr(); |
| 110 ResetRequestInvokeGLCallback(); | 110 ResetRequestInvokeGLCallback(); |
| 111 } | 111 } |
| 112 | 112 |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 176 | 176 |
| 177 gfx::Vector2d RenderThreadManager::GetScrollOffsetOnRT() { | 177 gfx::Vector2d RenderThreadManager::GetScrollOffsetOnRT() { |
| 178 base::AutoLock lock(lock_); | 178 base::AutoLock lock(lock_); |
| 179 return scroll_offset_; | 179 return scroll_offset_; |
| 180 } | 180 } |
| 181 | 181 |
| 182 std::unique_ptr<ChildFrame> RenderThreadManager::SetFrameOnUI( | 182 std::unique_ptr<ChildFrame> RenderThreadManager::SetFrameOnUI( |
| 183 std::unique_ptr<ChildFrame> new_frame) { | 183 std::unique_ptr<ChildFrame> new_frame) { |
| 184 DCHECK(new_frame); | 184 DCHECK(new_frame); |
| 185 base::AutoLock lock(lock_); | 185 base::AutoLock lock(lock_); |
| 186 | |
| 187 has_received_frame_ = true; | |
|
boliu
2016/12/06 16:15:35
maybe add a TODO here, this doesn't work if we swi
Tobias Sargeant
2016/12/06 18:11:26
Done.
| |
| 188 | |
| 186 if (child_frames_.empty()) { | 189 if (child_frames_.empty()) { |
| 187 child_frames_.emplace_back(std::move(new_frame)); | 190 child_frames_.emplace_back(std::move(new_frame)); |
| 188 return nullptr; | 191 return nullptr; |
| 189 } | 192 } |
| 190 std::unique_ptr<ChildFrame> uncommitted_frame; | 193 std::unique_ptr<ChildFrame> uncommitted_frame; |
| 191 if (new_frame->frame) { | 194 if (new_frame->frame) { |
| 192 // Optimization for synchronous path. | 195 // Optimization for synchronous path. |
| 193 // TODO(boliu): Remove when synchronous path is fully removed. | 196 // TODO(boliu): Remove when synchronous path is fully removed. |
| 194 DCHECK_LE(child_frames_.size(), 1u); | 197 DCHECK_LE(child_frames_.size(), 1u); |
| 195 if (!child_frames_.empty()) { | 198 if (!child_frames_.empty()) { |
| 196 uncommitted_frame = std::move(child_frames_.front()); | 199 uncommitted_frame = std::move(child_frames_.front()); |
| 197 child_frames_.pop_front(); | 200 child_frames_.pop_front(); |
| 198 } | 201 } |
| 199 child_frames_.emplace_back(std::move(new_frame)); | 202 child_frames_.emplace_back(std::move(new_frame)); |
| 200 return uncommitted_frame; | 203 return uncommitted_frame; |
| 201 } | 204 } |
| 202 | 205 |
| 203 DCHECK_LE(child_frames_.size(), 2u); | 206 DCHECK_LE(child_frames_.size(), 2u); |
| 204 ChildFrameQueue pruned_frames = | 207 ChildFrameQueue pruned_frames = |
| 205 HardwareRenderer::WaitAndPruneFrameQueue(&child_frames_); | 208 HardwareRenderer::WaitAndPruneFrameQueue(&child_frames_); |
| 206 DCHECK_LE(pruned_frames.size(), 1u); | 209 DCHECK_LE(pruned_frames.size(), 1u); |
| 207 if (pruned_frames.size()) | 210 if (pruned_frames.size()) |
| 208 uncommitted_frame = std::move(pruned_frames.front()); | 211 uncommitted_frame = std::move(pruned_frames.front()); |
| 209 child_frames_.emplace_back(std::move(new_frame)); | 212 child_frames_.emplace_back(std::move(new_frame)); |
| 210 return uncommitted_frame; | 213 return uncommitted_frame; |
| 211 } | 214 } |
| 212 | 215 |
| 213 ChildFrameQueue RenderThreadManager::PassFramesOnRT() { | 216 ChildFrameQueue RenderThreadManager::PassFramesOnRT() { |
| 214 base::AutoLock lock(lock_); | 217 base::AutoLock lock(lock_); |
| 215 hardware_renderer_has_frame_ = | |
| 216 hardware_renderer_has_frame_ || !child_frames_.empty(); | |
| 217 ChildFrameQueue returned_frames; | 218 ChildFrameQueue returned_frames; |
| 218 returned_frames.swap(child_frames_); | 219 returned_frames.swap(child_frames_); |
| 219 return returned_frames; | 220 return returned_frames; |
| 220 } | 221 } |
| 221 | 222 |
| 222 ChildFrameQueue RenderThreadManager::PassUncommittedFrameOnUI() { | 223 ChildFrameQueue RenderThreadManager::PassUncommittedFrameOnUI() { |
| 223 base::AutoLock lock(lock_); | 224 base::AutoLock lock(lock_); |
| 224 for (auto& frame_ptr : child_frames_) | 225 for (auto& frame_ptr : child_frames_) |
| 225 frame_ptr->WaitOnFutureIfNeeded(); | 226 frame_ptr->WaitOnFutureIfNeeded(); |
| 226 ChildFrameQueue returned_frames; | 227 ChildFrameQueue returned_frames; |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 327 !IsInsideHardwareRelease() && HasFrameForHardwareRendererOnRT()) { | 328 !IsInsideHardwareRelease() && HasFrameForHardwareRendererOnRT()) { |
| 328 hardware_renderer_.reset(new HardwareRenderer(this)); | 329 hardware_renderer_.reset(new HardwareRenderer(this)); |
| 329 hardware_renderer_->CommitFrame(); | 330 hardware_renderer_->CommitFrame(); |
| 330 } | 331 } |
| 331 | 332 |
| 332 if (draw_info->mode == AwDrawGLInfo::kModeProcessNoContext) { | 333 if (draw_info->mode == AwDrawGLInfo::kModeProcessNoContext) { |
| 333 LOG(ERROR) << "Received unexpected kModeProcessNoContext"; | 334 LOG(ERROR) << "Received unexpected kModeProcessNoContext"; |
| 334 } | 335 } |
| 335 | 336 |
| 336 if (IsInsideHardwareRelease()) { | 337 if (IsInsideHardwareRelease()) { |
| 337 hardware_renderer_has_frame_ = false; | |
| 338 hardware_renderer_.reset(); | 338 hardware_renderer_.reset(); |
| 339 // If there are no frames ready to pass to a new | |
| 340 // hardware_renderer_ then consider that equivalent to never | |
| 341 // having received a frame. | |
| 342 has_received_frame_ = HasFrameForHardwareRendererOnRT(); | |
|
boliu
2016/12/06 16:15:35
I don't understand this
also this means has_recei
Tobias Sargeant
2016/12/06 16:29:27
Good point about has_received_frame_. The thing I
boliu
2016/12/06 16:34:10
can you unset has_received_frame_ at end of Delete
Tobias Sargeant
2016/12/06 16:36:38
Yes. That's a much better solution.
Tobias Sargeant
2016/12/06 18:11:26
Done.
| |
| 339 // Flush the idle queue in tear down. | 343 // Flush the idle queue in tear down. |
| 340 DeferredGpuCommandService::GetInstance()->PerformAllIdleWork(); | 344 DeferredGpuCommandService::GetInstance()->PerformAllIdleWork(); |
| 341 return; | 345 return; |
| 342 } | 346 } |
| 343 | 347 |
| 344 if (draw_info->mode != AwDrawGLInfo::kModeDraw) { | 348 if (draw_info->mode != AwDrawGLInfo::kModeDraw) { |
| 345 if (draw_info->mode == AwDrawGLInfo::kModeProcess) { | 349 if (draw_info->mode == AwDrawGLInfo::kModeProcess) { |
| 346 DeferredGpuCommandService::GetInstance()->PerformIdleWork(true); | 350 DeferredGpuCommandService::GetInstance()->PerformIdleWork(true); |
| 347 } | 351 } |
| 348 return; | 352 return; |
| 349 } | 353 } |
| 350 | 354 |
| 351 if (hardware_renderer_) | 355 if (hardware_renderer_) |
| 352 hardware_renderer_->DrawGL(draw_info); | 356 hardware_renderer_->DrawGL(draw_info); |
| 353 DeferredGpuCommandService::GetInstance()->PerformIdleWork(false); | 357 DeferredGpuCommandService::GetInstance()->PerformIdleWork(false); |
| 354 } | 358 } |
| 355 | 359 |
| 356 void RenderThreadManager::DeleteHardwareRendererOnUI() { | 360 void RenderThreadManager::DeleteHardwareRendererOnUI() { |
| 357 DCHECK(ui_loop_->BelongsToCurrentThread()); | 361 DCHECK(ui_loop_->BelongsToCurrentThread()); |
| 358 | 362 |
| 359 InsideHardwareReleaseReset auto_inside_hardware_release_reset(this); | 363 InsideHardwareReleaseReset auto_inside_hardware_release_reset(this); |
| 360 | 364 |
| 365 client_->DetachFunctorFromView(); | |
| 366 | |
| 361 // If the WebView gets onTrimMemory >= MODERATE twice in a row, the 2nd | 367 // If the WebView gets onTrimMemory >= MODERATE twice in a row, the 2nd |
| 362 // onTrimMemory will result in an unnecessary Render Thread InvokeGL call. | 368 // onTrimMemory will result in an unnecessary Render Thread InvokeGL call. |
| 363 bool hardware_initialized = HasFrameOnUI(); | 369 if (has_received_frame_) { |
| 364 if (hardware_initialized) { | 370 // Receiving at least one frame is a precondition for |
| 365 // The functor has only been attached to the view hierarchy if a compositor | 371 // initialization (such as looing up GL bindings and constructing |
| 366 // frame has been generated. Thus, it should only be detached in this case. | 372 // hardware_renderer_). |
| 367 client_->DetachFunctorFromView(); | |
| 368 | |
| 369 bool draw_functor_succeeded = client_->RequestInvokeGL(true); | 373 bool draw_functor_succeeded = client_->RequestInvokeGL(true); |
| 370 if (!draw_functor_succeeded) { | 374 if (!draw_functor_succeeded) { |
| 371 LOG(ERROR) << "Unable to free GL resources. Has the Window leaked?"; | 375 LOG(ERROR) << "Unable to free GL resources. Has the Window leaked?"; |
| 372 // Calling release on wrong thread intentionally. | 376 // Calling release on wrong thread intentionally. |
| 373 AwDrawGLInfo info; | 377 AwDrawGLInfo info; |
| 374 info.mode = AwDrawGLInfo::kModeProcess; | 378 info.mode = AwDrawGLInfo::kModeProcess; |
| 375 DrawGL(&info); | 379 DrawGL(&info); |
| 376 } | 380 } |
| 377 } | 381 } |
| 378 | 382 |
| 379 GLViewRendererManager* manager = GLViewRendererManager::GetInstance(); | 383 GLViewRendererManager* manager = GLViewRendererManager::GetInstance(); |
| 380 | 384 |
| 381 { | 385 { |
| 382 base::AutoLock lock(lock_); | 386 base::AutoLock lock(lock_); |
| 383 if (renderer_manager_key_ != manager->NullKey()) { | 387 if (renderer_manager_key_ != manager->NullKey()) { |
| 384 manager->Remove(renderer_manager_key_); | 388 manager->Remove(renderer_manager_key_); |
| 385 renderer_manager_key_ = manager->NullKey(); | 389 renderer_manager_key_ = manager->NullKey(); |
| 386 } | 390 } |
| 387 } | 391 } |
| 388 | 392 |
| 389 if (hardware_initialized) { | 393 if (has_received_frame_) { |
| 390 // Flush any invoke functors that's caused by ReleaseHardware. | 394 // Flush any invoke functors that's caused by ReleaseHardware. |
| 391 client_->RequestInvokeGL(true); | 395 client_->RequestInvokeGL(true); |
| 392 } | 396 } |
| 393 } | 397 } |
| 394 | 398 |
| 395 void RenderThreadManager::SetCompositorFrameProducer( | 399 void RenderThreadManager::SetCompositorFrameProducer( |
| 396 CompositorFrameProducer* compositor_frame_producer) { | 400 CompositorFrameProducer* compositor_frame_producer) { |
| 397 DCHECK(compositor_frame_producer == compositor_frame_producer_ || | 401 DCHECK(compositor_frame_producer == compositor_frame_producer_ || |
| 398 compositor_frame_producer_ == nullptr || | 402 compositor_frame_producer_ == nullptr || |
| 399 compositor_frame_producer == nullptr); | 403 compositor_frame_producer == nullptr); |
| 400 compositor_frame_producer_ = compositor_frame_producer; | 404 compositor_frame_producer_ = compositor_frame_producer; |
| 401 } | 405 } |
| 402 | 406 |
| 403 bool RenderThreadManager::HasFrameOnUI() const { | 407 bool RenderThreadManager::HasFrameOnUI() const { |
| 404 base::AutoLock lock(lock_); | 408 base::AutoLock lock(lock_); |
| 405 return hardware_renderer_has_frame_ || !child_frames_.empty(); | 409 return has_received_frame_; |
| 406 } | 410 } |
| 407 | 411 |
| 408 bool RenderThreadManager::HasFrameForHardwareRendererOnRT() const { | 412 bool RenderThreadManager::HasFrameForHardwareRendererOnRT() const { |
| 409 base::AutoLock lock(lock_); | 413 base::AutoLock lock(lock_); |
| 410 return !child_frames_.empty(); | 414 return !child_frames_.empty(); |
| 411 } | 415 } |
| 412 | 416 |
| 413 void RenderThreadManager::InitializeHardwareDrawIfNeededOnUI() { | 417 void RenderThreadManager::InitializeHardwareDrawIfNeededOnUI() { |
| 414 DCHECK(ui_loop_->BelongsToCurrentThread()); | 418 DCHECK(ui_loop_->BelongsToCurrentThread()); |
| 415 GLViewRendererManager* manager = GLViewRendererManager::GetInstance(); | 419 GLViewRendererManager* manager = GLViewRendererManager::GetInstance(); |
| 416 | 420 |
| 417 base::AutoLock lock(lock_); | 421 base::AutoLock lock(lock_); |
| 418 if (renderer_manager_key_ == manager->NullKey()) { | 422 if (renderer_manager_key_ == manager->NullKey()) { |
| 419 renderer_manager_key_ = manager->PushBack(this); | 423 renderer_manager_key_ = manager->PushBack(this); |
| 420 } | 424 } |
| 421 } | 425 } |
| 422 | 426 |
| 423 RenderThreadManager::InsideHardwareReleaseReset::InsideHardwareReleaseReset( | 427 RenderThreadManager::InsideHardwareReleaseReset::InsideHardwareReleaseReset( |
| 424 RenderThreadManager* render_thread_manager) | 428 RenderThreadManager* render_thread_manager) |
| 425 : render_thread_manager_(render_thread_manager) { | 429 : render_thread_manager_(render_thread_manager) { |
| 426 DCHECK(!render_thread_manager_->IsInsideHardwareRelease()); | 430 DCHECK(!render_thread_manager_->IsInsideHardwareRelease()); |
| 427 render_thread_manager_->SetInsideHardwareRelease(true); | 431 render_thread_manager_->SetInsideHardwareRelease(true); |
| 428 } | 432 } |
| 429 | 433 |
| 430 RenderThreadManager::InsideHardwareReleaseReset::~InsideHardwareReleaseReset() { | 434 RenderThreadManager::InsideHardwareReleaseReset::~InsideHardwareReleaseReset() { |
| 431 render_thread_manager_->SetInsideHardwareRelease(false); | 435 render_thread_manager_->SetInsideHardwareRelease(false); |
| 432 } | 436 } |
| 433 | 437 |
| 434 } // namespace android_webview | 438 } // namespace android_webview |
| OLD | NEW |