diff options
author | boliu@chromium.org <boliu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-07-31 14:21:43 +0000 |
---|---|---|
committer | boliu@chromium.org <boliu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-07-31 14:21:43 +0000 |
commit | c06a8c075aea4f1c1e9140e507d3bb64b10986e2 (patch) | |
tree | bfb90a7dfdcecd807fe2157875602169318f9d26 /android_webview | |
parent | e359c40debd0d430a54d6dce6d703b217306bb15 (diff) | |
download | chromium_src-c06a8c075aea4f1c1e9140e507d3bb64b10986e2.zip chromium_src-c06a8c075aea4f1c1e9140e507d3bb64b10986e2.tar.gz chromium_src-c06a8c075aea4f1c1e9140e507d3bb64b10986e2.tar.bz2 |
[Android WebView] Handle clip size smaller than visible rect
The issue here is that compositor assumes every draw to match the
viewport exactly, and thus the whole viewport is updated each
draw. But we could be asked to draw a subset of the visible
rect, so there is a mismatch between what is really drawn and
what compositor assume is drawn.
Simple damage tracking inside compositor will not work for
webview because of all the other ways the view could be drawn.
Here is a simple fix. Whenever webview is asked to draw a subset
of the visible rect, invalidate the whole visible rect, regardless
of whether the compositor needs draws.
The assumption here is that the problem only manifests if we draw
a subset of the visible rect, so simply ensure the whole visible
rect drawn is immediately after. Ideally it should only be done if
we can detect the case of mismatch between compositor and what is
drawn, but this requires damage tracking and work through all the
different ways we can draw.
BUG=264275
NOTRY=true
Review URL: https://chromiumcodereview.appspot.com/21191002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@214727 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'android_webview')
-rw-r--r-- | android_webview/browser/in_process_view_renderer.cc | 67 | ||||
-rw-r--r-- | android_webview/browser/in_process_view_renderer.h | 15 |
2 files changed, 52 insertions, 30 deletions
diff --git a/android_webview/browser/in_process_view_renderer.cc b/android_webview/browser/in_process_view_renderer.cc index f5e1762..8bc7447 100644 --- a/android_webview/browser/in_process_view_renderer.cc +++ b/android_webview/browser/in_process_view_renderer.cc @@ -160,7 +160,7 @@ InProcessViewRenderer::InProcessViewRenderer( dip_scale_(0.0), page_scale_factor_(1.0), on_new_picture_enable_(false), - continuous_invalidate_(false), + compositor_needs_continuous_invalidate_(false), block_invalidates_(false), width_(0), height_(0), @@ -211,7 +211,7 @@ bool InProcessViewRenderer::OnDraw(jobject java_canvas, block_invalidates_ = true; bool result = DrawSWInternal(java_canvas, clip); block_invalidates_ = false; - EnsureContinuousInvalidation(NULL); + EnsureContinuousInvalidation(NULL, false); return result; } @@ -266,17 +266,19 @@ void InProcessViewRenderer::DrawGL(AwDrawGLInfo* draw_info) { scroll_at_start_of_frame_.y()); // TODO(joth): Check return value. block_invalidates_ = true; - compositor_->DemandDrawHw( - gfx::Size(draw_info->width, draw_info->height), - transform, - gfx::Rect(draw_info->clip_left, - draw_info->clip_top, - draw_info->clip_right - draw_info->clip_left, - draw_info->clip_bottom - draw_info->clip_top), - state_restore.stencil_enabled()); + gfx::Rect clip_rect(draw_info->clip_left, + draw_info->clip_top, + draw_info->clip_right - draw_info->clip_left, + draw_info->clip_bottom - draw_info->clip_top); + compositor_->DemandDrawHw(gfx::Size(draw_info->width, draw_info->height), + transform, + clip_rect, + state_restore.stencil_enabled()); block_invalidates_ = false; - EnsureContinuousInvalidation(draw_info); + bool drew_full_visible_rect = + clip_rect.Contains(global_visible_rect_at_start_of_frame_); + EnsureContinuousInvalidation(draw_info, !drew_full_visible_rect); } bool InProcessViewRenderer::DrawSWInternal(jobject java_canvas, @@ -506,7 +508,7 @@ void InProcessViewRenderer::DidDestroyCompositor( } void InProcessViewRenderer::SetContinuousInvalidate(bool invalidate) { - if (continuous_invalidate_ == invalidate) + if (compositor_needs_continuous_invalidate_ == invalidate) return; TRACE_EVENT_INSTANT1("android_webview", @@ -514,8 +516,8 @@ void InProcessViewRenderer::SetContinuousInvalidate(bool invalidate) { TRACE_EVENT_SCOPE_THREAD, "invalidate", invalidate); - continuous_invalidate_ = invalidate; - EnsureContinuousInvalidation(NULL); + compositor_needs_continuous_invalidate_ = invalidate; + EnsureContinuousInvalidation(NULL, false); } void InProcessViewRenderer::SetDipScale(float dip_scale) { @@ -591,8 +593,11 @@ void InProcessViewRenderer::DidOverscroll( } void InProcessViewRenderer::EnsureContinuousInvalidation( - AwDrawGLInfo* draw_info) { - if (continuous_invalidate_ && !block_invalidates_) { + AwDrawGLInfo* draw_info, + bool invalidate_ignore_compositor) { + if ((compositor_needs_continuous_invalidate_ || + invalidate_ignore_compositor) && + !block_invalidates_) { if (draw_info) { draw_info->dirty_left = global_visible_rect_at_start_of_frame_.x(); draw_info->dirty_top = global_visible_rect_at_start_of_frame_.y(); @@ -603,36 +608,43 @@ void InProcessViewRenderer::EnsureContinuousInvalidation( client_->PostInvalidate(); } + block_invalidates_ = true; + // Unretained here is safe because the callback is cancelled when // |fallback_tick_| is destroyed. fallback_tick_.Reset(base::Bind(&InProcessViewRenderer::FallbackTickFired, base::Unretained(this))); - base::MessageLoop::current()->PostDelayedTask( - FROM_HERE, - fallback_tick_.callback(), - base::TimeDelta::FromMilliseconds(kFallbackTickTimeoutInMilliseconds)); - block_invalidates_ = true; + // No need to reschedule fallback tick if compositor does not need to be + // ticked. This can happen if this is reached because + // invalidate_ignore_compositor is true. + if (compositor_needs_continuous_invalidate_) { + base::MessageLoop::current()->PostDelayedTask( + FROM_HERE, + fallback_tick_.callback(), + base::TimeDelta::FromMilliseconds( + kFallbackTickTimeoutInMilliseconds)); + } } } void InProcessViewRenderer::FallbackTickFired() { TRACE_EVENT1("android_webview", "InProcessViewRenderer::FallbackTickFired", - "continuous_invalidate_", - continuous_invalidate_); + "compositor_needs_continuous_invalidate_", + compositor_needs_continuous_invalidate_); // This should only be called if OnDraw or DrawGL did not come in time, which // means block_invalidates_ must still be true. DCHECK(block_invalidates_); - if (continuous_invalidate_ && compositor_) { + if (compositor_needs_continuous_invalidate_ && compositor_) { SkDevice device(SkBitmap::kARGB_8888_Config, 1, 1); SkCanvas canvas(&device); block_invalidates_ = true; CompositeSW(&canvas); } block_invalidates_ = false; - EnsureContinuousInvalidation(NULL); + EnsureContinuousInvalidation(NULL, false); } bool InProcessViewRenderer::CompositeSW(SkCanvas* canvas) { @@ -645,8 +657,9 @@ std::string InProcessViewRenderer::ToString(AwDrawGLInfo* draw_info) const { base::StringAppendF(&str, "visible: %d ", visible_); base::StringAppendF(&str, "dip_scale: %f ", dip_scale_); base::StringAppendF(&str, "page_scale_factor: %f ", page_scale_factor_); - base::StringAppendF( - &str, "continuous_invalidate: %d ", continuous_invalidate_); + base::StringAppendF(&str, + "compositor_needs_continuous_invalidate: %d ", + compositor_needs_continuous_invalidate_); base::StringAppendF(&str, "block_invalidates: %d ", block_invalidates_); base::StringAppendF(&str, "view width height: [%d %d] ", width_, height_); base::StringAppendF(&str, "attached_to_window: %d ", attached_to_window_); diff --git a/android_webview/browser/in_process_view_renderer.h b/android_webview/browser/in_process_view_renderer.h index 642c8a8..d7ed85a 100644 --- a/android_webview/browser/in_process_view_renderer.h +++ b/android_webview/browser/in_process_view_renderer.h @@ -74,7 +74,12 @@ class InProcessViewRenderer : public BrowserViewRenderer, void WebContentsGone(); private: - void EnsureContinuousInvalidation(AwDrawGLInfo* draw_info); + // Checks the continuous invalidate and block invalidate state, and schedule + // invalidates appropriately. If |invalidate_ignore_compositor| is true, + // then send a view invalidate regardless of compositor expectation. + void EnsureContinuousInvalidation( + AwDrawGLInfo* draw_info, + bool invalidate_ignore_compositor); bool DrawSWInternal(jobject java_canvas, const gfx::Rect& clip_bounds); bool CompositeSW(SkCanvas* canvas); @@ -98,12 +103,16 @@ class InProcessViewRenderer : public BrowserViewRenderer, bool on_new_picture_enable_; // When true, we should continuously invalidate and keep drawing, for example - // to drive animation. - bool continuous_invalidate_; + // to drive animation. This value is set by the compositor and should always + // reflect the expectation of the compositor and not be reused for other + // states. + bool compositor_needs_continuous_invalidate_; + // Used to block additional invalidates while one is already pending or before // compositor draw which may switch continuous_invalidate on and off in the // process. bool block_invalidates_; + // Holds a callback to FallbackTickFired while it is pending. base::CancelableClosure fallback_tick_; |