| 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
|
|
|