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/common/aw_switches.h"
9 #include "base/auto_reset.h"
10 #include "base/command_line.h"
11 #include "base/debug/trace_event_argument.h"
12 #include "base/logging.h"
13 #include "base/strings/string_number_conversions.h"
14 #include "base/strings/stringprintf.h"
15 #include "cc/output/compositor_frame.h"
16 #include "content/public/common/content_switches.h"
17 #include "gpu/command_buffer/service/gpu_switches.h"
18 #include "third_party/skia/include/core/SkBitmap.h"
19 #include "third_party/skia/include/core/SkCanvas.h"
20 #include "third_party/skia/include/core/SkPicture.h"
21 #include "third_party/skia/include/core/SkPictureRecorder.h"
22 #include "ui/gfx/geometry/vector2d_conversions.h"
24 namespace android_webview
{
28 const int64 kFallbackTickTimeoutInMilliseconds
= 100;
30 // Used to calculate memory allocation. Determined experimentally.
31 const size_t kMemoryMultiplier
= 20;
32 const size_t kBytesPerPixel
= 4;
33 const size_t kMemoryAllocationStep
= 5 * 1024 * 1024;
34 uint64 g_memory_override_in_bytes
= 0u;
39 void BrowserViewRenderer::CalculateTileMemoryPolicy() {
40 base::CommandLine
* cl
= base::CommandLine::ForCurrentProcess();
42 // If the value was overridden on the command line, use the specified value.
43 bool client_hard_limit_bytes_overridden
=
44 cl
->HasSwitch(switches::kForceGpuMemAvailableMb
);
45 if (client_hard_limit_bytes_overridden
) {
47 base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
48 switches::kForceGpuMemAvailableMb
),
49 &g_memory_override_in_bytes
);
50 g_memory_override_in_bytes
*= 1024 * 1024;
54 BrowserViewRenderer::BrowserViewRenderer(
55 BrowserViewRendererClient
* client
,
56 const scoped_refptr
<base::SingleThreadTaskRunner
>& ui_task_runner
)
58 shared_renderer_state_(ui_task_runner
, this),
59 ui_task_runner_(ui_task_runner
),
63 window_visible_(false),
64 attached_to_window_(false),
65 hardware_enabled_(false),
67 page_scale_factor_(1.0),
68 on_new_picture_enable_(false),
70 compositor_needs_continuous_invalidate_(false),
71 invalidate_after_composite_(false),
72 block_invalidates_(false),
73 fallback_tick_pending_(false) {
76 BrowserViewRenderer::~BrowserViewRenderer() {
79 intptr_t BrowserViewRenderer::GetAwDrawGLViewContext() {
80 return reinterpret_cast<intptr_t>(&shared_renderer_state_
);
83 bool BrowserViewRenderer::RequestDrawGL(bool wait_for_completion
) {
84 return client_
->RequestDrawGL(wait_for_completion
);
87 // This function updates the resource allocation in GlobalTileManager.
88 void BrowserViewRenderer::TrimMemory(const int level
, const bool visible
) {
89 DCHECK(ui_task_runner_
->BelongsToCurrentThread());
90 // Constants from Android ComponentCallbacks2.
92 TRIM_MEMORY_RUNNING_LOW
= 10,
93 TRIM_MEMORY_UI_HIDDEN
= 20,
94 TRIM_MEMORY_BACKGROUND
= 40,
95 TRIM_MEMORY_MODERATE
= 60,
98 // Not urgent enough. TRIM_MEMORY_UI_HIDDEN is treated specially because
99 // it does not indicate memory pressure, but merely that the app is
101 if (level
< TRIM_MEMORY_RUNNING_LOW
|| level
== TRIM_MEMORY_UI_HIDDEN
)
104 // Do not release resources on view we expect to get DrawGL soon.
105 if (level
< TRIM_MEMORY_BACKGROUND
&& visible
)
109 if (!compositor_
|| !hardware_enabled_
)
112 TRACE_EVENT0("android_webview", "BrowserViewRenderer::TrimMemory");
114 // Drop everything in hardware.
115 if (level
>= TRIM_MEMORY_MODERATE
) {
116 shared_renderer_state_
.ReleaseHardwareDrawIfNeededOnUI();
120 // Just set the memory limit to 0 and drop all tiles. This will be reset to
121 // normal levels in the next DrawGL call.
122 compositor_
->SetMemoryPolicy(0u);
123 ForceFakeCompositeSW();
126 size_t BrowserViewRenderer::CalculateDesiredMemoryPolicy() {
127 if (g_memory_override_in_bytes
)
128 return static_cast<size_t>(g_memory_override_in_bytes
);
130 size_t width
= last_on_draw_global_visible_rect_
.width();
131 size_t height
= last_on_draw_global_visible_rect_
.height();
132 size_t bytes_limit
= kMemoryMultiplier
* kBytesPerPixel
* width
* height
;
133 // Round up to a multiple of kMemoryAllocationStep.
135 (bytes_limit
/ kMemoryAllocationStep
+ 1) * kMemoryAllocationStep
;
139 void BrowserViewRenderer::PrepareToDraw(const gfx::Vector2d
& scroll
,
140 const gfx::Rect
& global_visible_rect
) {
141 last_on_draw_scroll_offset_
= scroll
;
142 last_on_draw_global_visible_rect_
= global_visible_rect
;
145 bool BrowserViewRenderer::OnDrawHardware() {
146 TRACE_EVENT0("android_webview", "BrowserViewRenderer::OnDrawHardware");
147 shared_renderer_state_
.InitializeHardwareDrawIfNeededOnUI();
151 shared_renderer_state_
.SetScrollOffsetOnUI(last_on_draw_scroll_offset_
);
153 if (!hardware_enabled_
) {
154 hardware_enabled_
= compositor_
->InitializeHwDraw();
156 if (!hardware_enabled_
)
159 if (last_on_draw_global_visible_rect_
.IsEmpty() &&
160 parent_draw_constraints_
.surface_rect
.IsEmpty()) {
161 TRACE_EVENT_INSTANT0("android_webview",
162 "EarlyOut_EmptyVisibleRect",
163 TRACE_EVENT_SCOPE_THREAD
);
164 shared_renderer_state_
.SetForceInvalidateOnNextDrawGLOnUI(true);
168 ReturnResourceFromParent();
169 if (shared_renderer_state_
.HasCompositorFrameOnUI()) {
170 TRACE_EVENT_INSTANT0("android_webview",
171 "EarlyOut_PreviousFrameUnconsumed",
172 TRACE_EVENT_SCOPE_THREAD
);
173 DidSkipCompositeInDraw();
177 scoped_ptr
<cc::CompositorFrame
> frame
= CompositeHw();
181 shared_renderer_state_
.SetCompositorFrameOnUI(frame
.Pass(), false);
185 scoped_ptr
<cc::CompositorFrame
> BrowserViewRenderer::CompositeHw() {
186 compositor_
->SetMemoryPolicy(CalculateDesiredMemoryPolicy());
188 parent_draw_constraints_
=
189 shared_renderer_state_
.GetParentDrawConstraintsOnUI();
190 gfx::Size
surface_size(size_
);
191 gfx::Rect
viewport(surface_size
);
192 gfx::Rect clip
= viewport
;
193 gfx::Transform transform_for_tile_priority
=
194 parent_draw_constraints_
.transform
;
196 // If the WebView is on a layer, WebView does not know what transform is
197 // applied onto the layer so global visible rect does not make sense here.
198 // In this case, just use the surface rect for tiling.
199 gfx::Rect viewport_rect_for_tile_priority
;
200 if (parent_draw_constraints_
.is_layer
||
201 last_on_draw_global_visible_rect_
.IsEmpty()) {
202 viewport_rect_for_tile_priority
= parent_draw_constraints_
.surface_rect
;
204 viewport_rect_for_tile_priority
= last_on_draw_global_visible_rect_
;
207 scoped_ptr
<cc::CompositorFrame
> frame
=
208 compositor_
->DemandDrawHw(surface_size
,
212 viewport_rect_for_tile_priority
,
213 transform_for_tile_priority
);
219 void BrowserViewRenderer::UpdateParentDrawConstraints() {
220 // Post an invalidate if the parent draw constraints are stale and there is
221 // no pending invalidate.
222 bool needs_force_invalidate
=
223 shared_renderer_state_
.NeedsForceInvalidateOnNextDrawGLOnUI();
224 if (needs_force_invalidate
||
225 !parent_draw_constraints_
.Equals(
226 shared_renderer_state_
.GetParentDrawConstraintsOnUI())) {
227 shared_renderer_state_
.SetForceInvalidateOnNextDrawGLOnUI(false);
228 EnsureContinuousInvalidation(true, needs_force_invalidate
);
232 void BrowserViewRenderer::ReturnUnusedResource(
233 scoped_ptr
<cc::CompositorFrame
> frame
) {
237 cc::CompositorFrameAck frame_ack
;
238 cc::TransferableResource::ReturnResources(
239 frame
->delegated_frame_data
->resource_list
, &frame_ack
.resources
);
240 if (compositor_
&& !frame_ack
.resources
.empty())
241 compositor_
->ReturnResources(frame_ack
);
244 void BrowserViewRenderer::ReturnResourceFromParent() {
245 cc::CompositorFrameAck frame_ack
;
246 shared_renderer_state_
.SwapReturnedResourcesOnUI(&frame_ack
.resources
);
247 if (compositor_
&& !frame_ack
.resources
.empty()) {
248 compositor_
->ReturnResources(frame_ack
);
252 void BrowserViewRenderer::DidSkipCommitFrame() {
253 // Treat it the same way as skipping onDraw.
254 DidSkipCompositeInDraw();
257 void BrowserViewRenderer::InvalidateOnFunctorDestroy() {
258 client_
->InvalidateOnFunctorDestroy();
261 bool BrowserViewRenderer::OnDrawSoftware(SkCanvas
* canvas
) {
263 TRACE_EVENT_INSTANT0(
264 "android_webview", "EarlyOut_NoCompositor", TRACE_EVENT_SCOPE_THREAD
);
268 return CompositeSW(canvas
);
271 skia::RefPtr
<SkPicture
> BrowserViewRenderer::CapturePicture(int width
,
273 TRACE_EVENT0("android_webview", "BrowserViewRenderer::CapturePicture");
275 // Return empty Picture objects for empty SkPictures.
276 if (width
<= 0 || height
<= 0) {
277 SkPictureRecorder emptyRecorder
;
278 emptyRecorder
.beginRecording(0, 0);
279 return skia::AdoptRef(emptyRecorder
.endRecording());
282 // Reset scroll back to the origin, will go back to the old
283 // value when scroll_reset is out of scope.
284 base::AutoReset
<gfx::Vector2dF
> scroll_reset(&scroll_offset_dip_
,
287 SkPictureRecorder recorder
;
288 SkCanvas
* rec_canvas
= recorder
.beginRecording(width
, height
, NULL
, 0);
290 CompositeSW(rec_canvas
);
291 return skia::AdoptRef(recorder
.endRecording());
294 void BrowserViewRenderer::EnableOnNewPicture(bool enabled
) {
295 on_new_picture_enable_
= enabled
;
298 void BrowserViewRenderer::ClearView() {
299 TRACE_EVENT_INSTANT0("android_webview",
300 "BrowserViewRenderer::ClearView",
301 TRACE_EVENT_SCOPE_THREAD
);
306 // Always invalidate ignoring the compositor to actually clear the webview.
307 EnsureContinuousInvalidation(true, false);
310 void BrowserViewRenderer::SetIsPaused(bool paused
) {
311 TRACE_EVENT_INSTANT1("android_webview",
312 "BrowserViewRenderer::SetIsPaused",
313 TRACE_EVENT_SCOPE_THREAD
,
317 EnsureContinuousInvalidation(false, false);
320 void BrowserViewRenderer::SetViewVisibility(bool view_visible
) {
321 TRACE_EVENT_INSTANT1("android_webview",
322 "BrowserViewRenderer::SetViewVisibility",
323 TRACE_EVENT_SCOPE_THREAD
,
326 view_visible_
= view_visible
;
329 void BrowserViewRenderer::SetWindowVisibility(bool window_visible
) {
330 TRACE_EVENT_INSTANT1("android_webview",
331 "BrowserViewRenderer::SetWindowVisibility",
332 TRACE_EVENT_SCOPE_THREAD
,
335 window_visible_
= window_visible
;
336 EnsureContinuousInvalidation(false, false);
339 void BrowserViewRenderer::OnSizeChanged(int width
, int height
) {
340 TRACE_EVENT_INSTANT2("android_webview",
341 "BrowserViewRenderer::OnSizeChanged",
342 TRACE_EVENT_SCOPE_THREAD
,
347 size_
.SetSize(width
, height
);
350 void BrowserViewRenderer::OnAttachedToWindow(int width
, int height
) {
351 TRACE_EVENT2("android_webview",
352 "BrowserViewRenderer::OnAttachedToWindow",
357 attached_to_window_
= true;
358 size_
.SetSize(width
, height
);
361 void BrowserViewRenderer::OnDetachedFromWindow() {
362 TRACE_EVENT0("android_webview", "BrowserViewRenderer::OnDetachedFromWindow");
363 shared_renderer_state_
.ReleaseHardwareDrawIfNeededOnUI();
364 attached_to_window_
= false;
365 DCHECK(!hardware_enabled_
);
368 void BrowserViewRenderer::ReleaseHardware() {
369 DCHECK(hardware_enabled_
);
370 ReturnUnusedResource(shared_renderer_state_
.PassUncommittedFrameOnUI());
371 ReturnResourceFromParent();
372 DCHECK(shared_renderer_state_
.ReturnedResourcesEmptyOnUI());
375 compositor_
->ReleaseHwDraw();
378 hardware_enabled_
= false;
381 bool BrowserViewRenderer::IsVisible() const {
382 // Ignore |window_visible_| if |attached_to_window_| is false.
383 return view_visible_
&& (!attached_to_window_
|| window_visible_
);
386 gfx::Rect
BrowserViewRenderer::GetScreenRect() const {
387 return gfx::Rect(client_
->GetLocationOnScreen(), size_
);
390 void BrowserViewRenderer::DidInitializeCompositor(
391 content::SynchronousCompositor
* compositor
) {
392 TRACE_EVENT0("android_webview",
393 "BrowserViewRenderer::DidInitializeCompositor");
395 DCHECK(!compositor_
);
396 compositor_
= compositor
;
399 void BrowserViewRenderer::DidDestroyCompositor(
400 content::SynchronousCompositor
* compositor
) {
401 TRACE_EVENT0("android_webview", "BrowserViewRenderer::DidDestroyCompositor");
406 void BrowserViewRenderer::SetContinuousInvalidate(bool invalidate
) {
407 if (compositor_needs_continuous_invalidate_
== invalidate
)
410 TRACE_EVENT_INSTANT1("android_webview",
411 "BrowserViewRenderer::SetContinuousInvalidate",
412 TRACE_EVENT_SCOPE_THREAD
,
415 compositor_needs_continuous_invalidate_
= invalidate
;
417 EnsureContinuousInvalidation(false, false);
420 void BrowserViewRenderer::SetDipScale(float dip_scale
) {
421 dip_scale_
= dip_scale
;
422 CHECK_GT(dip_scale_
, 0);
425 gfx::Vector2d
BrowserViewRenderer::max_scroll_offset() const {
426 DCHECK_GT(dip_scale_
, 0);
427 return gfx::ToCeiledVector2d(gfx::ScaleVector2d(
428 max_scroll_offset_dip_
, dip_scale_
* page_scale_factor_
));
431 void BrowserViewRenderer::ScrollTo(gfx::Vector2d scroll_offset
) {
432 gfx::Vector2d max_offset
= max_scroll_offset();
433 gfx::Vector2dF scroll_offset_dip
;
434 // To preserve the invariant that scrolling to the maximum physical pixel
435 // value also scrolls to the maximum dip pixel value we transform the physical
436 // offset into the dip offset by using a proportion (instead of dividing by
437 // dip_scale * page_scale_factor).
438 if (max_offset
.x()) {
439 scroll_offset_dip
.set_x((scroll_offset
.x() * max_scroll_offset_dip_
.x()) /
442 if (max_offset
.y()) {
443 scroll_offset_dip
.set_y((scroll_offset
.y() * max_scroll_offset_dip_
.y()) /
447 DCHECK_LE(0, scroll_offset_dip
.x());
448 DCHECK_LE(0, scroll_offset_dip
.y());
449 DCHECK_LE(scroll_offset_dip
.x(), max_scroll_offset_dip_
.x());
450 DCHECK_LE(scroll_offset_dip
.y(), max_scroll_offset_dip_
.y());
452 if (scroll_offset_dip_
== scroll_offset_dip
)
455 scroll_offset_dip_
= scroll_offset_dip
;
457 TRACE_EVENT_INSTANT2("android_webview",
458 "BrowserViewRenderer::ScrollTo",
459 TRACE_EVENT_SCOPE_THREAD
,
461 scroll_offset_dip
.x(),
463 scroll_offset_dip
.y());
466 compositor_
->DidChangeRootLayerScrollOffset();
469 void BrowserViewRenderer::DidUpdateContent() {
470 TRACE_EVENT_INSTANT0("android_webview",
471 "BrowserViewRenderer::DidUpdateContent",
472 TRACE_EVENT_SCOPE_THREAD
);
474 if (on_new_picture_enable_
)
475 client_
->OnNewPicture();
478 void BrowserViewRenderer::SetTotalRootLayerScrollOffset(
479 gfx::Vector2dF scroll_offset_dip
) {
480 // TOOD(mkosiba): Add a DCHECK to say that this does _not_ get called during
481 // DrawGl when http://crbug.com/249972 is fixed.
482 if (scroll_offset_dip_
== scroll_offset_dip
)
485 scroll_offset_dip_
= scroll_offset_dip
;
487 gfx::Vector2d max_offset
= max_scroll_offset();
488 gfx::Vector2d scroll_offset
;
489 // For an explanation as to why this is done this way see the comment in
490 // BrowserViewRenderer::ScrollTo.
491 if (max_scroll_offset_dip_
.x()) {
492 scroll_offset
.set_x((scroll_offset_dip
.x() * max_offset
.x()) /
493 max_scroll_offset_dip_
.x());
496 if (max_scroll_offset_dip_
.y()) {
497 scroll_offset
.set_y((scroll_offset_dip
.y() * max_offset
.y()) /
498 max_scroll_offset_dip_
.y());
501 DCHECK_LE(0, scroll_offset
.x());
502 DCHECK_LE(0, scroll_offset
.y());
503 DCHECK_LE(scroll_offset
.x(), max_offset
.x());
504 DCHECK_LE(scroll_offset
.y(), max_offset
.y());
506 client_
->ScrollContainerViewTo(scroll_offset
);
509 gfx::Vector2dF
BrowserViewRenderer::GetTotalRootLayerScrollOffset() {
510 return scroll_offset_dip_
;
513 bool BrowserViewRenderer::IsExternalFlingActive() const {
514 return client_
->IsFlingActive();
517 void BrowserViewRenderer::UpdateRootLayerState(
518 const gfx::Vector2dF
& total_scroll_offset_dip
,
519 const gfx::Vector2dF
& max_scroll_offset_dip
,
520 const gfx::SizeF
& scrollable_size_dip
,
521 float page_scale_factor
,
522 float min_page_scale_factor
,
523 float max_page_scale_factor
) {
524 TRACE_EVENT_INSTANT1(
526 "BrowserViewRenderer::UpdateRootLayerState",
527 TRACE_EVENT_SCOPE_THREAD
,
529 RootLayerStateAsValue(total_scroll_offset_dip
, scrollable_size_dip
));
531 DCHECK_GT(dip_scale_
, 0);
533 max_scroll_offset_dip_
= max_scroll_offset_dip
;
534 DCHECK_LE(0, max_scroll_offset_dip_
.x());
535 DCHECK_LE(0, max_scroll_offset_dip_
.y());
537 page_scale_factor_
= page_scale_factor
;
538 DCHECK_GT(page_scale_factor_
, 0);
540 client_
->UpdateScrollState(max_scroll_offset(),
543 min_page_scale_factor
,
544 max_page_scale_factor
);
545 SetTotalRootLayerScrollOffset(total_scroll_offset_dip
);
548 scoped_refptr
<base::debug::ConvertableToTraceFormat
>
549 BrowserViewRenderer::RootLayerStateAsValue(
550 const gfx::Vector2dF
& total_scroll_offset_dip
,
551 const gfx::SizeF
& scrollable_size_dip
) {
552 scoped_refptr
<base::debug::TracedValue
> state
=
553 new base::debug::TracedValue();
555 state
->SetDouble("total_scroll_offset_dip.x", total_scroll_offset_dip
.x());
556 state
->SetDouble("total_scroll_offset_dip.y", total_scroll_offset_dip
.y());
558 state
->SetDouble("max_scroll_offset_dip.x", max_scroll_offset_dip_
.x());
559 state
->SetDouble("max_scroll_offset_dip.y", max_scroll_offset_dip_
.y());
561 state
->SetDouble("scrollable_size_dip.width", scrollable_size_dip
.width());
562 state
->SetDouble("scrollable_size_dip.height", scrollable_size_dip
.height());
564 state
->SetDouble("page_scale_factor", page_scale_factor_
);
568 void BrowserViewRenderer::DidOverscroll(gfx::Vector2dF accumulated_overscroll
,
569 gfx::Vector2dF latest_overscroll_delta
,
570 gfx::Vector2dF current_fling_velocity
) {
571 const float physical_pixel_scale
= dip_scale_
* page_scale_factor_
;
572 if (accumulated_overscroll
== latest_overscroll_delta
)
573 overscroll_rounding_error_
= gfx::Vector2dF();
574 gfx::Vector2dF scaled_overscroll_delta
=
575 gfx::ScaleVector2d(latest_overscroll_delta
, physical_pixel_scale
);
576 gfx::Vector2d rounded_overscroll_delta
= gfx::ToRoundedVector2d(
577 scaled_overscroll_delta
+ overscroll_rounding_error_
);
578 overscroll_rounding_error_
=
579 scaled_overscroll_delta
- rounded_overscroll_delta
;
580 client_
->DidOverscroll(rounded_overscroll_delta
);
583 void BrowserViewRenderer::EnsureContinuousInvalidation(
584 bool force_invalidate
,
585 bool skip_reschedule_tick
) {
586 if (force_invalidate
)
587 invalidate_after_composite_
= true;
589 // This method should be called again when any of these conditions change.
590 bool need_invalidate
=
591 compositor_needs_continuous_invalidate_
|| invalidate_after_composite_
;
592 if (!need_invalidate
|| block_invalidates_
)
595 if (!compositor_needs_continuous_invalidate_
&& invalidate_after_composite_
)
596 invalidate_after_composite_
= false;
598 // Always call view invalidate. We rely the Android framework to ignore the
599 // invalidate when it's not needed such as when view is not visible.
600 client_
->PostInvalidate();
602 // Stop fallback ticks when one of these is true.
603 // 1) Webview is paused. Also need to check we are not in clear view since
604 // paused, offscreen still expect clear view to recover.
605 // 2) If we are attached to window and the window is not visible (eg when
606 // app is in the background). We are sure in this case the webview is used
607 // "on-screen" but that updates are not needed when in the background.
608 bool throttle_fallback_tick
=
609 (is_paused_
&& !clear_view_
) || (attached_to_window_
&& !window_visible_
);
610 if (throttle_fallback_tick
)
613 block_invalidates_
= compositor_needs_continuous_invalidate_
;
614 if (skip_reschedule_tick
&& fallback_tick_pending_
)
617 // Unretained here is safe because the callbacks are cancelled when
618 // they are destroyed.
619 post_fallback_tick_
.Reset(base::Bind(&BrowserViewRenderer::PostFallbackTick
,
620 base::Unretained(this)));
621 fallback_tick_fired_
.Cancel();
622 fallback_tick_pending_
= false;
624 // No need to reschedule fallback tick if compositor does not need to be
625 // ticked. This can happen if this is reached because force_invalidate is
627 if (compositor_needs_continuous_invalidate_
) {
628 fallback_tick_pending_
= true;
629 ui_task_runner_
->PostTask(FROM_HERE
, post_fallback_tick_
.callback());
633 void BrowserViewRenderer::PostFallbackTick() {
634 DCHECK(fallback_tick_fired_
.IsCancelled());
635 fallback_tick_fired_
.Reset(base::Bind(&BrowserViewRenderer::FallbackTickFired
,
636 base::Unretained(this)));
637 if (compositor_needs_continuous_invalidate_
) {
638 ui_task_runner_
->PostDelayedTask(
640 fallback_tick_fired_
.callback(),
641 base::TimeDelta::FromMilliseconds(kFallbackTickTimeoutInMilliseconds
));
643 // Pretend we just composited to unblock further invalidates.
648 void BrowserViewRenderer::FallbackTickFired() {
649 TRACE_EVENT1("android_webview",
650 "BrowserViewRenderer::FallbackTickFired",
651 "compositor_needs_continuous_invalidate_",
652 compositor_needs_continuous_invalidate_
);
654 // This should only be called if OnDraw or DrawGL did not come in time, which
655 // means block_invalidates_ must still be true.
656 DCHECK(block_invalidates_
);
657 fallback_tick_pending_
= false;
658 if (compositor_needs_continuous_invalidate_
&& compositor_
) {
659 if (hardware_enabled_
) {
660 ReturnResourceFromParent();
661 ReturnUnusedResource(shared_renderer_state_
.PassUncommittedFrameOnUI());
662 scoped_ptr
<cc::CompositorFrame
> frame
= CompositeHw();
664 shared_renderer_state_
.SetCompositorFrameOnUI(frame
.Pass(), true);
667 ForceFakeCompositeSW();
670 // Pretend we just composited to unblock further invalidates.
675 void BrowserViewRenderer::ForceFakeCompositeSW() {
678 bitmap
.allocN32Pixels(1, 1);
679 bitmap
.eraseColor(0);
680 SkCanvas
canvas(bitmap
);
681 CompositeSW(&canvas
);
684 bool BrowserViewRenderer::CompositeSW(SkCanvas
* canvas
) {
686 ReturnResourceFromParent();
687 bool result
= compositor_
->DemandDrawSw(canvas
);
692 void BrowserViewRenderer::DidComposite() {
693 block_invalidates_
= false;
694 post_fallback_tick_
.Cancel();
695 fallback_tick_fired_
.Cancel();
696 fallback_tick_pending_
= false;
697 EnsureContinuousInvalidation(false, false);
700 void BrowserViewRenderer::DidSkipCompositeInDraw() {
701 block_invalidates_
= false;
702 EnsureContinuousInvalidation(true, true);
705 std::string
BrowserViewRenderer::ToString() const {
707 base::StringAppendF(&str
, "is_paused: %d ", is_paused_
);
708 base::StringAppendF(&str
, "view_visible: %d ", view_visible_
);
709 base::StringAppendF(&str
, "window_visible: %d ", window_visible_
);
710 base::StringAppendF(&str
, "dip_scale: %f ", dip_scale_
);
711 base::StringAppendF(&str
, "page_scale_factor: %f ", page_scale_factor_
);
712 base::StringAppendF(&str
,
713 "compositor_needs_continuous_invalidate: %d ",
714 compositor_needs_continuous_invalidate_
);
715 base::StringAppendF(&str
, "block_invalidates: %d ", block_invalidates_
);
716 base::StringAppendF(&str
, "view size: %s ", size_
.ToString().c_str());
717 base::StringAppendF(&str
, "attached_to_window: %d ", attached_to_window_
);
718 base::StringAppendF(&str
,
719 "global visible rect: %s ",
720 last_on_draw_global_visible_rect_
.ToString().c_str());
722 &str
, "scroll_offset_dip: %s ", scroll_offset_dip_
.ToString().c_str());
723 base::StringAppendF(&str
,
724 "overscroll_rounding_error_: %s ",
725 overscroll_rounding_error_
.ToString().c_str());
727 &str
, "on_new_picture_enable: %d ", on_new_picture_enable_
);
728 base::StringAppendF(&str
, "clear_view: %d ", clear_view_
);
732 } // namespace android_webview