Commit c1e540d0 authored by boliu@chromium.org's avatar boliu@chromium.org

[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
parent 317caf49
...@@ -140,6 +140,9 @@ class BrowserViewRenderer { ...@@ -140,6 +140,9 @@ class BrowserViewRenderer {
virtual bool IsVisible() = 0; virtual bool IsVisible() = 0;
virtual gfx::Rect GetScreenRect() = 0; virtual gfx::Rect GetScreenRect() = 0;
// ComponentCallbacks2.onTrimMemory callback.
virtual void TrimMemory(int level) = 0;
virtual ~BrowserViewRenderer() {} virtual ~BrowserViewRenderer() {}
}; };
......
...@@ -19,7 +19,6 @@ ...@@ -19,7 +19,6 @@
#include "base/logging.h" #include "base/logging.h"
#include "base/strings/string_number_conversions.h" #include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.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/browser_thread.h"
#include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents.h"
#include "content/public/common/content_switches.h" #include "content/public/common/content_switches.h"
...@@ -316,6 +315,65 @@ bool InProcessViewRenderer::RequestProcessGL() { ...@@ -316,6 +315,65 @@ bool InProcessViewRenderer::RequestProcessGL() {
return client_->RequestDrawGL(NULL); 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() { void InProcessViewRenderer::UpdateCachedGlobalVisibleRect() {
client_->UpdateGlobalVisibleRect(); client_->UpdateGlobalVisibleRect();
} }
...@@ -423,7 +481,7 @@ void InProcessViewRenderer::DrawGL(AwDrawGLInfo* draw_info) { ...@@ -423,7 +481,7 @@ void InProcessViewRenderer::DrawGL(AwDrawGLInfo* draw_info) {
policy.bytes_limit = policy.bytes_limit =
(policy.bytes_limit / kMemoryAllocationStep + 1) * kMemoryAllocationStep; (policy.bytes_limit / kMemoryAllocationStep + 1) * kMemoryAllocationStep;
policy.num_resources_limit = kMaxNumTilesToFillDisplay * g_memory_multiplier; policy.num_resources_limit = kMaxNumTilesToFillDisplay * g_memory_multiplier;
compositor_->SetMemoryPolicy(policy); SetMemoryPolicy(policy);
DCHECK(gl_surface_); DCHECK(gl_surface_);
gl_surface_->SetBackingFrameBufferObject( gl_surface_->SetBackingFrameBufferObject(
...@@ -638,7 +696,7 @@ void InProcessViewRenderer::OnDetachedFromWindow() { ...@@ -638,7 +696,7 @@ void InProcessViewRenderer::OnDetachedFromWindow() {
DCHECK(compositor_); DCHECK(compositor_);
ScopedAppGLStateRestore state_restore( ScopedAppGLStateRestore state_restore(
ScopedAppGLStateRestore::MODE_DETACH_FROM_WINDOW); ScopedAppGLStateRestore::MODE_RESOURCE_MANAGEMENT);
gpu::InProcessCommandBuffer::ProcessGpuWorkOnCurrentThread(); gpu::InProcessCommandBuffer::ProcessGpuWorkOnCurrentThread();
ScopedAllowGL allow_gl; ScopedAllowGL allow_gl;
compositor_->ReleaseHwDraw(); compositor_->ReleaseHwDraw();
...@@ -869,11 +927,15 @@ void InProcessViewRenderer::FallbackTickFired() { ...@@ -869,11 +927,15 @@ void InProcessViewRenderer::FallbackTickFired() {
// This should only be called if OnDraw or DrawGL did not come in time, which // This should only be called if OnDraw or DrawGL did not come in time, which
// means block_invalidates_ must still be true. // means block_invalidates_ must still be true.
DCHECK(block_invalidates_); DCHECK(block_invalidates_);
if (compositor_needs_continuous_invalidate_ && compositor_) { if (compositor_needs_continuous_invalidate_ && compositor_)
SkBitmapDevice device(SkBitmap::kARGB_8888_Config, 1, 1); ForceFakeCompositeSW();
SkCanvas canvas(&device); }
CompositeSW(&canvas);
} void InProcessViewRenderer::ForceFakeCompositeSW() {
DCHECK(compositor_);
SkBitmapDevice device(SkBitmap::kARGB_8888_Config, 1, 1);
SkCanvas canvas(&device);
CompositeSW(&canvas);
} }
bool InProcessViewRenderer::CompositeSW(SkCanvas* canvas) { bool InProcessViewRenderer::CompositeSW(SkCanvas* canvas) {
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "android_webview/browser/browser_view_renderer.h" #include "android_webview/browser/browser_view_renderer.h"
#include "android_webview/browser/gl_view_renderer_manager.h" #include "android_webview/browser/gl_view_renderer_manager.h"
#include "base/cancelable_callback.h" #include "base/cancelable_callback.h"
#include "content/public/browser/android/synchronous_compositor.h"
#include "content/public/browser/android/synchronous_compositor_client.h" #include "content/public/browser/android/synchronous_compositor_client.h"
#include "ui/gfx/vector2d_f.h" #include "ui/gfx/vector2d_f.h"
...@@ -71,6 +72,7 @@ class InProcessViewRenderer : public BrowserViewRenderer, ...@@ -71,6 +72,7 @@ class InProcessViewRenderer : public BrowserViewRenderer,
virtual bool IsAttachedToWindow() OVERRIDE; virtual bool IsAttachedToWindow() OVERRIDE;
virtual bool IsVisible() OVERRIDE; virtual bool IsVisible() OVERRIDE;
virtual gfx::Rect GetScreenRect() OVERRIDE; virtual gfx::Rect GetScreenRect() OVERRIDE;
virtual void TrimMemory(int level) OVERRIDE;
// SynchronousCompositorClient overrides // SynchronousCompositorClient overrides
virtual void DidInitializeCompositor( virtual void DidInitializeCompositor(
...@@ -108,6 +110,7 @@ class InProcessViewRenderer : public BrowserViewRenderer, ...@@ -108,6 +110,7 @@ class InProcessViewRenderer : public BrowserViewRenderer,
// If we call up view invalidate and OnDraw is not called before a deadline, // 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. // then we keep ticking the SynchronousCompositor so it can make progress.
void FallbackTickFired(); void FallbackTickFired();
void ForceFakeCompositeSW();
void NoLongerExpectsDrawGL(); void NoLongerExpectsDrawGL();
...@@ -115,6 +118,8 @@ class InProcessViewRenderer : public BrowserViewRenderer, ...@@ -115,6 +118,8 @@ class InProcessViewRenderer : public BrowserViewRenderer,
gfx::Vector2d max_scroll_offset() const; gfx::Vector2d max_scroll_offset() const;
void SetMemoryPolicy(content::SynchronousCompositorMemoryPolicy& new_policy);
// For debug tracing or logging. Return the string representation of this // For debug tracing or logging. Return the string representation of this
// view renderer's state and the |draw_info| if provided. // view renderer's state and the |draw_info| if provided.
std::string ToString(AwDrawGLInfo* draw_info) const; std::string ToString(AwDrawGLInfo* draw_info) const;
...@@ -176,6 +181,8 @@ class InProcessViewRenderer : public BrowserViewRenderer, ...@@ -176,6 +181,8 @@ class InProcessViewRenderer : public BrowserViewRenderer,
GLViewRendererManager::Key manager_key_; GLViewRendererManager::Key manager_key_;
content::SynchronousCompositorMemoryPolicy memory_policy_;
DISALLOW_COPY_AND_ASSIGN(InProcessViewRenderer); DISALLOW_COPY_AND_ASSIGN(InProcessViewRenderer);
}; };
......
...@@ -64,7 +64,7 @@ ScopedAppGLStateRestore::ScopedAppGLStateRestore(CallMode mode) : mode_(mode) { ...@@ -64,7 +64,7 @@ ScopedAppGLStateRestore::ScopedAppGLStateRestore(CallMode mode) : mode_(mode) {
DCHECK_EQ(0, vertex_array_buffer_binding_); DCHECK_EQ(0, vertex_array_buffer_binding_);
DCHECK_EQ(0, index_array_buffer_binding_); DCHECK_EQ(0, index_array_buffer_binding_);
break; break;
case MODE_DETACH_FROM_WINDOW: case MODE_RESOURCE_MANAGEMENT:
glGetBooleanv(GL_BLEND, &blend_enabled_); glGetBooleanv(GL_BLEND, &blend_enabled_);
glGetIntegerv(GL_BLEND_SRC_RGB, &blend_src_rgb_); glGetIntegerv(GL_BLEND_SRC_RGB, &blend_src_rgb_);
glGetIntegerv(GL_BLEND_SRC_ALPHA, &blend_src_alpha_); glGetIntegerv(GL_BLEND_SRC_ALPHA, &blend_src_alpha_);
...@@ -205,17 +205,22 @@ ScopedAppGLStateRestore::~ScopedAppGLStateRestore() { ...@@ -205,17 +205,22 @@ ScopedAppGLStateRestore::~ScopedAppGLStateRestore() {
enable_sample_alpha_to_coverage_); enable_sample_alpha_to_coverage_);
GLEnableDisable(GL_SAMPLE_COVERAGE, enable_sample_coverage_); GLEnableDisable(GL_SAMPLE_COVERAGE, enable_sample_coverage_);
if (mode_ == MODE_DETACH_FROM_WINDOW) { switch(mode_) {
GLEnableDisable(GL_BLEND, blend_enabled_); case MODE_DRAW:
glBlendFuncSeparate( // No-op.
blend_src_rgb_, blend_dest_rgb_, blend_src_alpha_, blend_dest_alpha_); 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( glScissor(
scissor_box_[0], scissor_box_[1], scissor_box_[2], scissor_box_[3]); scissor_box_[0], scissor_box_[1], scissor_box_[2], scissor_box_[3]);
break;
} }
GLEnableDisable(GL_STENCIL_TEST, stencil_test_); GLEnableDisable(GL_STENCIL_TEST, stencil_test_);
......
...@@ -18,7 +18,7 @@ class ScopedAppGLStateRestore { ...@@ -18,7 +18,7 @@ class ScopedAppGLStateRestore {
public: public:
enum CallMode { enum CallMode {
MODE_DRAW, MODE_DRAW,
MODE_DETACH_FROM_WINDOW MODE_RESOURCE_MANAGEMENT,
}; };
ScopedAppGLStateRestore(CallMode mode); ScopedAppGLStateRestore(CallMode mode);
......
...@@ -4,6 +4,8 @@ ...@@ -4,6 +4,8 @@
package org.chromium.android_webview; package org.chromium.android_webview;
import android.content.ComponentCallbacks2;
import android.content.Context;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.content.res.Configuration; import android.content.res.Configuration;
import android.graphics.Bitmap; import android.graphics.Bitmap;
...@@ -193,6 +195,8 @@ public class AwContents { ...@@ -193,6 +195,8 @@ public class AwContents {
private AwAutofillManagerDelegate mAwAutofillManagerDelegate; private AwAutofillManagerDelegate mAwAutofillManagerDelegate;
private ComponentCallbacks2 mComponentCallbacks;
private static final class DestroyRunnable implements Runnable { private static final class DestroyRunnable implements Runnable {
private int mNativeAwContents; private int mNativeAwContents;
private DestroyRunnable(int nativeAwContents) { private DestroyRunnable(int nativeAwContents) {
...@@ -431,6 +435,22 @@ public class AwContents { ...@@ -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 browserContext the browsing context to associate this view contents with.
* @param containerView the view-hierarchy item this object will be bound to. * @param containerView the view-hierarchy item this object will be bound to.
...@@ -1480,6 +1500,10 @@ public class AwContents { ...@@ -1480,6 +1500,10 @@ public class AwContents {
mContentViewCore.onAttachedToWindow(); mContentViewCore.onAttachedToWindow();
nativeOnAttachedToWindow(mNativeAwContents, mContainerView.getWidth(), nativeOnAttachedToWindow(mNativeAwContents, mContainerView.getWidth(),
mContainerView.getHeight()); mContainerView.getHeight());
if (mComponentCallbacks != null) return;
mComponentCallbacks = new AwComponentCallbacks();
mContainerView.getContext().registerComponentCallbacks(mComponentCallbacks);
} }
/** /**
...@@ -1494,6 +1518,11 @@ public class AwContents { ...@@ -1494,6 +1518,11 @@ public class AwContents {
mContentViewCore.onDetachedFromWindow(); mContentViewCore.onDetachedFromWindow();
if (mComponentCallbacks != null) {
mContainerView.getContext().unregisterComponentCallbacks(mComponentCallbacks);
mComponentCallbacks = null;
}
if (mPendingDetachCleanupReferences != null) { if (mPendingDetachCleanupReferences != null) {
for (int i = 0; i < mPendingDetachCleanupReferences.size(); ++i) { for (int i = 0; i < mPendingDetachCleanupReferences.size(); ++i) {
mPendingDetachCleanupReferences.get(i).cleanupNow(); mPendingDetachCleanupReferences.get(i).cleanupNow();
...@@ -1967,4 +1996,6 @@ public class AwContents { ...@@ -1967,4 +1996,6 @@ public class AwContents {
int nativeAwContents, boolean value, String requestingFrame); int nativeAwContents, boolean value, String requestingFrame);
private native void nativeSetJsOnlineProperty(int nativeAwContents, boolean networkUp); private native void nativeSetJsOnlineProperty(int nativeAwContents, boolean networkUp);
private native void nativeTrimMemory(int nativeAwContents, int level);
} }
...@@ -898,4 +898,8 @@ void AwContents::SetJsOnlineProperty(JNIEnv* env, ...@@ -898,4 +898,8 @@ void AwContents::SetJsOnlineProperty(JNIEnv* env,
render_view_host_ext_->SetJsOnlineProperty(network_up); render_view_host_ext_->SetJsOnlineProperty(network_up);
} }
void AwContents::TrimMemory(JNIEnv* env, jobject obj, jint level) {
browser_view_renderer_->TrimMemory(level);
}
} // namespace android_webview } // namespace android_webview
...@@ -179,6 +179,7 @@ class AwContents : public FindHelper::Listener, ...@@ -179,6 +179,7 @@ class AwContents : public FindHelper::Listener,
void SetAwAutofillManagerDelegate(jobject delegate); void SetAwAutofillManagerDelegate(jobject delegate);
void SetJsOnlineProperty(JNIEnv* env, jobject obj, jboolean network_up); void SetJsOnlineProperty(JNIEnv* env, jobject obj, jboolean network_up);
void TrimMemory(JNIEnv* env, jobject obj, jint level);
private: private:
void InitAutofillIfNecessary(bool enabled); void InitAutofillIfNecessary(bool enabled);
......
...@@ -9,4 +9,15 @@ namespace content { ...@@ -9,4 +9,15 @@ namespace content {
SynchronousCompositorMemoryPolicy::SynchronousCompositorMemoryPolicy() SynchronousCompositorMemoryPolicy::SynchronousCompositorMemoryPolicy()
: bytes_limit(0), num_resources_limit(0) {} : 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 } // namespace content
...@@ -31,6 +31,9 @@ struct CONTENT_EXPORT SynchronousCompositorMemoryPolicy { ...@@ -31,6 +31,9 @@ struct CONTENT_EXPORT SynchronousCompositorMemoryPolicy {
size_t num_resources_limit; size_t num_resources_limit;
SynchronousCompositorMemoryPolicy(); SynchronousCompositorMemoryPolicy();
bool operator==(const SynchronousCompositorMemoryPolicy& other) const;
bool operator!=(const SynchronousCompositorMemoryPolicy& other) const;
}; };
// Interface for embedders that wish to direct compositing operations // Interface for embedders that wish to direct compositing operations
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment