Revert 279378 "Update V8 to version 3.28.1 (based on bleeding_ed..."
[chromium-blink-merge.git] / android_webview / browser / browser_view_renderer.cc
blob7ac57f2d796e73c5cce02d7b935017253903cd2a
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
3 // found in the LICENSE file.
5 #include "android_webview/browser/browser_view_renderer.h"
7 #include "android_webview/browser/browser_view_renderer_client.h"
8 #include "android_webview/browser/shared_renderer_state.h"
9 #include "android_webview/public/browser/draw_gl.h"
10 #include "base/android/jni_android.h"
11 #include "base/auto_reset.h"
12 #include "base/command_line.h"
13 #include "base/debug/trace_event.h"
14 #include "base/json/json_writer.h"
15 #include "base/logging.h"
16 #include "base/strings/string_number_conversions.h"
17 #include "base/strings/stringprintf.h"
18 #include "cc/output/compositor_frame.h"
19 #include "content/public/browser/browser_thread.h"
20 #include "content/public/browser/web_contents.h"
21 #include "content/public/common/content_switches.h"
22 #include "third_party/skia/include/core/SkBitmap.h"
23 #include "third_party/skia/include/core/SkCanvas.h"
24 #include "third_party/skia/include/core/SkPicture.h"
25 #include "third_party/skia/include/core/SkPictureRecorder.h"
26 #include "ui/gfx/vector2d_conversions.h"
28 using base::android::AttachCurrentThread;
29 using base::android::JavaRef;
30 using base::android::ScopedJavaLocalRef;
31 using content::BrowserThread;
32 using content::SynchronousCompositorMemoryPolicy;
34 namespace android_webview {
36 namespace {
38 const int64 kFallbackTickTimeoutInMilliseconds = 20;
40 // Used to calculate memory allocation. Determined experimentally.
41 const size_t kMemoryMultiplier = 10;
42 const size_t kBytesPerPixel = 4;
43 const size_t kMemoryAllocationStep = 5 * 1024 * 1024;
45 // Used to calculate tile allocation. Determined experimentally.
46 const size_t kTileMultiplier = 12;
47 const size_t kTileAllocationStep = 20;
48 // This will be set by static function CalculateTileMemoryPolicy() during init.
49 // See AwMainDelegate::BasicStartupComplete.
50 size_t g_tile_area;
52 class TracedValue : public base::debug::ConvertableToTraceFormat {
53 public:
54 explicit TracedValue(base::Value* value) : value_(value) {}
55 static scoped_refptr<base::debug::ConvertableToTraceFormat> FromValue(
56 base::Value* value) {
57 return scoped_refptr<base::debug::ConvertableToTraceFormat>(
58 new TracedValue(value));
60 virtual void AppendAsTraceFormat(std::string* out) const OVERRIDE {
61 std::string tmp;
62 base::JSONWriter::Write(value_.get(), &tmp);
63 *out += tmp;
66 private:
67 virtual ~TracedValue() {}
68 scoped_ptr<base::Value> value_;
70 DISALLOW_COPY_AND_ASSIGN(TracedValue);
73 } // namespace
75 // static
76 void BrowserViewRenderer::CalculateTileMemoryPolicy() {
77 CommandLine* cl = CommandLine::ForCurrentProcess();
78 const char kDefaultTileSize[] = "384";
80 if (!cl->HasSwitch(switches::kDefaultTileWidth))
81 cl->AppendSwitchASCII(switches::kDefaultTileWidth, kDefaultTileSize);
83 if (!cl->HasSwitch(switches::kDefaultTileHeight))
84 cl->AppendSwitchASCII(switches::kDefaultTileHeight, kDefaultTileSize);
86 size_t tile_size;
87 base::StringToSizeT(kDefaultTileSize, &tile_size);
88 g_tile_area = tile_size * tile_size;
91 BrowserViewRenderer::BrowserViewRenderer(
92 BrowserViewRendererClient* client,
93 SharedRendererState* shared_renderer_state,
94 content::WebContents* web_contents,
95 const scoped_refptr<base::SingleThreadTaskRunner>& ui_task_runner)
96 : client_(client),
97 shared_renderer_state_(shared_renderer_state),
98 web_contents_(web_contents),
99 weak_factory_on_ui_thread_(this),
100 ui_thread_weak_ptr_(weak_factory_on_ui_thread_.GetWeakPtr()),
101 ui_task_runner_(ui_task_runner),
102 compositor_(NULL),
103 is_paused_(false),
104 view_visible_(false),
105 window_visible_(false),
106 attached_to_window_(false),
107 hardware_enabled_(false),
108 dip_scale_(0.0),
109 page_scale_factor_(1.0),
110 on_new_picture_enable_(false),
111 clear_view_(false),
112 compositor_needs_continuous_invalidate_(false),
113 block_invalidates_(false),
114 width_(0),
115 height_(0),
116 num_tiles_(0u),
117 num_bytes_(0u) {
118 CHECK(web_contents_);
119 content::SynchronousCompositor::SetClientForWebContents(web_contents_, this);
121 // Currently the logic in this class relies on |compositor_| remaining
122 // NULL until the DidInitializeCompositor() call, hence it is not set here.
125 BrowserViewRenderer::~BrowserViewRenderer() {
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.
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,
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;
148 // Do not release resources on view we expect to get DrawGL soon.
149 if (level < TRIM_MEMORY_BACKGROUND && visible)
150 return;
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 (memory_policy_ == zero_policy)
156 return;
158 TRACE_EVENT0("android_webview", "BrowserViewRenderer::TrimMemory");
160 RequestMemoryPolicy(zero_policy);
161 EnforceMemoryPolicyImmediately(zero_policy);
164 SynchronousCompositorMemoryPolicy
165 BrowserViewRenderer::CalculateDesiredMemoryPolicy() {
166 SynchronousCompositorMemoryPolicy policy;
167 size_t width = last_on_draw_global_visible_rect_.width();
168 size_t height = last_on_draw_global_visible_rect_.height();
169 policy.bytes_limit = kMemoryMultiplier * kBytesPerPixel * width * height;
170 // Round up to a multiple of kMemoryAllocationStep.
171 policy.bytes_limit =
172 (policy.bytes_limit / kMemoryAllocationStep + 1) * kMemoryAllocationStep;
174 size_t tiles = width * height * kTileMultiplier / g_tile_area;
175 // Round up to a multiple of kTileAllocationStep. The minimum number of tiles
176 // is also kTileAllocationStep.
177 tiles = (tiles / kTileAllocationStep + 1) * kTileAllocationStep;
178 policy.num_resources_limit = tiles;
179 return policy;
182 // This function updates the cached memory policy in shared renderer state, as
183 // well as the tile resource allocation in GlobalTileManager.
184 void BrowserViewRenderer::RequestMemoryPolicy(
185 SynchronousCompositorMemoryPolicy& new_policy) {
186 // This will be used in SetNumTiles.
187 num_bytes_ = new_policy.bytes_limit;
189 GlobalTileManager* manager = GlobalTileManager::GetInstance();
191 // The following line will call BrowserViewRenderer::SetTilesNum().
192 manager->RequestTiles(new_policy.num_resources_limit, tile_manager_key_);
195 void BrowserViewRenderer::SetNumTiles(size_t num_tiles,
196 bool effective_immediately) {
197 if (num_tiles == num_tiles_)
198 return;
199 num_tiles_ = num_tiles;
201 memory_policy_.num_resources_limit = num_tiles_;
202 memory_policy_.bytes_limit = num_bytes_;
204 if (effective_immediately)
205 EnforceMemoryPolicyImmediately(memory_policy_);
208 void BrowserViewRenderer::EnforceMemoryPolicyImmediately(
209 SynchronousCompositorMemoryPolicy new_policy) {
210 compositor_->SetMemoryPolicy(new_policy);
211 ForceFakeCompositeSW();
214 size_t BrowserViewRenderer::GetNumTiles() const {
215 return memory_policy_.num_resources_limit;
218 bool BrowserViewRenderer::OnDraw(jobject java_canvas,
219 bool is_hardware_canvas,
220 const gfx::Vector2d& scroll,
221 const gfx::Rect& global_visible_rect,
222 const gfx::Rect& clip) {
223 last_on_draw_scroll_offset_ = scroll;
224 last_on_draw_global_visible_rect_ = global_visible_rect;
226 if (clear_view_)
227 return false;
229 if (is_hardware_canvas && attached_to_window_)
230 return OnDrawHardware(java_canvas);
231 // Perform a software draw
232 return DrawSWInternal(java_canvas, clip);
235 bool BrowserViewRenderer::OnDrawHardware(jobject java_canvas) {
236 if (!compositor_)
237 return false;
239 if (!hardware_enabled_) {
240 hardware_enabled_ = compositor_->InitializeHwDraw();
241 if (hardware_enabled_) {
242 gpu::GLInProcessContext* share_context = compositor_->GetShareContext();
243 DCHECK(share_context);
244 shared_renderer_state_->SetSharedContext(share_context);
247 if (!hardware_enabled_)
248 return false;
250 ReturnResources();
251 SynchronousCompositorMemoryPolicy new_policy = CalculateDesiredMemoryPolicy();
252 RequestMemoryPolicy(new_policy);
253 compositor_->SetMemoryPolicy(memory_policy_);
255 scoped_ptr<DrawGLInput> draw_gl_input(new DrawGLInput);
256 draw_gl_input->scroll_offset = last_on_draw_scroll_offset_;
257 draw_gl_input->width = width_;
258 draw_gl_input->height = height_;
260 gfx::Transform transform;
261 gfx::Size surface_size(width_, height_);
262 gfx::Rect viewport(surface_size);
263 // TODO(boliu): Should really be |last_on_draw_global_visible_rect_|.
264 // See crbug.com/372073.
265 gfx::Rect clip = viewport;
266 scoped_ptr<cc::CompositorFrame> frame = compositor_->DemandDrawHw(
267 surface_size, transform, viewport, clip);
268 if (!frame.get())
269 return false;
271 GlobalTileManager::GetInstance()->DidUse(tile_manager_key_);
273 frame->AssignTo(&draw_gl_input->frame);
274 scoped_ptr<DrawGLInput> old_input = shared_renderer_state_->PassDrawGLInput();
275 if (old_input.get()) {
276 shared_renderer_state_->ReturnResources(
277 old_input->frame.delegated_frame_data->resource_list);
279 shared_renderer_state_->SetDrawGLInput(draw_gl_input.Pass());
281 DidComposite();
282 bool did_request = client_->RequestDrawGL(java_canvas, false);
283 if (did_request)
284 return true;
286 ReturnResources();
287 return false;
290 void BrowserViewRenderer::DidDrawDelegated() {
291 if (!ui_task_runner_->BelongsToCurrentThread()) {
292 // TODO(boliu): This should be a cancelable callback.
293 // TODO(boliu): Do this PostTask in AwContents instead so every method in
294 // this class is called by UI thread.
295 ui_task_runner_->PostTask(FROM_HERE,
296 base::Bind(&BrowserViewRenderer::DidDrawDelegated,
297 ui_thread_weak_ptr_));
298 return;
300 ReturnResources();
303 void BrowserViewRenderer::ReturnResources() {
304 cc::CompositorFrameAck frame_ack;
305 shared_renderer_state_->SwapReturnedResources(&frame_ack.resources);
306 if (!frame_ack.resources.empty()) {
307 compositor_->ReturnResources(frame_ack);
311 bool BrowserViewRenderer::DrawSWInternal(jobject java_canvas,
312 const gfx::Rect& clip) {
313 if (clip.IsEmpty()) {
314 TRACE_EVENT_INSTANT0(
315 "android_webview", "EarlyOut_EmptyClip", TRACE_EVENT_SCOPE_THREAD);
316 return true;
319 if (!compositor_) {
320 TRACE_EVENT_INSTANT0(
321 "android_webview", "EarlyOut_NoCompositor", TRACE_EVENT_SCOPE_THREAD);
322 return false;
325 return BrowserViewRendererJavaHelper::GetInstance()
326 ->RenderViaAuxilaryBitmapIfNeeded(
327 java_canvas,
328 last_on_draw_scroll_offset_,
329 clip,
330 base::Bind(&BrowserViewRenderer::CompositeSW,
331 base::Unretained(this)));
334 skia::RefPtr<SkPicture> BrowserViewRenderer::CapturePicture(int width,
335 int height) {
336 TRACE_EVENT0("android_webview", "BrowserViewRenderer::CapturePicture");
338 // Return empty Picture objects for empty SkPictures.
339 if (width <= 0 || height <= 0) {
340 return skia::AdoptRef(new SkPicture);
343 // Reset scroll back to the origin, will go back to the old
344 // value when scroll_reset is out of scope.
345 base::AutoReset<gfx::Vector2dF> scroll_reset(&scroll_offset_dip_,
346 gfx::Vector2dF());
348 SkPictureRecorder recorder;
349 SkCanvas* rec_canvas = recorder.beginRecording(width, height, NULL, 0);
350 if (compositor_)
351 CompositeSW(rec_canvas);
352 return skia::AdoptRef(recorder.endRecording());
355 void BrowserViewRenderer::EnableOnNewPicture(bool enabled) {
356 on_new_picture_enable_ = enabled;
359 void BrowserViewRenderer::ClearView() {
360 TRACE_EVENT_INSTANT0("android_webview",
361 "BrowserViewRenderer::ClearView",
362 TRACE_EVENT_SCOPE_THREAD);
363 if (clear_view_)
364 return;
366 clear_view_ = true;
367 // Always invalidate ignoring the compositor to actually clear the webview.
368 EnsureContinuousInvalidation(true);
371 void BrowserViewRenderer::SetIsPaused(bool paused) {
372 TRACE_EVENT_INSTANT1("android_webview",
373 "BrowserViewRenderer::SetIsPaused",
374 TRACE_EVENT_SCOPE_THREAD,
375 "paused",
376 paused);
377 is_paused_ = paused;
378 EnsureContinuousInvalidation(false);
381 void BrowserViewRenderer::SetViewVisibility(bool view_visible) {
382 TRACE_EVENT_INSTANT1("android_webview",
383 "BrowserViewRenderer::SetViewVisibility",
384 TRACE_EVENT_SCOPE_THREAD,
385 "view_visible",
386 view_visible);
387 view_visible_ = view_visible;
390 void BrowserViewRenderer::SetWindowVisibility(bool window_visible) {
391 TRACE_EVENT_INSTANT1("android_webview",
392 "BrowserViewRenderer::SetWindowVisibility",
393 TRACE_EVENT_SCOPE_THREAD,
394 "window_visible",
395 window_visible);
396 window_visible_ = window_visible;
397 EnsureContinuousInvalidation(false);
400 void BrowserViewRenderer::OnSizeChanged(int width, int height) {
401 TRACE_EVENT_INSTANT2("android_webview",
402 "BrowserViewRenderer::OnSizeChanged",
403 TRACE_EVENT_SCOPE_THREAD,
404 "width",
405 width,
406 "height",
407 height);
408 width_ = width;
409 height_ = height;
412 void BrowserViewRenderer::OnAttachedToWindow(int width, int height) {
413 TRACE_EVENT2("android_webview",
414 "BrowserViewRenderer::OnAttachedToWindow",
415 "width",
416 width,
417 "height",
418 height);
419 attached_to_window_ = true;
420 width_ = width;
421 height_ = height;
422 tile_manager_key_ = GlobalTileManager::GetInstance()->PushBack(this);
425 void BrowserViewRenderer::OnDetachedFromWindow() {
426 TRACE_EVENT0("android_webview", "BrowserViewRenderer::OnDetachedFromWindow");
427 attached_to_window_ = false;
428 if (hardware_enabled_) {
429 scoped_ptr<DrawGLInput> input = shared_renderer_state_->PassDrawGLInput();
430 if (input.get()) {
431 shared_renderer_state_->ReturnResources(
432 input->frame.delegated_frame_data->resource_list);
434 ReturnResources();
435 DCHECK(shared_renderer_state_->ReturnedResourcesEmpty());
437 compositor_->ReleaseHwDraw();
438 shared_renderer_state_->SetSharedContext(NULL);
439 hardware_enabled_ = false;
441 SynchronousCompositorMemoryPolicy zero_policy;
442 RequestMemoryPolicy(zero_policy);
443 GlobalTileManager::GetInstance()->Remove(tile_manager_key_);
444 // The hardware resources are released in the destructor of hardware renderer,
445 // so we don't need to do it here.
446 // See AwContents::ReleaseHardwareDrawOnRenderThread(JNIEnv*, jobject).
449 bool BrowserViewRenderer::IsAttachedToWindow() const {
450 return attached_to_window_;
453 bool BrowserViewRenderer::IsVisible() const {
454 // Ignore |window_visible_| if |attached_to_window_| is false.
455 return view_visible_ && (!attached_to_window_ || window_visible_);
458 gfx::Rect BrowserViewRenderer::GetScreenRect() const {
459 return gfx::Rect(client_->GetLocationOnScreen(), gfx::Size(width_, height_));
462 void BrowserViewRenderer::DidInitializeCompositor(
463 content::SynchronousCompositor* compositor) {
464 TRACE_EVENT0("android_webview",
465 "BrowserViewRenderer::DidInitializeCompositor");
466 DCHECK(compositor);
467 DCHECK(!compositor_);
468 compositor_ = compositor;
471 void BrowserViewRenderer::DidDestroyCompositor(
472 content::SynchronousCompositor* compositor) {
473 TRACE_EVENT0("android_webview", "BrowserViewRenderer::DidDestroyCompositor");
474 DCHECK(compositor_);
475 compositor_ = NULL;
476 SynchronousCompositorMemoryPolicy zero_policy;
477 DCHECK(memory_policy_ == zero_policy);
480 void BrowserViewRenderer::SetContinuousInvalidate(bool invalidate) {
481 if (compositor_needs_continuous_invalidate_ == invalidate)
482 return;
484 TRACE_EVENT_INSTANT1("android_webview",
485 "BrowserViewRenderer::SetContinuousInvalidate",
486 TRACE_EVENT_SCOPE_THREAD,
487 "invalidate",
488 invalidate);
489 compositor_needs_continuous_invalidate_ = invalidate;
491 EnsureContinuousInvalidation(false);
494 void BrowserViewRenderer::SetDipScale(float dip_scale) {
495 dip_scale_ = dip_scale;
496 CHECK(dip_scale_ > 0);
499 gfx::Vector2d BrowserViewRenderer::max_scroll_offset() const {
500 DCHECK_GT(dip_scale_, 0);
501 return gfx::ToCeiledVector2d(gfx::ScaleVector2d(
502 max_scroll_offset_dip_, dip_scale_ * page_scale_factor_));
505 void BrowserViewRenderer::ScrollTo(gfx::Vector2d scroll_offset) {
506 gfx::Vector2d max_offset = max_scroll_offset();
507 gfx::Vector2dF scroll_offset_dip;
508 // To preserve the invariant that scrolling to the maximum physical pixel
509 // value also scrolls to the maximum dip pixel value we transform the physical
510 // offset into the dip offset by using a proportion (instead of dividing by
511 // dip_scale * page_scale_factor).
512 if (max_offset.x()) {
513 scroll_offset_dip.set_x((scroll_offset.x() * max_scroll_offset_dip_.x()) /
514 max_offset.x());
516 if (max_offset.y()) {
517 scroll_offset_dip.set_y((scroll_offset.y() * max_scroll_offset_dip_.y()) /
518 max_offset.y());
521 DCHECK_LE(0, scroll_offset_dip.x());
522 DCHECK_LE(0, scroll_offset_dip.y());
523 DCHECK_LE(scroll_offset_dip.x(), max_scroll_offset_dip_.x());
524 DCHECK_LE(scroll_offset_dip.y(), max_scroll_offset_dip_.y());
526 if (scroll_offset_dip_ == scroll_offset_dip)
527 return;
529 scroll_offset_dip_ = scroll_offset_dip;
531 TRACE_EVENT_INSTANT2("android_webview",
532 "BrowserViewRenderer::ScrollTo",
533 TRACE_EVENT_SCOPE_THREAD,
534 "x",
535 scroll_offset_dip.x(),
536 "y",
537 scroll_offset_dip.y());
539 if (compositor_)
540 compositor_->DidChangeRootLayerScrollOffset();
543 void BrowserViewRenderer::DidUpdateContent() {
544 TRACE_EVENT_INSTANT0("android_webview",
545 "BrowserViewRenderer::DidUpdateContent",
546 TRACE_EVENT_SCOPE_THREAD);
547 clear_view_ = false;
548 if (on_new_picture_enable_)
549 client_->OnNewPicture();
552 void BrowserViewRenderer::SetTotalRootLayerScrollOffset(
553 gfx::Vector2dF scroll_offset_dip) {
554 // TOOD(mkosiba): Add a DCHECK to say that this does _not_ get called during
555 // DrawGl when http://crbug.com/249972 is fixed.
556 if (scroll_offset_dip_ == scroll_offset_dip)
557 return;
559 scroll_offset_dip_ = scroll_offset_dip;
561 gfx::Vector2d max_offset = max_scroll_offset();
562 gfx::Vector2d scroll_offset;
563 // For an explanation as to why this is done this way see the comment in
564 // BrowserViewRenderer::ScrollTo.
565 if (max_scroll_offset_dip_.x()) {
566 scroll_offset.set_x((scroll_offset_dip.x() * max_offset.x()) /
567 max_scroll_offset_dip_.x());
570 if (max_scroll_offset_dip_.y()) {
571 scroll_offset.set_y((scroll_offset_dip.y() * max_offset.y()) /
572 max_scroll_offset_dip_.y());
575 DCHECK(0 <= scroll_offset.x());
576 DCHECK(0 <= scroll_offset.y());
577 DCHECK(scroll_offset.x() <= max_offset.x());
578 DCHECK(scroll_offset.y() <= max_offset.y());
580 client_->ScrollContainerViewTo(scroll_offset);
583 gfx::Vector2dF BrowserViewRenderer::GetTotalRootLayerScrollOffset() {
584 return scroll_offset_dip_;
587 bool BrowserViewRenderer::IsExternalFlingActive() const {
588 return client_->IsFlingActive();
591 void BrowserViewRenderer::UpdateRootLayerState(
592 const gfx::Vector2dF& total_scroll_offset_dip,
593 const gfx::Vector2dF& max_scroll_offset_dip,
594 const gfx::SizeF& scrollable_size_dip,
595 float page_scale_factor,
596 float min_page_scale_factor,
597 float max_page_scale_factor) {
598 TRACE_EVENT_INSTANT1(
599 "android_webview",
600 "BrowserViewRenderer::UpdateRootLayerState",
601 TRACE_EVENT_SCOPE_THREAD,
602 "state",
603 TracedValue::FromValue(
604 RootLayerStateAsValue(total_scroll_offset_dip, scrollable_size_dip)
605 .release()));
607 DCHECK_GT(dip_scale_, 0);
609 max_scroll_offset_dip_ = max_scroll_offset_dip;
610 DCHECK_LE(0, max_scroll_offset_dip_.x());
611 DCHECK_LE(0, max_scroll_offset_dip_.y());
613 page_scale_factor_ = page_scale_factor;
614 DCHECK_GT(page_scale_factor_, 0);
616 client_->UpdateScrollState(max_scroll_offset(),
617 scrollable_size_dip,
618 page_scale_factor,
619 min_page_scale_factor,
620 max_page_scale_factor);
621 SetTotalRootLayerScrollOffset(total_scroll_offset_dip);
624 scoped_ptr<base::Value> BrowserViewRenderer::RootLayerStateAsValue(
625 const gfx::Vector2dF& total_scroll_offset_dip,
626 const gfx::SizeF& scrollable_size_dip) {
627 scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue);
629 state->SetDouble("total_scroll_offset_dip.x", total_scroll_offset_dip.x());
630 state->SetDouble("total_scroll_offset_dip.y", total_scroll_offset_dip.y());
632 state->SetDouble("max_scroll_offset_dip.x", max_scroll_offset_dip_.x());
633 state->SetDouble("max_scroll_offset_dip.y", max_scroll_offset_dip_.y());
635 state->SetDouble("scrollable_size_dip.width", scrollable_size_dip.width());
636 state->SetDouble("scrollable_size_dip.height", scrollable_size_dip.height());
638 state->SetDouble("page_scale_factor", page_scale_factor_);
639 return state.PassAs<base::Value>();
642 void BrowserViewRenderer::DidOverscroll(gfx::Vector2dF accumulated_overscroll,
643 gfx::Vector2dF latest_overscroll_delta,
644 gfx::Vector2dF current_fling_velocity) {
645 const float physical_pixel_scale = dip_scale_ * page_scale_factor_;
646 if (accumulated_overscroll == latest_overscroll_delta)
647 overscroll_rounding_error_ = gfx::Vector2dF();
648 gfx::Vector2dF scaled_overscroll_delta =
649 gfx::ScaleVector2d(latest_overscroll_delta, physical_pixel_scale);
650 gfx::Vector2d rounded_overscroll_delta = gfx::ToRoundedVector2d(
651 scaled_overscroll_delta + overscroll_rounding_error_);
652 overscroll_rounding_error_ =
653 scaled_overscroll_delta - rounded_overscroll_delta;
654 client_->DidOverscroll(rounded_overscroll_delta);
657 void BrowserViewRenderer::EnsureContinuousInvalidation(bool force_invalidate) {
658 // This method should be called again when any of these conditions change.
659 bool need_invalidate =
660 compositor_needs_continuous_invalidate_ || force_invalidate;
661 if (!need_invalidate || block_invalidates_)
662 return;
664 // Always call view invalidate. We rely the Android framework to ignore the
665 // invalidate when it's not needed such as when view is not visible.
666 client_->PostInvalidate();
668 // Stop fallback ticks when one of these is true.
669 // 1) Webview is paused. Also need to check we are not in clear view since
670 // paused, offscreen still expect clear view to recover.
671 // 2) If we are attached to window and the window is not visible (eg when
672 // app is in the background). We are sure in this case the webview is used
673 // "on-screen" but that updates are not needed when in the background.
674 bool throttle_fallback_tick =
675 (is_paused_ && !clear_view_) || (attached_to_window_ && !window_visible_);
676 if (throttle_fallback_tick)
677 return;
679 block_invalidates_ = compositor_needs_continuous_invalidate_;
681 // Unretained here is safe because the callback is cancelled when
682 // |fallback_tick_| is destroyed.
683 fallback_tick_.Reset(base::Bind(&BrowserViewRenderer::FallbackTickFired,
684 base::Unretained(this)));
686 // No need to reschedule fallback tick if compositor does not need to be
687 // ticked. This can happen if this is reached because force_invalidate is
688 // true.
689 if (compositor_needs_continuous_invalidate_) {
690 ui_task_runner_->PostDelayedTask(
691 FROM_HERE,
692 fallback_tick_.callback(),
693 base::TimeDelta::FromMilliseconds(kFallbackTickTimeoutInMilliseconds));
697 void BrowserViewRenderer::FallbackTickFired() {
698 TRACE_EVENT1("android_webview",
699 "BrowserViewRenderer::FallbackTickFired",
700 "compositor_needs_continuous_invalidate_",
701 compositor_needs_continuous_invalidate_);
703 // This should only be called if OnDraw or DrawGL did not come in time, which
704 // means block_invalidates_ must still be true.
705 DCHECK(block_invalidates_);
706 if (compositor_needs_continuous_invalidate_ && compositor_)
707 ForceFakeCompositeSW();
710 void BrowserViewRenderer::ForceFakeCompositeSW() {
711 DCHECK(compositor_);
712 SkBitmap bitmap;
713 bitmap.allocN32Pixels(1, 1);
714 bitmap.eraseColor(0);
715 SkCanvas canvas(bitmap);
716 CompositeSW(&canvas);
719 bool BrowserViewRenderer::CompositeSW(SkCanvas* canvas) {
720 DCHECK(compositor_);
721 bool result = compositor_->DemandDrawSw(canvas);
722 DidComposite();
723 return result;
726 void BrowserViewRenderer::DidComposite() {
727 block_invalidates_ = false;
728 fallback_tick_.Cancel();
729 EnsureContinuousInvalidation(false);
732 std::string BrowserViewRenderer::ToString(AwDrawGLInfo* draw_info) const {
733 std::string str;
734 base::StringAppendF(&str, "is_paused: %d ", is_paused_);
735 base::StringAppendF(&str, "view_visible: %d ", view_visible_);
736 base::StringAppendF(&str, "window_visible: %d ", window_visible_);
737 base::StringAppendF(&str, "dip_scale: %f ", dip_scale_);
738 base::StringAppendF(&str, "page_scale_factor: %f ", page_scale_factor_);
739 base::StringAppendF(&str,
740 "compositor_needs_continuous_invalidate: %d ",
741 compositor_needs_continuous_invalidate_);
742 base::StringAppendF(&str, "block_invalidates: %d ", block_invalidates_);
743 base::StringAppendF(&str, "view width height: [%d %d] ", width_, height_);
744 base::StringAppendF(&str, "attached_to_window: %d ", attached_to_window_);
745 base::StringAppendF(&str,
746 "global visible rect: %s ",
747 last_on_draw_global_visible_rect_.ToString().c_str());
748 base::StringAppendF(
749 &str, "scroll_offset_dip: %s ", scroll_offset_dip_.ToString().c_str());
750 base::StringAppendF(&str,
751 "overscroll_rounding_error_: %s ",
752 overscroll_rounding_error_.ToString().c_str());
753 base::StringAppendF(
754 &str, "on_new_picture_enable: %d ", on_new_picture_enable_);
755 base::StringAppendF(&str, "clear_view: %d ", clear_view_);
756 if (draw_info) {
757 base::StringAppendF(&str,
758 "clip left top right bottom: [%d %d %d %d] ",
759 draw_info->clip_left,
760 draw_info->clip_top,
761 draw_info->clip_right,
762 draw_info->clip_bottom);
763 base::StringAppendF(&str,
764 "surface width height: [%d %d] ",
765 draw_info->width,
766 draw_info->height);
767 base::StringAppendF(&str, "is_layer: %d ", draw_info->is_layer);
769 return str;
772 } // namespace android_webview