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/logging.h"
15 #include "base/strings/string_number_conversions.h"
16 #include "base/strings/stringprintf.h"
17 #include "content/public/browser/android/synchronous_compositor.h"
18 #include "content/public/browser/browser_thread.h"
19 #include "content/public/browser/web_contents.h"
20 #include "content/public/common/content_switches.h"
21 #include "third_party/skia/include/core/SkBitmap.h"
22 #include "third_party/skia/include/core/SkCanvas.h"
23 #include "third_party/skia/include/core/SkPicture.h"
24 #include "third_party/skia/include/core/SkPictureRecorder.h"
25 #include "ui/gfx/vector2d_conversions.h"
27 using base::android::AttachCurrentThread;
28 using base::android::JavaRef;
29 using base::android::ScopedJavaLocalRef;
30 using content::BrowserThread;
31 using content::SynchronousCompositorMemoryPolicy;
33 namespace android_webview {
37 const int64 kFallbackTickTimeoutInMilliseconds = 20;
39 // Used to calculate memory allocation. Determined experimentally.
40 const size_t kMemoryMultiplier = 10;
41 const size_t kBytesPerPixel = 4;
42 const size_t kMemoryAllocationStep = 5 * 1024 * 1024;
44 // Used to calculate tile allocation. Determined experimentally.
45 const size_t kTileMultiplier = 12;
46 const size_t kTileAllocationStep = 20;
47 // This will be set by static function CalculateTileMemoryPolicy() during init.
48 // See AwMainDelegate::BasicStartupComplete.
51 class AutoResetWithLock {
53 AutoResetWithLock(gfx::Vector2dF* scoped_variable,
54 gfx::Vector2dF new_value,
56 : scoped_variable_(scoped_variable),
57 original_value_(*scoped_variable),
59 base::AutoLock auto_lock(lock_);
60 *scoped_variable_ = new_value;
63 ~AutoResetWithLock() {
64 base::AutoLock auto_lock(lock_);
65 *scoped_variable_ = original_value_;
69 gfx::Vector2dF* scoped_variable_;
70 gfx::Vector2dF original_value_;
73 DISALLOW_COPY_AND_ASSIGN(AutoResetWithLock);
79 void BrowserViewRenderer::CalculateTileMemoryPolicy() {
80 CommandLine* cl = CommandLine::ForCurrentProcess();
81 const char kDefaultTileSize[] = "384";
83 if (!cl->HasSwitch(switches::kDefaultTileWidth))
84 cl->AppendSwitchASCII(switches::kDefaultTileWidth, kDefaultTileSize);
86 if (!cl->HasSwitch(switches::kDefaultTileHeight))
87 cl->AppendSwitchASCII(switches::kDefaultTileHeight, kDefaultTileSize);
90 base::StringToSizeT(kDefaultTileSize, &tile_size);
91 g_tile_area = tile_size * tile_size;
94 BrowserViewRenderer::BrowserViewRenderer(
95 BrowserViewRendererClient* client,
96 SharedRendererState* shared_renderer_state,
97 content::WebContents* web_contents,
98 const scoped_refptr<base::SingleThreadTaskRunner>& ui_task_runner)
100 shared_renderer_state_(shared_renderer_state),
101 web_contents_(web_contents),
102 weak_factory_on_ui_thread_(this),
103 ui_thread_weak_ptr_(weak_factory_on_ui_thread_.GetWeakPtr()),
104 ui_task_runner_(ui_task_runner),
105 has_compositor_(false),
107 view_visible_(false),
108 window_visible_(false),
109 attached_to_window_(false),
111 page_scale_factor_(1.0),
112 on_new_picture_enable_(false),
114 compositor_needs_continuous_invalidate_(false),
115 block_invalidates_(false),
120 CHECK(web_contents_);
121 content::SynchronousCompositor::SetClientForWebContents(web_contents_, this);
123 // Currently the logic in this class relies on |has_compositor_| remaining
124 // false until the DidInitializeCompositor() call, hence it is not set here.
127 BrowserViewRenderer::~BrowserViewRenderer() {
128 content::SynchronousCompositor::SetClientForWebContents(web_contents_, NULL);
129 // OnDetachedFromWindow should be called before the destructor, so the memory
130 // policy should have already been updated.
133 // This function updates the cached memory policy in shared renderer state, as
134 // well as the tile resource allocation in GlobalTileManager.
135 void BrowserViewRenderer::TrimMemory(const int level, const bool visible) {
136 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
137 // Constants from Android ComponentCallbacks2.
139 TRIM_MEMORY_RUNNING_LOW = 10,
140 TRIM_MEMORY_UI_HIDDEN = 20,
141 TRIM_MEMORY_BACKGROUND = 40,
144 // Not urgent enough. TRIM_MEMORY_UI_HIDDEN is treated specially because
145 // it does not indicate memory pressure, but merely that the app is
147 if (level < TRIM_MEMORY_RUNNING_LOW || level == TRIM_MEMORY_UI_HIDDEN)
150 // Do not release resources on view we expect to get DrawGL soon.
151 if (level < TRIM_MEMORY_BACKGROUND && visible)
154 // Just set the memory limit to 0 and drop all tiles. This will be reset to
155 // normal levels in the next DrawGL call.
156 SynchronousCompositorMemoryPolicy zero_policy;
157 if (shared_renderer_state_->GetMemoryPolicy() == zero_policy)
160 TRACE_EVENT0("android_webview", "BrowserViewRenderer::TrimMemory");
162 RequestMemoryPolicy(zero_policy);
163 EnforceMemoryPolicyImmediately(zero_policy);
166 SynchronousCompositorMemoryPolicy
167 BrowserViewRenderer::CalculateDesiredMemoryPolicy() {
168 SynchronousCompositorMemoryPolicy policy;
169 size_t width = draw_gl_input_.global_visible_rect.width();
170 size_t height = draw_gl_input_.global_visible_rect.height();
171 policy.bytes_limit = kMemoryMultiplier * kBytesPerPixel * width * height;
172 // Round up to a multiple of kMemoryAllocationStep.
174 (policy.bytes_limit / kMemoryAllocationStep + 1) * kMemoryAllocationStep;
176 size_t tiles = width * height * kTileMultiplier / g_tile_area;
177 // Round up to a multiple of kTileAllocationStep. The minimum number of tiles
178 // is also kTileAllocationStep.
179 tiles = (tiles / kTileAllocationStep + 1) * kTileAllocationStep;
180 policy.num_resources_limit = tiles;
184 // This function updates the cached memory policy in shared renderer state, as
185 // well as the tile resource allocation in GlobalTileManager.
186 void BrowserViewRenderer::RequestMemoryPolicy(
187 SynchronousCompositorMemoryPolicy& new_policy) {
188 // This will be used in SetNumTiles.
189 num_bytes_ = new_policy.bytes_limit;
191 GlobalTileManager* manager = GlobalTileManager::GetInstance();
193 // The following line will call BrowserViewRenderer::SetTilesNum().
194 manager->RequestTiles(new_policy.num_resources_limit, tile_manager_key_);
197 void BrowserViewRenderer::SetNumTiles(size_t num_tiles,
198 bool effective_immediately) {
199 if (num_tiles == num_tiles_)
201 num_tiles_ = num_tiles;
203 SynchronousCompositorMemoryPolicy new_policy;
204 new_policy.num_resources_limit = num_tiles_;
205 new_policy.bytes_limit = num_bytes_;
206 shared_renderer_state_->SetMemoryPolicy(new_policy);
208 if (effective_immediately)
209 EnforceMemoryPolicyImmediately(new_policy);
212 void BrowserViewRenderer::EnforceMemoryPolicyImmediately(
213 SynchronousCompositorMemoryPolicy new_policy) {
214 shared_renderer_state_->GetCompositor()->SetMemoryPolicy(new_policy);
215 ForceFakeCompositeSW();
216 shared_renderer_state_->SetMemoryPolicyDirty(false);
219 size_t BrowserViewRenderer::GetNumTiles() const {
220 return shared_renderer_state_->GetMemoryPolicy().num_resources_limit;
223 bool BrowserViewRenderer::OnDraw(jobject java_canvas,
224 bool is_hardware_canvas,
225 const gfx::Vector2d& scroll,
226 const gfx::Rect& global_visible_rect,
227 const gfx::Rect& clip) {
228 draw_gl_input_.frame_id++;
229 draw_gl_input_.scroll_offset = scroll;
230 draw_gl_input_.global_visible_rect = global_visible_rect;
231 draw_gl_input_.width = width_;
232 draw_gl_input_.height = height_;
235 if (is_hardware_canvas && attached_to_window_) {
236 shared_renderer_state_->SetDrawGLInput(draw_gl_input_);
238 SynchronousCompositorMemoryPolicy old_policy =
239 shared_renderer_state_->GetMemoryPolicy();
240 SynchronousCompositorMemoryPolicy new_policy =
241 CalculateDesiredMemoryPolicy();
242 RequestMemoryPolicy(new_policy);
243 // We should be performing a hardware draw here. If we don't have the
244 // compositor yet or if RequestDrawGL fails, it means we failed this draw
245 // and thus return false here to clear to background color for this draw.
247 has_compositor_ && client_->RequestDrawGL(java_canvas, false);
249 GlobalTileManager::GetInstance()->DidUse(tile_manager_key_);
251 RequestMemoryPolicy(old_policy);
255 // Perform a software draw
256 return DrawSWInternal(java_canvas, clip);
259 void BrowserViewRenderer::DidDrawGL(const DrawGLResult& result) {
260 DidComposite(!result.clip_contains_visible_rect);
263 bool BrowserViewRenderer::DrawSWInternal(jobject java_canvas,
264 const gfx::Rect& clip) {
265 if (clip.IsEmpty()) {
266 TRACE_EVENT_INSTANT0(
267 "android_webview", "EarlyOut_EmptyClip", TRACE_EVENT_SCOPE_THREAD);
271 if (!has_compositor_) {
272 TRACE_EVENT_INSTANT0(
273 "android_webview", "EarlyOut_NoCompositor", TRACE_EVENT_SCOPE_THREAD);
277 return BrowserViewRendererJavaHelper::GetInstance()
278 ->RenderViaAuxilaryBitmapIfNeeded(
280 draw_gl_input_.scroll_offset,
282 base::Bind(&BrowserViewRenderer::CompositeSW,
283 base::Unretained(this)));
286 skia::RefPtr<SkPicture> BrowserViewRenderer::CapturePicture(int width,
288 TRACE_EVENT0("android_webview", "BrowserViewRenderer::CapturePicture");
290 // Return empty Picture objects for empty SkPictures.
291 if (width <= 0 || height <= 0) {
292 return skia::AdoptRef(new SkPicture);
295 // Reset scroll back to the origin, will go back to the old
296 // value when scroll_reset is out of scope.
297 AutoResetWithLock scroll_reset(
298 &scroll_offset_dip_, gfx::Vector2dF(), render_thread_lock_);
300 SkPictureRecorder recorder;
301 SkCanvas* rec_canvas = recorder.beginRecording(width, height, NULL, 0);
303 CompositeSW(rec_canvas);
304 return skia::AdoptRef(recorder.endRecording());
307 void BrowserViewRenderer::EnableOnNewPicture(bool enabled) {
308 on_new_picture_enable_ = enabled;
311 void BrowserViewRenderer::ClearView() {
312 TRACE_EVENT_INSTANT0("android_webview",
313 "BrowserViewRenderer::ClearView",
314 TRACE_EVENT_SCOPE_THREAD);
319 // Always invalidate ignoring the compositor to actually clear the webview.
320 EnsureContinuousInvalidation(true);
323 void BrowserViewRenderer::SetIsPaused(bool paused) {
324 TRACE_EVENT_INSTANT1("android_webview",
325 "BrowserViewRenderer::SetIsPaused",
326 TRACE_EVENT_SCOPE_THREAD,
330 EnsureContinuousInvalidation(false);
333 void BrowserViewRenderer::SetViewVisibility(bool view_visible) {
334 TRACE_EVENT_INSTANT1("android_webview",
335 "BrowserViewRenderer::SetViewVisibility",
336 TRACE_EVENT_SCOPE_THREAD,
339 view_visible_ = view_visible;
342 void BrowserViewRenderer::SetWindowVisibility(bool window_visible) {
343 TRACE_EVENT_INSTANT1("android_webview",
344 "BrowserViewRenderer::SetWindowVisibility",
345 TRACE_EVENT_SCOPE_THREAD,
348 window_visible_ = window_visible;
349 EnsureContinuousInvalidation(false);
352 void BrowserViewRenderer::OnSizeChanged(int width, int height) {
353 TRACE_EVENT_INSTANT2("android_webview",
354 "BrowserViewRenderer::OnSizeChanged",
355 TRACE_EVENT_SCOPE_THREAD,
364 void BrowserViewRenderer::OnAttachedToWindow(int width, int height) {
365 TRACE_EVENT2("android_webview",
366 "BrowserViewRenderer::OnAttachedToWindow",
371 attached_to_window_ = true;
374 tile_manager_key_ = GlobalTileManager::GetInstance()->PushBack(this);
377 void BrowserViewRenderer::OnDetachedFromWindow() {
378 TRACE_EVENT0("android_webview", "BrowserViewRenderer::OnDetachedFromWindow");
379 attached_to_window_ = false;
380 SynchronousCompositorMemoryPolicy zero_policy;
381 RequestMemoryPolicy(zero_policy);
382 GlobalTileManager::GetInstance()->Remove(tile_manager_key_);
383 // The hardware resources are released in the destructor of hardware renderer,
384 // so we don't need to do it here.
385 // See AwContents::ReleaseHardwareDrawOnRenderThread(JNIEnv*, jobject).
388 bool BrowserViewRenderer::IsAttachedToWindow() const {
389 return attached_to_window_;
392 bool BrowserViewRenderer::IsVisible() const {
393 // Ignore |window_visible_| if |attached_to_window_| is false.
394 return view_visible_ && (!attached_to_window_ || window_visible_);
397 gfx::Rect BrowserViewRenderer::GetScreenRect() const {
398 return gfx::Rect(client_->GetLocationOnScreen(), gfx::Size(width_, height_));
401 void BrowserViewRenderer::DidInitializeCompositor(
402 content::SynchronousCompositor* compositor) {
403 TRACE_EVENT0("android_webview",
404 "BrowserViewRenderer::DidInitializeCompositor");
406 DCHECK(!has_compositor_);
407 DCHECK(ui_task_runner_->BelongsToCurrentThread());
408 has_compositor_ = true;
409 shared_renderer_state_->SetCompositorOnUiThread(compositor);
412 void BrowserViewRenderer::DidDestroyCompositor(
413 content::SynchronousCompositor* compositor) {
414 TRACE_EVENT0("android_webview", "BrowserViewRenderer::DidDestroyCompositor");
415 DCHECK(has_compositor_);
416 DCHECK(ui_task_runner_->BelongsToCurrentThread());
417 has_compositor_ = false;
418 shared_renderer_state_->SetCompositorOnUiThread(NULL);
419 SynchronousCompositorMemoryPolicy zero_policy;
420 DCHECK(shared_renderer_state_->GetMemoryPolicy() == zero_policy);
423 void BrowserViewRenderer::SetContinuousInvalidate(bool invalidate) {
425 base::AutoLock lock(render_thread_lock_);
426 if (compositor_needs_continuous_invalidate_ == invalidate)
429 TRACE_EVENT_INSTANT1("android_webview",
430 "BrowserViewRenderer::SetContinuousInvalidate",
431 TRACE_EVENT_SCOPE_THREAD,
434 compositor_needs_continuous_invalidate_ = invalidate;
437 if (ui_task_runner_->BelongsToCurrentThread()) {
438 EnsureContinuousInvalidation(false);
441 ui_task_runner_->PostTask(
443 base::Bind(&BrowserViewRenderer::EnsureContinuousInvalidation,
448 void BrowserViewRenderer::SetDipScale(float dip_scale) {
449 dip_scale_ = dip_scale;
450 CHECK(dip_scale_ > 0);
453 gfx::Vector2d BrowserViewRenderer::max_scroll_offset() const {
454 DCHECK_GT(dip_scale_, 0);
455 return gfx::ToCeiledVector2d(gfx::ScaleVector2d(
456 max_scroll_offset_dip_, dip_scale_ * page_scale_factor_));
459 void BrowserViewRenderer::ScrollTo(gfx::Vector2d scroll_offset) {
460 gfx::Vector2d max_offset = max_scroll_offset();
461 gfx::Vector2dF scroll_offset_dip;
462 // To preserve the invariant that scrolling to the maximum physical pixel
463 // value also scrolls to the maximum dip pixel value we transform the physical
464 // offset into the dip offset by using a proportion (instead of dividing by
465 // dip_scale * page_scale_factor).
466 if (max_offset.x()) {
467 scroll_offset_dip.set_x((scroll_offset.x() * max_scroll_offset_dip_.x()) /
470 if (max_offset.y()) {
471 scroll_offset_dip.set_y((scroll_offset.y() * max_scroll_offset_dip_.y()) /
475 DCHECK_LE(0, scroll_offset_dip.x());
476 DCHECK_LE(0, scroll_offset_dip.y());
477 DCHECK_LE(scroll_offset_dip.x(), max_scroll_offset_dip_.x());
478 DCHECK_LE(scroll_offset_dip.y(), max_scroll_offset_dip_.y());
481 base::AutoLock lock(render_thread_lock_);
482 if (scroll_offset_dip_ == scroll_offset_dip)
485 scroll_offset_dip_ = scroll_offset_dip;
489 shared_renderer_state_->GetCompositor()->
490 DidChangeRootLayerScrollOffset();
493 void BrowserViewRenderer::DidUpdateContent() {
494 if (!ui_task_runner_->BelongsToCurrentThread()) {
495 ui_task_runner_->PostTask(FROM_HERE,
496 base::Bind(&BrowserViewRenderer::DidUpdateContent,
497 ui_thread_weak_ptr_));
500 TRACE_EVENT_INSTANT0("android_webview",
501 "BrowserViewRenderer::DidUpdateContent",
502 TRACE_EVENT_SCOPE_THREAD);
504 if (on_new_picture_enable_)
505 client_->OnNewPicture();
508 void BrowserViewRenderer::SetMaxRootLayerScrollOffset(
509 gfx::Vector2dF new_value_dip) {
510 if (!ui_task_runner_->BelongsToCurrentThread()) {
511 ui_task_runner_->PostTask(
513 base::Bind(&BrowserViewRenderer::SetMaxRootLayerScrollOffset,
518 DCHECK_GT(dip_scale_, 0);
520 max_scroll_offset_dip_ = new_value_dip;
521 DCHECK_LE(0, max_scroll_offset_dip_.x());
522 DCHECK_LE(0, max_scroll_offset_dip_.y());
524 client_->SetMaxContainerViewScrollOffset(max_scroll_offset());
527 void BrowserViewRenderer::SetTotalRootLayerScrollOffset(
528 gfx::Vector2dF scroll_offset_dip) {
529 if (!ui_task_runner_->BelongsToCurrentThread()) {
530 ui_task_runner_->PostTask(
532 base::Bind(&BrowserViewRenderer::SetTotalRootLayerScrollOffset,
539 base::AutoLock lock(render_thread_lock_);
540 // TOOD(mkosiba): Add a DCHECK to say that this does _not_ get called during
541 // DrawGl when http://crbug.com/249972 is fixed.
542 if (scroll_offset_dip_ == scroll_offset_dip)
545 scroll_offset_dip_ = scroll_offset_dip;
548 gfx::Vector2d max_offset = max_scroll_offset();
549 gfx::Vector2d scroll_offset;
550 // For an explanation as to why this is done this way see the comment in
551 // BrowserViewRenderer::ScrollTo.
552 if (max_scroll_offset_dip_.x()) {
553 scroll_offset.set_x((scroll_offset_dip.x() * max_offset.x()) /
554 max_scroll_offset_dip_.x());
557 if (max_scroll_offset_dip_.y()) {
558 scroll_offset.set_y((scroll_offset_dip.y() * max_offset.y()) /
559 max_scroll_offset_dip_.y());
562 DCHECK(0 <= scroll_offset.x());
563 DCHECK(0 <= scroll_offset.y());
564 // Disabled because the conditions are being violated while running
565 // AwZoomTest.testMagnification, see http://crbug.com/340648
566 // DCHECK(scroll_offset.x() <= max_offset.x());
567 // DCHECK(scroll_offset.y() <= max_offset.y());
569 client_->ScrollContainerViewTo(scroll_offset);
572 gfx::Vector2dF BrowserViewRenderer::GetTotalRootLayerScrollOffset() {
573 base::AutoLock lock(render_thread_lock_);
574 return scroll_offset_dip_;
577 bool BrowserViewRenderer::IsExternalFlingActive() const {
578 if (!ui_task_runner_->BelongsToCurrentThread()) {
579 // TODO(boliu): This is short term hack since we cannot call into
580 // view system on non-UI thread.
583 return client_->IsFlingActive();
586 void BrowserViewRenderer::SetRootLayerPageScaleFactorAndLimits(
587 float page_scale_factor,
588 float min_page_scale_factor,
589 float max_page_scale_factor) {
590 if (!ui_task_runner_->BelongsToCurrentThread()) {
591 ui_task_runner_->PostTask(
593 base::Bind(&BrowserViewRenderer::SetRootLayerPageScaleFactorAndLimits,
596 min_page_scale_factor,
597 max_page_scale_factor));
600 page_scale_factor_ = page_scale_factor;
601 DCHECK_GT(page_scale_factor_, 0);
602 client_->SetPageScaleFactorAndLimits(
603 page_scale_factor, min_page_scale_factor, max_page_scale_factor);
604 client_->SetMaxContainerViewScrollOffset(max_scroll_offset());
607 void BrowserViewRenderer::SetRootLayerScrollableSize(
608 gfx::SizeF scrollable_size) {
609 if (!ui_task_runner_->BelongsToCurrentThread()) {
610 ui_task_runner_->PostTask(
612 base::Bind(&BrowserViewRenderer::SetRootLayerScrollableSize,
617 client_->SetContentsSize(scrollable_size);
620 void BrowserViewRenderer::DidOverscroll(gfx::Vector2dF accumulated_overscroll,
621 gfx::Vector2dF latest_overscroll_delta,
622 gfx::Vector2dF current_fling_velocity) {
623 if (!ui_task_runner_->BelongsToCurrentThread()) {
624 ui_task_runner_->PostTask(
626 base::Bind(&BrowserViewRenderer::DidOverscroll,
628 accumulated_overscroll,
629 latest_overscroll_delta,
630 current_fling_velocity));
633 const float physical_pixel_scale = dip_scale_ * page_scale_factor_;
634 if (accumulated_overscroll == latest_overscroll_delta)
635 overscroll_rounding_error_ = gfx::Vector2dF();
636 gfx::Vector2dF scaled_overscroll_delta =
637 gfx::ScaleVector2d(latest_overscroll_delta, physical_pixel_scale);
638 gfx::Vector2d rounded_overscroll_delta = gfx::ToRoundedVector2d(
639 scaled_overscroll_delta + overscroll_rounding_error_);
640 overscroll_rounding_error_ =
641 scaled_overscroll_delta - rounded_overscroll_delta;
642 client_->DidOverscroll(rounded_overscroll_delta);
645 void BrowserViewRenderer::EnsureContinuousInvalidation(bool force_invalidate) {
646 // This method should be called again when any of these conditions change.
647 bool need_invalidate =
648 compositor_needs_continuous_invalidate_ || force_invalidate;
649 if (!need_invalidate || block_invalidates_)
652 // Always call view invalidate. We rely the Android framework to ignore the
653 // invalidate when it's not needed such as when view is not visible.
654 client_->PostInvalidate();
656 // Stop fallback ticks when one of these is true.
657 // 1) Webview is paused. Also need to check we are not in clear view since
658 // paused, offscreen still expect clear view to recover.
659 // 2) If we are attached to window and the window is not visible (eg when
660 // app is in the background). We are sure in this case the webview is used
661 // "on-screen" but that updates are not needed when in the background.
662 bool throttle_fallback_tick =
663 (is_paused_ && !clear_view_) || (attached_to_window_ && !window_visible_);
664 if (throttle_fallback_tick)
667 block_invalidates_ = compositor_needs_continuous_invalidate_;
669 // Unretained here is safe because the callback is cancelled when
670 // |fallback_tick_| is destroyed.
671 fallback_tick_.Reset(base::Bind(&BrowserViewRenderer::FallbackTickFired,
672 base::Unretained(this)));
674 // No need to reschedule fallback tick if compositor does not need to be
675 // ticked. This can happen if this is reached because force_invalidate is
677 if (compositor_needs_continuous_invalidate_) {
678 ui_task_runner_->PostDelayedTask(
680 fallback_tick_.callback(),
681 base::TimeDelta::FromMilliseconds(kFallbackTickTimeoutInMilliseconds));
685 void BrowserViewRenderer::FallbackTickFired() {
686 TRACE_EVENT1("android_webview",
687 "BrowserViewRenderer::FallbackTickFired",
688 "compositor_needs_continuous_invalidate_",
689 compositor_needs_continuous_invalidate_);
691 // This should only be called if OnDraw or DrawGL did not come in time, which
692 // means block_invalidates_ must still be true.
693 DCHECK(block_invalidates_);
694 if (compositor_needs_continuous_invalidate_ && has_compositor_)
695 ForceFakeCompositeSW();
698 void BrowserViewRenderer::ForceFakeCompositeSW() {
699 DCHECK(has_compositor_);
701 bitmap.allocN32Pixels(1, 1);
702 bitmap.eraseColor(0);
703 SkCanvas canvas(bitmap);
704 CompositeSW(&canvas);
707 bool BrowserViewRenderer::CompositeSW(SkCanvas* canvas) {
708 DCHECK(has_compositor_);
709 bool result = shared_renderer_state_->GetCompositor()->
710 DemandDrawSw(canvas);
715 void BrowserViewRenderer::DidComposite(bool force_invalidate) {
716 fallback_tick_.Cancel();
717 block_invalidates_ = false;
718 EnsureContinuousInvalidation(force_invalidate);
721 std::string BrowserViewRenderer::ToString(AwDrawGLInfo* draw_info) const {
723 base::StringAppendF(&str, "is_paused: %d ", is_paused_);
724 base::StringAppendF(&str, "view_visible: %d ", view_visible_);
725 base::StringAppendF(&str, "window_visible: %d ", window_visible_);
726 base::StringAppendF(&str, "dip_scale: %f ", dip_scale_);
727 base::StringAppendF(&str, "page_scale_factor: %f ", page_scale_factor_);
728 base::StringAppendF(&str,
729 "compositor_needs_continuous_invalidate: %d ",
730 compositor_needs_continuous_invalidate_);
731 base::StringAppendF(&str, "block_invalidates: %d ", block_invalidates_);
732 base::StringAppendF(&str, "view width height: [%d %d] ", width_, height_);
733 base::StringAppendF(&str, "attached_to_window: %d ", attached_to_window_);
734 base::StringAppendF(&str,
735 "global visible rect: %s ",
736 draw_gl_input_.global_visible_rect.ToString().c_str());
738 &str, "scroll_offset_dip: %s ", scroll_offset_dip_.ToString().c_str());
739 base::StringAppendF(&str,
740 "overscroll_rounding_error_: %s ",
741 overscroll_rounding_error_.ToString().c_str());
743 &str, "on_new_picture_enable: %d ", on_new_picture_enable_);
744 base::StringAppendF(&str, "clear_view: %d ", clear_view_);
746 base::StringAppendF(&str,
747 "clip left top right bottom: [%d %d %d %d] ",
748 draw_info->clip_left,
750 draw_info->clip_right,
751 draw_info->clip_bottom);
752 base::StringAppendF(&str,
753 "surface width height: [%d %d] ",
756 base::StringAppendF(&str, "is_layer: %d ", draw_info->is_layer);
761 } // namespace android_webview