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
{
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
{
44 BrowserViewRendererUserData(BrowserViewRenderer
* ptr
) : bvr_(ptr
) {}
46 static BrowserViewRenderer
* GetBrowserViewRenderer(
47 content::WebContents
* web_contents
) {
50 BrowserViewRendererUserData
* data
=
51 static_cast<BrowserViewRendererUserData
*>(
52 web_contents
->GetUserData(kBrowserViewRendererUserDataKey
));
53 return data
? data
->bvr_
: NULL
;
57 BrowserViewRenderer
* bvr_
;
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
) {
71 base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
72 switches::kForceGpuMemAvailableMb
),
73 &g_memory_override_in_bytes
);
74 g_memory_override_in_bytes
*= 1024 * 1024;
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
)
88 shared_renderer_state_(ui_task_runner
, this),
89 ui_task_runner_(ui_task_runner
),
93 window_visible_(false),
94 attached_to_window_(false),
95 hardware_enabled_(false),
97 page_scale_factor_(1.0),
98 on_new_picture_enable_(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 // This function updates the resource allocation in GlobalTileManager.
122 void BrowserViewRenderer::TrimMemory(const int level
, const bool visible
) {
123 DCHECK(ui_task_runner_
->BelongsToCurrentThread());
124 // Constants from Android ComponentCallbacks2.
126 TRIM_MEMORY_RUNNING_LOW
= 10,
127 TRIM_MEMORY_UI_HIDDEN
= 20,
128 TRIM_MEMORY_BACKGROUND
= 40,
129 TRIM_MEMORY_MODERATE
= 60,
132 // Not urgent enough. TRIM_MEMORY_UI_HIDDEN is treated specially because
133 // it does not indicate memory pressure, but merely that the app is
135 if (level
< TRIM_MEMORY_RUNNING_LOW
|| level
== TRIM_MEMORY_UI_HIDDEN
)
138 // Do not release resources on view we expect to get DrawGL soon.
139 if (level
< TRIM_MEMORY_BACKGROUND
&& visible
)
143 if (!compositor_
|| !hardware_enabled_
)
146 TRACE_EVENT0("android_webview", "BrowserViewRenderer::TrimMemory");
148 // Drop everything in hardware.
149 if (level
>= TRIM_MEMORY_MODERATE
) {
150 shared_renderer_state_
.ReleaseHardwareDrawIfNeededOnUI();
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 compositor_
->SetMemoryPolicy(0u);
157 ForceFakeCompositeSW();
160 size_t BrowserViewRenderer::CalculateDesiredMemoryPolicy() {
161 if (g_memory_override_in_bytes
)
162 return static_cast<size_t>(g_memory_override_in_bytes
);
164 gfx::Rect interest_rect
= offscreen_pre_raster_
166 : last_on_draw_global_visible_rect_
;
167 size_t width
= interest_rect
.width();
168 size_t height
= interest_rect
.height();
169 size_t bytes_limit
= kMemoryMultiplier
* kBytesPerPixel
* width
* height
;
170 // Round up to a multiple of kMemoryAllocationStep.
172 (bytes_limit
/ kMemoryAllocationStep
+ 1) * kMemoryAllocationStep
;
176 void BrowserViewRenderer::PrepareToDraw(const gfx::Vector2d
& scroll
,
177 const gfx::Rect
& global_visible_rect
) {
178 last_on_draw_scroll_offset_
= scroll
;
179 last_on_draw_global_visible_rect_
= global_visible_rect
;
182 bool BrowserViewRenderer::CanOnDraw() {
184 TRACE_EVENT_INSTANT0("android_webview", "EarlyOut_NoCompositor",
185 TRACE_EVENT_SCOPE_THREAD
);
189 TRACE_EVENT_INSTANT0("android_webview", "EarlyOut_ClearView",
190 TRACE_EVENT_SCOPE_THREAD
);
197 bool BrowserViewRenderer::OnDrawHardware() {
198 TRACE_EVENT0("android_webview", "BrowserViewRenderer::OnDrawHardware");
200 shared_renderer_state_
.InitializeHardwareDrawIfNeededOnUI();
206 shared_renderer_state_
.SetScrollOffsetOnUI(last_on_draw_scroll_offset_
);
208 if (!hardware_enabled_
) {
209 TRACE_EVENT0("android_webview", "InitializeHwDraw");
210 hardware_enabled_
= compositor_
->InitializeHwDraw();
212 if (!hardware_enabled_
) {
213 TRACE_EVENT_INSTANT0("android_webview", "EarlyOut_HardwareNotEnabled",
214 TRACE_EVENT_SCOPE_THREAD
);
218 return CompositeHw();
221 bool BrowserViewRenderer::CompositeHw() {
222 CancelFallbackTick();
224 ReturnResourceFromParent();
225 compositor_
->SetMemoryPolicy(CalculateDesiredMemoryPolicy());
227 ParentCompositorDrawConstraints parent_draw_constraints
=
228 shared_renderer_state_
.GetParentDrawConstraintsOnUI();
229 gfx::Size
surface_size(size_
);
230 gfx::Rect
viewport(surface_size
);
231 gfx::Rect clip
= viewport
;
232 gfx::Transform transform_for_tile_priority
=
233 parent_draw_constraints
.transform
;
235 // If the WebView is on a layer, WebView does not know what transform is
236 // applied onto the layer so global visible rect does not make sense here.
237 // In this case, just use the surface rect for tiling.
238 gfx::Rect viewport_rect_for_tile_priority
;
240 // Leave viewport_rect_for_tile_priority empty if offscreen_pre_raster_ is on.
241 if (!offscreen_pre_raster_
) {
242 if (parent_draw_constraints
.is_layer
) {
243 viewport_rect_for_tile_priority
= parent_draw_constraints
.surface_rect
;
245 viewport_rect_for_tile_priority
= last_on_draw_global_visible_rect_
;
249 scoped_ptr
<cc::CompositorFrame
> frame
=
250 compositor_
->DemandDrawHw(surface_size
,
254 viewport_rect_for_tile_priority
,
255 transform_for_tile_priority
);
257 TRACE_EVENT_INSTANT0("android_webview", "NoNewFrame",
258 TRACE_EVENT_SCOPE_THREAD
);
262 scoped_ptr
<ChildFrame
> child_frame
= make_scoped_ptr(
263 new ChildFrame(frame
.Pass(), viewport_rect_for_tile_priority
,
264 transform_for_tile_priority
, offscreen_pre_raster_
,
265 parent_draw_constraints
.is_layer
));
267 // Uncommitted frame can happen with consecutive fallback ticks.
268 ReturnUnusedResource(shared_renderer_state_
.PassUncommittedFrameOnUI());
269 shared_renderer_state_
.SetCompositorFrameOnUI(child_frame
.Pass());
273 void BrowserViewRenderer::UpdateParentDrawConstraints() {
274 PostInvalidateWithFallback();
275 ParentCompositorDrawConstraints parent_draw_constraints
=
276 shared_renderer_state_
.GetParentDrawConstraintsOnUI();
277 client_
->ParentDrawConstraintsUpdated(parent_draw_constraints
);
280 void BrowserViewRenderer::ReturnUnusedResource(
281 scoped_ptr
<ChildFrame
> child_frame
) {
282 if (!child_frame
.get() || !child_frame
->frame
.get())
285 cc::CompositorFrameAck frame_ack
;
286 cc::TransferableResource::ReturnResources(
287 child_frame
->frame
->delegated_frame_data
->resource_list
,
288 &frame_ack
.resources
);
289 if (compositor_
&& !frame_ack
.resources
.empty())
290 compositor_
->ReturnResources(frame_ack
);
293 void BrowserViewRenderer::ReturnResourceFromParent() {
294 cc::CompositorFrameAck frame_ack
;
295 shared_renderer_state_
.SwapReturnedResourcesOnUI(&frame_ack
.resources
);
296 if (compositor_
&& !frame_ack
.resources
.empty()) {
297 compositor_
->ReturnResources(frame_ack
);
301 void BrowserViewRenderer::DetachFunctorFromView() {
302 client_
->DetachFunctorFromView();
305 bool BrowserViewRenderer::OnDrawSoftware(SkCanvas
* canvas
) {
306 return CanOnDraw() && CompositeSW(canvas
);
309 skia::RefPtr
<SkPicture
> BrowserViewRenderer::CapturePicture(int width
,
311 TRACE_EVENT0("android_webview", "BrowserViewRenderer::CapturePicture");
313 // Return empty Picture objects for empty SkPictures.
314 if (width
<= 0 || height
<= 0) {
315 SkPictureRecorder emptyRecorder
;
316 emptyRecorder
.beginRecording(0, 0);
317 return skia::AdoptRef(emptyRecorder
.endRecording());
320 // Reset scroll back to the origin, will go back to the old
321 // value when scroll_reset is out of scope.
322 base::AutoReset
<gfx::Vector2dF
> scroll_reset(&scroll_offset_dip_
,
325 SkPictureRecorder recorder
;
326 SkCanvas
* rec_canvas
= recorder
.beginRecording(width
, height
, NULL
, 0);
328 CompositeSW(rec_canvas
);
329 return skia::AdoptRef(recorder
.endRecording());
332 void BrowserViewRenderer::EnableOnNewPicture(bool enabled
) {
333 on_new_picture_enable_
= enabled
;
336 void BrowserViewRenderer::ClearView() {
337 TRACE_EVENT_INSTANT0("android_webview",
338 "BrowserViewRenderer::ClearView",
339 TRACE_EVENT_SCOPE_THREAD
);
344 // Always invalidate ignoring the compositor to actually clear the webview.
345 PostInvalidateWithFallback();
348 void BrowserViewRenderer::SetOffscreenPreRaster(bool enable
) {
349 // TODO(hush): anything to do when the setting is toggled?
350 offscreen_pre_raster_
= enable
;
353 void BrowserViewRenderer::SetIsPaused(bool paused
) {
354 TRACE_EVENT_INSTANT1("android_webview",
355 "BrowserViewRenderer::SetIsPaused",
356 TRACE_EVENT_SCOPE_THREAD
,
360 UpdateCompositorIsActive();
363 void BrowserViewRenderer::SetViewVisibility(bool view_visible
) {
364 TRACE_EVENT_INSTANT1("android_webview",
365 "BrowserViewRenderer::SetViewVisibility",
366 TRACE_EVENT_SCOPE_THREAD
,
369 view_visible_
= view_visible
;
372 void BrowserViewRenderer::SetWindowVisibility(bool window_visible
) {
373 TRACE_EVENT_INSTANT1("android_webview",
374 "BrowserViewRenderer::SetWindowVisibility",
375 TRACE_EVENT_SCOPE_THREAD
,
378 window_visible_
= window_visible
;
379 UpdateCompositorIsActive();
382 void BrowserViewRenderer::OnSizeChanged(int width
, int height
) {
383 TRACE_EVENT_INSTANT2("android_webview",
384 "BrowserViewRenderer::OnSizeChanged",
385 TRACE_EVENT_SCOPE_THREAD
,
390 size_
.SetSize(width
, height
);
393 void BrowserViewRenderer::OnAttachedToWindow(int width
, int height
) {
394 TRACE_EVENT2("android_webview",
395 "BrowserViewRenderer::OnAttachedToWindow",
400 attached_to_window_
= true;
401 size_
.SetSize(width
, height
);
402 UpdateCompositorIsActive();
405 void BrowserViewRenderer::OnDetachedFromWindow() {
406 TRACE_EVENT0("android_webview", "BrowserViewRenderer::OnDetachedFromWindow");
407 shared_renderer_state_
.ReleaseHardwareDrawIfNeededOnUI();
408 attached_to_window_
= false;
409 DCHECK(!hardware_enabled_
);
410 UpdateCompositorIsActive();
413 void BrowserViewRenderer::ReleaseHardware() {
414 DCHECK(hardware_enabled_
);
415 ReturnUnusedResource(shared_renderer_state_
.PassUncommittedFrameOnUI());
416 ReturnResourceFromParent();
417 DCHECK(shared_renderer_state_
.ReturnedResourcesEmptyOnUI());
420 compositor_
->ReleaseHwDraw();
423 hardware_enabled_
= false;
426 bool BrowserViewRenderer::IsVisible() const {
427 // Ignore |window_visible_| if |attached_to_window_| is false.
428 return view_visible_
&& (!attached_to_window_
|| window_visible_
);
431 gfx::Rect
BrowserViewRenderer::GetScreenRect() const {
432 return gfx::Rect(client_
->GetLocationOnScreen(), size_
);
435 void BrowserViewRenderer::DidInitializeCompositor(
436 content::SynchronousCompositor
* compositor
) {
437 TRACE_EVENT0("android_webview",
438 "BrowserViewRenderer::DidInitializeCompositor");
440 DCHECK(!compositor_
);
441 compositor_
= compositor
;
442 UpdateCompositorIsActive();
445 void BrowserViewRenderer::DidDestroyCompositor(
446 content::SynchronousCompositor
* compositor
) {
447 TRACE_EVENT0("android_webview", "BrowserViewRenderer::DidDestroyCompositor");
452 void BrowserViewRenderer::SetDipScale(float dip_scale
) {
453 dip_scale_
= dip_scale
;
454 CHECK_GT(dip_scale_
, 0.f
);
457 gfx::Vector2d
BrowserViewRenderer::max_scroll_offset() const {
458 DCHECK_GT(dip_scale_
, 0.f
);
459 return gfx::ToCeiledVector2d(gfx::ScaleVector2d(
460 max_scroll_offset_dip_
, dip_scale_
* page_scale_factor_
));
463 void BrowserViewRenderer::ScrollTo(gfx::Vector2d scroll_offset
) {
464 gfx::Vector2d max_offset
= max_scroll_offset();
465 gfx::Vector2dF scroll_offset_dip
;
466 // To preserve the invariant that scrolling to the maximum physical pixel
467 // value also scrolls to the maximum dip pixel value we transform the physical
468 // offset into the dip offset by using a proportion (instead of dividing by
469 // dip_scale * page_scale_factor).
470 if (max_offset
.x()) {
471 scroll_offset_dip
.set_x((scroll_offset
.x() * max_scroll_offset_dip_
.x()) /
474 if (max_offset
.y()) {
475 scroll_offset_dip
.set_y((scroll_offset
.y() * max_scroll_offset_dip_
.y()) /
479 DCHECK_LE(0.f
, scroll_offset_dip
.x());
480 DCHECK_LE(0.f
, scroll_offset_dip
.y());
481 DCHECK(scroll_offset_dip
.x() < max_scroll_offset_dip_
.x() ||
482 scroll_offset_dip
.x() - max_scroll_offset_dip_
.x() < kEpsilon
)
483 << scroll_offset_dip
.x() << " " << max_scroll_offset_dip_
.x();
484 DCHECK(scroll_offset_dip
.y() < max_scroll_offset_dip_
.y() ||
485 scroll_offset_dip
.y() - max_scroll_offset_dip_
.y() < kEpsilon
)
486 << scroll_offset_dip
.y() << " " << max_scroll_offset_dip_
.y();
488 if (scroll_offset_dip_
== scroll_offset_dip
)
491 scroll_offset_dip_
= scroll_offset_dip
;
493 TRACE_EVENT_INSTANT2("android_webview",
494 "BrowserViewRenderer::ScrollTo",
495 TRACE_EVENT_SCOPE_THREAD
,
497 scroll_offset_dip
.x(),
499 scroll_offset_dip
.y());
502 compositor_
->DidChangeRootLayerScrollOffset();
505 void BrowserViewRenderer::DidUpdateContent() {
506 TRACE_EVENT_INSTANT0("android_webview",
507 "BrowserViewRenderer::DidUpdateContent",
508 TRACE_EVENT_SCOPE_THREAD
);
510 if (on_new_picture_enable_
)
511 client_
->OnNewPicture();
514 void BrowserViewRenderer::SetTotalRootLayerScrollOffset(
515 gfx::Vector2dF scroll_offset_dip
) {
516 // TOOD(mkosiba): Add a DCHECK to say that this does _not_ get called during
517 // DrawGl when http://crbug.com/249972 is fixed.
518 if (scroll_offset_dip_
== scroll_offset_dip
)
521 scroll_offset_dip_
= scroll_offset_dip
;
523 gfx::Vector2d max_offset
= max_scroll_offset();
524 gfx::Vector2d scroll_offset
;
525 // For an explanation as to why this is done this way see the comment in
526 // BrowserViewRenderer::ScrollTo.
527 if (max_scroll_offset_dip_
.x()) {
528 scroll_offset
.set_x((scroll_offset_dip
.x() * max_offset
.x()) /
529 max_scroll_offset_dip_
.x());
532 if (max_scroll_offset_dip_
.y()) {
533 scroll_offset
.set_y((scroll_offset_dip
.y() * max_offset
.y()) /
534 max_scroll_offset_dip_
.y());
537 DCHECK_LE(0, scroll_offset
.x());
538 DCHECK_LE(0, scroll_offset
.y());
539 DCHECK_LE(scroll_offset
.x(), max_offset
.x());
540 DCHECK_LE(scroll_offset
.y(), max_offset
.y());
542 client_
->ScrollContainerViewTo(scroll_offset
);
545 gfx::Vector2dF
BrowserViewRenderer::GetTotalRootLayerScrollOffset() {
546 return scroll_offset_dip_
;
549 bool BrowserViewRenderer::IsExternalFlingActive() const {
550 return client_
->IsFlingActive();
553 void BrowserViewRenderer::UpdateRootLayerState(
554 const gfx::Vector2dF
& total_scroll_offset_dip
,
555 const gfx::Vector2dF
& max_scroll_offset_dip
,
556 const gfx::SizeF
& scrollable_size_dip
,
557 float page_scale_factor
,
558 float min_page_scale_factor
,
559 float max_page_scale_factor
) {
560 TRACE_EVENT_INSTANT1(
562 "BrowserViewRenderer::UpdateRootLayerState",
563 TRACE_EVENT_SCOPE_THREAD
,
565 RootLayerStateAsValue(total_scroll_offset_dip
, scrollable_size_dip
));
567 DCHECK_GT(dip_scale_
, 0.f
);
569 max_scroll_offset_dip_
= max_scroll_offset_dip
;
570 DCHECK_LE(0.f
, max_scroll_offset_dip_
.x());
571 DCHECK_LE(0.f
, max_scroll_offset_dip_
.y());
573 page_scale_factor_
= page_scale_factor
;
574 DCHECK_GT(page_scale_factor_
, 0.f
);
576 client_
->UpdateScrollState(max_scroll_offset(),
579 min_page_scale_factor
,
580 max_page_scale_factor
);
581 SetTotalRootLayerScrollOffset(total_scroll_offset_dip
);
584 scoped_refptr
<base::trace_event::ConvertableToTraceFormat
>
585 BrowserViewRenderer::RootLayerStateAsValue(
586 const gfx::Vector2dF
& total_scroll_offset_dip
,
587 const gfx::SizeF
& scrollable_size_dip
) {
588 scoped_refptr
<base::trace_event::TracedValue
> state
=
589 new base::trace_event::TracedValue();
591 state
->SetDouble("total_scroll_offset_dip.x", total_scroll_offset_dip
.x());
592 state
->SetDouble("total_scroll_offset_dip.y", total_scroll_offset_dip
.y());
594 state
->SetDouble("max_scroll_offset_dip.x", max_scroll_offset_dip_
.x());
595 state
->SetDouble("max_scroll_offset_dip.y", max_scroll_offset_dip_
.y());
597 state
->SetDouble("scrollable_size_dip.width", scrollable_size_dip
.width());
598 state
->SetDouble("scrollable_size_dip.height", scrollable_size_dip
.height());
600 state
->SetDouble("page_scale_factor", page_scale_factor_
);
604 void BrowserViewRenderer::DidOverscroll(gfx::Vector2dF accumulated_overscroll
,
605 gfx::Vector2dF latest_overscroll_delta
,
606 gfx::Vector2dF current_fling_velocity
) {
607 const float physical_pixel_scale
= dip_scale_
* page_scale_factor_
;
608 if (accumulated_overscroll
== latest_overscroll_delta
)
609 overscroll_rounding_error_
= gfx::Vector2dF();
610 gfx::Vector2dF scaled_overscroll_delta
=
611 gfx::ScaleVector2d(latest_overscroll_delta
, physical_pixel_scale
);
612 gfx::Vector2d rounded_overscroll_delta
= gfx::ToRoundedVector2d(
613 scaled_overscroll_delta
+ overscroll_rounding_error_
);
614 overscroll_rounding_error_
=
615 scaled_overscroll_delta
- rounded_overscroll_delta
;
616 client_
->DidOverscroll(rounded_overscroll_delta
);
619 void BrowserViewRenderer::PostInvalidate() {
620 TRACE_EVENT_INSTANT0("android_webview", "BrowserViewRenderer::PostInvalidate",
621 TRACE_EVENT_SCOPE_THREAD
);
622 PostInvalidateWithFallback();
625 void BrowserViewRenderer::PostInvalidateWithFallback() {
626 // Always call view invalidate. We rely the Android framework to ignore the
627 // invalidate when it's not needed such as when view is not visible.
628 client_
->PostInvalidate();
630 // Stop fallback ticks when one of these is true.
631 // 1) Webview is paused. Also need to check we are not in clear view since
632 // paused, offscreen still expect clear view to recover.
633 // 2) If we are attached to window and the window is not visible (eg when
634 // app is in the background). We are sure in this case the webview is used
635 // "on-screen" but that updates are not needed when in the background.
636 bool throttle_fallback_tick
=
637 (is_paused_
&& !clear_view_
) || (attached_to_window_
&& !window_visible_
);
639 if (throttle_fallback_tick
|| fallback_tick_pending_
)
642 DCHECK(post_fallback_tick_
.IsCancelled());
643 DCHECK(fallback_tick_fired_
.IsCancelled());
645 post_fallback_tick_
.Reset(base::Bind(&BrowserViewRenderer::PostFallbackTick
,
646 base::Unretained(this)));
647 ui_task_runner_
->PostTask(FROM_HERE
, post_fallback_tick_
.callback());
648 fallback_tick_pending_
= true;
651 void BrowserViewRenderer::CancelFallbackTick() {
652 post_fallback_tick_
.Cancel();
653 fallback_tick_fired_
.Cancel();
654 fallback_tick_pending_
= false;
657 void BrowserViewRenderer::PostFallbackTick() {
658 DCHECK(fallback_tick_fired_
.IsCancelled());
659 TRACE_EVENT0("android_webview", "BrowserViewRenderer::PostFallbackTick");
660 post_fallback_tick_
.Cancel();
661 fallback_tick_fired_
.Reset(base::Bind(&BrowserViewRenderer::FallbackTickFired
,
662 base::Unretained(this)));
663 ui_task_runner_
->PostDelayedTask(
664 FROM_HERE
, fallback_tick_fired_
.callback(),
665 base::TimeDelta::FromMilliseconds(kFallbackTickTimeoutInMilliseconds
));
668 void BrowserViewRenderer::FallbackTickFired() {
669 TRACE_EVENT0("android_webview", "BrowserViewRenderer::FallbackTickFired");
670 // This should only be called if OnDraw or DrawGL did not come in time, which
671 // means fallback_tick_pending_ must still be true.
672 DCHECK(fallback_tick_pending_
);
673 fallback_tick_fired_
.Cancel();
674 fallback_tick_pending_
= false;
676 if (hardware_enabled_
) {
679 ForceFakeCompositeSW();
684 void BrowserViewRenderer::ForceFakeCompositeSW() {
687 bitmap
.allocN32Pixels(1, 1);
688 bitmap
.eraseColor(0);
689 SkCanvas
canvas(bitmap
);
690 CompositeSW(&canvas
);
693 bool BrowserViewRenderer::CompositeSW(SkCanvas
* canvas
) {
695 CancelFallbackTick();
696 ReturnResourceFromParent();
697 return compositor_
->DemandDrawSw(canvas
);
700 void BrowserViewRenderer::UpdateCompositorIsActive() {
702 compositor_
->SetIsActive(!is_paused_
&&
703 (!attached_to_window_
|| window_visible_
));
706 std::string
BrowserViewRenderer::ToString() const {
708 base::StringAppendF(&str
, "is_paused: %d ", is_paused_
);
709 base::StringAppendF(&str
, "view_visible: %d ", view_visible_
);
710 base::StringAppendF(&str
, "window_visible: %d ", window_visible_
);
711 base::StringAppendF(&str
, "dip_scale: %f ", dip_scale_
);
712 base::StringAppendF(&str
, "page_scale_factor: %f ", page_scale_factor_
);
713 base::StringAppendF(&str
, "fallback_tick_pending: %d ",
714 fallback_tick_pending_
);
715 base::StringAppendF(&str
, "view size: %s ", size_
.ToString().c_str());
716 base::StringAppendF(&str
, "attached_to_window: %d ", attached_to_window_
);
717 base::StringAppendF(&str
,
718 "global visible rect: %s ",
719 last_on_draw_global_visible_rect_
.ToString().c_str());
721 &str
, "scroll_offset_dip: %s ", scroll_offset_dip_
.ToString().c_str());
722 base::StringAppendF(&str
,
723 "overscroll_rounding_error_: %s ",
724 overscroll_rounding_error_
.ToString().c_str());
726 &str
, "on_new_picture_enable: %d ", on_new_picture_enable_
);
727 base::StringAppendF(&str
, "clear_view: %d ", clear_view_
);
731 } // namespace android_webview