summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorboliu@chromium.org <boliu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-10-03 01:08:15 +0000
committerboliu@chromium.org <boliu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-10-03 01:08:15 +0000
commitc1e540d03eda7b2273354ea91dd511711355228c (patch)
treec4dc6422255e96ef0d61dd84c07873fc18be2982
parent317caf49898fcc6bd3024b7627da535b9b157ab7 (diff)
downloadchromium_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
-rw-r--r--android_webview/browser/browser_view_renderer.h3
-rw-r--r--android_webview/browser/in_process_view_renderer.cc78
-rw-r--r--android_webview/browser/in_process_view_renderer.h7
-rw-r--r--android_webview/browser/scoped_app_gl_state_restore.cc23
-rw-r--r--android_webview/browser/scoped_app_gl_state_restore.h2
-rw-r--r--android_webview/java/src/org/chromium/android_webview/AwContents.java31
-rw-r--r--android_webview/native/aw_contents.cc4
-rw-r--r--android_webview/native/aw_contents.h1
-rw-r--r--content/public/browser/android/synchronous_compositor.cc11
-rw-r--r--content/public/browser/android/synchronous_compositor.h3
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