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