diff options
author | jamesr@chromium.org <jamesr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-02-04 00:42:21 +0000 |
---|---|---|
committer | jamesr@chromium.org <jamesr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-02-04 00:42:21 +0000 |
commit | ee3d3addf3c97aab93c735e03a264f1ba486c2e7 (patch) | |
tree | 57c353feaf31e961d0f1e76b2b026cfb40d8eeb2 /chrome/renderer | |
parent | adea95416730f56928e046c134b760daf0a87f36 (diff) | |
download | chromium_src-ee3d3addf3c97aab93c735e03a264f1ba486c2e7.zip chromium_src-ee3d3addf3c97aab93c735e03a264f1ba486c2e7.tar.gz chromium_src-ee3d3addf3c97aab93c735e03a264f1ba486c2e7.tar.bz2 |
Calculate animation_floor_time_ only when actually updating animations
This ensures that imperative animations still hit the target framerate if
we can render fast enough regardless of when in the animation loop the page
calls webkitRequestAnimationFrame().
BUG=71379
TEST=
Review URL: http://codereview.chromium.org/6409007
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@73717 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/renderer')
-rw-r--r-- | chrome/renderer/render_widget.cc | 53 | ||||
-rw-r--r-- | chrome/renderer/render_widget.h | 2 |
2 files changed, 41 insertions, 14 deletions
diff --git a/chrome/renderer/render_widget.cc b/chrome/renderer/render_widget.cc index d96ef05..7187e3c 100644 --- a/chrome/renderer/render_widget.cc +++ b/chrome/renderer/render_widget.cc @@ -77,7 +77,8 @@ RenderWidget::RenderWidget(RenderThreadBase* render_thread, pending_window_rect_count_(0), suppress_next_char_events_(false), is_accelerated_compositing_active_(false), - animation_update_pending_(false) { + animation_update_pending_(false), + animation_waiting_for_paint_(false) { RenderProcess::current()->AddRefProcess(); DCHECK(render_thread_); } @@ -488,11 +489,17 @@ void RenderWidget::CallDoDeferredUpdate() { } void RenderWidget::UpdateAnimationsIfNeeded() { - if (webwidget_ && !is_hidden() && animation_update_pending_) { + if (webwidget_ && !is_hidden() && animation_update_pending_ && + !animation_waiting_for_paint_) { base::Time now = base::Time::Now(); if (now >= animation_floor_time_) { - animation_update_pending_ = false; - webwidget_->animate(); + UpdateAnimationsAndFloorTime(); + // If updating the animation caused invalidations, make sure that we paint + // at least once before we call animate() again. + // Update layout first as that might cause further invalidations. + webwidget_->layout(); + if (paint_aggregator_.HasPendingUpdate()) + animation_waiting_for_paint_ = true; } else { // This code uses base::Time::Now() to calculate the floor and next fire // time because javascript's Date object uses base::Time::Now(). The @@ -501,7 +508,7 @@ void RenderWidget::UpdateAnimationsIfNeeded() { // The upshot of all this is that this function might be called before // base::Time::Now() has advanced past the animation_floor_time_. To // avoid exposing this delay to javascript, we keep posting delayed - // tasks until we observe base::Time::Now() advancing far enough. + // tasks until base::Time::Now() has advanced far enough. int64 delay = (animation_floor_time_ - now).InMillisecondsRoundedUp(); MessageLoop::current()->PostDelayedTask(FROM_HERE, NewRunnableMethod( this, &RenderWidget::UpdateAnimationsIfNeeded), delay); @@ -509,6 +516,13 @@ void RenderWidget::UpdateAnimationsIfNeeded() { } } +void RenderWidget::UpdateAnimationsAndFloorTime() { + animation_update_pending_ = false; + animation_floor_time_ = + base::Time::Now() + base::TimeDelta::FromMilliseconds(16); + webwidget_->animate(); +} + void RenderWidget::DoDeferredUpdate() { if (!webwidget_ || update_reply_pending()) return; @@ -520,8 +534,21 @@ void RenderWidget::DoDeferredUpdate() { return; } - if (base::Time::Now() > animation_floor_time_) - UpdateAnimationsIfNeeded(); + if (animation_update_pending_) { + if (animation_waiting_for_paint_) { + // If we have pending animation updates but need to paint before updating + // them, post a task to UpdateAnimationsIfNeeded that will either update + // animations directly (if the animation floor time has passed by the time + // the function runs) or post a delayed task if the floor time is not yet + // reached. + MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod( + this, &RenderWidget::UpdateAnimationsIfNeeded)); + } else if (base::Time::Now() > animation_floor_time_) { + // Otherwise, if it's time to update the animations go ahead. + UpdateAnimationsAndFloorTime(); + } + } + animation_waiting_for_paint_ = false; // Layout may generate more invalidation. It may also enable the // GPU acceleration, so make sure to run layout before we send the @@ -715,13 +742,11 @@ void RenderWidget::scheduleComposite() { } void RenderWidget::scheduleAnimation() { - if (!animation_update_pending_) { - animation_update_pending_ = true; - animation_floor_time_ = - base::Time::Now() + base::TimeDelta::FromMilliseconds(10); - MessageLoop::current()->PostDelayedTask(FROM_HERE, NewRunnableMethod( - this, &RenderWidget::UpdateAnimationsIfNeeded), 10); - } + if (!animation_update_pending_) { + animation_update_pending_ = true; + MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod( + this, &RenderWidget::UpdateAnimationsIfNeeded)); + } } void RenderWidget::didChangeCursor(const WebCursorInfo& cursor_info) { diff --git a/chrome/renderer/render_widget.h b/chrome/renderer/render_widget.h index a76623f..f130190 100644 --- a/chrome/renderer/render_widget.h +++ b/chrome/renderer/render_widget.h @@ -161,6 +161,7 @@ class RenderWidget : public IPC::Channel::Listener, void CallDoDeferredUpdate(); void UpdateAnimationsIfNeeded(); + void UpdateAnimationsAndFloorTime(); void DoDeferredUpdate(); void DoDeferredClose(); void DoDeferredSetWindowRect(const WebKit::WebRect& pos); @@ -372,6 +373,7 @@ class RenderWidget : public IPC::Channel::Listener, base::Time animation_floor_time_; bool animation_update_pending_; + bool animation_waiting_for_paint_; DISALLOW_COPY_AND_ASSIGN(RenderWidget); }; |