Chromium Code Reviews| 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 { |