summaryrefslogtreecommitdiffstats
path: root/android_webview/browser
diff options
context:
space:
mode:
authorhush <hush@chromium.org>2014-10-29 18:34:14 -0700
committerCommit bot <commit-bot@chromium.org>2014-10-30 01:34:29 +0000
commitc4a6fc020e5de65add90f1755519b4228036cbae (patch)
tree903ea21a79b54250f607e9545506d572adc1eba8 /android_webview/browser
parent03dbe8ae71dbf674627acad91fff64a2fa9d4eb6 (diff)
downloadchromium_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.cc12
-rw-r--r--android_webview/browser/browser_view_renderer.h1
-rw-r--r--android_webview/browser/browser_view_renderer_client.h4
-rw-r--r--android_webview/browser/hardware_renderer.cc2
-rw-r--r--android_webview/browser/shared_renderer_state.cc139
-rw-r--r--android_webview/browser/shared_renderer_state.h76
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_