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

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: Rewrote the API for GlobalTileManager and Client. 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 "third_party/skia/include/core/SkPictureRecorder.h" 21 #include "third_party/skia/include/core/SkPictureRecorder.h"
21 #include "ui/gfx/vector2d_conversions.h" 22 #include "ui/gfx/vector2d_conversions.h"
22 23
23 using base::android::AttachCurrentThread; 24 using base::android::AttachCurrentThread;
24 using base::android::JavaRef; 25 using base::android::JavaRef;
25 using base::android::ScopedJavaLocalRef; 26 using base::android::ScopedJavaLocalRef;
27 using content::BrowserThread;
28 using content::SynchronousCompositorMemoryPolicy;
26 29
27 namespace android_webview { 30 namespace android_webview {
28 31
29 namespace { 32 namespace {
30 33
31 const int64 kFallbackTickTimeoutInMilliseconds = 20; 34 const int64 kFallbackTickTimeoutInMilliseconds = 20;
32 35
36 // Used to calculate memory allocation. Determined experimentally.
37 const size_t kMemoryMultiplier = 10;
38 const size_t kBytesPerPixel = 4;
39 const size_t kMemoryAllocationStep = 5 * 1024 * 1024;
40
41 // Used to calculate tile allocatino. Determined experimentally.
42 const size_t kTileMultiplier = 12;
43 const size_t kTileAllocationStep = 20;
44 const size_t kTileArea = 372 * 372;
boliu 2014/05/02 17:54:34 I lied, it's kDefaultTileSize in HR, which is 384.
45
33 class AutoResetWithLock { 46 class AutoResetWithLock {
34 public: 47 public:
35 AutoResetWithLock(gfx::Vector2dF* scoped_variable, 48 AutoResetWithLock(gfx::Vector2dF* scoped_variable,
36 gfx::Vector2dF new_value, 49 gfx::Vector2dF new_value,
37 base::Lock& lock) 50 base::Lock& lock)
38 : scoped_variable_(scoped_variable), 51 : scoped_variable_(scoped_variable),
39 original_value_(*scoped_variable), 52 original_value_(*scoped_variable),
40 lock_(lock) { 53 lock_(lock) {
41 base::AutoLock auto_lock(lock_); 54 base::AutoLock auto_lock(lock_);
42 *scoped_variable_ = new_value; 55 *scoped_variable_ = new_value;
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
83 height_(0) { 96 height_(0) {
84 CHECK(web_contents_); 97 CHECK(web_contents_);
85 content::SynchronousCompositor::SetClientForWebContents(web_contents_, this); 98 content::SynchronousCompositor::SetClientForWebContents(web_contents_, this);
86 99
87 // Currently the logic in this class relies on |has_compositor_| remaining 100 // Currently the logic in this class relies on |has_compositor_| remaining
88 // false until the DidInitializeCompositor() call, hence it is not set here. 101 // false until the DidInitializeCompositor() call, hence it is not set here.
89 } 102 }
90 103
91 BrowserViewRenderer::~BrowserViewRenderer() { 104 BrowserViewRenderer::~BrowserViewRenderer() {
92 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, true);
140 }
141
142 SynchronousCompositorMemoryPolicy
143 BrowserViewRenderer::CalculateDesiredMemoryPolicy() {
144 SynchronousCompositorMemoryPolicy policy;
145 size_t width = draw_gl_input_.global_visible_rect.width();
146 size_t height = draw_gl_input_.global_visible_rect.height();
147 policy.bytes_limit = kMemoryMultiplier * kBytesPerPixel * width * height;
148 // Round up to a multiple of kMemoryAllocationStep.
149 policy.bytes_limit =
150 (policy.bytes_limit / kMemoryAllocationStep + 1) * kMemoryAllocationStep;
151 policy.num_resources_limit = CalculateTileRequest(width, height);
152 return policy;
153 }
154
155 // This function updates the cached memory policy in shared renderer state, as
156 // well as the tile resource allocation in GlobalTileManager.
157 void BrowserViewRenderer::RequestMemoryPolicy(
158 SynchronousCompositorMemoryPolicy& new_policy,
159 bool effective_immediately) {
160 // This will be used in SetNumTiles.
161 num_bytes_ = new_policy.bytes_limit;
162
163 GlobalTileManager* manager = GlobalTileManager::GetInstance();
164
165 // The following line will call BrowserViewRenderer::SetTilesNum().
166 manager->RequestTiles(
167 new_policy.num_resources_limit, effective_immediately, tile_manager_key_);
168 }
169
170 size_t BrowserViewRenderer::CalculateTileRequest(
171 size_t global_visible_width,
172 size_t global_visible_height) const {
173 double area =
174 static_cast<double>(global_visible_width * global_visible_height);
175 size_t tiles = std::max(area / kTileArea * kTileMultiplier, 1.0);
176 // Round up to a multiple of kTileAllocationStep. The minimum number of tiles
177 // is also kTileAllocationStep.
178 tiles = (tiles + kTileAllocationStep - 1) / kTileAllocationStep *
179 kTileAllocationStep;
180 return tiles;
181 }
182
183 void BrowserViewRenderer::SetNumTiles(size_t num_tiles,
184 bool effective_immediately) {
185 num_tiles_ = num_tiles;
186
187 SynchronousCompositorMemoryPolicy new_policy;
188 new_policy.num_resources_limit = num_tiles_;
189 new_policy.bytes_limit = num_bytes_;
190 shared_renderer_state_->SetMemoryPolicy(new_policy);
191
192 if (effective_immediately) {
193 shared_renderer_state_->GetCompositor()->SetMemoryPolicy(new_policy);
194 ForceFakeCompositeSW();
195 }
196 }
197
198 size_t BrowserViewRenderer::GetNumTiles() const {
199 return shared_renderer_state_->GetMemoryPolicy().num_resources_limit;
93 } 200 }
94 201
95 bool BrowserViewRenderer::OnDraw(jobject java_canvas, 202 bool BrowserViewRenderer::OnDraw(jobject java_canvas,
96 bool is_hardware_canvas, 203 bool is_hardware_canvas,
97 const gfx::Vector2d& scroll, 204 const gfx::Vector2d& scroll,
98 const gfx::Rect& global_visible_rect, 205 const gfx::Rect& global_visible_rect,
99 const gfx::Rect& clip) { 206 const gfx::Rect& clip) {
100 draw_gl_input_.frame_id++; 207 draw_gl_input_.frame_id++;
101 draw_gl_input_.scroll_offset = scroll; 208 draw_gl_input_.scroll_offset = scroll;
102 draw_gl_input_.global_visible_rect = global_visible_rect; 209 draw_gl_input_.global_visible_rect = global_visible_rect;
103 draw_gl_input_.width = width_; 210 draw_gl_input_.width = width_;
104 draw_gl_input_.height = height_; 211 draw_gl_input_.height = height_;
105 if (clear_view_) 212 if (clear_view_)
106 return false; 213 return false;
107 if (is_hardware_canvas && attached_to_window_) { 214 if (is_hardware_canvas && attached_to_window_) {
108 shared_renderer_state_->SetDrawGLInput(draw_gl_input_); 215 shared_renderer_state_->SetDrawGLInput(draw_gl_input_);
216
217 SynchronousCompositorMemoryPolicy old_policy =
218 shared_renderer_state_->GetMemoryPolicy();
219 SynchronousCompositorMemoryPolicy new_policy =
220 CalculateDesiredMemoryPolicy();
221 RequestMemoryPolicy(new_policy, false);
109 // We should be performing a hardware draw here. If we don't have the 222 // 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 223 // 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. 224 // and thus return false here to clear to background color for this draw.
112 return has_compositor_ && client_->RequestDrawGL(java_canvas, false); 225 bool did_draw_gl =
226 has_compositor_ && client_->RequestDrawGL(java_canvas, false);
227 if (did_draw_gl)
228 GlobalTileManager::GetInstance()->DidUse(tile_manager_key_);
229 else
230 RequestMemoryPolicy(old_policy, false);
231
232 return did_draw_gl;
113 } 233 }
114 // Perform a software draw 234 // Perform a software draw
115 return DrawSWInternal(java_canvas, clip); 235 return DrawSWInternal(java_canvas, clip);
116 } 236 }
117 237
118 void BrowserViewRenderer::DidDrawGL(const DrawGLResult& result) { 238 void BrowserViewRenderer::DidDrawGL(const DrawGLResult& result) {
119 DidComposite(!result.clip_contains_visible_rect); 239 DidComposite(!result.clip_contains_visible_rect);
120 } 240 }
121 241
122 bool BrowserViewRenderer::DrawSWInternal(jobject java_canvas, 242 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) { 343 void BrowserViewRenderer::OnAttachedToWindow(int width, int height) {
224 TRACE_EVENT2("android_webview", 344 TRACE_EVENT2("android_webview",
225 "BrowserViewRenderer::OnAttachedToWindow", 345 "BrowserViewRenderer::OnAttachedToWindow",
226 "width", 346 "width",
227 width, 347 width,
228 "height", 348 "height",
229 height); 349 height);
230 attached_to_window_ = true; 350 attached_to_window_ = true;
231 width_ = width; 351 width_ = width;
232 height_ = height; 352 height_ = height;
353 tile_manager_key_ = GlobalTileManager::GetInstance()->PushBack(this);
233 } 354 }
234 355
235 void BrowserViewRenderer::OnDetachedFromWindow() { 356 void BrowserViewRenderer::OnDetachedFromWindow() {
236 TRACE_EVENT0("android_webview", "BrowserViewRenderer::OnDetachedFromWindow"); 357 TRACE_EVENT0("android_webview", "BrowserViewRenderer::OnDetachedFromWindow");
237 attached_to_window_ = false; 358 attached_to_window_ = false;
359 SynchronousCompositorMemoryPolicy zero_policy;
360 RequestMemoryPolicy(zero_policy, true);
361 GlobalTileManager::GetInstance()->Remove(tile_manager_key_);
362 // The hardware resources are released in the destructor of hardware renderer,
363 // so we don't need to do it here.
364 // See AwContents::ReleaseHardwareDrawOnRenderThread(JNIEnv*, jobject).
238 } 365 }
239 366
240 bool BrowserViewRenderer::IsAttachedToWindow() const { 367 bool BrowserViewRenderer::IsAttachedToWindow() const {
241 return attached_to_window_; 368 return attached_to_window_;
242 } 369 }
243 370
244 bool BrowserViewRenderer::IsVisible() const { 371 bool BrowserViewRenderer::IsVisible() const {
245 // Ignore |window_visible_| if |attached_to_window_| is false. 372 // Ignore |window_visible_| if |attached_to_window_| is false.
246 return view_visible_ && (!attached_to_window_ || window_visible_); 373 return view_visible_ && (!attached_to_window_ || window_visible_);
247 } 374 }
(...skipping 13 matching lines...) Expand all
261 shared_renderer_state_->SetCompositorOnUiThread(compositor); 388 shared_renderer_state_->SetCompositorOnUiThread(compositor);
262 } 389 }
263 390
264 void BrowserViewRenderer::DidDestroyCompositor( 391 void BrowserViewRenderer::DidDestroyCompositor(
265 content::SynchronousCompositor* compositor) { 392 content::SynchronousCompositor* compositor) {
266 TRACE_EVENT0("android_webview", "BrowserViewRenderer::DidDestroyCompositor"); 393 TRACE_EVENT0("android_webview", "BrowserViewRenderer::DidDestroyCompositor");
267 DCHECK(has_compositor_); 394 DCHECK(has_compositor_);
268 DCHECK(ui_task_runner_->BelongsToCurrentThread()); 395 DCHECK(ui_task_runner_->BelongsToCurrentThread());
269 has_compositor_ = false; 396 has_compositor_ = false;
270 shared_renderer_state_->SetCompositorOnUiThread(NULL); 397 shared_renderer_state_->SetCompositorOnUiThread(NULL);
398 SynchronousCompositorMemoryPolicy zero_policy;
399 DCHECK(shared_renderer_state_->GetMemoryPolicy() == zero_policy);
271 } 400 }
272 401
273 void BrowserViewRenderer::SetContinuousInvalidate(bool invalidate) { 402 void BrowserViewRenderer::SetContinuousInvalidate(bool invalidate) {
274 if (!ui_task_runner_->BelongsToCurrentThread()) { 403 if (!ui_task_runner_->BelongsToCurrentThread()) {
275 ui_task_runner_->PostTask( 404 ui_task_runner_->PostTask(
276 FROM_HERE, 405 FROM_HERE,
277 base::Bind(&BrowserViewRenderer::SetContinuousInvalidate, 406 base::Bind(&BrowserViewRenderer::SetContinuousInvalidate,
278 ui_thread_weak_ptr_, 407 ui_thread_weak_ptr_,
279 invalidate)); 408 invalidate));
280 return; 409 return;
(...skipping 317 matching lines...) Expand 10 before | Expand all | Expand 10 after
598 base::StringAppendF(&str, 727 base::StringAppendF(&str,
599 "surface width height: [%d %d] ", 728 "surface width height: [%d %d] ",
600 draw_info->width, 729 draw_info->width,
601 draw_info->height); 730 draw_info->height);
602 base::StringAppendF(&str, "is_layer: %d ", draw_info->is_layer); 731 base::StringAppendF(&str, "is_layer: %d ", draw_info->is_layer);
603 } 732 }
604 return str; 733 return str;
605 } 734 }
606 735
607 } // namespace android_webview 736 } // namespace android_webview
OLDNEW
« no previous file with comments | « android_webview/browser/browser_view_renderer.h ('k') | android_webview/browser/global_tile_manager.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698