diff options
author | boliu@chromium.org <boliu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-10-03 01:08:15 +0000 |
---|---|---|
committer | boliu@chromium.org <boliu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-10-03 01:08:15 +0000 |
commit | c1e540d03eda7b2273354ea91dd511711355228c (patch) | |
tree | c4dc6422255e96ef0d61dd84c07873fc18be2982 | |
parent | 317caf49898fcc6bd3024b7627da535b9b157ab7 (diff) | |
download | chromium_src-c1e540d03eda7b2273354ea91dd511711355228c.zip chromium_src-c1e540d03eda7b2273354ea91dd511711355228c.tar.gz chromium_src-c1e540d03eda7b2273354ea91dd511711355228c.tar.bz2 |
[Android WebView] OnMemoryPressure to drop tile memory
In OnMemoryPressure, drop tiles on invisible browser views.
Not reusing base::MemoryPressureListener because Android
WebView requires onTrimMemory to be called synchronously.
BUG=
NOTRY=true
Review URL: https://codereview.chromium.org/25082006
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@226643 0039d316-1c4b-4281-b951-d872f2087c98
10 files changed, 145 insertions, 18 deletions
diff --git a/android_webview/browser/browser_view_renderer.h b/android_webview/browser/browser_view_renderer.h index 0ae9538..73c48b9 100644 --- a/android_webview/browser/browser_view_renderer.h +++ b/android_webview/browser/browser_view_renderer.h @@ -140,6 +140,9 @@ class BrowserViewRenderer { virtual bool IsVisible() = 0; virtual gfx::Rect GetScreenRect() = 0; + // ComponentCallbacks2.onTrimMemory callback. + virtual void TrimMemory(int level) = 0; + virtual ~BrowserViewRenderer() {} }; diff --git a/android_webview/browser/in_process_view_renderer.cc b/android_webview/browser/in_process_view_renderer.cc index 39bd2f6..a41644d 100644 --- a/android_webview/browser/in_process_view_renderer.cc +++ b/android_webview/browser/in_process_view_renderer.cc @@ -19,7 +19,6 @@ #include "base/logging.h" #include "base/strings/string_number_conversions.h" #include "base/strings/stringprintf.h" -#include "content/public/browser/android/synchronous_compositor.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/web_contents.h" #include "content/public/common/content_switches.h" @@ -316,6 +315,65 @@ bool InProcessViewRenderer::RequestProcessGL() { return client_->RequestDrawGL(NULL); } +void InProcessViewRenderer::TrimMemory(int level) { + // Constants from Android ComponentCallbacks2. + enum { + TRIM_MEMORY_RUNNING_LOW = 10, + TRIM_MEMORY_UI_HIDDEN = 20, + TRIM_MEMORY_BACKGROUND = 40, + }; + + // Not urgent enough. TRIM_MEMORY_UI_HIDDEN is treated specially because + // it does not indicate memory pressure, but merely that the app is + // backgrounded. + if (level < TRIM_MEMORY_RUNNING_LOW || level == TRIM_MEMORY_UI_HIDDEN) + return; + + // Nothing to drop. + if (!attached_to_window_ || !hardware_initialized_ || !compositor_) + return; + + // Do not release resources on view we expect to get DrawGL soon. + if (level < TRIM_MEMORY_BACKGROUND) { + client_->UpdateGlobalVisibleRect(); + if (view_visible_ && window_visible_ && + !cached_global_visible_rect_.IsEmpty()) { + return; + } + } + + if (!eglGetCurrentContext()) { + NOTREACHED(); + return; + } + + // Just set the memory limit to 0 and drop all tiles. This will be reset to + // normal levels in the next DrawGL call. + content::SynchronousCompositorMemoryPolicy policy; + policy.bytes_limit = 0; + policy.num_resources_limit = 0; + if (memory_policy_ == policy) + return; + + TRACE_EVENT0("android_webview", "InProcessViewRenderer::TrimMemory"); + ScopedAppGLStateRestore state_restore( + ScopedAppGLStateRestore::MODE_RESOURCE_MANAGEMENT); + gpu::InProcessCommandBuffer::ProcessGpuWorkOnCurrentThread(); + ScopedAllowGL allow_gl; + + SetMemoryPolicy(policy); + ForceFakeCompositeSW(); +} + +void InProcessViewRenderer::SetMemoryPolicy( + content::SynchronousCompositorMemoryPolicy& new_policy) { + if (memory_policy_ == new_policy) + return; + + memory_policy_ = new_policy; + compositor_->SetMemoryPolicy(memory_policy_); +} + void InProcessViewRenderer::UpdateCachedGlobalVisibleRect() { client_->UpdateGlobalVisibleRect(); } @@ -423,7 +481,7 @@ void InProcessViewRenderer::DrawGL(AwDrawGLInfo* draw_info) { policy.bytes_limit = (policy.bytes_limit / kMemoryAllocationStep + 1) * kMemoryAllocationStep; policy.num_resources_limit = kMaxNumTilesToFillDisplay * g_memory_multiplier; - compositor_->SetMemoryPolicy(policy); + SetMemoryPolicy(policy); DCHECK(gl_surface_); gl_surface_->SetBackingFrameBufferObject( @@ -638,7 +696,7 @@ void InProcessViewRenderer::OnDetachedFromWindow() { DCHECK(compositor_); ScopedAppGLStateRestore state_restore( - ScopedAppGLStateRestore::MODE_DETACH_FROM_WINDOW); + ScopedAppGLStateRestore::MODE_RESOURCE_MANAGEMENT); gpu::InProcessCommandBuffer::ProcessGpuWorkOnCurrentThread(); ScopedAllowGL allow_gl; compositor_->ReleaseHwDraw(); @@ -869,11 +927,15 @@ void InProcessViewRenderer::FallbackTickFired() { // This should only be called if OnDraw or DrawGL did not come in time, which // means block_invalidates_ must still be true. DCHECK(block_invalidates_); - if (compositor_needs_continuous_invalidate_ && compositor_) { - SkBitmapDevice device(SkBitmap::kARGB_8888_Config, 1, 1); - SkCanvas canvas(&device); - CompositeSW(&canvas); - } + if (compositor_needs_continuous_invalidate_ && compositor_) + ForceFakeCompositeSW(); +} + +void InProcessViewRenderer::ForceFakeCompositeSW() { + DCHECK(compositor_); + SkBitmapDevice device(SkBitmap::kARGB_8888_Config, 1, 1); + SkCanvas canvas(&device); + CompositeSW(&canvas); } bool InProcessViewRenderer::CompositeSW(SkCanvas* canvas) { diff --git a/android_webview/browser/in_process_view_renderer.h b/android_webview/browser/in_process_view_renderer.h index ce5c584..42eac24 100644 --- a/android_webview/browser/in_process_view_renderer.h +++ b/android_webview/browser/in_process_view_renderer.h @@ -10,6 +10,7 @@ #include "android_webview/browser/browser_view_renderer.h" #include "android_webview/browser/gl_view_renderer_manager.h" #include "base/cancelable_callback.h" +#include "content/public/browser/android/synchronous_compositor.h" #include "content/public/browser/android/synchronous_compositor_client.h" #include "ui/gfx/vector2d_f.h" @@ -71,6 +72,7 @@ class InProcessViewRenderer : public BrowserViewRenderer, virtual bool IsAttachedToWindow() OVERRIDE; virtual bool IsVisible() OVERRIDE; virtual gfx::Rect GetScreenRect() OVERRIDE; + virtual void TrimMemory(int level) OVERRIDE; // SynchronousCompositorClient overrides virtual void DidInitializeCompositor( @@ -108,6 +110,7 @@ class InProcessViewRenderer : public BrowserViewRenderer, // If we call up view invalidate and OnDraw is not called before a deadline, // then we keep ticking the SynchronousCompositor so it can make progress. void FallbackTickFired(); + void ForceFakeCompositeSW(); void NoLongerExpectsDrawGL(); @@ -115,6 +118,8 @@ class InProcessViewRenderer : public BrowserViewRenderer, gfx::Vector2d max_scroll_offset() const; + void SetMemoryPolicy(content::SynchronousCompositorMemoryPolicy& new_policy); + // For debug tracing or logging. Return the string representation of this // view renderer's state and the |draw_info| if provided. std::string ToString(AwDrawGLInfo* draw_info) const; @@ -176,6 +181,8 @@ class InProcessViewRenderer : public BrowserViewRenderer, GLViewRendererManager::Key manager_key_; + content::SynchronousCompositorMemoryPolicy memory_policy_; + DISALLOW_COPY_AND_ASSIGN(InProcessViewRenderer); }; diff --git a/android_webview/browser/scoped_app_gl_state_restore.cc b/android_webview/browser/scoped_app_gl_state_restore.cc index f72c1b4..6f71eee 100644 --- a/android_webview/browser/scoped_app_gl_state_restore.cc +++ b/android_webview/browser/scoped_app_gl_state_restore.cc @@ -64,7 +64,7 @@ ScopedAppGLStateRestore::ScopedAppGLStateRestore(CallMode mode) : mode_(mode) { DCHECK_EQ(0, vertex_array_buffer_binding_); DCHECK_EQ(0, index_array_buffer_binding_); break; - case MODE_DETACH_FROM_WINDOW: + case MODE_RESOURCE_MANAGEMENT: glGetBooleanv(GL_BLEND, &blend_enabled_); glGetIntegerv(GL_BLEND_SRC_RGB, &blend_src_rgb_); glGetIntegerv(GL_BLEND_SRC_ALPHA, &blend_src_alpha_); @@ -205,17 +205,22 @@ ScopedAppGLStateRestore::~ScopedAppGLStateRestore() { enable_sample_alpha_to_coverage_); GLEnableDisable(GL_SAMPLE_COVERAGE, enable_sample_coverage_); - if (mode_ == MODE_DETACH_FROM_WINDOW) { - GLEnableDisable(GL_BLEND, blend_enabled_); - glBlendFuncSeparate( - blend_src_rgb_, blend_dest_rgb_, blend_src_alpha_, blend_dest_alpha_); + switch(mode_) { + case MODE_DRAW: + // No-op. + break; + case MODE_RESOURCE_MANAGEMENT: + GLEnableDisable(GL_BLEND, blend_enabled_); + glBlendFuncSeparate( + blend_src_rgb_, blend_dest_rgb_, blend_src_alpha_, blend_dest_alpha_); - glViewport(viewport_[0], viewport_[1], viewport_[2], viewport_[3]); + glViewport(viewport_[0], viewport_[1], viewport_[2], viewport_[3]); - GLEnableDisable(GL_SCISSOR_TEST, scissor_test_); + GLEnableDisable(GL_SCISSOR_TEST, scissor_test_); - glScissor( - scissor_box_[0], scissor_box_[1], scissor_box_[2], scissor_box_[3]); + glScissor( + scissor_box_[0], scissor_box_[1], scissor_box_[2], scissor_box_[3]); + break; } GLEnableDisable(GL_STENCIL_TEST, stencil_test_); diff --git a/android_webview/browser/scoped_app_gl_state_restore.h b/android_webview/browser/scoped_app_gl_state_restore.h index 93b5ad5..a6e1b93 100644 --- a/android_webview/browser/scoped_app_gl_state_restore.h +++ b/android_webview/browser/scoped_app_gl_state_restore.h @@ -18,7 +18,7 @@ class ScopedAppGLStateRestore { public: enum CallMode { MODE_DRAW, - MODE_DETACH_FROM_WINDOW + MODE_RESOURCE_MANAGEMENT, }; ScopedAppGLStateRestore(CallMode mode); diff --git a/android_webview/java/src/org/chromium/android_webview/AwContents.java b/android_webview/java/src/org/chromium/android_webview/AwContents.java index f0f286f..08f191d 100644 --- a/android_webview/java/src/org/chromium/android_webview/AwContents.java +++ b/android_webview/java/src/org/chromium/android_webview/AwContents.java @@ -4,6 +4,8 @@ package org.chromium.android_webview; +import android.content.ComponentCallbacks2; +import android.content.Context; import android.content.pm.PackageManager; import android.content.res.Configuration; import android.graphics.Bitmap; @@ -193,6 +195,8 @@ public class AwContents { private AwAutofillManagerDelegate mAwAutofillManagerDelegate; + private ComponentCallbacks2 mComponentCallbacks; + private static final class DestroyRunnable implements Runnable { private int mNativeAwContents; private DestroyRunnable(int nativeAwContents) { @@ -431,6 +435,22 @@ public class AwContents { } } + private class AwComponentCallbacks implements ComponentCallbacks2 { + @Override + public void onTrimMemory(int level) { + if (mNativeAwContents == 0) return; + nativeTrimMemory(mNativeAwContents, level); + } + + @Override + public void onLowMemory() { + } + + @Override + public void onConfigurationChanged(Configuration configuration) { + } + }; + /** * @param browserContext the browsing context to associate this view contents with. * @param containerView the view-hierarchy item this object will be bound to. @@ -1480,6 +1500,10 @@ public class AwContents { mContentViewCore.onAttachedToWindow(); nativeOnAttachedToWindow(mNativeAwContents, mContainerView.getWidth(), mContainerView.getHeight()); + + if (mComponentCallbacks != null) return; + mComponentCallbacks = new AwComponentCallbacks(); + mContainerView.getContext().registerComponentCallbacks(mComponentCallbacks); } /** @@ -1494,6 +1518,11 @@ public class AwContents { mContentViewCore.onDetachedFromWindow(); + if (mComponentCallbacks != null) { + mContainerView.getContext().unregisterComponentCallbacks(mComponentCallbacks); + mComponentCallbacks = null; + } + if (mPendingDetachCleanupReferences != null) { for (int i = 0; i < mPendingDetachCleanupReferences.size(); ++i) { mPendingDetachCleanupReferences.get(i).cleanupNow(); @@ -1967,4 +1996,6 @@ public class AwContents { int nativeAwContents, boolean value, String requestingFrame); private native void nativeSetJsOnlineProperty(int nativeAwContents, boolean networkUp); + + private native void nativeTrimMemory(int nativeAwContents, int level); } diff --git a/android_webview/native/aw_contents.cc b/android_webview/native/aw_contents.cc index 9108f3a..bbf71c2 100644 --- a/android_webview/native/aw_contents.cc +++ b/android_webview/native/aw_contents.cc @@ -898,4 +898,8 @@ void AwContents::SetJsOnlineProperty(JNIEnv* env, render_view_host_ext_->SetJsOnlineProperty(network_up); } +void AwContents::TrimMemory(JNIEnv* env, jobject obj, jint level) { + browser_view_renderer_->TrimMemory(level); +} + } // namespace android_webview diff --git a/android_webview/native/aw_contents.h b/android_webview/native/aw_contents.h index 1afc409..a27ced9 100644 --- a/android_webview/native/aw_contents.h +++ b/android_webview/native/aw_contents.h @@ -179,6 +179,7 @@ class AwContents : public FindHelper::Listener, void SetAwAutofillManagerDelegate(jobject delegate); void SetJsOnlineProperty(JNIEnv* env, jobject obj, jboolean network_up); + void TrimMemory(JNIEnv* env, jobject obj, jint level); private: void InitAutofillIfNecessary(bool enabled); diff --git a/content/public/browser/android/synchronous_compositor.cc b/content/public/browser/android/synchronous_compositor.cc index 051aa5b..25c4dc4 100644 --- a/content/public/browser/android/synchronous_compositor.cc +++ b/content/public/browser/android/synchronous_compositor.cc @@ -9,4 +9,15 @@ namespace content { SynchronousCompositorMemoryPolicy::SynchronousCompositorMemoryPolicy() : bytes_limit(0), num_resources_limit(0) {} +bool SynchronousCompositorMemoryPolicy::operator==( + const SynchronousCompositorMemoryPolicy& other) const { + return bytes_limit == other.bytes_limit && + num_resources_limit == other.num_resources_limit; +} + +bool SynchronousCompositorMemoryPolicy::operator!=( + const SynchronousCompositorMemoryPolicy& other) const { + return !(*this == other); +} + } // namespace content diff --git a/content/public/browser/android/synchronous_compositor.h b/content/public/browser/android/synchronous_compositor.h index 45b01eb..c77d2a8 100644 --- a/content/public/browser/android/synchronous_compositor.h +++ b/content/public/browser/android/synchronous_compositor.h @@ -31,6 +31,9 @@ struct CONTENT_EXPORT SynchronousCompositorMemoryPolicy { size_t num_resources_limit; SynchronousCompositorMemoryPolicy(); + + bool operator==(const SynchronousCompositorMemoryPolicy& other) const; + bool operator!=(const SynchronousCompositorMemoryPolicy& other) const; }; // Interface for embedders that wish to direct compositing operations |