Revert "Fix broken channel icon in chrome://help on CrOS" and try again
[chromium-blink-merge.git] / android_webview / browser / browser_view_renderer.cc
blob48ea197b027ff9543fe6be487991c0a5e95df7d3
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/child_frame.h"
9 #include "base/auto_reset.h"
10 #include "base/command_line.h"
11 #include "base/logging.h"
12 #include "base/strings/string_number_conversions.h"
13 #include "base/strings/stringprintf.h"
14 #include "base/supports_user_data.h"
15 #include "base/trace_event/trace_event_argument.h"
16 #include "cc/output/compositor_frame.h"
17 #include "content/public/browser/web_contents.h"
18 #include "content/public/common/content_switches.h"
19 #include "gpu/command_buffer/service/gpu_switches.h"
20 #include "third_party/skia/include/core/SkBitmap.h"
21 #include "third_party/skia/include/core/SkCanvas.h"
22 #include "third_party/skia/include/core/SkPicture.h"
23 #include "third_party/skia/include/core/SkPictureRecorder.h"
24 #include "ui/gfx/geometry/vector2d_conversions.h"
26 namespace android_webview {
28 namespace {
30 const double kEpsilon = 1e-8;
32 const int64 kFallbackTickTimeoutInMilliseconds = 100;
34 // Used to calculate memory allocation. Determined experimentally.
35 const size_t kMemoryMultiplier = 20;
36 const size_t kBytesPerPixel = 4;
37 const size_t kMemoryAllocationStep = 5 * 1024 * 1024;
38 uint64 g_memory_override_in_bytes = 0u;
40 const void* kBrowserViewRendererUserDataKey = &kBrowserViewRendererUserDataKey;
42 class BrowserViewRendererUserData : public base::SupportsUserData::Data {
43 public:
44 BrowserViewRendererUserData(BrowserViewRenderer* ptr) : bvr_(ptr) {}
46 static BrowserViewRenderer* GetBrowserViewRenderer(
47 content::WebContents* web_contents) {
48 if (!web_contents)
49 return NULL;
50 BrowserViewRendererUserData* data =
51 static_cast<BrowserViewRendererUserData*>(
52 web_contents->GetUserData(kBrowserViewRendererUserDataKey));
53 return data ? data->bvr_ : NULL;
56 private:
57 BrowserViewRenderer* bvr_;
60 } // namespace
62 // static
63 void BrowserViewRenderer::CalculateTileMemoryPolicy() {
64 base::CommandLine* cl = base::CommandLine::ForCurrentProcess();
66 // If the value was overridden on the command line, use the specified value.
67 bool client_hard_limit_bytes_overridden =
68 cl->HasSwitch(switches::kForceGpuMemAvailableMb);
69 if (client_hard_limit_bytes_overridden) {
70 base::StringToUint64(
71 base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
72 switches::kForceGpuMemAvailableMb),
73 &g_memory_override_in_bytes);
74 g_memory_override_in_bytes *= 1024 * 1024;
78 // static
79 BrowserViewRenderer* BrowserViewRenderer::FromWebContents(
80 content::WebContents* web_contents) {
81 return BrowserViewRendererUserData::GetBrowserViewRenderer(web_contents);
84 BrowserViewRenderer::BrowserViewRenderer(
85 BrowserViewRendererClient* client,
86 const scoped_refptr<base::SingleThreadTaskRunner>& ui_task_runner)
87 : client_(client),
88 shared_renderer_state_(ui_task_runner, this),
89 ui_task_runner_(ui_task_runner),
90 compositor_(NULL),
91 is_paused_(false),
92 view_visible_(false),
93 window_visible_(false),
94 attached_to_window_(false),
95 hardware_enabled_(false),
96 dip_scale_(0.0),
97 page_scale_factor_(1.0),
98 on_new_picture_enable_(false),
99 clear_view_(false),
100 offscreen_pre_raster_(false),
101 fallback_tick_pending_(false) {
104 BrowserViewRenderer::~BrowserViewRenderer() {
107 void BrowserViewRenderer::RegisterWithWebContents(
108 content::WebContents* web_contents) {
109 web_contents->SetUserData(kBrowserViewRendererUserDataKey,
110 new BrowserViewRendererUserData(this));
113 SharedRendererState* BrowserViewRenderer::GetAwDrawGLViewContext() {
114 return &shared_renderer_state_;
117 bool BrowserViewRenderer::RequestDrawGL(bool wait_for_completion) {
118 return client_->RequestDrawGL(wait_for_completion);
121 void BrowserViewRenderer::TrimMemory(const int level, const bool visible) {
122 DCHECK(ui_task_runner_->BelongsToCurrentThread());
123 // Constants from Android ComponentCallbacks2.
124 enum {
125 TRIM_MEMORY_RUNNING_LOW = 10,
126 TRIM_MEMORY_UI_HIDDEN = 20,
127 TRIM_MEMORY_BACKGROUND = 40,
128 TRIM_MEMORY_MODERATE = 60,
131 // Not urgent enough. TRIM_MEMORY_UI_HIDDEN is treated specially because
132 // it does not indicate memory pressure, but merely that the app is
133 // backgrounded.
134 if (level < TRIM_MEMORY_RUNNING_LOW || level == TRIM_MEMORY_UI_HIDDEN)
135 return;
137 // Do not release resources on view we expect to get DrawGL soon.
138 if (level < TRIM_MEMORY_BACKGROUND && visible)
139 return;
141 // Nothing to drop.
142 if (!compositor_ || !hardware_enabled_)
143 return;
145 TRACE_EVENT0("android_webview", "BrowserViewRenderer::TrimMemory");
147 // If offscreen pre-raster is disabled, drop everything in hardware. Otherwise
148 // keep the tiles and just delete the HardwareRenderer.
149 if (level >= TRIM_MEMORY_MODERATE) {
150 if (offscreen_pre_raster_)
151 shared_renderer_state_.DeleteHardwareRendererOnUI();
152 else
153 shared_renderer_state_.ReleaseHardwareDrawIfNeededOnUI();
154 return;
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 if (!offscreen_pre_raster_)
160 compositor_->SetMemoryPolicy(0u);
163 void BrowserViewRenderer::UpdateMemoryPolicy() {
164 if (!hardware_enabled_) {
165 compositor_->SetMemoryPolicy(0u);
166 return;
169 size_t bytes_limit = 0u;
170 if (g_memory_override_in_bytes) {
171 bytes_limit = static_cast<size_t>(g_memory_override_in_bytes);
172 } else {
173 ParentCompositorDrawConstraints parent_draw_constraints =
174 shared_renderer_state_.GetParentDrawConstraintsOnUI();
175 gfx::Rect interest_rect =
176 offscreen_pre_raster_ || parent_draw_constraints.is_layer
177 ? gfx::Rect(size_)
178 : last_on_draw_global_visible_rect_;
179 size_t width = interest_rect.width();
180 size_t height = interest_rect.height();
181 bytes_limit = kMemoryMultiplier * kBytesPerPixel * width * height;
182 // Round up to a multiple of kMemoryAllocationStep.
183 bytes_limit =
184 (bytes_limit / kMemoryAllocationStep + 1) * kMemoryAllocationStep;
187 compositor_->SetMemoryPolicy(bytes_limit);
190 void BrowserViewRenderer::PrepareToDraw(const gfx::Vector2d& scroll,
191 const gfx::Rect& global_visible_rect) {
192 last_on_draw_scroll_offset_ = scroll;
193 last_on_draw_global_visible_rect_ = global_visible_rect;
196 bool BrowserViewRenderer::CanOnDraw() {
197 if (!compositor_) {
198 TRACE_EVENT_INSTANT0("android_webview", "EarlyOut_NoCompositor",
199 TRACE_EVENT_SCOPE_THREAD);
200 return false;
202 if (clear_view_) {
203 TRACE_EVENT_INSTANT0("android_webview", "EarlyOut_ClearView",
204 TRACE_EVENT_SCOPE_THREAD);
205 return false;
208 return true;
211 bool BrowserViewRenderer::OnDrawHardware() {
212 TRACE_EVENT0("android_webview", "BrowserViewRenderer::OnDrawHardware");
214 shared_renderer_state_.InitializeHardwareDrawIfNeededOnUI();
216 if (!CanOnDraw()) {
217 return false;
220 shared_renderer_state_.SetScrollOffsetOnUI(last_on_draw_scroll_offset_);
221 hardware_enabled_ = true;
223 return CompositeHw();
226 bool BrowserViewRenderer::CompositeHw() {
227 CancelFallbackTick();
229 ReturnResourceFromParent();
230 UpdateMemoryPolicy();
232 ParentCompositorDrawConstraints parent_draw_constraints =
233 shared_renderer_state_.GetParentDrawConstraintsOnUI();
234 gfx::Size surface_size(size_);
235 gfx::Rect viewport(surface_size);
236 gfx::Rect clip = viewport;
237 gfx::Transform transform_for_tile_priority =
238 parent_draw_constraints.transform;
240 // If the WebView is on a layer, WebView does not know what transform is
241 // applied onto the layer so global visible rect does not make sense here.
242 // In this case, just use the surface rect for tiling.
243 gfx::Rect viewport_rect_for_tile_priority;
245 // Leave viewport_rect_for_tile_priority empty if offscreen_pre_raster_ is on.
246 if (!offscreen_pre_raster_ && !parent_draw_constraints.is_layer) {
247 viewport_rect_for_tile_priority = last_on_draw_global_visible_rect_;
250 scoped_ptr<cc::CompositorFrame> frame =
251 compositor_->DemandDrawHw(surface_size,
252 gfx::Transform(),
253 viewport,
254 clip,
255 viewport_rect_for_tile_priority,
256 transform_for_tile_priority);
257 if (!frame.get()) {
258 TRACE_EVENT_INSTANT0("android_webview", "NoNewFrame",
259 TRACE_EVENT_SCOPE_THREAD);
260 return false;
263 scoped_ptr<ChildFrame> child_frame = make_scoped_ptr(
264 new ChildFrame(frame.Pass(), viewport_rect_for_tile_priority.IsEmpty(),
265 transform_for_tile_priority, offscreen_pre_raster_,
266 parent_draw_constraints.is_layer));
268 // Uncommitted frame can happen with consecutive fallback ticks.
269 ReturnUnusedResource(shared_renderer_state_.PassUncommittedFrameOnUI());
270 shared_renderer_state_.SetCompositorFrameOnUI(child_frame.Pass());
271 return true;
274 void BrowserViewRenderer::UpdateParentDrawConstraints() {
275 PostInvalidateWithFallback();
276 ParentCompositorDrawConstraints parent_draw_constraints =
277 shared_renderer_state_.GetParentDrawConstraintsOnUI();
278 client_->ParentDrawConstraintsUpdated(parent_draw_constraints);
281 void BrowserViewRenderer::ReturnUnusedResource(
282 scoped_ptr<ChildFrame> child_frame) {
283 if (!child_frame.get() || !child_frame->frame.get())
284 return;
286 cc::CompositorFrameAck frame_ack;
287 cc::TransferableResource::ReturnResources(
288 child_frame->frame->delegated_frame_data->resource_list,
289 &frame_ack.resources);
290 if (compositor_ && !frame_ack.resources.empty())
291 compositor_->ReturnResources(frame_ack);
294 void BrowserViewRenderer::ReturnResourceFromParent() {
295 cc::CompositorFrameAck frame_ack;
296 shared_renderer_state_.SwapReturnedResourcesOnUI(&frame_ack.resources);
297 if (compositor_ && !frame_ack.resources.empty()) {
298 compositor_->ReturnResources(frame_ack);
302 void BrowserViewRenderer::DetachFunctorFromView() {
303 client_->DetachFunctorFromView();
306 bool BrowserViewRenderer::OnDrawSoftware(SkCanvas* canvas) {
307 return CanOnDraw() && CompositeSW(canvas);
310 skia::RefPtr<SkPicture> BrowserViewRenderer::CapturePicture(int width,
311 int height) {
312 TRACE_EVENT0("android_webview", "BrowserViewRenderer::CapturePicture");
314 // Return empty Picture objects for empty SkPictures.
315 if (width <= 0 || height <= 0) {
316 SkPictureRecorder emptyRecorder;
317 emptyRecorder.beginRecording(0, 0);
318 return skia::AdoptRef(emptyRecorder.endRecording());
321 SkPictureRecorder recorder;
322 SkCanvas* rec_canvas = recorder.beginRecording(width, height, NULL, 0);
323 if (compositor_) {
325 // Reset scroll back to the origin, will go back to the old
326 // value when scroll_reset is out of scope.
327 base::AutoReset<gfx::Vector2dF> scroll_reset(&scroll_offset_dip_,
328 gfx::Vector2dF());
329 compositor_->DidChangeRootLayerScrollOffset();
330 CompositeSW(rec_canvas);
332 compositor_->DidChangeRootLayerScrollOffset();
334 return skia::AdoptRef(recorder.endRecording());
337 void BrowserViewRenderer::EnableOnNewPicture(bool enabled) {
338 on_new_picture_enable_ = enabled;
341 void BrowserViewRenderer::ClearView() {
342 TRACE_EVENT_INSTANT0("android_webview",
343 "BrowserViewRenderer::ClearView",
344 TRACE_EVENT_SCOPE_THREAD);
345 if (clear_view_)
346 return;
348 clear_view_ = true;
349 // Always invalidate ignoring the compositor to actually clear the webview.
350 PostInvalidateWithFallback();
353 void BrowserViewRenderer::SetOffscreenPreRaster(bool enable) {
354 if (offscreen_pre_raster_ != enable && compositor_)
355 UpdateMemoryPolicy();
357 offscreen_pre_raster_ = enable;
360 void BrowserViewRenderer::SetIsPaused(bool paused) {
361 TRACE_EVENT_INSTANT1("android_webview",
362 "BrowserViewRenderer::SetIsPaused",
363 TRACE_EVENT_SCOPE_THREAD,
364 "paused",
365 paused);
366 is_paused_ = paused;
367 UpdateCompositorIsActive();
370 void BrowserViewRenderer::SetViewVisibility(bool view_visible) {
371 TRACE_EVENT_INSTANT1("android_webview",
372 "BrowserViewRenderer::SetViewVisibility",
373 TRACE_EVENT_SCOPE_THREAD,
374 "view_visible",
375 view_visible);
376 view_visible_ = view_visible;
379 void BrowserViewRenderer::SetWindowVisibility(bool window_visible) {
380 TRACE_EVENT_INSTANT1("android_webview",
381 "BrowserViewRenderer::SetWindowVisibility",
382 TRACE_EVENT_SCOPE_THREAD,
383 "window_visible",
384 window_visible);
385 window_visible_ = window_visible;
386 UpdateCompositorIsActive();
389 void BrowserViewRenderer::OnSizeChanged(int width, int height) {
390 TRACE_EVENT_INSTANT2("android_webview",
391 "BrowserViewRenderer::OnSizeChanged",
392 TRACE_EVENT_SCOPE_THREAD,
393 "width",
394 width,
395 "height",
396 height);
397 size_.SetSize(width, height);
400 void BrowserViewRenderer::OnAttachedToWindow(int width, int height) {
401 TRACE_EVENT2("android_webview",
402 "BrowserViewRenderer::OnAttachedToWindow",
403 "width",
404 width,
405 "height",
406 height);
407 attached_to_window_ = true;
408 size_.SetSize(width, height);
409 UpdateCompositorIsActive();
412 void BrowserViewRenderer::OnDetachedFromWindow() {
413 TRACE_EVENT0("android_webview", "BrowserViewRenderer::OnDetachedFromWindow");
414 shared_renderer_state_.ReleaseHardwareDrawIfNeededOnUI();
415 attached_to_window_ = false;
416 DCHECK(!hardware_enabled_);
417 UpdateCompositorIsActive();
420 void BrowserViewRenderer::OnComputeScroll(base::TimeTicks animation_time) {
421 if (pending_fling_animation_.is_null())
422 return;
423 TRACE_EVENT0("android_webview", "BrowserViewRenderer::OnComputeScroll");
424 DCHECK(!pending_fling_animation_.is_null());
425 AnimationCallback animation = pending_fling_animation_;
426 pending_fling_animation_.Reset();
427 animation.Run(animation_time);
430 void BrowserViewRenderer::ReleaseHardware() {
431 DCHECK(hardware_enabled_);
432 ReturnUnusedResource(shared_renderer_state_.PassUncommittedFrameOnUI());
433 ReturnResourceFromParent();
434 DCHECK(shared_renderer_state_.ReturnedResourcesEmptyOnUI());
436 if (compositor_) {
437 compositor_->SetMemoryPolicy(0u);
440 hardware_enabled_ = false;
443 bool BrowserViewRenderer::IsVisible() const {
444 // Ignore |window_visible_| if |attached_to_window_| is false.
445 return view_visible_ && (!attached_to_window_ || window_visible_);
448 gfx::Rect BrowserViewRenderer::GetScreenRect() const {
449 return gfx::Rect(client_->GetLocationOnScreen(), size_);
452 void BrowserViewRenderer::DidInitializeCompositor(
453 content::SynchronousCompositor* compositor) {
454 TRACE_EVENT0("android_webview",
455 "BrowserViewRenderer::DidInitializeCompositor");
456 DCHECK(compositor);
457 DCHECK(!compositor_);
458 compositor_ = compositor;
459 UpdateCompositorIsActive();
462 void BrowserViewRenderer::DidDestroyCompositor(
463 content::SynchronousCompositor* compositor) {
464 TRACE_EVENT0("android_webview", "BrowserViewRenderer::DidDestroyCompositor");
465 DCHECK(compositor_);
466 compositor_->SetIsActive(false);
467 compositor_ = NULL;
470 void BrowserViewRenderer::SetDipScale(float dip_scale) {
471 dip_scale_ = dip_scale;
472 CHECK_GT(dip_scale_, 0.f);
475 gfx::Vector2d BrowserViewRenderer::max_scroll_offset() const {
476 DCHECK_GT(dip_scale_, 0.f);
477 return gfx::ToCeiledVector2d(gfx::ScaleVector2d(
478 max_scroll_offset_dip_, dip_scale_ * page_scale_factor_));
481 void BrowserViewRenderer::ScrollTo(gfx::Vector2d scroll_offset) {
482 gfx::Vector2d max_offset = max_scroll_offset();
483 gfx::Vector2dF scroll_offset_dip;
484 // To preserve the invariant that scrolling to the maximum physical pixel
485 // value also scrolls to the maximum dip pixel value we transform the physical
486 // offset into the dip offset by using a proportion (instead of dividing by
487 // dip_scale * page_scale_factor).
488 if (max_offset.x()) {
489 scroll_offset_dip.set_x((scroll_offset.x() * max_scroll_offset_dip_.x()) /
490 max_offset.x());
492 if (max_offset.y()) {
493 scroll_offset_dip.set_y((scroll_offset.y() * max_scroll_offset_dip_.y()) /
494 max_offset.y());
497 DCHECK_LE(0.f, scroll_offset_dip.x());
498 DCHECK_LE(0.f, scroll_offset_dip.y());
499 DCHECK(scroll_offset_dip.x() < max_scroll_offset_dip_.x() ||
500 scroll_offset_dip.x() - max_scroll_offset_dip_.x() < kEpsilon)
501 << scroll_offset_dip.x() << " " << max_scroll_offset_dip_.x();
502 DCHECK(scroll_offset_dip.y() < max_scroll_offset_dip_.y() ||
503 scroll_offset_dip.y() - max_scroll_offset_dip_.y() < kEpsilon)
504 << scroll_offset_dip.y() << " " << max_scroll_offset_dip_.y();
506 if (scroll_offset_dip_ == scroll_offset_dip)
507 return;
509 scroll_offset_dip_ = scroll_offset_dip;
511 TRACE_EVENT_INSTANT2("android_webview",
512 "BrowserViewRenderer::ScrollTo",
513 TRACE_EVENT_SCOPE_THREAD,
514 "x",
515 scroll_offset_dip.x(),
516 "y",
517 scroll_offset_dip.y());
519 if (compositor_)
520 compositor_->DidChangeRootLayerScrollOffset();
523 void BrowserViewRenderer::DidUpdateContent() {
524 TRACE_EVENT_INSTANT0("android_webview",
525 "BrowserViewRenderer::DidUpdateContent",
526 TRACE_EVENT_SCOPE_THREAD);
527 clear_view_ = false;
528 if (on_new_picture_enable_)
529 client_->OnNewPicture();
532 void BrowserViewRenderer::SetTotalRootLayerScrollOffset(
533 gfx::Vector2dF scroll_offset_dip) {
534 // TOOD(mkosiba): Add a DCHECK to say that this does _not_ get called during
535 // DrawGl when http://crbug.com/249972 is fixed.
536 if (scroll_offset_dip_ == scroll_offset_dip)
537 return;
539 scroll_offset_dip_ = scroll_offset_dip;
541 gfx::Vector2d max_offset = max_scroll_offset();
542 gfx::Vector2d scroll_offset;
543 // For an explanation as to why this is done this way see the comment in
544 // BrowserViewRenderer::ScrollTo.
545 if (max_scroll_offset_dip_.x()) {
546 scroll_offset.set_x((scroll_offset_dip.x() * max_offset.x()) /
547 max_scroll_offset_dip_.x());
550 if (max_scroll_offset_dip_.y()) {
551 scroll_offset.set_y((scroll_offset_dip.y() * max_offset.y()) /
552 max_scroll_offset_dip_.y());
555 DCHECK_LE(0, scroll_offset.x());
556 DCHECK_LE(0, scroll_offset.y());
557 DCHECK_LE(scroll_offset.x(), max_offset.x());
558 DCHECK_LE(scroll_offset.y(), max_offset.y());
560 client_->ScrollContainerViewTo(scroll_offset);
563 gfx::Vector2dF BrowserViewRenderer::GetTotalRootLayerScrollOffset() {
564 return scroll_offset_dip_;
567 bool BrowserViewRenderer::IsExternalScrollActive() const {
568 return client_->IsSmoothScrollingActive();
571 void BrowserViewRenderer::UpdateRootLayerState(
572 const gfx::Vector2dF& total_scroll_offset_dip,
573 const gfx::Vector2dF& max_scroll_offset_dip,
574 const gfx::SizeF& scrollable_size_dip,
575 float page_scale_factor,
576 float min_page_scale_factor,
577 float max_page_scale_factor) {
578 TRACE_EVENT_INSTANT1(
579 "android_webview",
580 "BrowserViewRenderer::UpdateRootLayerState",
581 TRACE_EVENT_SCOPE_THREAD,
582 "state",
583 RootLayerStateAsValue(total_scroll_offset_dip, scrollable_size_dip));
585 DCHECK_GT(dip_scale_, 0.f);
587 max_scroll_offset_dip_ = max_scroll_offset_dip;
588 DCHECK_LE(0.f, max_scroll_offset_dip_.x());
589 DCHECK_LE(0.f, max_scroll_offset_dip_.y());
591 page_scale_factor_ = page_scale_factor;
592 DCHECK_GT(page_scale_factor_, 0.f);
594 client_->UpdateScrollState(max_scroll_offset(),
595 scrollable_size_dip,
596 page_scale_factor,
597 min_page_scale_factor,
598 max_page_scale_factor);
599 SetTotalRootLayerScrollOffset(total_scroll_offset_dip);
602 scoped_refptr<base::trace_event::ConvertableToTraceFormat>
603 BrowserViewRenderer::RootLayerStateAsValue(
604 const gfx::Vector2dF& total_scroll_offset_dip,
605 const gfx::SizeF& scrollable_size_dip) {
606 scoped_refptr<base::trace_event::TracedValue> state =
607 new base::trace_event::TracedValue();
609 state->SetDouble("total_scroll_offset_dip.x", total_scroll_offset_dip.x());
610 state->SetDouble("total_scroll_offset_dip.y", total_scroll_offset_dip.y());
612 state->SetDouble("max_scroll_offset_dip.x", max_scroll_offset_dip_.x());
613 state->SetDouble("max_scroll_offset_dip.y", max_scroll_offset_dip_.y());
615 state->SetDouble("scrollable_size_dip.width", scrollable_size_dip.width());
616 state->SetDouble("scrollable_size_dip.height", scrollable_size_dip.height());
618 state->SetDouble("page_scale_factor", page_scale_factor_);
619 return state;
622 void BrowserViewRenderer::SetNeedsAnimateScroll(
623 const AnimationCallback& scroll_animation) {
624 pending_fling_animation_ = scroll_animation;
625 // No need to reschedule the fallback tick here because the compositor is
626 // fine with the animation not being ticked. The invalidate could happen some
627 // time later, or not at all.
628 client_->PostInvalidate();
631 void BrowserViewRenderer::DidOverscroll(gfx::Vector2dF accumulated_overscroll,
632 gfx::Vector2dF latest_overscroll_delta,
633 gfx::Vector2dF current_fling_velocity) {
634 const float physical_pixel_scale = dip_scale_ * page_scale_factor_;
635 if (accumulated_overscroll == latest_overscroll_delta)
636 overscroll_rounding_error_ = gfx::Vector2dF();
637 gfx::Vector2dF scaled_overscroll_delta =
638 gfx::ScaleVector2d(latest_overscroll_delta, physical_pixel_scale);
639 gfx::Vector2d rounded_overscroll_delta = gfx::ToRoundedVector2d(
640 scaled_overscroll_delta + overscroll_rounding_error_);
641 overscroll_rounding_error_ =
642 scaled_overscroll_delta - rounded_overscroll_delta;
643 gfx::Vector2dF fling_velocity_pixels =
644 gfx::ScaleVector2d(current_fling_velocity, physical_pixel_scale);
646 client_->DidOverscroll(rounded_overscroll_delta, fling_velocity_pixels);
649 void BrowserViewRenderer::PostInvalidate() {
650 TRACE_EVENT_INSTANT0("android_webview", "BrowserViewRenderer::PostInvalidate",
651 TRACE_EVENT_SCOPE_THREAD);
652 PostInvalidateWithFallback();
655 void BrowserViewRenderer::PostInvalidateWithFallback() {
656 // Always call view invalidate. We rely the Android framework to ignore the
657 // invalidate when it's not needed such as when view is not visible.
658 client_->PostInvalidate();
660 // Stop fallback ticks when one of these is true.
661 // 1) Webview is paused. Also need to check we are not in clear view since
662 // paused, offscreen still expect clear view to recover.
663 // 2) If we are attached to window and the window is not visible (eg when
664 // app is in the background). We are sure in this case the webview is used
665 // "on-screen" but that updates are not needed when in the background.
666 bool throttle_fallback_tick =
667 (is_paused_ && !clear_view_) || (attached_to_window_ && !window_visible_);
669 if (throttle_fallback_tick || fallback_tick_pending_)
670 return;
672 DCHECK(post_fallback_tick_.IsCancelled());
673 DCHECK(fallback_tick_fired_.IsCancelled());
675 post_fallback_tick_.Reset(base::Bind(&BrowserViewRenderer::PostFallbackTick,
676 base::Unretained(this)));
677 ui_task_runner_->PostTask(FROM_HERE, post_fallback_tick_.callback());
678 fallback_tick_pending_ = true;
681 void BrowserViewRenderer::CancelFallbackTick() {
682 post_fallback_tick_.Cancel();
683 fallback_tick_fired_.Cancel();
684 fallback_tick_pending_ = false;
687 void BrowserViewRenderer::PostFallbackTick() {
688 DCHECK(fallback_tick_fired_.IsCancelled());
689 TRACE_EVENT0("android_webview", "BrowserViewRenderer::PostFallbackTick");
690 post_fallback_tick_.Cancel();
691 fallback_tick_fired_.Reset(base::Bind(&BrowserViewRenderer::FallbackTickFired,
692 base::Unretained(this)));
693 ui_task_runner_->PostDelayedTask(
694 FROM_HERE, fallback_tick_fired_.callback(),
695 base::TimeDelta::FromMilliseconds(kFallbackTickTimeoutInMilliseconds));
698 void BrowserViewRenderer::FallbackTickFired() {
699 TRACE_EVENT0("android_webview", "BrowserViewRenderer::FallbackTickFired");
700 // This should only be called if OnDraw or DrawGL did not come in time, which
701 // means fallback_tick_pending_ must still be true.
702 DCHECK(fallback_tick_pending_);
703 fallback_tick_fired_.Cancel();
704 fallback_tick_pending_ = false;
705 if (compositor_) {
706 if (hardware_enabled_) {
707 CompositeHw();
708 } else {
709 ForceFakeCompositeSW();
714 void BrowserViewRenderer::ForceFakeCompositeSW() {
715 DCHECK(compositor_);
716 SkBitmap bitmap;
717 bitmap.allocN32Pixels(1, 1);
718 bitmap.eraseColor(0);
719 SkCanvas canvas(bitmap);
720 CompositeSW(&canvas);
723 bool BrowserViewRenderer::CompositeSW(SkCanvas* canvas) {
724 DCHECK(compositor_);
725 CancelFallbackTick();
726 ReturnResourceFromParent();
727 return compositor_->DemandDrawSw(canvas);
730 void BrowserViewRenderer::UpdateCompositorIsActive() {
731 if (compositor_)
732 compositor_->SetIsActive(!is_paused_ &&
733 (!attached_to_window_ || window_visible_));
736 std::string BrowserViewRenderer::ToString() const {
737 std::string str;
738 base::StringAppendF(&str, "is_paused: %d ", is_paused_);
739 base::StringAppendF(&str, "view_visible: %d ", view_visible_);
740 base::StringAppendF(&str, "window_visible: %d ", window_visible_);
741 base::StringAppendF(&str, "dip_scale: %f ", dip_scale_);
742 base::StringAppendF(&str, "page_scale_factor: %f ", page_scale_factor_);
743 base::StringAppendF(&str, "fallback_tick_pending: %d ",
744 fallback_tick_pending_);
745 base::StringAppendF(&str, "view size: %s ", size_.ToString().c_str());
746 base::StringAppendF(&str, "attached_to_window: %d ", attached_to_window_);
747 base::StringAppendF(&str,
748 "global visible rect: %s ",
749 last_on_draw_global_visible_rect_.ToString().c_str());
750 base::StringAppendF(
751 &str, "scroll_offset_dip: %s ", scroll_offset_dip_.ToString().c_str());
752 base::StringAppendF(&str,
753 "overscroll_rounding_error_: %s ",
754 overscroll_rounding_error_.ToString().c_str());
755 base::StringAppendF(
756 &str, "on_new_picture_enable: %d ", on_new_picture_enable_);
757 base::StringAppendF(&str, "clear_view: %d ", clear_view_);
758 return str;
761 } // namespace android_webview