Index: android_webview/browser/shared_renderer_state.cc |
diff --git a/android_webview/browser/shared_renderer_state.cc b/android_webview/browser/shared_renderer_state.cc |
index da12c34f993b8792857b7d9ea07013bd2f274dc6..52e34791615dbc6e43707b6a7c792420ceb9b426 100644 |
--- a/android_webview/browser/shared_renderer_state.cc |
+++ b/android_webview/browser/shared_renderer_state.cc |
@@ -5,6 +5,10 @@ |
#include "android_webview/browser/shared_renderer_state.h" |
#include "android_webview/browser/browser_view_renderer.h" |
+#include "android_webview/browser/deferred_gpu_command_service.h" |
+#include "android_webview/browser/hardware_renderer.h" |
+#include "android_webview/browser/scoped_app_gl_state_restore.h" |
+#include "android_webview/public/browser/draw_gl.h" |
#include "base/bind.h" |
#include "base/lazy_instance.h" |
#include "base/location.h" |
@@ -72,6 +76,7 @@ SharedRendererState::SharedRendererState( |
BrowserViewRenderer* browser_view_renderer) |
: ui_loop_(ui_loop), |
browser_view_renderer_(browser_view_renderer), |
+ renderer_manager_key_(GLViewRendererManager::GetInstance()->NullKey()), |
force_commit_(false), |
inside_hardware_release_(false), |
needs_force_invalidate_on_next_draw_gl_(false), |
@@ -84,13 +89,14 @@ SharedRendererState::SharedRendererState( |
SharedRendererState::~SharedRendererState() { |
DCHECK(ui_loop_->BelongsToCurrentThread()); |
+ DCHECK(!hardware_renderer_.get()); |
} |
void SharedRendererState::ClientRequestDrawGL() { |
if (ui_loop_->BelongsToCurrentThread()) { |
if (!g_request_draw_gl_tracker.Get().ShouldRequestOnUiThread(this)) |
return; |
- ClientRequestDrawGLOnUIThread(); |
+ ClientRequestDrawGLOnUI(); |
} else { |
if (!g_request_draw_gl_tracker.Get().ShouldRequestOnNonUiThread(this)) |
return; |
@@ -110,13 +116,12 @@ void SharedRendererState::DidDrawGLProcess() { |
void SharedRendererState::ResetRequestDrawGLCallback() { |
DCHECK(ui_loop_->BelongsToCurrentThread()); |
base::AutoLock lock(lock_); |
- request_draw_gl_cancelable_closure_.Reset( |
- base::Bind(&SharedRendererState::ClientRequestDrawGLOnUIThread, |
- base::Unretained(this))); |
+ request_draw_gl_cancelable_closure_.Reset(base::Bind( |
+ &SharedRendererState::ClientRequestDrawGLOnUI, base::Unretained(this))); |
request_draw_gl_closure_ = request_draw_gl_cancelable_closure_.callback(); |
} |
-void SharedRendererState::ClientRequestDrawGLOnUIThread() { |
+void SharedRendererState::ClientRequestDrawGLOnUI() { |
DCHECK(ui_loop_->BelongsToCurrentThread()); |
ResetRequestDrawGLCallback(); |
if (!browser_view_renderer_->RequestDrawGL(false)) { |
@@ -125,7 +130,7 @@ void SharedRendererState::ClientRequestDrawGLOnUIThread() { |
} |
} |
-void SharedRendererState::UpdateParentDrawConstraintsOnUIThread() { |
+void SharedRendererState::UpdateParentDrawConstraintsOnUI() { |
DCHECK(ui_loop_->BelongsToCurrentThread()); |
browser_view_renderer_->UpdateParentDrawConstraints(); |
} |
@@ -154,7 +159,13 @@ void SharedRendererState::SetCompositorFrameOnUI( |
force_commit_ = force_commit; |
} |
-scoped_ptr<cc::CompositorFrame> SharedRendererState::PassCompositorFrame() { |
+scoped_ptr<cc::CompositorFrame> SharedRendererState::PassCompositorFrameOnRT() { |
+ base::AutoLock lock(lock_); |
+ return compositor_frame_.Pass(); |
+} |
+ |
+scoped_ptr<cc::CompositorFrame> |
+SharedRendererState::PassUncommittedFrameOnUI() { |
base::AutoLock lock(lock_); |
return compositor_frame_.Pass(); |
} |
@@ -182,7 +193,7 @@ void SharedRendererState::PostExternalDrawConstraintsToChildCompositorOnRT( |
// No need to hold the lock_ during the post task. |
ui_loop_->PostTask( |
FROM_HERE, |
- base::Bind(&SharedRendererState::UpdateParentDrawConstraintsOnUIThread, |
+ base::Bind(&SharedRendererState::UpdateParentDrawConstraintsOnUI, |
ui_thread_weak_ptr_)); |
} |
} |
@@ -240,19 +251,125 @@ void SharedRendererState::SwapReturnedResourcesOnUI( |
resources->swap(returned_resources_); |
} |
-bool SharedRendererState::ReturnedResourcesEmpty() const { |
+bool SharedRendererState::ReturnedResourcesEmptyOnUI() const { |
base::AutoLock lock(lock_); |
return returned_resources_.empty(); |
} |
-InsideHardwareReleaseReset::InsideHardwareReleaseReset( |
+void SharedRendererState::DrawGL(AwDrawGLInfo* draw_info) { |
+ if (draw_info->mode == AwDrawGLInfo::kModeSync) { |
+ if (hardware_renderer_) |
+ hardware_renderer_->CommitFrame(); |
+ return; |
+ } |
+ |
+ { |
+ GLViewRendererManager* manager = GLViewRendererManager::GetInstance(); |
+ base::AutoLock lock(lock_); |
+ if (renderer_manager_key_ != manager->NullKey()) { |
+ manager->DidDrawGL(renderer_manager_key_); |
+ } |
+ } |
+ |
+ ScopedAppGLStateRestore state_restore( |
+ draw_info->mode == AwDrawGLInfo::kModeDraw |
+ ? ScopedAppGLStateRestore::MODE_DRAW |
+ : ScopedAppGLStateRestore::MODE_RESOURCE_MANAGEMENT); |
+ ScopedAllowGL allow_gl; |
+ |
+ if (draw_info->mode == AwDrawGLInfo::kModeProcessNoContext) { |
+ LOG(ERROR) << "Received unexpected kModeProcessNoContext"; |
+ } |
+ |
+ // kModeProcessNoContext should never happen because we tear down hardware |
+ // in onTrimMemory. However that guarantee is maintained outside of chromium |
+ // code. Not notifying shared state in kModeProcessNoContext can lead to |
+ // immediate deadlock, which is slightly more catastrophic than leaks or |
+ // corruption. |
+ if (draw_info->mode == AwDrawGLInfo::kModeProcess || |
+ draw_info->mode == AwDrawGLInfo::kModeProcessNoContext) { |
+ DidDrawGLProcess(); |
+ } |
+ |
+ if (IsInsideHardwareRelease()) { |
+ hardware_renderer_.reset(); |
+ // Flush the idle queue in tear down. |
+ DeferredGpuCommandService::GetInstance()->PerformAllIdleWork(); |
+ return; |
+ } |
+ |
+ if (draw_info->mode != AwDrawGLInfo::kModeDraw) { |
+ if (draw_info->mode == AwDrawGLInfo::kModeProcess) { |
+ DeferredGpuCommandService::GetInstance()->PerformIdleWork(true); |
+ } |
+ return; |
+ } |
+ |
+ if (!hardware_renderer_) { |
+ hardware_renderer_.reset(new HardwareRenderer(this)); |
+ hardware_renderer_->CommitFrame(); |
+ } |
+ |
+ hardware_renderer_->DrawGL(state_restore.stencil_enabled(), |
+ state_restore.framebuffer_binding_ext(), |
+ draw_info); |
+ DeferredGpuCommandService::GetInstance()->PerformIdleWork(false); |
+} |
+ |
+void SharedRendererState::ReleaseHardwareDrawIfNeededOnUI() { |
+ DCHECK(ui_loop_->BelongsToCurrentThread()); |
+ InsideHardwareReleaseReset auto_inside_hardware_release_reset(this); |
+ |
+ browser_view_renderer_->InvalidateOnFunctorDestroy(); |
+ bool hardware_initialized = browser_view_renderer_->hardware_enabled(); |
+ if (hardware_initialized) { |
+ bool draw_functor_succeeded = browser_view_renderer_->RequestDrawGL(true); |
+ if (!draw_functor_succeeded) { |
+ LOG(ERROR) << "Unable to free GL resources. Has the Window leaked?"; |
+ // Calling release on wrong thread intentionally. |
+ AwDrawGLInfo info; |
+ info.mode = AwDrawGLInfo::kModeProcess; |
+ DrawGL(&info); |
+ } |
+ |
+ browser_view_renderer_->ReleaseHardware(); |
+ } |
+ |
+ GLViewRendererManager* manager = GLViewRendererManager::GetInstance(); |
+ |
+ { |
+ base::AutoLock lock(lock_); |
+ if (renderer_manager_key_ != manager->NullKey()) { |
+ manager->Remove(renderer_manager_key_); |
+ renderer_manager_key_ = manager->NullKey(); |
+ } |
+ } |
+ |
+ if (hardware_initialized) { |
+ // Flush any invoke functors that's caused by ReleaseHardware. |
+ browser_view_renderer_->RequestDrawGL(true); |
+ } |
+} |
+ |
+void SharedRendererState::InitializeHardwareDrawIfNeededOnUI() { |
+ DCHECK(ui_loop_->BelongsToCurrentThread()); |
+ GLViewRendererManager* manager = GLViewRendererManager::GetInstance(); |
+ |
+ base::AutoLock lock(lock_); |
+ if (renderer_manager_key_ == manager->NullKey()) { |
+ renderer_manager_key_ = manager->PushBack(this); |
+ DeferredGpuCommandService::SetInstance(); |
+ } |
+} |
+ |
+SharedRendererState::InsideHardwareReleaseReset::InsideHardwareReleaseReset( |
SharedRendererState* shared_renderer_state) |
: shared_renderer_state_(shared_renderer_state) { |
DCHECK(!shared_renderer_state_->IsInsideHardwareRelease()); |
shared_renderer_state_->SetInsideHardwareRelease(true); |
} |
-InsideHardwareReleaseReset::~InsideHardwareReleaseReset() { |
+SharedRendererState::InsideHardwareReleaseReset::~InsideHardwareReleaseReset() { |
shared_renderer_state_->SetInsideHardwareRelease(false); |
} |