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

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: Remove unnecessary code 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;
25 26 using content::BrowserThread;
26 namespace android_webview { 27 namespace android_webview {
27 28
28 namespace { 29 namespace {
29 30
30 const int64 kFallbackTickTimeoutInMilliseconds = 20; 31 const int64 kFallbackTickTimeoutInMilliseconds = 20;
31 32
33 // Used to calculate memory and resource allocation. Determined experimentally.
34 const size_t kMemoryMultiplier = 10;
35 const size_t kNumGrallocLimit = 150;
36 const size_t kBytesPerPixel = 4;
37 const size_t kMemoryAllocationStep = 5 * 1024 * 1024;
38 // Needs |kNumGrallocLimit| tiles to draw quickly, but it will be resource
39 // hungry if it only gets allocated less than |kGrallocHungryLimit|.
40 const size_t kGrallocHungryLimit = 100;
41 // 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
42 // row.
43 const size_t kStarvedTimes = 5;
44
45 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.
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_hungry_(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 Policy zero_policy;
107 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
108 }
109
110 // This function is supposed to be called after HardwareRenderer trims the
111 // memory of the compositor.
112 // It will update the cached memory policy in shared renderer state, as well as
113 // the tile resource allocation in GlobalTileManager.
114 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
115 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
116 Policy zero_policy;
117 SetMemoryPolicy(zero_policy);
118 ForceFakeCompositeSW();
119 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,
120 }
121
122 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
123 Policy policy;
124 policy.bytes_limit = kMemoryMultiplier * kBytesPerPixel *
125 draw_gl_input_.global_visible_rect.width() *
126 draw_gl_input_.global_visible_rect.height();
127 // Round up to a multiple of kMemoryAllocationStep.
128 policy.bytes_limit =
129 (policy.bytes_limit / kMemoryAllocationStep + 1) * kMemoryAllocationStep;
130 policy.num_resources_limit = CalculateTileRequest();
131 return policy;
132 }
133
134 // This function updates the cached memory policy in shared renderer state, as
135 // well as the tile resource allocation in GlobalTileManager.
136 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
137 Policy current_policy = shared_renderer_state_->GetMemoryPolicy();
138 GlobalTileManager* manager = GlobalTileManager::GetInstance();
139
140 size_t num_tiles = manager->RequestTiles(current_policy.num_resources_limit,
141 new_policy.num_resources_limit, IsStarved(), tile_manager_key_);
142 if (num_tiles <
143 std::min(kGrallocHungryLimit, new_policy.num_resources_limit)) {
144 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
145 } else {
146 num_hungry_ = 0;
147 }
148
149 new_policy.num_resources_limit = num_tiles;
150 shared_renderer_state_->SetMemoryPolicy(new_policy);
151 }
152
153 size_t BrowserViewRenderer::CalculateTileRequest() {
154 return kNumGrallocLimit;
155 }
156
157 bool BrowserViewRenderer::IsStarved() {
158 // If the hardware renderer is hungry for kStarvedTimes in a row, this
159 // hardware renderer is considered starved.
160 return num_hungry_ >= kStarvedTimes;
161 }
162
163 size_t BrowserViewRenderer::ForceDropTiles() {
164 size_t dropped_tiles =
165 shared_renderer_state_->GetMemoryPolicy().num_resources_limit;
166 Policy zero_policy;
167
168 shared_renderer_state_->SetMemoryPolicy(zero_policy);
169 shared_renderer_state_->GetCompositor()->
170 SetMemoryPolicy(zero_policy);
171
172 // Now force a fake SW draw to make sure the tiles are dropped because the
173 // tile manager only manages tiles after a Draw.
174 // Making a fake SW draw is a hacky way to forcibly drop tiles. Maybe we can
175 // find better implementations.
176 ForceFakeCompositeSW();
177 return dropped_tiles;
92 } 178 }
93 179
94 bool BrowserViewRenderer::OnDraw(jobject java_canvas, 180 bool BrowserViewRenderer::OnDraw(jobject java_canvas,
95 bool is_hardware_canvas, 181 bool is_hardware_canvas,
96 const gfx::Vector2d& scroll, 182 const gfx::Vector2d& scroll,
97 const gfx::Rect& global_visible_rect, 183 const gfx::Rect& global_visible_rect,
98 const gfx::Rect& clip) { 184 const gfx::Rect& clip) {
99 draw_gl_input_.frame_id++; 185 draw_gl_input_.frame_id++;
100 draw_gl_input_.scroll_offset = scroll; 186 draw_gl_input_.scroll_offset = scroll;
101 draw_gl_input_.global_visible_rect = global_visible_rect; 187 draw_gl_input_.global_visible_rect = global_visible_rect;
102 draw_gl_input_.width = width_; 188 draw_gl_input_.width = width_;
103 draw_gl_input_.height = height_; 189 draw_gl_input_.height = height_;
104 if (clear_view_) 190 if (clear_view_)
105 return false; 191 return false;
106 if (is_hardware_canvas && attached_to_window_) { 192 if (is_hardware_canvas && attached_to_window_) {
107 shared_renderer_state_->SetDrawGLInput(draw_gl_input_); 193 shared_renderer_state_->SetDrawGLInput(draw_gl_input_);
194
195 Policy old_policy = shared_renderer_state_->GetMemoryPolicy();
196 Policy new_policy = CalculateMemoryPolicy();
197 SetMemoryPolicy(new_policy);
108 // We should be performing a hardware draw here. If we don't have the 198 // 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 199 // 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. 200 // and thus return false here to clear to background color for this draw.
111 return has_compositor_ && client_->RequestDrawGL(java_canvas); 201 bool did_draw_gl = has_compositor_ && client_->RequestDrawGL(java_canvas);
202 if (did_draw_gl)
203 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
204 else
205 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
206
207 return did_draw_gl;
112 } 208 }
113 // Perform a software draw 209 // Perform a software draw
114 return DrawSWInternal(java_canvas, clip); 210 return DrawSWInternal(java_canvas, clip);
115 } 211 }
116 212
117 void BrowserViewRenderer::DidDrawGL(const DrawGLResult& result) { 213 void BrowserViewRenderer::DidDrawGL(const DrawGLResult& result) {
118 DidComposite(!result.clip_contains_visible_rect); 214 DidComposite(!result.clip_contains_visible_rect);
119 } 215 }
120 216
121 bool BrowserViewRenderer::DrawSWInternal(jobject java_canvas, 217 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) { 319 void BrowserViewRenderer::OnAttachedToWindow(int width, int height) {
224 TRACE_EVENT2("android_webview", 320 TRACE_EVENT2("android_webview",
225 "BrowserViewRenderer::OnAttachedToWindow", 321 "BrowserViewRenderer::OnAttachedToWindow",
226 "width", 322 "width",
227 width, 323 width,
228 "height", 324 "height",
229 height); 325 height);
230 attached_to_window_ = true; 326 attached_to_window_ = true;
231 width_ = width; 327 width_ = width;
232 height_ = height; 328 height_ = height;
329 tile_manager_key_ = GlobalTileManager::GetInstance()->PushBack(this);
330 num_hungry_ = 0;
233 } 331 }
234 332
235 void BrowserViewRenderer::OnDetachedFromWindow() { 333 void BrowserViewRenderer::OnDetachedFromWindow() {
236 TRACE_EVENT0("android_webview", "BrowserViewRenderer::OnDetachedFromWindow"); 334 TRACE_EVENT0("android_webview", "BrowserViewRenderer::OnDetachedFromWindow");
237 attached_to_window_ = false; 335 attached_to_window_ = false;
336 Policy zero_policy;
337 SetMemoryPolicy(zero_policy);
338 GlobalTileManager::GetInstance()->Remove(tile_manager_key_);
339 num_hungry_ = 0;
340 // The hardware resources are released in the destructor of hardware renderer,
341 // so we don't need to do it here.
342 // See AwContents::ReleaseHardwareDrawOnRenderThread(JNIEnv*, jobject).
238 } 343 }
239 344
240 bool BrowserViewRenderer::IsAttachedToWindow() const { 345 bool BrowserViewRenderer::IsAttachedToWindow() const {
241 return attached_to_window_; 346 return attached_to_window_;
242 } 347 }
243 348
244 bool BrowserViewRenderer::IsVisible() const { 349 bool BrowserViewRenderer::IsVisible() const {
245 // Ignore |window_visible_| if |attached_to_window_| is false. 350 // Ignore |window_visible_| if |attached_to_window_| is false.
246 return view_visible_ && (!attached_to_window_ || window_visible_); 351 return view_visible_ && (!attached_to_window_ || window_visible_);
247 } 352 }
(...skipping 12 matching lines...) Expand all
260 has_compositor_ = true; 365 has_compositor_ = true;
261 shared_renderer_state_->SetCompositorOnUiThread(compositor); 366 shared_renderer_state_->SetCompositorOnUiThread(compositor);
262 } 367 }
263 368
264 void BrowserViewRenderer::DidDestroyCompositor( 369 void BrowserViewRenderer::DidDestroyCompositor(
265 content::SynchronousCompositor* compositor) { 370 content::SynchronousCompositor* compositor) {
266 TRACE_EVENT0("android_webview", "BrowserViewRenderer::DidDestroyCompositor"); 371 TRACE_EVENT0("android_webview", "BrowserViewRenderer::DidDestroyCompositor");
267 DCHECK(has_compositor_); 372 DCHECK(has_compositor_);
268 DCHECK(ui_task_runner_->BelongsToCurrentThread()); 373 DCHECK(ui_task_runner_->BelongsToCurrentThread());
269 has_compositor_ = false; 374 has_compositor_ = false;
270 shared_renderer_state_->SetCompositorOnUiThread(NULL); 375 shared_renderer_state_->SetCompositorOnUiThread(NULL);
boliu 2014/04/28 22:22:15 DCHECK here memory policy is 0, (this should only
hush (inactive) 2014/04/30 20:50:17 Yeah. That makes sense. On 2014/04/28 22:22:15, bo
271 } 376 }
272 377
273 void BrowserViewRenderer::SetContinuousInvalidate(bool invalidate) { 378 void BrowserViewRenderer::SetContinuousInvalidate(bool invalidate) {
274 if (!ui_task_runner_->BelongsToCurrentThread()) { 379 if (!ui_task_runner_->BelongsToCurrentThread()) {
275 ui_task_runner_->PostTask( 380 ui_task_runner_->PostTask(
276 FROM_HERE, 381 FROM_HERE,
277 base::Bind(&BrowserViewRenderer::SetContinuousInvalidate, 382 base::Bind(&BrowserViewRenderer::SetContinuousInvalidate,
278 ui_thread_weak_ptr_, 383 ui_thread_weak_ptr_,
279 invalidate)); 384 invalidate));
280 return; 385 return;
(...skipping 317 matching lines...) Expand 10 before | Expand all | Expand 10 after
598 base::StringAppendF(&str, 703 base::StringAppendF(&str,
599 "surface width height: [%d %d] ", 704 "surface width height: [%d %d] ",
600 draw_info->width, 705 draw_info->width,
601 draw_info->height); 706 draw_info->height);
602 base::StringAppendF(&str, "is_layer: %d ", draw_info->is_layer); 707 base::StringAppendF(&str, "is_layer: %d ", draw_info->is_layer);
603 } 708 }
604 return str; 709 return str;
605 } 710 }
606 711
607 } // namespace android_webview 712 } // namespace android_webview
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698