diff options
author | hush <hush@chromium.org> | 2014-10-29 18:34:14 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2014-10-30 01:34:29 +0000 |
commit | c4a6fc020e5de65add90f1755519b4228036cbae (patch) | |
tree | 903ea21a79b54250f607e9545506d572adc1eba8 /android_webview/browser | |
parent | 03dbe8ae71dbf674627acad91fff64a2fa9d4eb6 (diff) | |
download | chromium_src-c4a6fc020e5de65add90f1755519b4228036cbae.zip chromium_src-c4a6fc020e5de65add90f1755519b4228036cbae.tar.gz chromium_src-c4a6fc020e5de65add90f1755519b4228036cbae.tar.bz2 |
Part 2: Refactor Android WebView graphics code
1. Change the object ownership to be:
AwContents -> BrowserViewRenderer -> SharedRendererState ->
HardwareRenderer
(The left object owns the right object.)
2. Move DrawGL, InitializeHardwareIfNeeded, ReleaseHardwareIfNeeded from
AwContents to SharedRendererState.
BUG=418346
Review URL: https://codereview.chromium.org/653173004
Cr-Commit-Position: refs/heads/master@{#302011}
Diffstat (limited to 'android_webview/browser')
-rw-r--r-- | android_webview/browser/browser_view_renderer.cc | 12 | ||||
-rw-r--r-- | android_webview/browser/browser_view_renderer.h | 1 | ||||
-rw-r--r-- | android_webview/browser/browser_view_renderer_client.h | 4 | ||||
-rw-r--r-- | android_webview/browser/hardware_renderer.cc | 2 | ||||
-rw-r--r-- | android_webview/browser/shared_renderer_state.cc | 139 | ||||
-rw-r--r-- | android_webview/browser/shared_renderer_state.h | 76 |
6 files changed, 184 insertions, 50 deletions
diff --git a/android_webview/browser/browser_view_renderer.cc b/android_webview/browser/browser_view_renderer.cc index 51c62f8..df10d0b 100644 --- a/android_webview/browser/browser_view_renderer.cc +++ b/android_webview/browser/browser_view_renderer.cc @@ -273,6 +273,10 @@ void BrowserViewRenderer::DidSkipCommitFrame() { DidSkipCompositeInDraw(); } +void BrowserViewRenderer::InvalidateOnFunctorDestroy() { + client_->InvalidateOnFunctorDestroy(); +} + bool BrowserViewRenderer::OnDrawSoftware(jobject java_canvas) { if (!compositor_) { TRACE_EVENT_INSTANT0( @@ -395,11 +399,9 @@ void BrowserViewRenderer::OnDetachedFromWindow() { void BrowserViewRenderer::ReleaseHardware() { DCHECK(hardware_enabled_); - // TODO(hush): do this in somewhere else. Either in hardware render or in - // shared renderer state. - ReturnUnusedResource(shared_renderer_state_.PassCompositorFrame()); + ReturnUnusedResource(shared_renderer_state_.PassUncommittedFrameOnUI()); ReturnResourceFromParent(); - DCHECK(shared_renderer_state_.ReturnedResourcesEmpty()); + DCHECK(shared_renderer_state_.ReturnedResourcesEmptyOnUI()); if (compositor_) { compositor_->ReleaseHwDraw(); @@ -688,7 +690,7 @@ void BrowserViewRenderer::FallbackTickFired() { if (compositor_needs_continuous_invalidate_ && compositor_) { if (hardware_enabled_) { ReturnResourceFromParent(); - ReturnUnusedResource(shared_renderer_state_.PassCompositorFrame()); + ReturnUnusedResource(shared_renderer_state_.PassUncommittedFrameOnUI()); scoped_ptr<cc::CompositorFrame> frame = CompositeHw(); if (frame.get()) { shared_renderer_state_.SetCompositorFrameOnUI(frame.Pass(), true); diff --git a/android_webview/browser/browser_view_renderer.h b/android_webview/browser/browser_view_renderer.h index c2d44f1..4b40240 100644 --- a/android_webview/browser/browser_view_renderer.h +++ b/android_webview/browser/browser_view_renderer.h @@ -128,6 +128,7 @@ class BrowserViewRenderer : public content::SynchronousCompositorClient { void UpdateParentDrawConstraints(); void DidSkipCommitFrame(); + void InvalidateOnFunctorDestroy(); private: void SetTotalRootLayerScrollOffset(gfx::Vector2dF new_value_dip); diff --git a/android_webview/browser/browser_view_renderer_client.h b/android_webview/browser/browser_view_renderer_client.h index dfa5ff0..17d0dc4 100644 --- a/android_webview/browser/browser_view_renderer_client.h +++ b/android_webview/browser/browser_view_renderer_client.h @@ -27,6 +27,10 @@ class BrowserViewRendererClient { // Called to trigger view invalidations. virtual void PostInvalidate() = 0; + // Call postInvalidateOnAnimation for invalidations. This is only used to + // synchronize draw functor destruction. + virtual void InvalidateOnFunctorDestroy() = 0; + // Called to update the parent draw constraints in browser view renderer. virtual void UpdateParentDrawConstraints() = 0; diff --git a/android_webview/browser/hardware_renderer.cc b/android_webview/browser/hardware_renderer.cc index 75f712c..5af1109 100644 --- a/android_webview/browser/hardware_renderer.cc +++ b/android_webview/browser/hardware_renderer.cc @@ -150,7 +150,7 @@ void HardwareRenderer::CommitFrame() { return; } - committed_frame_ = shared_renderer_state_->PassCompositorFrame(); + committed_frame_ = shared_renderer_state_->PassCompositorFrameOnRT(); // Happens with empty global visible rect. if (!committed_frame_.get()) return; diff --git a/android_webview/browser/shared_renderer_state.cc b/android_webview/browser/shared_renderer_state.cc index da12c34..52e3479 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); } diff --git a/android_webview/browser/shared_renderer_state.h b/android_webview/browser/shared_renderer_state.h index 270d318..d0555b72 100644 --- a/android_webview/browser/shared_renderer_state.h +++ b/android_webview/browser/shared_renderer_state.h @@ -5,6 +5,7 @@ #ifndef ANDROID_WEBVIEW_BROWSER_SHARED_RENDERER_STATE_H_ #define ANDROID_WEBVIEW_BROWSER_SHARED_RENDERER_STATE_H_ +#include "android_webview/browser/gl_view_renderer_manager.h" #include "android_webview/browser/parent_compositor_draw_constraints.h" #include "base/cancelable_callback.h" #include "base/memory/weak_ptr.h" @@ -15,6 +16,8 @@ #include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/vector2d.h" +struct AwDrawGLInfo; + namespace android_webview { namespace internal { @@ -22,10 +25,10 @@ class RequestDrawGLTracker; } class BrowserViewRenderer; +class HardwareRenderer; class InsideHardwareReleaseReset; // This class is used to pass data between UI thread and RenderThread. -// TODO(hush): this class should own HardwareRenderer. class SharedRendererState { public: SharedRendererState( @@ -33,53 +36,72 @@ class SharedRendererState { BrowserViewRenderer* browser_view_renderer); ~SharedRendererState(); + // This function can be called from any thread. void ClientRequestDrawGL(); - void DidDrawGLProcess(); + // UI thread methods. void SetScrollOffsetOnUI(gfx::Vector2d scroll_offset); - gfx::Vector2d GetScrollOffsetOnRT(); - bool HasCompositorFrameOnUI() const; void SetCompositorFrameOnUI(scoped_ptr<cc::CompositorFrame> frame, bool force_commit); - // Right now this method is called on both UI and RT. - // TODO(hush): Make it only called from RT. - scoped_ptr<cc::CompositorFrame> PassCompositorFrame(); - bool ForceCommitOnRT() const; + void InitializeHardwareDrawIfNeededOnUI(); + void ReleaseHardwareDrawIfNeededOnUI(); + ParentCompositorDrawConstraints GetParentDrawConstraintsOnUI() const; + void SetForceInvalidateOnNextDrawGLOnUI( + bool needs_force_invalidate_on_next_draw_gl); + bool NeedsForceInvalidateOnNextDrawGLOnUI() const; + void SwapReturnedResourcesOnUI(cc::ReturnedResourceArray* resources); + bool ReturnedResourcesEmptyOnUI() const; + scoped_ptr<cc::CompositorFrame> PassUncommittedFrameOnUI(); - // TODO(hush): this will be private after DrawGL moves to this class. - bool IsInsideHardwareRelease() const; + // RT thread methods. + gfx::Vector2d GetScrollOffsetOnRT(); + scoped_ptr<cc::CompositorFrame> PassCompositorFrameOnRT(); + bool ForceCommitOnRT() const; + void DrawGL(AwDrawGLInfo* draw_info); // Returns true if the draw constraints are updated. bool UpdateDrawConstraintsOnRT( const ParentCompositorDrawConstraints& parent_draw_constraints); void PostExternalDrawConstraintsToChildCompositorOnRT( const ParentCompositorDrawConstraints& parent_draw_constraints); - ParentCompositorDrawConstraints GetParentDrawConstraintsOnUI() const; - void DidSkipCommitFrameOnRT(); - void SetForceInvalidateOnNextDrawGLOnUI( - bool needs_force_invalidate_on_next_draw_gl); - bool NeedsForceInvalidateOnNextDrawGLOnUI() const; - void InsertReturnedResourcesOnRT(const cc::ReturnedResourceArray& resources); - void SwapReturnedResourcesOnUI(cc::ReturnedResourceArray* resources); - bool ReturnedResourcesEmpty() const; private: - friend class InsideHardwareReleaseReset; friend class internal::RequestDrawGLTracker; + class InsideHardwareReleaseReset { + public: + explicit InsideHardwareReleaseReset( + SharedRendererState* shared_renderer_state); + ~InsideHardwareReleaseReset(); + private: + SharedRendererState* shared_renderer_state_; + }; + + // RT thread method. + void DidDrawGLProcess(); + + // UI thread methods. void ResetRequestDrawGLCallback(); - void ClientRequestDrawGLOnUIThread(); - void UpdateParentDrawConstraintsOnUIThread(); + void ClientRequestDrawGLOnUI(); + void UpdateParentDrawConstraintsOnUI(); void DidSkipCommitFrameOnUI(); + bool IsInsideHardwareRelease() const; void SetInsideHardwareRelease(bool inside); + // Accessed by UI thread. scoped_refptr<base::SingleThreadTaskRunner> ui_loop_; BrowserViewRenderer* browser_view_renderer_; base::WeakPtr<SharedRendererState> ui_thread_weak_ptr_; base::CancelableClosure request_draw_gl_cancelable_closure_; + // Accessed by RT thread. + scoped_ptr<HardwareRenderer> hardware_renderer_; + + // This is accessed by both UI and RT now. TODO(hush): move to RT only. + GLViewRendererManager::Key renderer_manager_key_; + // Accessed by both UI and RT thread. mutable base::Lock lock_; gfx::Vector2d scroll_offset_; @@ -96,18 +118,6 @@ class SharedRendererState { DISALLOW_COPY_AND_ASSIGN(SharedRendererState); }; -class InsideHardwareReleaseReset { - public: - explicit InsideHardwareReleaseReset( - SharedRendererState* shared_renderer_state); - ~InsideHardwareReleaseReset(); - - private: - SharedRendererState* shared_renderer_state_; - - DISALLOW_COPY_AND_ASSIGN(InsideHardwareReleaseReset); -}; - } // namespace android_webview #endif // ANDROID_WEBVIEW_BROWSER_SHARED_RENDERER_STATE_H_ |