blob: 505919d9d87ce5fa434524c40d89c4962fd00599 [file] [log] [blame]
[email protected]23063762014-02-26 01:01:561// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "android_webview/browser/browser_view_renderer.h"
6
[email protected]e4a0b192014-02-27 01:47:057#include "android_webview/browser/browser_view_renderer_client.h"
[email protected]e4a0b192014-02-27 01:47:058#include "android_webview/browser/shared_renderer_state.h"
[email protected]be4bd27a2014-07-11 20:10:319#include "android_webview/common/aw_switches.h"
[email protected]23063762014-02-26 01:01:5610#include "android_webview/public/browser/draw_gl.h"
11#include "base/android/jni_android.h"
12#include "base/auto_reset.h"
[email protected]7d67302a2014-05-03 02:17:0713#include "base/command_line.h"
[email protected]23063762014-02-26 01:01:5614#include "base/debug/trace_event.h"
[email protected]ec2322e2014-05-15 16:32:0015#include "base/json/json_writer.h"
[email protected]23063762014-02-26 01:01:5616#include "base/logging.h"
[email protected]7d67302a2014-05-03 02:17:0717#include "base/strings/string_number_conversions.h"
[email protected]23063762014-02-26 01:01:5618#include "base/strings/stringprintf.h"
[email protected]8705654b2014-05-24 01:16:1919#include "cc/output/compositor_frame.h"
[email protected]7d67302a2014-05-03 02:17:0720#include "content/public/browser/browser_thread.h"
[email protected]23063762014-02-26 01:01:5621#include "content/public/browser/web_contents.h"
[email protected]7d67302a2014-05-03 02:17:0722#include "content/public/common/content_switches.h"
boliu6be0a9122014-08-29 18:59:1023#include "gpu/command_buffer/service/gpu_switches.h"
[email protected]23063762014-02-26 01:01:5624#include "third_party/skia/include/core/SkBitmap.h"
[email protected]23063762014-02-26 01:01:5625#include "third_party/skia/include/core/SkCanvas.h"
26#include "third_party/skia/include/core/SkPicture.h"
[email protected]1dfaaff2014-04-30 14:54:5927#include "third_party/skia/include/core/SkPictureRecorder.h"
[email protected]23063762014-02-26 01:01:5628#include "ui/gfx/vector2d_conversions.h"
29
30using base::android::AttachCurrentThread;
31using base::android::JavaRef;
32using base::android::ScopedJavaLocalRef;
[email protected]7d67302a2014-05-03 02:17:0733using content::BrowserThread;
34using content::SynchronousCompositorMemoryPolicy;
[email protected]23063762014-02-26 01:01:5635
36namespace android_webview {
37
38namespace {
39
[email protected]691ac7a2014-06-27 19:09:4940const int64 kFallbackTickTimeoutInMilliseconds = 100;
[email protected]23063762014-02-26 01:01:5641
[email protected]7d67302a2014-05-03 02:17:0742// Used to calculate memory allocation. Determined experimentally.
[email protected]14f7a8b2014-07-03 03:44:5143const size_t kMemoryMultiplier = 20;
[email protected]7d67302a2014-05-03 02:17:0744const size_t kBytesPerPixel = 4;
45const size_t kMemoryAllocationStep = 5 * 1024 * 1024;
boliu6be0a9122014-08-29 18:59:1046uint64 g_memory_override_in_bytes = 0u;
[email protected]7d67302a2014-05-03 02:17:0747
48// Used to calculate tile allocation. Determined experimentally.
49const size_t kTileMultiplier = 12;
50const size_t kTileAllocationStep = 20;
51// This will be set by static function CalculateTileMemoryPolicy() during init.
52// See AwMainDelegate::BasicStartupComplete.
53size_t g_tile_area;
54
[email protected]ec2322e2014-05-15 16:32:0055class TracedValue : public base::debug::ConvertableToTraceFormat {
56 public:
57 explicit TracedValue(base::Value* value) : value_(value) {}
58 static scoped_refptr<base::debug::ConvertableToTraceFormat> FromValue(
59 base::Value* value) {
60 return scoped_refptr<base::debug::ConvertableToTraceFormat>(
61 new TracedValue(value));
62 }
63 virtual void AppendAsTraceFormat(std::string* out) const OVERRIDE {
64 std::string tmp;
65 base::JSONWriter::Write(value_.get(), &tmp);
66 *out += tmp;
67 }
68
69 private:
70 virtual ~TracedValue() {}
71 scoped_ptr<base::Value> value_;
72
73 DISALLOW_COPY_AND_ASSIGN(TracedValue);
74};
75
[email protected]23063762014-02-26 01:01:5676} // namespace
77
[email protected]7d67302a2014-05-03 02:17:0778// static
revemanec103f02014-09-29 19:12:3179void BrowserViewRenderer::CalculateTileMemoryPolicy() {
boliu6be0a9122014-08-29 18:59:1080 CommandLine* cl = CommandLine::ForCurrentProcess();
81
82 // If the value was overridden on the command line, use the specified value.
83 bool client_hard_limit_bytes_overridden =
84 cl->HasSwitch(switches::kForceGpuMemAvailableMb);
85 if (client_hard_limit_bytes_overridden) {
86 base::StringToUint64(
87 base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
88 switches::kForceGpuMemAvailableMb),
89 &g_memory_override_in_bytes);
90 g_memory_override_in_bytes *= 1024 * 1024;
91 }
92
revemanec103f02014-09-29 19:12:3193 // Use chrome's default tile size, which varies from 256 to 512.
94 // Be conservative here and use the smallest tile size possible.
95 g_tile_area = 256 * 256;
[email protected]a373757bf52014-08-01 01:55:5896
revemanec103f02014-09-29 19:12:3197 // Also use a high tile limit since there are no file descriptor issues.
98 GlobalTileManager::GetInstance()->SetTileLimit(1000);
[email protected]7d67302a2014-05-03 02:17:0799}
100
[email protected]e4a0b192014-02-27 01:47:05101BrowserViewRenderer::BrowserViewRenderer(
102 BrowserViewRendererClient* client,
103 SharedRendererState* shared_renderer_state,
[email protected]596f7e72014-03-21 20:03:26104 content::WebContents* web_contents,
105 const scoped_refptr<base::SingleThreadTaskRunner>& ui_task_runner)
[email protected]23063762014-02-26 01:01:56106 : client_(client),
[email protected]e4a0b192014-02-27 01:47:05107 shared_renderer_state_(shared_renderer_state),
[email protected]23063762014-02-26 01:01:56108 web_contents_(web_contents),
[email protected]596f7e72014-03-21 20:03:26109 ui_task_runner_(ui_task_runner),
[email protected]7a461432014-06-17 23:50:12110 compositor_(NULL),
[email protected]23063762014-02-26 01:01:56111 is_paused_(false),
112 view_visible_(false),
113 window_visible_(false),
114 attached_to_window_(false),
[email protected]8705654b2014-05-24 01:16:19115 hardware_enabled_(false),
[email protected]23063762014-02-26 01:01:56116 dip_scale_(0.0),
117 page_scale_factor_(1.0),
118 on_new_picture_enable_(false),
119 clear_view_(false),
120 compositor_needs_continuous_invalidate_(false),
121 block_invalidates_(false),
122 width_(0),
hush550317a2014-09-17 19:59:50123 height_(0) {
[email protected]23063762014-02-26 01:01:56124 CHECK(web_contents_);
125 content::SynchronousCompositor::SetClientForWebContents(web_contents_, this);
126
[email protected]7a461432014-06-17 23:50:12127 // Currently the logic in this class relies on |compositor_| remaining
128 // NULL until the DidInitializeCompositor() call, hence it is not set here.
[email protected]23063762014-02-26 01:01:56129}
130
131BrowserViewRenderer::~BrowserViewRenderer() {
132 content::SynchronousCompositor::SetClientForWebContents(web_contents_, NULL);
[email protected]7d67302a2014-05-03 02:17:07133 // OnDetachedFromWindow should be called before the destructor, so the memory
134 // policy should have already been updated.
135}
136
hush947fb1c2014-09-10 19:10:38137// This function updates the resource allocation in GlobalTileManager.
[email protected]7d67302a2014-05-03 02:17:07138void BrowserViewRenderer::TrimMemory(const int level, const bool visible) {
139 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
140 // Constants from Android ComponentCallbacks2.
141 enum {
142 TRIM_MEMORY_RUNNING_LOW = 10,
143 TRIM_MEMORY_UI_HIDDEN = 20,
144 TRIM_MEMORY_BACKGROUND = 40,
145 };
146
147 // Not urgent enough. TRIM_MEMORY_UI_HIDDEN is treated specially because
148 // it does not indicate memory pressure, but merely that the app is
149 // backgrounded.
150 if (level < TRIM_MEMORY_RUNNING_LOW || level == TRIM_MEMORY_UI_HIDDEN)
151 return;
152
153 // Do not release resources on view we expect to get DrawGL soon.
154 if (level < TRIM_MEMORY_BACKGROUND && visible)
155 return;
156
157 // Just set the memory limit to 0 and drop all tiles. This will be reset to
158 // normal levels in the next DrawGL call.
159 SynchronousCompositorMemoryPolicy zero_policy;
[email protected]7a461432014-06-17 23:50:12160 if (memory_policy_ == zero_policy)
[email protected]7d67302a2014-05-03 02:17:07161 return;
162
163 TRACE_EVENT0("android_webview", "BrowserViewRenderer::TrimMemory");
164
165 RequestMemoryPolicy(zero_policy);
166 EnforceMemoryPolicyImmediately(zero_policy);
167}
168
169SynchronousCompositorMemoryPolicy
170BrowserViewRenderer::CalculateDesiredMemoryPolicy() {
171 SynchronousCompositorMemoryPolicy policy;
[email protected]8705654b2014-05-24 01:16:19172 size_t width = last_on_draw_global_visible_rect_.width();
173 size_t height = last_on_draw_global_visible_rect_.height();
[email protected]7d67302a2014-05-03 02:17:07174 policy.bytes_limit = kMemoryMultiplier * kBytesPerPixel * width * height;
175 // Round up to a multiple of kMemoryAllocationStep.
176 policy.bytes_limit =
177 (policy.bytes_limit / kMemoryAllocationStep + 1) * kMemoryAllocationStep;
178
boliu6be0a9122014-08-29 18:59:10179 if (g_memory_override_in_bytes)
180 policy.bytes_limit = static_cast<size_t>(g_memory_override_in_bytes);
181
[email protected]a73bb2c2014-05-04 18:48:57182 size_t tiles = width * height * kTileMultiplier / g_tile_area;
[email protected]7d67302a2014-05-03 02:17:07183 // Round up to a multiple of kTileAllocationStep. The minimum number of tiles
184 // is also kTileAllocationStep.
[email protected]a73bb2c2014-05-04 18:48:57185 tiles = (tiles / kTileAllocationStep + 1) * kTileAllocationStep;
[email protected]7d67302a2014-05-03 02:17:07186 policy.num_resources_limit = tiles;
187 return policy;
188}
189
190// This function updates the cached memory policy in shared renderer state, as
191// well as the tile resource allocation in GlobalTileManager.
192void BrowserViewRenderer::RequestMemoryPolicy(
193 SynchronousCompositorMemoryPolicy& new_policy) {
[email protected]7d67302a2014-05-03 02:17:07194 GlobalTileManager* manager = GlobalTileManager::GetInstance();
195
hush550317a2014-09-17 19:59:50196 // The following line will call BrowserViewRenderer::SetMemoryPolicy().
197 manager->RequestTiles(new_policy, tile_manager_key_);
[email protected]7d67302a2014-05-03 02:17:07198}
199
hush550317a2014-09-17 19:59:50200void BrowserViewRenderer::SetMemoryPolicy(
201 SynchronousCompositorMemoryPolicy new_policy,
202 bool effective_immediately) {
203 memory_policy_ = new_policy;
[email protected]7d67302a2014-05-03 02:17:07204 if (effective_immediately)
[email protected]7a461432014-06-17 23:50:12205 EnforceMemoryPolicyImmediately(memory_policy_);
[email protected]7d67302a2014-05-03 02:17:07206}
207
208void BrowserViewRenderer::EnforceMemoryPolicyImmediately(
209 SynchronousCompositorMemoryPolicy new_policy) {
[email protected]7a461432014-06-17 23:50:12210 compositor_->SetMemoryPolicy(new_policy);
[email protected]7d67302a2014-05-03 02:17:07211 ForceFakeCompositeSW();
[email protected]7d67302a2014-05-03 02:17:07212}
213
hush550317a2014-09-17 19:59:50214SynchronousCompositorMemoryPolicy BrowserViewRenderer::GetMemoryPolicy() const {
215 return memory_policy_;
[email protected]23063762014-02-26 01:01:56216}
217
[email protected]23063762014-02-26 01:01:56218bool BrowserViewRenderer::OnDraw(jobject java_canvas,
219 bool is_hardware_canvas,
220 const gfx::Vector2d& scroll,
[email protected]abf9d8a12014-07-14 23:40:09221 const gfx::Rect& global_visible_rect) {
[email protected]8705654b2014-05-24 01:16:19222 last_on_draw_scroll_offset_ = scroll;
223 last_on_draw_global_visible_rect_ = global_visible_rect;
224
[email protected]23063762014-02-26 01:01:56225 if (clear_view_)
226 return false;
[email protected]8705654b2014-05-24 01:16:19227
[email protected]be4bd27a2014-07-11 20:10:31228 if (is_hardware_canvas && attached_to_window_ &&
229 !switches::ForceAuxiliaryBitmap()) {
[email protected]7a461432014-06-17 23:50:12230 return OnDrawHardware(java_canvas);
[email protected]be4bd27a2014-07-11 20:10:31231 }
232
[email protected]23063762014-02-26 01:01:56233 // Perform a software draw
[email protected]abf9d8a12014-07-14 23:40:09234 return OnDrawSoftware(java_canvas);
[email protected]23063762014-02-26 01:01:56235}
236
[email protected]8705654b2014-05-24 01:16:19237bool BrowserViewRenderer::OnDrawHardware(jobject java_canvas) {
boliu9b78e172014-09-20 13:18:06238 TRACE_EVENT0("android_webview", "BrowserViewRenderer::OnDrawHardware");
[email protected]7a461432014-06-17 23:50:12239 if (!compositor_)
[email protected]8705654b2014-05-24 01:16:19240 return false;
241
boliu9b78e172014-09-20 13:18:06242 if (last_on_draw_global_visible_rect_.IsEmpty()) {
243 TRACE_EVENT_INSTANT0("android_webview",
244 "EarlyOut_EmptyVisibleRect",
245 TRACE_EVENT_SCOPE_THREAD);
hush673cf012014-09-25 00:20:01246 shared_renderer_state_->SetForceInvalidateOnNextDrawGL(true);
boliu693c6a02014-09-10 03:31:02247 return client_->RequestDrawGL(java_canvas, false);
boliu9b78e172014-09-20 13:18:06248 }
boliu693c6a02014-09-10 03:31:02249
[email protected]8705654b2014-05-24 01:16:19250 if (!hardware_enabled_) {
[email protected]7a461432014-06-17 23:50:12251 hardware_enabled_ = compositor_->InitializeHwDraw();
[email protected]8705654b2014-05-24 01:16:19252 if (hardware_enabled_) {
[email protected]686474c72014-07-22 02:09:50253 tile_manager_key_ = GlobalTileManager::GetInstance()->PushBack(this);
[email protected]8705654b2014-05-24 01:16:19254 }
255 }
256 if (!hardware_enabled_)
257 return false;
258
[email protected]c62fc982014-06-27 04:49:02259 ReturnResourceFromParent();
[email protected]8705654b2014-05-24 01:16:19260 SynchronousCompositorMemoryPolicy new_policy = CalculateDesiredMemoryPolicy();
261 RequestMemoryPolicy(new_policy);
[email protected]7a461432014-06-17 23:50:12262 compositor_->SetMemoryPolicy(memory_policy_);
[email protected]8705654b2014-05-24 01:16:19263
boliu9b78e172014-09-20 13:18:06264 if (shared_renderer_state_->HasDrawGLInput()) {
265 TRACE_EVENT_INSTANT0("android_webview",
266 "EarlyOut_PreviousFrameUnconsumed",
267 TRACE_EVENT_SCOPE_THREAD);
268 // TODO(boliu): Rename this method. We didn't actually composite here.
269 DidComposite();
270 return client_->RequestDrawGL(java_canvas, false);
271 }
272
[email protected]8705654b2014-05-24 01:16:19273 scoped_ptr<DrawGLInput> draw_gl_input(new DrawGLInput);
274 draw_gl_input->scroll_offset = last_on_draw_scroll_offset_;
[email protected]8705654b2014-05-24 01:16:19275 draw_gl_input->width = width_;
276 draw_gl_input->height = height_;
277
[email protected]bd5324592014-07-31 09:09:33278 parent_draw_constraints_ = shared_renderer_state_->ParentDrawConstraints();
[email protected]8705654b2014-05-24 01:16:19279 gfx::Size surface_size(width_, height_);
280 gfx::Rect viewport(surface_size);
[email protected]8705654b2014-05-24 01:16:19281 gfx::Rect clip = viewport;
[email protected]bd5324592014-07-31 09:09:33282 gfx::Transform transform_for_tile_priority =
283 parent_draw_constraints_.transform;
284
285 // If the WebView is on a layer, WebView does not know what transform is
286 // applied onto the layer so global visible rect does not make sense here.
287 // In this case, just use the surface rect for tiling.
288 gfx::Rect viewport_rect_for_tile_priority;
289 if (parent_draw_constraints_.is_layer)
290 viewport_rect_for_tile_priority = parent_draw_constraints_.surface_rect;
291 else
292 viewport_rect_for_tile_priority = last_on_draw_global_visible_rect_;
293
294 scoped_ptr<cc::CompositorFrame> frame =
295 compositor_->DemandDrawHw(surface_size,
296 gfx::Transform(),
297 viewport,
298 clip,
299 viewport_rect_for_tile_priority,
300 transform_for_tile_priority);
[email protected]8705654b2014-05-24 01:16:19301 if (!frame.get())
302 return false;
303
304 GlobalTileManager::GetInstance()->DidUse(tile_manager_key_);
305
306 frame->AssignTo(&draw_gl_input->frame);
[email protected]8705654b2014-05-24 01:16:19307 shared_renderer_state_->SetDrawGLInput(draw_gl_input.Pass());
[email protected]7a461432014-06-17 23:50:12308 DidComposite();
[email protected]c62fc982014-06-27 04:49:02309 return client_->RequestDrawGL(java_canvas, false);
[email protected]8705654b2014-05-24 01:16:19310}
311
[email protected]bd5324592014-07-31 09:09:33312void BrowserViewRenderer::UpdateParentDrawConstraints() {
313 // Post an invalidate if the parent draw constraints are stale and there is
314 // no pending invalidate.
hush673cf012014-09-25 00:20:01315 if (shared_renderer_state_->NeedsForceInvalidateOnNextDrawGL() ||
316 !parent_draw_constraints_.Equals(
317 shared_renderer_state_->ParentDrawConstraints())) {
318 shared_renderer_state_->SetForceInvalidateOnNextDrawGL(false);
[email protected]bd5324592014-07-31 09:09:33319 EnsureContinuousInvalidation(true);
hush673cf012014-09-25 00:20:01320 }
[email protected]bd5324592014-07-31 09:09:33321}
322
[email protected]c62fc982014-06-27 04:49:02323void BrowserViewRenderer::ReturnUnusedResource(scoped_ptr<DrawGLInput> input) {
324 if (!input.get())
[email protected]8705654b2014-05-24 01:16:19325 return;
[email protected]c62fc982014-06-27 04:49:02326
327 cc::CompositorFrameAck frame_ack;
328 cc::TransferableResource::ReturnResources(
329 input->frame.delegated_frame_data->resource_list,
330 &frame_ack.resources);
331 if (!frame_ack.resources.empty())
332 compositor_->ReturnResources(frame_ack);
[email protected]8705654b2014-05-24 01:16:19333}
334
[email protected]c62fc982014-06-27 04:49:02335void BrowserViewRenderer::ReturnResourceFromParent() {
[email protected]8705654b2014-05-24 01:16:19336 cc::CompositorFrameAck frame_ack;
337 shared_renderer_state_->SwapReturnedResources(&frame_ack.resources);
338 if (!frame_ack.resources.empty()) {
[email protected]7a461432014-06-17 23:50:12339 compositor_->ReturnResources(frame_ack);
[email protected]8705654b2014-05-24 01:16:19340 }
[email protected]23063762014-02-26 01:01:56341}
342
[email protected]abf9d8a12014-07-14 23:40:09343bool BrowserViewRenderer::OnDrawSoftware(jobject java_canvas) {
[email protected]7a461432014-06-17 23:50:12344 if (!compositor_) {
[email protected]23063762014-02-26 01:01:56345 TRACE_EVENT_INSTANT0(
346 "android_webview", "EarlyOut_NoCompositor", TRACE_EVENT_SCOPE_THREAD);
347 return false;
348 }
349
[email protected]7894de82014-07-24 14:21:12350 // TODO(hush): right now webview size is passed in as the auxiliary bitmap
351 // size, which might hurt performace (only for software draws with auxiliary
352 // bitmap). For better performance, get global visible rect, transform it
353 // from screen space to view space, then intersect with the webview in
354 // viewspace. Use the resulting rect as the auxiliary
355 // bitmap.
[email protected]23063762014-02-26 01:01:56356 return BrowserViewRendererJavaHelper::GetInstance()
357 ->RenderViaAuxilaryBitmapIfNeeded(
[email protected]7894de82014-07-24 14:21:12358 java_canvas,
359 last_on_draw_scroll_offset_,
360 gfx::Size(width_, height_),
361 base::Bind(&BrowserViewRenderer::CompositeSW,
362 base::Unretained(this)));
[email protected]23063762014-02-26 01:01:56363}
364
365skia::RefPtr<SkPicture> BrowserViewRenderer::CapturePicture(int width,
366 int height) {
367 TRACE_EVENT0("android_webview", "BrowserViewRenderer::CapturePicture");
368
369 // Return empty Picture objects for empty SkPictures.
[email protected]23063762014-02-26 01:01:56370 if (width <= 0 || height <= 0) {
[email protected]c7bd0542014-07-14 18:22:04371 SkPictureRecorder emptyRecorder;
372 emptyRecorder.beginRecording(0, 0);
373 return skia::AdoptRef(emptyRecorder.endRecording());
[email protected]23063762014-02-26 01:01:56374 }
375
376 // Reset scroll back to the origin, will go back to the old
377 // value when scroll_reset is out of scope.
[email protected]7a461432014-06-17 23:50:12378 base::AutoReset<gfx::Vector2dF> scroll_reset(&scroll_offset_dip_,
379 gfx::Vector2dF());
[email protected]23063762014-02-26 01:01:56380
[email protected]1dfaaff2014-04-30 14:54:59381 SkPictureRecorder recorder;
382 SkCanvas* rec_canvas = recorder.beginRecording(width, height, NULL, 0);
[email protected]7a461432014-06-17 23:50:12383 if (compositor_)
[email protected]23063762014-02-26 01:01:56384 CompositeSW(rec_canvas);
[email protected]1dfaaff2014-04-30 14:54:59385 return skia::AdoptRef(recorder.endRecording());
[email protected]23063762014-02-26 01:01:56386}
387
388void BrowserViewRenderer::EnableOnNewPicture(bool enabled) {
389 on_new_picture_enable_ = enabled;
[email protected]23063762014-02-26 01:01:56390}
391
392void BrowserViewRenderer::ClearView() {
393 TRACE_EVENT_INSTANT0("android_webview",
394 "BrowserViewRenderer::ClearView",
395 TRACE_EVENT_SCOPE_THREAD);
396 if (clear_view_)
397 return;
398
399 clear_view_ = true;
400 // Always invalidate ignoring the compositor to actually clear the webview.
[email protected]e4a0b192014-02-27 01:47:05401 EnsureContinuousInvalidation(true);
[email protected]23063762014-02-26 01:01:56402}
403
404void BrowserViewRenderer::SetIsPaused(bool paused) {
405 TRACE_EVENT_INSTANT1("android_webview",
406 "BrowserViewRenderer::SetIsPaused",
407 TRACE_EVENT_SCOPE_THREAD,
408 "paused",
409 paused);
410 is_paused_ = paused;
[email protected]e4a0b192014-02-27 01:47:05411 EnsureContinuousInvalidation(false);
[email protected]23063762014-02-26 01:01:56412}
413
414void BrowserViewRenderer::SetViewVisibility(bool view_visible) {
415 TRACE_EVENT_INSTANT1("android_webview",
416 "BrowserViewRenderer::SetViewVisibility",
417 TRACE_EVENT_SCOPE_THREAD,
418 "view_visible",
419 view_visible);
420 view_visible_ = view_visible;
421}
422
423void BrowserViewRenderer::SetWindowVisibility(bool window_visible) {
424 TRACE_EVENT_INSTANT1("android_webview",
425 "BrowserViewRenderer::SetWindowVisibility",
426 TRACE_EVENT_SCOPE_THREAD,
427 "window_visible",
428 window_visible);
429 window_visible_ = window_visible;
[email protected]e4a0b192014-02-27 01:47:05430 EnsureContinuousInvalidation(false);
[email protected]23063762014-02-26 01:01:56431}
432
433void BrowserViewRenderer::OnSizeChanged(int width, int height) {
434 TRACE_EVENT_INSTANT2("android_webview",
435 "BrowserViewRenderer::OnSizeChanged",
436 TRACE_EVENT_SCOPE_THREAD,
437 "width",
438 width,
439 "height",
440 height);
441 width_ = width;
442 height_ = height;
443}
444
445void BrowserViewRenderer::OnAttachedToWindow(int width, int height) {
446 TRACE_EVENT2("android_webview",
447 "BrowserViewRenderer::OnAttachedToWindow",
448 "width",
449 width,
450 "height",
451 height);
452 attached_to_window_ = true;
453 width_ = width;
454 height_ = height;
455}
456
457void BrowserViewRenderer::OnDetachedFromWindow() {
458 TRACE_EVENT0("android_webview", "BrowserViewRenderer::OnDetachedFromWindow");
459 attached_to_window_ = false;
[email protected]686474c72014-07-22 02:09:50460 DCHECK(!hardware_enabled_);
461}
[email protected]8705654b2014-05-24 01:16:19462
[email protected]686474c72014-07-22 02:09:50463void BrowserViewRenderer::ReleaseHardware() {
464 DCHECK(hardware_enabled_);
465 ReturnUnusedResource(shared_renderer_state_->PassDrawGLInput());
466 ReturnResourceFromParent();
467 DCHECK(shared_renderer_state_->ReturnedResourcesEmpty());
468
469 compositor_->ReleaseHwDraw();
[email protected]686474c72014-07-22 02:09:50470 hardware_enabled_ = false;
471
[email protected]7d67302a2014-05-03 02:17:07472 SynchronousCompositorMemoryPolicy zero_policy;
473 RequestMemoryPolicy(zero_policy);
474 GlobalTileManager::GetInstance()->Remove(tile_manager_key_);
[email protected]23063762014-02-26 01:01:56475}
476
[email protected]23063762014-02-26 01:01:56477bool BrowserViewRenderer::IsVisible() const {
478 // Ignore |window_visible_| if |attached_to_window_| is false.
479 return view_visible_ && (!attached_to_window_ || window_visible_);
480}
481
482gfx::Rect BrowserViewRenderer::GetScreenRect() const {
483 return gfx::Rect(client_->GetLocationOnScreen(), gfx::Size(width_, height_));
484}
485
486void BrowserViewRenderer::DidInitializeCompositor(
487 content::SynchronousCompositor* compositor) {
488 TRACE_EVENT0("android_webview",
489 "BrowserViewRenderer::DidInitializeCompositor");
[email protected]e4a0b192014-02-27 01:47:05490 DCHECK(compositor);
[email protected]7a461432014-06-17 23:50:12491 DCHECK(!compositor_);
492 compositor_ = compositor;
[email protected]23063762014-02-26 01:01:56493}
494
495void BrowserViewRenderer::DidDestroyCompositor(
496 content::SynchronousCompositor* compositor) {
497 TRACE_EVENT0("android_webview", "BrowserViewRenderer::DidDestroyCompositor");
[email protected]7a461432014-06-17 23:50:12498 DCHECK(compositor_);
499 compositor_ = NULL;
[email protected]7d67302a2014-05-03 02:17:07500 SynchronousCompositorMemoryPolicy zero_policy;
[email protected]7a461432014-06-17 23:50:12501 DCHECK(memory_policy_ == zero_policy);
[email protected]23063762014-02-26 01:01:56502}
503
504void BrowserViewRenderer::SetContinuousInvalidate(bool invalidate) {
[email protected]7a461432014-06-17 23:50:12505 if (compositor_needs_continuous_invalidate_ == invalidate)
[email protected]596f7e72014-03-21 20:03:26506 return;
[email protected]7a461432014-06-17 23:50:12507
508 TRACE_EVENT_INSTANT1("android_webview",
509 "BrowserViewRenderer::SetContinuousInvalidate",
510 TRACE_EVENT_SCOPE_THREAD,
511 "invalidate",
512 invalidate);
513 compositor_needs_continuous_invalidate_ = invalidate;
514
515 EnsureContinuousInvalidation(false);
[email protected]23063762014-02-26 01:01:56516}
517
518void BrowserViewRenderer::SetDipScale(float dip_scale) {
519 dip_scale_ = dip_scale;
boliu2d46b522014-08-29 22:33:44520 CHECK_GT(dip_scale_, 0);
[email protected]23063762014-02-26 01:01:56521}
522
523gfx::Vector2d BrowserViewRenderer::max_scroll_offset() const {
524 DCHECK_GT(dip_scale_, 0);
525 return gfx::ToCeiledVector2d(gfx::ScaleVector2d(
526 max_scroll_offset_dip_, dip_scale_ * page_scale_factor_));
527}
528
529void BrowserViewRenderer::ScrollTo(gfx::Vector2d scroll_offset) {
530 gfx::Vector2d max_offset = max_scroll_offset();
531 gfx::Vector2dF scroll_offset_dip;
532 // To preserve the invariant that scrolling to the maximum physical pixel
533 // value also scrolls to the maximum dip pixel value we transform the physical
534 // offset into the dip offset by using a proportion (instead of dividing by
535 // dip_scale * page_scale_factor).
536 if (max_offset.x()) {
537 scroll_offset_dip.set_x((scroll_offset.x() * max_scroll_offset_dip_.x()) /
538 max_offset.x());
539 }
540 if (max_offset.y()) {
541 scroll_offset_dip.set_y((scroll_offset.y() * max_scroll_offset_dip_.y()) /
542 max_offset.y());
543 }
544
545 DCHECK_LE(0, scroll_offset_dip.x());
546 DCHECK_LE(0, scroll_offset_dip.y());
547 DCHECK_LE(scroll_offset_dip.x(), max_scroll_offset_dip_.x());
548 DCHECK_LE(scroll_offset_dip.y(), max_scroll_offset_dip_.y());
549
[email protected]7a461432014-06-17 23:50:12550 if (scroll_offset_dip_ == scroll_offset_dip)
551 return;
[email protected]23063762014-02-26 01:01:56552
[email protected]7a461432014-06-17 23:50:12553 scroll_offset_dip_ = scroll_offset_dip;
[email protected]23063762014-02-26 01:01:56554
[email protected]ec2322e2014-05-15 16:32:00555 TRACE_EVENT_INSTANT2("android_webview",
556 "BrowserViewRenderer::ScrollTo",
557 TRACE_EVENT_SCOPE_THREAD,
558 "x",
559 scroll_offset_dip.x(),
560 "y",
561 scroll_offset_dip.y());
562
[email protected]7a461432014-06-17 23:50:12563 if (compositor_)
564 compositor_->DidChangeRootLayerScrollOffset();
[email protected]23063762014-02-26 01:01:56565}
566
567void BrowserViewRenderer::DidUpdateContent() {
568 TRACE_EVENT_INSTANT0("android_webview",
569 "BrowserViewRenderer::DidUpdateContent",
570 TRACE_EVENT_SCOPE_THREAD);
571 clear_view_ = false;
[email protected]23063762014-02-26 01:01:56572 if (on_new_picture_enable_)
573 client_->OnNewPicture();
574}
575
[email protected]23063762014-02-26 01:01:56576void BrowserViewRenderer::SetTotalRootLayerScrollOffset(
577 gfx::Vector2dF scroll_offset_dip) {
[email protected]7a461432014-06-17 23:50:12578 // TOOD(mkosiba): Add a DCHECK to say that this does _not_ get called during
579 // DrawGl when http://crbug.com/249972 is fixed.
580 if (scroll_offset_dip_ == scroll_offset_dip)
581 return;
[email protected]23063762014-02-26 01:01:56582
[email protected]7a461432014-06-17 23:50:12583 scroll_offset_dip_ = scroll_offset_dip;
[email protected]23063762014-02-26 01:01:56584
585 gfx::Vector2d max_offset = max_scroll_offset();
586 gfx::Vector2d scroll_offset;
587 // For an explanation as to why this is done this way see the comment in
588 // BrowserViewRenderer::ScrollTo.
589 if (max_scroll_offset_dip_.x()) {
590 scroll_offset.set_x((scroll_offset_dip.x() * max_offset.x()) /
591 max_scroll_offset_dip_.x());
592 }
593
594 if (max_scroll_offset_dip_.y()) {
595 scroll_offset.set_y((scroll_offset_dip.y() * max_offset.y()) /
596 max_scroll_offset_dip_.y());
597 }
598
boliu2d46b522014-08-29 22:33:44599 DCHECK_LE(0, scroll_offset.x());
600 DCHECK_LE(0, scroll_offset.y());
601 DCHECK_LE(scroll_offset.x(), max_offset.x());
602 DCHECK_LE(scroll_offset.y(), max_offset.y());
[email protected]23063762014-02-26 01:01:56603
604 client_->ScrollContainerViewTo(scroll_offset);
605}
606
607gfx::Vector2dF BrowserViewRenderer::GetTotalRootLayerScrollOffset() {
608 return scroll_offset_dip_;
609}
610
611bool BrowserViewRenderer::IsExternalFlingActive() const {
612 return client_->IsFlingActive();
613}
614
[email protected]ec2322e2014-05-15 16:32:00615void BrowserViewRenderer::UpdateRootLayerState(
616 const gfx::Vector2dF& total_scroll_offset_dip,
617 const gfx::Vector2dF& max_scroll_offset_dip,
618 const gfx::SizeF& scrollable_size_dip,
[email protected]23063762014-02-26 01:01:56619 float page_scale_factor,
620 float min_page_scale_factor,
621 float max_page_scale_factor) {
[email protected]ec2322e2014-05-15 16:32:00622 TRACE_EVENT_INSTANT1(
623 "android_webview",
624 "BrowserViewRenderer::UpdateRootLayerState",
625 TRACE_EVENT_SCOPE_THREAD,
626 "state",
627 TracedValue::FromValue(
628 RootLayerStateAsValue(total_scroll_offset_dip, scrollable_size_dip)
629 .release()));
630
631 DCHECK_GT(dip_scale_, 0);
632
633 max_scroll_offset_dip_ = max_scroll_offset_dip;
634 DCHECK_LE(0, max_scroll_offset_dip_.x());
635 DCHECK_LE(0, max_scroll_offset_dip_.y());
636
[email protected]23063762014-02-26 01:01:56637 page_scale_factor_ = page_scale_factor;
638 DCHECK_GT(page_scale_factor_, 0);
[email protected]ec2322e2014-05-15 16:32:00639
640 client_->UpdateScrollState(max_scroll_offset(),
641 scrollable_size_dip,
642 page_scale_factor,
643 min_page_scale_factor,
644 max_page_scale_factor);
645 SetTotalRootLayerScrollOffset(total_scroll_offset_dip);
[email protected]23063762014-02-26 01:01:56646}
647
[email protected]ec2322e2014-05-15 16:32:00648scoped_ptr<base::Value> BrowserViewRenderer::RootLayerStateAsValue(
649 const gfx::Vector2dF& total_scroll_offset_dip,
650 const gfx::SizeF& scrollable_size_dip) {
651 scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue);
652
653 state->SetDouble("total_scroll_offset_dip.x", total_scroll_offset_dip.x());
654 state->SetDouble("total_scroll_offset_dip.y", total_scroll_offset_dip.y());
655
656 state->SetDouble("max_scroll_offset_dip.x", max_scroll_offset_dip_.x());
657 state->SetDouble("max_scroll_offset_dip.y", max_scroll_offset_dip_.y());
658
659 state->SetDouble("scrollable_size_dip.width", scrollable_size_dip.width());
660 state->SetDouble("scrollable_size_dip.height", scrollable_size_dip.height());
661
662 state->SetDouble("page_scale_factor", page_scale_factor_);
663 return state.PassAs<base::Value>();
[email protected]23063762014-02-26 01:01:56664}
665
666void BrowserViewRenderer::DidOverscroll(gfx::Vector2dF accumulated_overscroll,
667 gfx::Vector2dF latest_overscroll_delta,
668 gfx::Vector2dF current_fling_velocity) {
669 const float physical_pixel_scale = dip_scale_ * page_scale_factor_;
670 if (accumulated_overscroll == latest_overscroll_delta)
671 overscroll_rounding_error_ = gfx::Vector2dF();
672 gfx::Vector2dF scaled_overscroll_delta =
673 gfx::ScaleVector2d(latest_overscroll_delta, physical_pixel_scale);
674 gfx::Vector2d rounded_overscroll_delta = gfx::ToRoundedVector2d(
675 scaled_overscroll_delta + overscroll_rounding_error_);
676 overscroll_rounding_error_ =
677 scaled_overscroll_delta - rounded_overscroll_delta;
678 client_->DidOverscroll(rounded_overscroll_delta);
679}
680
[email protected]220e908a2014-03-05 06:23:04681void BrowserViewRenderer::EnsureContinuousInvalidation(bool force_invalidate) {
[email protected]23063762014-02-26 01:01:56682 // This method should be called again when any of these conditions change.
683 bool need_invalidate =
[email protected]220e908a2014-03-05 06:23:04684 compositor_needs_continuous_invalidate_ || force_invalidate;
[email protected]23063762014-02-26 01:01:56685 if (!need_invalidate || block_invalidates_)
686 return;
687
688 // Always call view invalidate. We rely the Android framework to ignore the
689 // invalidate when it's not needed such as when view is not visible.
[email protected]e4a0b192014-02-27 01:47:05690 client_->PostInvalidate();
[email protected]23063762014-02-26 01:01:56691
692 // Stop fallback ticks when one of these is true.
693 // 1) Webview is paused. Also need to check we are not in clear view since
694 // paused, offscreen still expect clear view to recover.
695 // 2) If we are attached to window and the window is not visible (eg when
696 // app is in the background). We are sure in this case the webview is used
697 // "on-screen" but that updates are not needed when in the background.
698 bool throttle_fallback_tick =
699 (is_paused_ && !clear_view_) || (attached_to_window_ && !window_visible_);
700 if (throttle_fallback_tick)
701 return;
702
[email protected]7a461432014-06-17 23:50:12703 block_invalidates_ = compositor_needs_continuous_invalidate_;
[email protected]23063762014-02-26 01:01:56704
[email protected]691ac7a2014-06-27 19:09:49705 // Unretained here is safe because the callbacks are cancelled when
706 // they are destroyed.
707 post_fallback_tick_.Reset(base::Bind(&BrowserViewRenderer::PostFallbackTick,
708 base::Unretained(this)));
709 fallback_tick_fired_.Cancel();
[email protected]23063762014-02-26 01:01:56710
711 // No need to reschedule fallback tick if compositor does not need to be
[email protected]220e908a2014-03-05 06:23:04712 // ticked. This can happen if this is reached because force_invalidate is
713 // true.
[email protected]691ac7a2014-06-27 19:09:49714 if (compositor_needs_continuous_invalidate_)
715 ui_task_runner_->PostTask(FROM_HERE, post_fallback_tick_.callback());
716}
717
718void BrowserViewRenderer::PostFallbackTick() {
719 DCHECK(fallback_tick_fired_.IsCancelled());
720 fallback_tick_fired_.Reset(base::Bind(&BrowserViewRenderer::FallbackTickFired,
721 base::Unretained(this)));
[email protected]23063762014-02-26 01:01:56722 if (compositor_needs_continuous_invalidate_) {
[email protected]596f7e72014-03-21 20:03:26723 ui_task_runner_->PostDelayedTask(
[email protected]23063762014-02-26 01:01:56724 FROM_HERE,
[email protected]691ac7a2014-06-27 19:09:49725 fallback_tick_fired_.callback(),
[email protected]23063762014-02-26 01:01:56726 base::TimeDelta::FromMilliseconds(kFallbackTickTimeoutInMilliseconds));
boliud3ba7202014-08-29 00:00:38727 } else {
728 // Pretend we just composited to unblock further invalidates.
729 DidComposite();
[email protected]23063762014-02-26 01:01:56730 }
731}
732
733void BrowserViewRenderer::FallbackTickFired() {
734 TRACE_EVENT1("android_webview",
735 "BrowserViewRenderer::FallbackTickFired",
736 "compositor_needs_continuous_invalidate_",
737 compositor_needs_continuous_invalidate_);
738
739 // This should only be called if OnDraw or DrawGL did not come in time, which
740 // means block_invalidates_ must still be true.
741 DCHECK(block_invalidates_);
boliud3ba7202014-08-29 00:00:38742 if (compositor_needs_continuous_invalidate_ && compositor_) {
[email protected]23063762014-02-26 01:01:56743 ForceFakeCompositeSW();
boliud3ba7202014-08-29 00:00:38744 } else {
745 // Pretend we just composited to unblock further invalidates.
746 DidComposite();
747 }
[email protected]23063762014-02-26 01:01:56748}
749
750void BrowserViewRenderer::ForceFakeCompositeSW() {
[email protected]7a461432014-06-17 23:50:12751 DCHECK(compositor_);
[email protected]e758a2372014-03-05 20:21:52752 SkBitmap bitmap;
753 bitmap.allocN32Pixels(1, 1);
754 bitmap.eraseColor(0);
755 SkCanvas canvas(bitmap);
[email protected]23063762014-02-26 01:01:56756 CompositeSW(&canvas);
757}
758
759bool BrowserViewRenderer::CompositeSW(SkCanvas* canvas) {
[email protected]7a461432014-06-17 23:50:12760 DCHECK(compositor_);
[email protected]c62fc982014-06-27 04:49:02761 ReturnResourceFromParent();
[email protected]7a461432014-06-17 23:50:12762 bool result = compositor_->DemandDrawSw(canvas);
763 DidComposite();
[email protected]220e908a2014-03-05 06:23:04764 return result;
765}
766
[email protected]7a461432014-06-17 23:50:12767void BrowserViewRenderer::DidComposite() {
768 block_invalidates_ = false;
[email protected]691ac7a2014-06-27 19:09:49769 post_fallback_tick_.Cancel();
770 fallback_tick_fired_.Cancel();
[email protected]7a461432014-06-17 23:50:12771 EnsureContinuousInvalidation(false);
[email protected]23063762014-02-26 01:01:56772}
773
774std::string BrowserViewRenderer::ToString(AwDrawGLInfo* draw_info) const {
775 std::string str;
776 base::StringAppendF(&str, "is_paused: %d ", is_paused_);
777 base::StringAppendF(&str, "view_visible: %d ", view_visible_);
778 base::StringAppendF(&str, "window_visible: %d ", window_visible_);
779 base::StringAppendF(&str, "dip_scale: %f ", dip_scale_);
780 base::StringAppendF(&str, "page_scale_factor: %f ", page_scale_factor_);
781 base::StringAppendF(&str,
782 "compositor_needs_continuous_invalidate: %d ",
783 compositor_needs_continuous_invalidate_);
784 base::StringAppendF(&str, "block_invalidates: %d ", block_invalidates_);
785 base::StringAppendF(&str, "view width height: [%d %d] ", width_, height_);
786 base::StringAppendF(&str, "attached_to_window: %d ", attached_to_window_);
787 base::StringAppendF(&str,
788 "global visible rect: %s ",
[email protected]8705654b2014-05-24 01:16:19789 last_on_draw_global_visible_rect_.ToString().c_str());
[email protected]23063762014-02-26 01:01:56790 base::StringAppendF(
791 &str, "scroll_offset_dip: %s ", scroll_offset_dip_.ToString().c_str());
792 base::StringAppendF(&str,
793 "overscroll_rounding_error_: %s ",
794 overscroll_rounding_error_.ToString().c_str());
795 base::StringAppendF(
796 &str, "on_new_picture_enable: %d ", on_new_picture_enable_);
797 base::StringAppendF(&str, "clear_view: %d ", clear_view_);
798 if (draw_info) {
799 base::StringAppendF(&str,
800 "clip left top right bottom: [%d %d %d %d] ",
801 draw_info->clip_left,
802 draw_info->clip_top,
803 draw_info->clip_right,
804 draw_info->clip_bottom);
805 base::StringAppendF(&str,
806 "surface width height: [%d %d] ",
807 draw_info->width,
808 draw_info->height);
809 base::StringAppendF(&str, "is_layer: %d ", draw_info->is_layer);
810 }
811 return str;
812}
813
814} // namespace android_webview