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

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: Use command line switch and move that from HR to BVR. 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/command_line.h"
12 #include "base/debug/trace_event.h" 13 #include "base/debug/trace_event.h"
13 #include "base/logging.h" 14 #include "base/logging.h"
15 #include "base/strings/string_number_conversions.h"
14 #include "base/strings/stringprintf.h" 16 #include "base/strings/stringprintf.h"
15 #include "content/public/browser/android/synchronous_compositor.h" 17 #include "content/public/browser/android/synchronous_compositor.h"
18 #include "content/public/browser/browser_thread.h"
16 #include "content/public/browser/web_contents.h" 19 #include "content/public/browser/web_contents.h"
20 #include "content/public/common/content_switches.h"
17 #include "third_party/skia/include/core/SkBitmap.h" 21 #include "third_party/skia/include/core/SkBitmap.h"
18 #include "third_party/skia/include/core/SkCanvas.h" 22 #include "third_party/skia/include/core/SkCanvas.h"
19 #include "third_party/skia/include/core/SkPicture.h" 23 #include "third_party/skia/include/core/SkPicture.h"
20 #include "third_party/skia/include/core/SkPictureRecorder.h" 24 #include "third_party/skia/include/core/SkPictureRecorder.h"
21 #include "ui/gfx/vector2d_conversions.h" 25 #include "ui/gfx/vector2d_conversions.h"
22 26
23 using base::android::AttachCurrentThread; 27 using base::android::AttachCurrentThread;
24 using base::android::JavaRef; 28 using base::android::JavaRef;
25 using base::android::ScopedJavaLocalRef; 29 using base::android::ScopedJavaLocalRef;
30 using content::BrowserThread;
31 using content::SynchronousCompositorMemoryPolicy;
26 32
27 namespace android_webview { 33 namespace android_webview {
28 34
29 namespace { 35 namespace {
30 36
31 const int64 kFallbackTickTimeoutInMilliseconds = 20; 37 const int64 kFallbackTickTimeoutInMilliseconds = 20;
32 38
39 // Used to calculate memory allocation. Determined experimentally.
40 const size_t kMemoryMultiplier = 10;
41 const size_t kBytesPerPixel = 4;
42 const size_t kMemoryAllocationStep = 5 * 1024 * 1024;
43
44 // Used to calculate tile allocation. Determined experimentally.
45 const size_t kTileMultiplier = 12;
46 const size_t kTileAllocationStep = 20;
47 // This will be set by static function CalculateTileMemoryPolicy() during init.
48 // See AwMainDelegate::BasicStartupComplete.
49 size_t g_tile_area;
50
33 class AutoResetWithLock { 51 class AutoResetWithLock {
34 public: 52 public:
35 AutoResetWithLock(gfx::Vector2dF* scoped_variable, 53 AutoResetWithLock(gfx::Vector2dF* scoped_variable,
36 gfx::Vector2dF new_value, 54 gfx::Vector2dF new_value,
37 base::Lock& lock) 55 base::Lock& lock)
38 : scoped_variable_(scoped_variable), 56 : scoped_variable_(scoped_variable),
39 original_value_(*scoped_variable), 57 original_value_(*scoped_variable),
40 lock_(lock) { 58 lock_(lock) {
41 base::AutoLock auto_lock(lock_); 59 base::AutoLock auto_lock(lock_);
42 *scoped_variable_ = new_value; 60 *scoped_variable_ = new_value;
43 } 61 }
44 62
45 ~AutoResetWithLock() { 63 ~AutoResetWithLock() {
46 base::AutoLock auto_lock(lock_); 64 base::AutoLock auto_lock(lock_);
47 *scoped_variable_ = original_value_; 65 *scoped_variable_ = original_value_;
48 } 66 }
49 67
50 private: 68 private:
51 gfx::Vector2dF* scoped_variable_; 69 gfx::Vector2dF* scoped_variable_;
52 gfx::Vector2dF original_value_; 70 gfx::Vector2dF original_value_;
53 base::Lock& lock_; 71 base::Lock& lock_;
54 72
55 DISALLOW_COPY_AND_ASSIGN(AutoResetWithLock); 73 DISALLOW_COPY_AND_ASSIGN(AutoResetWithLock);
56 }; 74 };
57 75
58 } // namespace 76 } // namespace
59 77
78 // static
79 void BrowserViewRenderer::CalculateTileMemoryPolicy() {
80 CommandLine* cl = CommandLine::ForCurrentProcess();
81 const char kDefaultTileSize[] = "384";
82
83 if (!cl->HasSwitch(switches::kDefaultTileWidth))
84 cl->AppendSwitchASCII(switches::kDefaultTileWidth, kDefaultTileSize);
85
86 if (!cl->HasSwitch(switches::kDefaultTileHeight))
87 cl->AppendSwitchASCII(switches::kDefaultTileHeight, kDefaultTileSize);
88
89 size_t tile_size;
90 base::StringToSizeT(kDefaultTileSize, &tile_size);
91 g_tile_area = tile_size * tile_size;
92 }
93
60 BrowserViewRenderer::BrowserViewRenderer( 94 BrowserViewRenderer::BrowserViewRenderer(
61 BrowserViewRendererClient* client, 95 BrowserViewRendererClient* client,
62 SharedRendererState* shared_renderer_state, 96 SharedRendererState* shared_renderer_state,
63 content::WebContents* web_contents, 97 content::WebContents* web_contents,
64 const scoped_refptr<base::SingleThreadTaskRunner>& ui_task_runner) 98 const scoped_refptr<base::SingleThreadTaskRunner>& ui_task_runner)
65 : client_(client), 99 : client_(client),
66 shared_renderer_state_(shared_renderer_state), 100 shared_renderer_state_(shared_renderer_state),
67 web_contents_(web_contents), 101 web_contents_(web_contents),
68 weak_factory_on_ui_thread_(this), 102 weak_factory_on_ui_thread_(this),
69 ui_thread_weak_ptr_(weak_factory_on_ui_thread_.GetWeakPtr()), 103 ui_thread_weak_ptr_(weak_factory_on_ui_thread_.GetWeakPtr()),
(...skipping 13 matching lines...) Expand all
83 height_(0) { 117 height_(0) {
84 CHECK(web_contents_); 118 CHECK(web_contents_);
85 content::SynchronousCompositor::SetClientForWebContents(web_contents_, this); 119 content::SynchronousCompositor::SetClientForWebContents(web_contents_, this);
86 120
87 // Currently the logic in this class relies on |has_compositor_| remaining 121 // Currently the logic in this class relies on |has_compositor_| remaining
88 // false until the DidInitializeCompositor() call, hence it is not set here. 122 // false until the DidInitializeCompositor() call, hence it is not set here.
89 } 123 }
90 124
91 BrowserViewRenderer::~BrowserViewRenderer() { 125 BrowserViewRenderer::~BrowserViewRenderer() {
92 content::SynchronousCompositor::SetClientForWebContents(web_contents_, NULL); 126 content::SynchronousCompositor::SetClientForWebContents(web_contents_, NULL);
127 // OnDetachedFromWindow should be called before the destructor, so the memory
128 // policy should have already been updated.
129 }
130
131 // This function updates the cached memory policy in shared renderer state, as
132 // well as the tile resource allocation in GlobalTileManager.
133 void BrowserViewRenderer::TrimMemory(const int level, const bool visible) {
134 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
135 // Constants from Android ComponentCallbacks2.
136 enum {
137 TRIM_MEMORY_RUNNING_LOW = 10,
138 TRIM_MEMORY_UI_HIDDEN = 20,
139 TRIM_MEMORY_BACKGROUND = 40,
140 };
141
142 // Not urgent enough. TRIM_MEMORY_UI_HIDDEN is treated specially because
143 // it does not indicate memory pressure, but merely that the app is
144 // backgrounded.
145 if (level < TRIM_MEMORY_RUNNING_LOW || level == TRIM_MEMORY_UI_HIDDEN)
146 return;
147
148 // Do not release resources on view we expect to get DrawGL soon.
149 if (level < TRIM_MEMORY_BACKGROUND && visible)
150 return;
151
152 // Just set the memory limit to 0 and drop all tiles. This will be reset to
153 // normal levels in the next DrawGL call.
154 SynchronousCompositorMemoryPolicy zero_policy;
155 if (shared_renderer_state_->GetMemoryPolicy() == zero_policy)
156 return;
157
158 TRACE_EVENT0("android_webview", "BrowserViewRenderer::TrimMemory");
159
160 RequestMemoryPolicy(zero_policy, true);
161 }
162
163 SynchronousCompositorMemoryPolicy
164 BrowserViewRenderer::CalculateDesiredMemoryPolicy() {
165 SynchronousCompositorMemoryPolicy policy;
166 size_t width = draw_gl_input_.global_visible_rect.width();
167 size_t height = draw_gl_input_.global_visible_rect.height();
168 policy.bytes_limit = kMemoryMultiplier * kBytesPerPixel * width * height;
169 // Round up to a multiple of kMemoryAllocationStep.
170 policy.bytes_limit =
171 (policy.bytes_limit / kMemoryAllocationStep + 1) * kMemoryAllocationStep;
172 policy.num_resources_limit = CalculateTileRequest(width, height);
173 return policy;
174 }
175
176 // This function updates the cached memory policy in shared renderer state, as
177 // well as the tile resource allocation in GlobalTileManager.
178 void BrowserViewRenderer::RequestMemoryPolicy(
179 SynchronousCompositorMemoryPolicy& new_policy,
180 bool effective_immediately) {
181 // This will be used in SetNumTiles.
182 num_bytes_ = new_policy.bytes_limit;
183
184 GlobalTileManager* manager = GlobalTileManager::GetInstance();
185
186 // The following line will call BrowserViewRenderer::SetTilesNum().
187 manager->RequestTiles(
188 new_policy.num_resources_limit, effective_immediately, tile_manager_key_);
189 }
190
191 size_t BrowserViewRenderer::CalculateTileRequest(
boliu 2014/05/02 20:28:34 Don't need this helper, this is only called from o
hush (inactive) 2014/05/02 22:07:40 Done.
192 size_t global_visible_width,
193 size_t global_visible_height) const {
194 double area =
195 static_cast<double>(global_visible_width * global_visible_height);
boliu 2014/05/02 20:28:34 Do we really need to cast it to double? We are rou
hush (inactive) 2014/05/02 22:07:40 (talked in person) I wanted to use double to preve
196 size_t tiles = std::max(area / g_tile_area * kTileMultiplier, 1.0);
197 // Round up to a multiple of kTileAllocationStep. The minimum number of tiles
198 // is also kTileAllocationStep.
199 tiles = (tiles + kTileAllocationStep - 1) / kTileAllocationStep *
200 kTileAllocationStep;
201 return tiles;
202 }
203
204 void BrowserViewRenderer::SetNumTiles(size_t num_tiles,
205 bool effective_immediately) {
206 num_tiles_ = num_tiles;
boliu 2014/05/02 20:28:34 Early out if these two are the same already.
hush (inactive) 2014/05/02 22:07:40 Done.
207
208 SynchronousCompositorMemoryPolicy new_policy;
209 new_policy.num_resources_limit = num_tiles_;
210 new_policy.bytes_limit = num_bytes_;
211 shared_renderer_state_->SetMemoryPolicy(new_policy);
212
213 if (effective_immediately) {
214 shared_renderer_state_->GetCompositor()->SetMemoryPolicy(new_policy);
215 ForceFakeCompositeSW();
boliu 2014/05/02 20:28:34 Set dirty to false after this.
hush (inactive) 2014/05/02 22:07:40 Done.
216 }
217 }
218
219 size_t BrowserViewRenderer::GetNumTiles() const {
220 return shared_renderer_state_->GetMemoryPolicy().num_resources_limit;
93 } 221 }
94 222
95 bool BrowserViewRenderer::OnDraw(jobject java_canvas, 223 bool BrowserViewRenderer::OnDraw(jobject java_canvas,
96 bool is_hardware_canvas, 224 bool is_hardware_canvas,
97 const gfx::Vector2d& scroll, 225 const gfx::Vector2d& scroll,
98 const gfx::Rect& global_visible_rect, 226 const gfx::Rect& global_visible_rect,
99 const gfx::Rect& clip) { 227 const gfx::Rect& clip) {
100 draw_gl_input_.frame_id++; 228 draw_gl_input_.frame_id++;
101 draw_gl_input_.scroll_offset = scroll; 229 draw_gl_input_.scroll_offset = scroll;
102 draw_gl_input_.global_visible_rect = global_visible_rect; 230 draw_gl_input_.global_visible_rect = global_visible_rect;
103 draw_gl_input_.width = width_; 231 draw_gl_input_.width = width_;
104 draw_gl_input_.height = height_; 232 draw_gl_input_.height = height_;
105 if (clear_view_) 233 if (clear_view_)
106 return false; 234 return false;
107 if (is_hardware_canvas && attached_to_window_) { 235 if (is_hardware_canvas && attached_to_window_) {
108 shared_renderer_state_->SetDrawGLInput(draw_gl_input_); 236 shared_renderer_state_->SetDrawGLInput(draw_gl_input_);
237
238 SynchronousCompositorMemoryPolicy old_policy =
239 shared_renderer_state_->GetMemoryPolicy();
240 SynchronousCompositorMemoryPolicy new_policy =
241 CalculateDesiredMemoryPolicy();
242 RequestMemoryPolicy(new_policy, false);
109 // We should be performing a hardware draw here. If we don't have the 243 // We should be performing a hardware draw here. If we don't have the
110 // compositor yet or if RequestDrawGL fails, it means we failed this draw 244 // compositor yet or if RequestDrawGL fails, it means we failed this draw
111 // and thus return false here to clear to background color for this draw. 245 // and thus return false here to clear to background color for this draw.
112 return has_compositor_ && client_->RequestDrawGL(java_canvas, false); 246 bool did_draw_gl =
247 has_compositor_ && client_->RequestDrawGL(java_canvas, false);
248 if (did_draw_gl)
249 GlobalTileManager::GetInstance()->DidUse(tile_manager_key_);
250 else
251 RequestMemoryPolicy(old_policy, false);
252
253 return did_draw_gl;
113 } 254 }
114 // Perform a software draw 255 // Perform a software draw
115 return DrawSWInternal(java_canvas, clip); 256 return DrawSWInternal(java_canvas, clip);
116 } 257 }
117 258
118 void BrowserViewRenderer::DidDrawGL(const DrawGLResult& result) { 259 void BrowserViewRenderer::DidDrawGL(const DrawGLResult& result) {
119 DidComposite(!result.clip_contains_visible_rect); 260 DidComposite(!result.clip_contains_visible_rect);
120 } 261 }
121 262
122 bool BrowserViewRenderer::DrawSWInternal(jobject java_canvas, 263 bool BrowserViewRenderer::DrawSWInternal(jobject java_canvas,
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
223 void BrowserViewRenderer::OnAttachedToWindow(int width, int height) { 364 void BrowserViewRenderer::OnAttachedToWindow(int width, int height) {
224 TRACE_EVENT2("android_webview", 365 TRACE_EVENT2("android_webview",
225 "BrowserViewRenderer::OnAttachedToWindow", 366 "BrowserViewRenderer::OnAttachedToWindow",
226 "width", 367 "width",
227 width, 368 width,
228 "height", 369 "height",
229 height); 370 height);
230 attached_to_window_ = true; 371 attached_to_window_ = true;
231 width_ = width; 372 width_ = width;
232 height_ = height; 373 height_ = height;
374 tile_manager_key_ = GlobalTileManager::GetInstance()->PushBack(this);
233 } 375 }
234 376
235 void BrowserViewRenderer::OnDetachedFromWindow() { 377 void BrowserViewRenderer::OnDetachedFromWindow() {
236 TRACE_EVENT0("android_webview", "BrowserViewRenderer::OnDetachedFromWindow"); 378 TRACE_EVENT0("android_webview", "BrowserViewRenderer::OnDetachedFromWindow");
237 attached_to_window_ = false; 379 attached_to_window_ = false;
380 SynchronousCompositorMemoryPolicy zero_policy;
381 RequestMemoryPolicy(zero_policy, true);
boliu 2014/05/02 20:28:34 Hmm, right now we don't need effective_immediately
hush (inactive) 2014/05/02 22:07:40 Done.
382 GlobalTileManager::GetInstance()->Remove(tile_manager_key_);
383 // The hardware resources are released in the destructor of hardware renderer,
384 // so we don't need to do it here.
385 // See AwContents::ReleaseHardwareDrawOnRenderThread(JNIEnv*, jobject).
238 } 386 }
239 387
240 bool BrowserViewRenderer::IsAttachedToWindow() const { 388 bool BrowserViewRenderer::IsAttachedToWindow() const {
241 return attached_to_window_; 389 return attached_to_window_;
242 } 390 }
243 391
244 bool BrowserViewRenderer::IsVisible() const { 392 bool BrowserViewRenderer::IsVisible() const {
245 // Ignore |window_visible_| if |attached_to_window_| is false. 393 // Ignore |window_visible_| if |attached_to_window_| is false.
246 return view_visible_ && (!attached_to_window_ || window_visible_); 394 return view_visible_ && (!attached_to_window_ || window_visible_);
247 } 395 }
(...skipping 13 matching lines...) Expand all
261 shared_renderer_state_->SetCompositorOnUiThread(compositor); 409 shared_renderer_state_->SetCompositorOnUiThread(compositor);
262 } 410 }
263 411
264 void BrowserViewRenderer::DidDestroyCompositor( 412 void BrowserViewRenderer::DidDestroyCompositor(
265 content::SynchronousCompositor* compositor) { 413 content::SynchronousCompositor* compositor) {
266 TRACE_EVENT0("android_webview", "BrowserViewRenderer::DidDestroyCompositor"); 414 TRACE_EVENT0("android_webview", "BrowserViewRenderer::DidDestroyCompositor");
267 DCHECK(has_compositor_); 415 DCHECK(has_compositor_);
268 DCHECK(ui_task_runner_->BelongsToCurrentThread()); 416 DCHECK(ui_task_runner_->BelongsToCurrentThread());
269 has_compositor_ = false; 417 has_compositor_ = false;
270 shared_renderer_state_->SetCompositorOnUiThread(NULL); 418 shared_renderer_state_->SetCompositorOnUiThread(NULL);
419 SynchronousCompositorMemoryPolicy zero_policy;
420 DCHECK(shared_renderer_state_->GetMemoryPolicy() == zero_policy);
271 } 421 }
272 422
273 void BrowserViewRenderer::SetContinuousInvalidate(bool invalidate) { 423 void BrowserViewRenderer::SetContinuousInvalidate(bool invalidate) {
274 if (!ui_task_runner_->BelongsToCurrentThread()) { 424 if (!ui_task_runner_->BelongsToCurrentThread()) {
275 ui_task_runner_->PostTask( 425 ui_task_runner_->PostTask(
276 FROM_HERE, 426 FROM_HERE,
277 base::Bind(&BrowserViewRenderer::SetContinuousInvalidate, 427 base::Bind(&BrowserViewRenderer::SetContinuousInvalidate,
278 ui_thread_weak_ptr_, 428 ui_thread_weak_ptr_,
279 invalidate)); 429 invalidate));
280 return; 430 return;
(...skipping 317 matching lines...) Expand 10 before | Expand all | Expand 10 after
598 base::StringAppendF(&str, 748 base::StringAppendF(&str,
599 "surface width height: [%d %d] ", 749 "surface width height: [%d %d] ",
600 draw_info->width, 750 draw_info->width,
601 draw_info->height); 751 draw_info->height);
602 base::StringAppendF(&str, "is_layer: %d ", draw_info->is_layer); 752 base::StringAppendF(&str, "is_layer: %d ", draw_info->is_layer);
603 } 753 }
604 return str; 754 return str;
605 } 755 }
606 756
607 } // namespace android_webview 757 } // namespace android_webview
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698