Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(658)

Unified Diff: android_webview/browser/browser_view_renderer.cc

Issue 226363004: Global GPU memory manager for android webview (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Remove unnecessary code Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: android_webview/browser/browser_view_renderer.cc
diff --git a/android_webview/browser/browser_view_renderer.cc b/android_webview/browser/browser_view_renderer.cc
index 937ed13259c1de75bde6d7c190b38566373c5351..48c2a3e45b96387663584e2ab0733f9dca879bfb 100644
--- a/android_webview/browser/browser_view_renderer.cc
+++ b/android_webview/browser/browser_view_renderer.cc
@@ -13,6 +13,7 @@
#include "base/logging.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 "third_party/skia/include/core/SkBitmap.h"
#include "third_party/skia/include/core/SkCanvas.h"
@@ -22,13 +23,26 @@
using base::android::AttachCurrentThread;
using base::android::JavaRef;
using base::android::ScopedJavaLocalRef;
-
+using content::BrowserThread;
namespace android_webview {
namespace {
const int64 kFallbackTickTimeoutInMilliseconds = 20;
+// Used to calculate memory and resource allocation. Determined experimentally.
+const size_t kMemoryMultiplier = 10;
+const size_t kNumGrallocLimit = 150;
+const size_t kBytesPerPixel = 4;
+const size_t kMemoryAllocationStep = 5 * 1024 * 1024;
+// Needs |kNumGrallocLimit| tiles to draw quickly, but it will be resource
+// hungry if it only gets allocated less than |kGrallocHungryLimit|.
+const size_t kGrallocHungryLimit = 100;
+// Becomes starved if the resource request cannot be granted kStarvedTimes in a
boliu 2014/04/28 22:22:15 heh, hungry -> starved, actually makes sense
+// row.
+const size_t kStarvedTimes = 5;
+
+typedef content::SynchronousCompositorMemoryPolicy Policy;
boliu 2014/04/28 22:22:15 Never do this. This is just confusing. If you want
hush (inactive) 2014/04/30 20:50:17 Done.
class AutoResetWithLock {
public:
AutoResetWithLock(gfx::Vector2dF* scoped_variable,
@@ -79,16 +93,88 @@ BrowserViewRenderer::BrowserViewRenderer(
compositor_needs_continuous_invalidate_(false),
block_invalidates_(false),
width_(0),
- height_(0) {
+ height_(0),
+ num_hungry_(0) {
CHECK(web_contents_);
content::SynchronousCompositor::SetClientForWebContents(web_contents_, this);
-
// Currently the logic in this class relies on |has_compositor_| remaining
// false until the DidInitializeCompositor() call, hence it is not set here.
}
BrowserViewRenderer::~BrowserViewRenderer() {
content::SynchronousCompositor::SetClientForWebContents(web_contents_, NULL);
+ Policy zero_policy;
+ SetMemoryPolicy(zero_policy);
boliu 2014/04/28 22:22:15 This should already happen in OnDetached, not need
hush (inactive) 2014/04/30 20:50:17 I'm just being safe here. Why is OnDetached guaran
boliu 2014/05/01 00:37:40 First, webview is never gc-ed before it is detache
+}
+
+// This function is supposed to be called after HardwareRenderer trims the
+// memory of the compositor.
+// It will update the cached memory policy in shared renderer state, as well as
+// the tile resource allocation in GlobalTileManager.
+void BrowserViewRenderer::TrimMemory() {
boliu 2014/04/28 22:22:15 Is TileManager aware that we are dropping tiles on
hush (inactive) 2014/04/30 20:50:17 You mean global tile manager? Yes it is aware of i
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ Policy zero_policy;
+ SetMemoryPolicy(zero_policy);
+ ForceFakeCompositeSW();
+ ForceDropTiles();
boliu 2014/04/28 22:22:15 Isn't ForceDropTiles enough? Why both?
hush (inactive) 2014/04/30 20:50:17 Yes it is enough. Removed. On 2014/04/28 22:22:15,
+}
+
+Policy BrowserViewRenderer::CalculateMemoryPolicy() {
boliu 2014/04/28 22:22:15 IdealPolicy? Or DesiredPolicy?
hush (inactive) 2014/04/30 20:50:17 I changed the function name to CalculateDesiredMem
+ Policy policy;
+ policy.bytes_limit = kMemoryMultiplier * kBytesPerPixel *
+ draw_gl_input_.global_visible_rect.width() *
+ draw_gl_input_.global_visible_rect.height();
+ // Round up to a multiple of kMemoryAllocationStep.
+ policy.bytes_limit =
+ (policy.bytes_limit / kMemoryAllocationStep + 1) * kMemoryAllocationStep;
+ policy.num_resources_limit = CalculateTileRequest();
+ return policy;
+}
+
+// This function updates the cached memory policy in shared renderer state, as
+// well as the tile resource allocation in GlobalTileManager.
+void BrowserViewRenderer::SetMemoryPolicy(Policy& new_policy) {
boliu 2014/04/28 22:22:15 SetMemoryPolicy sounds like a simple setter, this
hush (inactive) 2014/04/30 20:50:17 Good point (although I put some comments there to
+ Policy current_policy = shared_renderer_state_->GetMemoryPolicy();
+ GlobalTileManager* manager = GlobalTileManager::GetInstance();
+
+ size_t num_tiles = manager->RequestTiles(current_policy.num_resources_limit,
+ new_policy.num_resources_limit, IsStarved(), tile_manager_key_);
+ if (num_tiles <
+ std::min(kGrallocHungryLimit, new_policy.num_resources_limit)) {
+ num_hungry_++;
boliu 2014/04/28 22:22:15 this should only be modified in OnDraw. Too easy t
hush (inactive) 2014/04/30 20:50:17 SetMemoryPolicy is called in 3 places: OnDraw, Tri
+ } else {
+ num_hungry_ = 0;
+ }
+
+ new_policy.num_resources_limit = num_tiles;
+ shared_renderer_state_->SetMemoryPolicy(new_policy);
+}
+
+size_t BrowserViewRenderer::CalculateTileRequest() {
+ return kNumGrallocLimit;
+}
+
+bool BrowserViewRenderer::IsStarved() {
+ // If the hardware renderer is hungry for kStarvedTimes in a row, this
+ // hardware renderer is considered starved.
+ return num_hungry_ >= kStarvedTimes;
+}
+
+size_t BrowserViewRenderer::ForceDropTiles() {
+ size_t dropped_tiles =
+ shared_renderer_state_->GetMemoryPolicy().num_resources_limit;
+ Policy zero_policy;
+
+ shared_renderer_state_->SetMemoryPolicy(zero_policy);
+ shared_renderer_state_->GetCompositor()->
+ SetMemoryPolicy(zero_policy);
+
+ // Now force a fake SW draw to make sure the tiles are dropped because the
+ // tile manager only manages tiles after a Draw.
+ // Making a fake SW draw is a hacky way to forcibly drop tiles. Maybe we can
+ // find better implementations.
+ ForceFakeCompositeSW();
+ return dropped_tiles;
}
bool BrowserViewRenderer::OnDraw(jobject java_canvas,
@@ -105,10 +191,20 @@ bool BrowserViewRenderer::OnDraw(jobject java_canvas,
return false;
if (is_hardware_canvas && attached_to_window_) {
shared_renderer_state_->SetDrawGLInput(draw_gl_input_);
+
+ Policy old_policy = shared_renderer_state_->GetMemoryPolicy();
+ Policy new_policy = CalculateMemoryPolicy();
+ SetMemoryPolicy(new_policy);
// We should be performing a hardware draw here. If we don't have the
// compositor yet or if RequestDrawGL fails, it means we failed this draw
// and thus return false here to clear to background color for this draw.
- return has_compositor_ && client_->RequestDrawGL(java_canvas);
+ bool did_draw_gl = has_compositor_ && client_->RequestDrawGL(java_canvas);
+ if (did_draw_gl)
+ GlobalTileManager::GetInstance()->DidDrawGL(tile_manager_key_);
boliu 2014/04/28 22:22:15 Hmm, why do You you need to condition this on did_
hush (inactive) 2014/04/30 20:50:17 I want to be accurate about the MRU inside GlobalT
+ else
+ SetMemoryPolicy(old_policy);
boliu 2014/04/28 22:22:15 Why set back to old policy?
hush (inactive) 2014/04/30 20:50:17 The memory policy is supposedly read by HardwareRe
boliu 2014/05/01 00:37:40 Let's assume that never happens, that if HardwareR
+
+ return did_draw_gl;
}
// Perform a software draw
return DrawSWInternal(java_canvas, clip);
@@ -230,11 +326,20 @@ void BrowserViewRenderer::OnAttachedToWindow(int width, int height) {
attached_to_window_ = true;
width_ = width;
height_ = height;
+ tile_manager_key_ = GlobalTileManager::GetInstance()->PushBack(this);
+ num_hungry_ = 0;
}
void BrowserViewRenderer::OnDetachedFromWindow() {
TRACE_EVENT0("android_webview", "BrowserViewRenderer::OnDetachedFromWindow");
attached_to_window_ = false;
+ Policy zero_policy;
+ SetMemoryPolicy(zero_policy);
+ GlobalTileManager::GetInstance()->Remove(tile_manager_key_);
+ num_hungry_ = 0;
+ // The hardware resources are released in the destructor of hardware renderer,
+ // so we don't need to do it here.
+ // See AwContents::ReleaseHardwareDrawOnRenderThread(JNIEnv*, jobject).
}
bool BrowserViewRenderer::IsAttachedToWindow() const {

Powered by Google App Engine
This is Rietveld 408576698