Index: android_webview/browser/hardware_renderer.cc |
diff --git a/android_webview/browser/hardware_renderer.cc b/android_webview/browser/hardware_renderer.cc |
index a45da7ff724231c5775bfc66b33474068a95fe18..46e1620683913cadaa455f708f95ea868ae26dfd 100644 |
--- a/android_webview/browser/hardware_renderer.cc |
+++ b/android_webview/browser/hardware_renderer.cc |
@@ -6,7 +6,6 @@ |
#include "android_webview/browser/aw_gl_surface.h" |
#include "android_webview/browser/browser_view_renderer_client.h" |
-#include "android_webview/browser/gl_view_renderer_manager.h" |
#include "android_webview/browser/scoped_app_gl_state_restore.h" |
#include "android_webview/public/browser/draw_gl.h" |
#include "base/command_line.h" |
@@ -15,6 +14,8 @@ |
#include "content/public/browser/browser_thread.h" |
#include "content/public/common/content_switches.h" |
#include "gpu/command_buffer/service/shader_translator_cache.h" |
+#include "third_party/skia/include/core/SkBitmap.h" |
+#include "third_party/skia/include/core/SkCanvas.h" |
#include "ui/gfx/geometry/rect_conversions.h" |
#include "ui/gfx/geometry/rect_f.h" |
#include "ui/gfx/transform.h" |
@@ -30,6 +31,13 @@ const size_t g_memory_multiplier = 10; |
const size_t g_num_gralloc_limit = 150; |
const size_t kBytesPerPixel = 4; |
const size_t kMemoryAllocationStep = 5 * 1024 * 1024; |
+// HardwareRenderer needs |g_num_gralloc_limit| tiles to draw quickly, but it |
+// will be resource hungry if it only gets allocated less than |
+// |kGrallocHungryLimit|. |
+const size_t kGrallocHungryLimit = 100; |
+// HardwareRenderer becomes starved if the resource request cannot be granted |
+// kStarvedTimes in a row. |
+const size_t kStarvedTimes = 5; |
base::LazyInstance<scoped_refptr<internal::DeferredGpuCommandService> > |
g_service = LAZY_INSTANCE_INITIALIZER; |
@@ -39,9 +47,12 @@ base::LazyInstance<scoped_refptr<internal::DeferredGpuCommandService> > |
HardwareRenderer::HardwareRenderer(SharedRendererState* state) |
: shared_renderer_state_(state), |
last_egl_context_(eglGetCurrentContext()), |
- manager_key_(GLViewRendererManager::GetInstance()->PushBack( |
- shared_renderer_state_)) { |
+ renderer_manager_key_(GLViewRendererManager::GetInstance()->PushBack( |
+ shared_renderer_state_)), |
+ tile_manager_key_(GlobalTileManager::GetInstance()->PushBack(this)), |
+ num_hungry_(0) { |
DCHECK(last_egl_context_); |
+ |
if (!g_service.Get()) { |
g_service.Get() = new internal::DeferredGpuCommandService; |
content::SynchronousCompositor::SetGpuService(g_service.Get()); |
@@ -59,8 +70,13 @@ HardwareRenderer::HardwareRenderer(SharedRendererState* state) |
} |
HardwareRenderer::~HardwareRenderer() { |
- GLViewRendererManager* mru = GLViewRendererManager::GetInstance(); |
- mru->Remove(manager_key_); |
+ GLViewRendererManager* render_manager = GLViewRendererManager::GetInstance(); |
+ render_manager->Remove(renderer_manager_key_); |
+ |
+ GlobalTileManager* tile_manager = GlobalTileManager::GetInstance(); |
+ tile_manager->RequestTiles( |
+ memory_policy_.num_resources_limit, 0, IsStarved(), tile_manager_key_); |
+ tile_manager->Remove(tile_manager_key_); |
ScopedAppGLStateRestore state_restore( |
ScopedAppGLStateRestore::MODE_RESOURCE_MANAGEMENT); |
@@ -72,7 +88,8 @@ HardwareRenderer::~HardwareRenderer() { |
bool HardwareRenderer::DrawGL(AwDrawGLInfo* draw_info, DrawGLResult* result) { |
TRACE_EVENT0("android_webview", "HardwareRenderer::DrawGL"); |
- GLViewRendererManager::GetInstance()->DidDrawGL(manager_key_); |
+ GLViewRendererManager::GetInstance()->DidDrawGL(renderer_manager_key_); |
+ GlobalTileManager::GetInstance()->DidDrawGL(tile_manager_key_); |
const DrawGLInput input = shared_renderer_state_->GetDrawGLInput(); |
// We need to watch if the current Android context has changed and enforce |
@@ -167,10 +184,8 @@ bool HardwareRenderer::TrimMemory(int level, bool visible) { |
// 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) |
+ content::SynchronousCompositorMemoryPolicy zero_policy; |
+ if (memory_policy_ == zero_policy) |
return false; |
TRACE_EVENT0("android_webview", "HardwareRenderer::TrimMemory"); |
@@ -178,7 +193,7 @@ bool HardwareRenderer::TrimMemory(int level, bool visible) { |
ScopedAppGLStateRestore::MODE_RESOURCE_MANAGEMENT); |
internal::ScopedAllowGL allow_gl; |
- SetMemoryPolicy(policy); |
+ SetMemoryPolicy(zero_policy); |
return true; |
} |
@@ -187,9 +202,51 @@ void HardwareRenderer::SetMemoryPolicy( |
if (memory_policy_ == new_policy) |
return; |
+ GlobalTileManager* tile_manager = GlobalTileManager::GetInstance(); |
+ |
+ size_t num_tiles = tile_manager-> |
+ RequestTiles(memory_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_++; |
+ else |
+ num_hungry_ = 0; |
+ |
+ |
+ new_policy.num_resources_limit = num_tiles; |
+ |
+ shared_renderer_state_->GetCompositor()-> |
+ SetMemoryPolicy(new_policy); |
memory_policy_ = new_policy; |
+} |
+ |
+bool HardwareRenderer::IsStarved() { |
+ // If the hardware renderer is hungry for kStarvedTimes in a row, this |
+ // hardware renderer is considered starved. |
+ return (num_hungry_ >= kStarvedTimes); |
+} |
+ |
+size_t HardwareRenderer::ForceDropTiles() { |
+ size_t dropped_tiles = memory_policy_.num_resources_limit; |
+ content::SynchronousCompositorMemoryPolicy zero_policy; |
+ memory_policy_ = zero_policy; |
shared_renderer_state_->GetCompositor()-> |
- SetMemoryPolicy(memory_policy_); |
+ 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. |
+ SkBitmap bitmap; |
+ bitmap.allocN32Pixels(1, 1); |
+ bitmap.eraseColor(0); |
+ SkCanvas canvas(bitmap); |
+ |
+ shared_renderer_state_->GetCompositor()->DemandDrawSw(&canvas); |
+ return dropped_tiles; |
} |
// static |