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

Side by Side 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: address Bo's comments Created 6 years, 7 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 unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "android_webview/browser/browser_view_renderer.h" 5 #include "android_webview/browser/browser_view_renderer.h"
6 6
7 #include "android_webview/browser/browser_view_renderer_client.h" 7 #include "android_webview/browser/browser_view_renderer_client.h"
8 #include "android_webview/browser/shared_renderer_state.h" 8 #include "android_webview/browser/shared_renderer_state.h"
9 #include "android_webview/public/browser/draw_gl.h" 9 #include "android_webview/public/browser/draw_gl.h"
10 #include "base/android/jni_android.h" 10 #include "base/android/jni_android.h"
11 #include "base/auto_reset.h" 11 #include "base/auto_reset.h"
12 #include "base/debug/trace_event.h" 12 #include "base/debug/trace_event.h"
13 #include "base/logging.h" 13 #include "base/logging.h"
14 #include "base/strings/stringprintf.h" 14 #include "base/strings/stringprintf.h"
15 #include "content/public/browser/android/synchronous_compositor.h" 15 #include "content/public/browser/android/synchronous_compositor.h"
16 #include "content/public/browser/browser_thread.h"
16 #include "content/public/browser/web_contents.h" 17 #include "content/public/browser/web_contents.h"
17 #include "third_party/skia/include/core/SkBitmap.h" 18 #include "third_party/skia/include/core/SkBitmap.h"
18 #include "third_party/skia/include/core/SkCanvas.h" 19 #include "third_party/skia/include/core/SkCanvas.h"
19 #include "third_party/skia/include/core/SkPicture.h" 20 #include "third_party/skia/include/core/SkPicture.h"
20 #include "ui/gfx/vector2d_conversions.h" 21 #include "ui/gfx/vector2d_conversions.h"
21 22
22 using base::android::AttachCurrentThread; 23 using base::android::AttachCurrentThread;
23 using base::android::JavaRef; 24 using base::android::JavaRef;
24 using base::android::ScopedJavaLocalRef; 25 using base::android::ScopedJavaLocalRef;
26 using content::BrowserThread;
27 using content::SynchronousCompositorMemoryPolicy;
25 28
26 namespace android_webview { 29 namespace android_webview {
27 30
28 namespace { 31 namespace {
29 32
30 const int64 kFallbackTickTimeoutInMilliseconds = 20; 33 const int64 kFallbackTickTimeoutInMilliseconds = 20;
31 34
35 // Used to calculate memory and resource allocation. Determined experimentally.
36 const size_t kMemoryMultiplier = 10;
37 // The number of tiles needed if the view takes up the whole viewport.
38 const size_t kNumGrallocLimit = 150;
39 const size_t kBytesPerPixel = 4;
40 const size_t kMemoryAllocationStep = 5 * 1024 * 1024;
41 const size_t kTileAllocationStep = 20;
42 // Becomes starved if the resource request cannot be granted kStarvedTimes in a
43 // row. Let it be 1 for now to make it super aggresssive to evict other views.
44 const size_t kStarvedTimes = 1;
45
32 class AutoResetWithLock { 46 class AutoResetWithLock {
33 public: 47 public:
34 AutoResetWithLock(gfx::Vector2dF* scoped_variable, 48 AutoResetWithLock(gfx::Vector2dF* scoped_variable,
35 gfx::Vector2dF new_value, 49 gfx::Vector2dF new_value,
36 base::Lock& lock) 50 base::Lock& lock)
37 : scoped_variable_(scoped_variable), 51 : scoped_variable_(scoped_variable),
38 original_value_(*scoped_variable), 52 original_value_(*scoped_variable),
39 lock_(lock) { 53 lock_(lock) {
40 base::AutoLock auto_lock(lock_); 54 base::AutoLock auto_lock(lock_);
41 *scoped_variable_ = new_value; 55 *scoped_variable_ = new_value;
(...skipping 30 matching lines...) Expand all
72 view_visible_(false), 86 view_visible_(false),
73 window_visible_(false), 87 window_visible_(false),
74 attached_to_window_(false), 88 attached_to_window_(false),
75 dip_scale_(0.0), 89 dip_scale_(0.0),
76 page_scale_factor_(1.0), 90 page_scale_factor_(1.0),
77 on_new_picture_enable_(false), 91 on_new_picture_enable_(false),
78 clear_view_(false), 92 clear_view_(false),
79 compositor_needs_continuous_invalidate_(false), 93 compositor_needs_continuous_invalidate_(false),
80 block_invalidates_(false), 94 block_invalidates_(false),
81 width_(0), 95 width_(0),
82 height_(0) { 96 height_(0),
97 num_consecutive_hungry_frames_(0) {
83 CHECK(web_contents_); 98 CHECK(web_contents_);
84 content::SynchronousCompositor::SetClientForWebContents(web_contents_, this); 99 content::SynchronousCompositor::SetClientForWebContents(web_contents_, this);
85
86 // Currently the logic in this class relies on |has_compositor_| remaining 100 // Currently the logic in this class relies on |has_compositor_| remaining
87 // false until the DidInitializeCompositor() call, hence it is not set here. 101 // false until the DidInitializeCompositor() call, hence it is not set here.
88 } 102 }
89 103
90 BrowserViewRenderer::~BrowserViewRenderer() { 104 BrowserViewRenderer::~BrowserViewRenderer() {
91 content::SynchronousCompositor::SetClientForWebContents(web_contents_, NULL); 105 content::SynchronousCompositor::SetClientForWebContents(web_contents_, NULL);
106 // OnDetachedFromWindow should be called before the destructor, so the memory
107 // policy should have already been updated.
108 }
109
110 // This function updates the cached memory policy in shared renderer state, as
111 // well as the tile resource allocation in GlobalTileManager.
112 void BrowserViewRenderer::TrimMemory(const int level, const bool visible) {
113 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
114 // Constants from Android ComponentCallbacks2.
115 enum {
116 TRIM_MEMORY_RUNNING_LOW = 10,
117 TRIM_MEMORY_UI_HIDDEN = 20,
118 TRIM_MEMORY_BACKGROUND = 40,
119 };
120
121 // Not urgent enough. TRIM_MEMORY_UI_HIDDEN is treated specially because
122 // it does not indicate memory pressure, but merely that the app is
123 // backgrounded.
124 if (level < TRIM_MEMORY_RUNNING_LOW || level == TRIM_MEMORY_UI_HIDDEN)
125 return;
126
127 // Do not release resources on view we expect to get DrawGL soon.
128 if (level < TRIM_MEMORY_BACKGROUND && visible)
129 return;
130
131 // Just set the memory limit to 0 and drop all tiles. This will be reset to
132 // normal levels in the next DrawGL call.
133 SynchronousCompositorMemoryPolicy zero_policy;
134 if (shared_renderer_state_->GetMemoryPolicy() == zero_policy)
135 return;
136
137 TRACE_EVENT0("android_webview", "BrowserViewRenderer::TrimMemory");
138
139 RequestMemoryPolicy(zero_policy);
140 ForceDropTiles();
141 }
142
143 SynchronousCompositorMemoryPolicy
144 BrowserViewRenderer::CalculateDesiredMemoryPolicy() {
145 SynchronousCompositorMemoryPolicy policy;
146 policy.bytes_limit = kMemoryMultiplier * kBytesPerPixel *
147 draw_gl_input_.global_visible_rect.width() *
148 draw_gl_input_.global_visible_rect.height();
149 // Round up to a multiple of kMemoryAllocationStep.
150 policy.bytes_limit =
151 (policy.bytes_limit / kMemoryAllocationStep + 1) * kMemoryAllocationStep;
152 policy.num_resources_limit = CalculateTileRequest();
153 return policy;
154 }
155
156 // This function updates the cached memory policy in shared renderer state, as
157 // well as the tile resource allocation in GlobalTileManager.
158 void BrowserViewRenderer::RequestMemoryPolicy(
159 SynchronousCompositorMemoryPolicy& new_policy) {
160 SynchronousCompositorMemoryPolicy current_policy =
161 shared_renderer_state_->GetMemoryPolicy();
162 GlobalTileManager* manager = GlobalTileManager::GetInstance();
163
164 size_t num_tiles = manager->RequestTiles(current_policy.num_resources_limit,
165 new_policy.num_resources_limit,
166 NeedsEviction(),
167 tile_manager_key_);
168 if (num_tiles < new_policy.num_resources_limit)
169 num_consecutive_hungry_frames_++;
170 else
171 num_consecutive_hungry_frames_ = 0;
172
173 new_policy.num_resources_limit = num_tiles;
174 shared_renderer_state_->SetMemoryPolicy(new_policy);
175 }
176
177 size_t BrowserViewRenderer::CalculateTileRequest() const {
178 double area = (double)draw_gl_input_.global_visible_rect.width() *
boliu 2014/05/01 00:37:40 against style guide to use c-style casts, always u
hush (inactive) 2014/05/01 19:03:04 CalculateTileRequest() is an inherited method. I w
179 draw_gl_input_.global_visible_rect.height();
180 double viewport = (double)draw_gl_input_.width * draw_gl_input_.height;
181 // Round up to a multiple of kTileAllocationStep. The minimum number of tiles
182 // is also kTileAllocationStep.
183 size_t tiles = std::max(kNumGrallocLimit * (area / viewport), 1.0);
184 tiles = (tiles + kTileAllocationStep - 1) / kTileAllocationStep *
185 kTileAllocationStep;
186 return tiles;
187 }
188
189 bool BrowserViewRenderer::NeedsEviction() const {
190 // If the hardware renderer is hungry for kStarvedTimes in a row, this
191 // browser view renderer is considered starved.
192 return num_consecutive_hungry_frames_ >= kStarvedTimes;
193 }
194
195 size_t BrowserViewRenderer::ForceDropTiles() {
196 size_t dropped_tiles = GetTilesNum();
197 SynchronousCompositorMemoryPolicy zero_policy;
198
199 shared_renderer_state_->SetMemoryPolicy(zero_policy);
200 shared_renderer_state_->GetCompositor()->SetMemoryPolicy(zero_policy);
201
202 // Now force a fake SW draw to make sure the tiles are dropped because the
203 // tile manager only manages tiles after a Draw.
204 // Making a fake SW draw is a hacky way to forcibly drop tiles. Maybe we can
205 // find better implementations.
206 ForceFakeCompositeSW();
207 return dropped_tiles;
208 }
209
210 size_t BrowserViewRenderer::GetTilesNum() const {
211 return shared_renderer_state_->GetMemoryPolicy().num_resources_limit;
92 } 212 }
93 213
94 bool BrowserViewRenderer::OnDraw(jobject java_canvas, 214 bool BrowserViewRenderer::OnDraw(jobject java_canvas,
95 bool is_hardware_canvas, 215 bool is_hardware_canvas,
96 const gfx::Vector2d& scroll, 216 const gfx::Vector2d& scroll,
97 const gfx::Rect& global_visible_rect, 217 const gfx::Rect& global_visible_rect,
98 const gfx::Rect& clip) { 218 const gfx::Rect& clip) {
99 draw_gl_input_.frame_id++; 219 draw_gl_input_.frame_id++;
100 draw_gl_input_.scroll_offset = scroll; 220 draw_gl_input_.scroll_offset = scroll;
101 draw_gl_input_.global_visible_rect = global_visible_rect; 221 draw_gl_input_.global_visible_rect = global_visible_rect;
102 draw_gl_input_.width = width_; 222 draw_gl_input_.width = width_;
103 draw_gl_input_.height = height_; 223 draw_gl_input_.height = height_;
104 if (clear_view_) 224 if (clear_view_)
105 return false; 225 return false;
106 if (is_hardware_canvas && attached_to_window_) { 226 if (is_hardware_canvas && attached_to_window_) {
107 shared_renderer_state_->SetDrawGLInput(draw_gl_input_); 227 shared_renderer_state_->SetDrawGLInput(draw_gl_input_);
228
229 SynchronousCompositorMemoryPolicy old_policy =
230 shared_renderer_state_->GetMemoryPolicy();
231 SynchronousCompositorMemoryPolicy new_policy =
232 CalculateDesiredMemoryPolicy();
233 RequestMemoryPolicy(new_policy);
108 // We should be performing a hardware draw here. If we don't have the 234 // We should be performing a hardware draw here. If we don't have the
109 // compositor yet or if RequestDrawGL fails, it means we failed this draw 235 // compositor yet or if RequestDrawGL fails, it means we failed this draw
110 // and thus return false here to clear to background color for this draw. 236 // and thus return false here to clear to background color for this draw.
111 return has_compositor_ && client_->RequestDrawGL(java_canvas); 237 bool did_draw_gl = has_compositor_ && client_->RequestDrawGL(java_canvas);
238 if (did_draw_gl)
239 GlobalTileManager::GetInstance()->DidUse(tile_manager_key_);
240 else
241 RequestMemoryPolicy(old_policy);
242
243 return did_draw_gl;
112 } 244 }
113 // Perform a software draw 245 // Perform a software draw
114 return DrawSWInternal(java_canvas, clip); 246 return DrawSWInternal(java_canvas, clip);
115 } 247 }
116 248
117 void BrowserViewRenderer::DidDrawGL(const DrawGLResult& result) { 249 void BrowserViewRenderer::DidDrawGL(const DrawGLResult& result) {
118 DidComposite(!result.clip_contains_visible_rect); 250 DidComposite(!result.clip_contains_visible_rect);
119 } 251 }
120 252
121 bool BrowserViewRenderer::DrawSWInternal(jobject java_canvas, 253 bool BrowserViewRenderer::DrawSWInternal(jobject java_canvas,
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
223 void BrowserViewRenderer::OnAttachedToWindow(int width, int height) { 355 void BrowserViewRenderer::OnAttachedToWindow(int width, int height) {
224 TRACE_EVENT2("android_webview", 356 TRACE_EVENT2("android_webview",
225 "BrowserViewRenderer::OnAttachedToWindow", 357 "BrowserViewRenderer::OnAttachedToWindow",
226 "width", 358 "width",
227 width, 359 width,
228 "height", 360 "height",
229 height); 361 height);
230 attached_to_window_ = true; 362 attached_to_window_ = true;
231 width_ = width; 363 width_ = width;
232 height_ = height; 364 height_ = height;
365 tile_manager_key_ = GlobalTileManager::GetInstance()->PushBack(this);
366 num_consecutive_hungry_frames_ = 0;
233 } 367 }
234 368
235 void BrowserViewRenderer::OnDetachedFromWindow() { 369 void BrowserViewRenderer::OnDetachedFromWindow() {
236 TRACE_EVENT0("android_webview", "BrowserViewRenderer::OnDetachedFromWindow"); 370 TRACE_EVENT0("android_webview", "BrowserViewRenderer::OnDetachedFromWindow");
237 attached_to_window_ = false; 371 attached_to_window_ = false;
372 SynchronousCompositorMemoryPolicy zero_policy;
373 RequestMemoryPolicy(zero_policy);
374 GlobalTileManager::GetInstance()->Remove(tile_manager_key_);
375 num_consecutive_hungry_frames_ = 0;
376 // The hardware resources are released in the destructor of hardware renderer,
377 // so we don't need to do it here.
378 // See AwContents::ReleaseHardwareDrawOnRenderThread(JNIEnv*, jobject).
238 } 379 }
239 380
240 bool BrowserViewRenderer::IsAttachedToWindow() const { 381 bool BrowserViewRenderer::IsAttachedToWindow() const {
241 return attached_to_window_; 382 return attached_to_window_;
242 } 383 }
243 384
244 bool BrowserViewRenderer::IsVisible() const { 385 bool BrowserViewRenderer::IsVisible() const {
245 // Ignore |window_visible_| if |attached_to_window_| is false. 386 // Ignore |window_visible_| if |attached_to_window_| is false.
246 return view_visible_ && (!attached_to_window_ || window_visible_); 387 return view_visible_ && (!attached_to_window_ || window_visible_);
247 } 388 }
(...skipping 13 matching lines...) Expand all
261 shared_renderer_state_->SetCompositorOnUiThread(compositor); 402 shared_renderer_state_->SetCompositorOnUiThread(compositor);
262 } 403 }
263 404
264 void BrowserViewRenderer::DidDestroyCompositor( 405 void BrowserViewRenderer::DidDestroyCompositor(
265 content::SynchronousCompositor* compositor) { 406 content::SynchronousCompositor* compositor) {
266 TRACE_EVENT0("android_webview", "BrowserViewRenderer::DidDestroyCompositor"); 407 TRACE_EVENT0("android_webview", "BrowserViewRenderer::DidDestroyCompositor");
267 DCHECK(has_compositor_); 408 DCHECK(has_compositor_);
268 DCHECK(ui_task_runner_->BelongsToCurrentThread()); 409 DCHECK(ui_task_runner_->BelongsToCurrentThread());
269 has_compositor_ = false; 410 has_compositor_ = false;
270 shared_renderer_state_->SetCompositorOnUiThread(NULL); 411 shared_renderer_state_->SetCompositorOnUiThread(NULL);
412 SynchronousCompositorMemoryPolicy zero_policy;
413 DCHECK(shared_renderer_state_->GetMemoryPolicy() == zero_policy);
271 } 414 }
272 415
273 void BrowserViewRenderer::SetContinuousInvalidate(bool invalidate) { 416 void BrowserViewRenderer::SetContinuousInvalidate(bool invalidate) {
274 if (!ui_task_runner_->BelongsToCurrentThread()) { 417 if (!ui_task_runner_->BelongsToCurrentThread()) {
275 ui_task_runner_->PostTask( 418 ui_task_runner_->PostTask(
276 FROM_HERE, 419 FROM_HERE,
277 base::Bind(&BrowserViewRenderer::SetContinuousInvalidate, 420 base::Bind(&BrowserViewRenderer::SetContinuousInvalidate,
278 ui_thread_weak_ptr_, 421 ui_thread_weak_ptr_,
279 invalidate)); 422 invalidate));
280 return; 423 return;
(...skipping 317 matching lines...) Expand 10 before | Expand all | Expand 10 after
598 base::StringAppendF(&str, 741 base::StringAppendF(&str,
599 "surface width height: [%d %d] ", 742 "surface width height: [%d %d] ",
600 draw_info->width, 743 draw_info->width,
601 draw_info->height); 744 draw_info->height);
602 base::StringAppendF(&str, "is_layer: %d ", draw_info->is_layer); 745 base::StringAppendF(&str, "is_layer: %d ", draw_info->is_layer);
603 } 746 }
604 return str; 747 return str;
605 } 748 }
606 749
607 } // namespace android_webview 750 } // namespace android_webview
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698