summaryrefslogtreecommitdiffstats
path: root/ui
diff options
context:
space:
mode:
authorbrianderson@chromium.org <brianderson@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-10-25 19:46:46 +0000
committerbrianderson@chromium.org <brianderson@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-10-25 19:46:46 +0000
commitde2cf8caf24f9dff41462b4ed164d18c553b30e3 (patch)
tree9b7833a432e15c49b8217d529e17cc474c0e47af /ui
parent406e93caa0d00078548cbbb830767f5cc976e32d (diff)
downloadchromium_src-de2cf8caf24f9dff41462b4ed164d18c553b30e3.zip
chromium_src-de2cf8caf24f9dff41462b4ed164d18c553b30e3.tar.gz
chromium_src-de2cf8caf24f9dff41462b4ed164d18c553b30e3.tar.bz2
cc: Use HighResNow as timebase if it is fast and reliable
If base::TimeTicks::HighResNow is fast and reliable, we use it for frame times, animations, and scheduling. Otherwise, we use base::TimeTicks::Now and use a timebase of zero to avoid an incorrect or jittery timebase. This adds a gfx::FrameTime::Now() function, so the same timebase is used across the ui and cc directories. Additionally, the OutputSurface now uses a HighRes version of the DelayBasedTimesource if gfx::FrameTime::Now() is HighRes. BUG=303356 Review URL: https://codereview.chromium.org/27710005 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@231089 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui')
-rw-r--r--ui/compositor/compositor.cc7
-rw-r--r--ui/compositor/layer_animator.cc6
-rw-r--r--ui/compositor/layer_animator_unittest.cc5
-rw-r--r--ui/compositor/test/layer_animator_test_controller.cc4
-rw-r--r--ui/gfx/animation/animation_container.cc7
-rw-r--r--ui/gfx/frame_time.h37
-rw-r--r--ui/gfx/gfx.gyp1
-rw-r--r--ui/gl/gl_surface_win.cc13
-rw-r--r--ui/surface/accelerated_surface_win.cc13
9 files changed, 76 insertions, 17 deletions
diff --git a/ui/compositor/compositor.cc b/ui/compositor/compositor.cc
index 6f6b084..9c57dc7 100644
--- a/ui/compositor/compositor.cc
+++ b/ui/compositor/compositor.cc
@@ -31,6 +31,7 @@
#include "ui/compositor/dip_util.h"
#include "ui/compositor/layer.h"
#include "ui/compositor/reflector.h"
+#include "ui/gfx/frame_time.h"
#include "ui/gl/gl_context.h"
#include "ui/gl/gl_implementation.h"
#include "ui/gl/gl_surface.h"
@@ -555,7 +556,7 @@ void Compositor::Terminate() {
void Compositor::ScheduleDraw() {
if (g_compositor_thread) {
- host_->Composite(base::TimeTicks::Now());
+ host_->Composite(gfx::FrameTime::Now());
} else if (!defer_draw_scheduling_) {
defer_draw_scheduling_ = true;
base::MessageLoop::current()->PostTask(
@@ -603,7 +604,7 @@ void Compositor::Draw() {
// TODO(nduca): Temporary while compositor calls
// compositeImmediately() directly.
Layout();
- host_->Composite(base::TimeTicks::Now());
+ host_->Composite(gfx::FrameTime::Now());
#if defined(OS_WIN)
// While we resize, we are usually a few frames behind. By blocking
@@ -740,7 +741,7 @@ void Compositor::DidCommit() {
}
void Compositor::DidCommitAndDrawFrame() {
- base::TimeTicks start_time = base::TimeTicks::Now();
+ base::TimeTicks start_time = gfx::FrameTime::Now();
FOR_EACH_OBSERVER(CompositorObserver,
observer_list_,
OnCompositingStarted(this, start_time));
diff --git a/ui/compositor/layer_animator.cc b/ui/compositor/layer_animator.cc
index c287574..dd727a6 100644
--- a/ui/compositor/layer_animator.cc
+++ b/ui/compositor/layer_animator.cc
@@ -8,12 +8,14 @@
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "cc/animation/animation_id_provider.h"
+#include "cc/output/begin_frame_args.h"
#include "ui/compositor/compositor.h"
#include "ui/compositor/layer.h"
#include "ui/compositor/layer_animation_delegate.h"
#include "ui/compositor/layer_animation_observer.h"
#include "ui/compositor/layer_animation_sequence.h"
#include "ui/gfx/animation/animation_container.h"
+#include "ui/gfx/frame_time.h"
#define SAFE_INVOKE_VOID(function, running_anim, ...) \
if (running_anim.is_sequence_alive()) \
@@ -177,7 +179,7 @@ void LayerAnimator::StartTogether(
if (GetAnimationContainer()->is_running())
last_step_time_ = GetAnimationContainer()->last_tick_time();
else
- last_step_time_ = base::TimeTicks::Now();
+ last_step_time_ = gfx::FrameTime::Now();
}
// Collect all the affected properties.
@@ -768,7 +770,7 @@ bool LayerAnimator::StartSequenceImmediately(LayerAnimationSequence* sequence) {
else if (GetAnimationContainer()->is_running())
start_time = GetAnimationContainer()->last_tick_time();
else
- start_time = base::TimeTicks::Now();
+ start_time = gfx::FrameTime::Now();
if (!sequence->animation_group_id())
sequence->set_animation_group_id(cc::AnimationIdProvider::NextGroupId());
diff --git a/ui/compositor/layer_animator_unittest.cc b/ui/compositor/layer_animator_unittest.cc
index a1167bd..7c52200 100644
--- a/ui/compositor/layer_animator_unittest.cc
+++ b/ui/compositor/layer_animator_unittest.cc
@@ -20,6 +20,7 @@
#include "ui/compositor/test/test_layer_animation_delegate.h"
#include "ui/compositor/test/test_layer_animation_observer.h"
#include "ui/compositor/test/test_utils.h"
+#include "ui/gfx/frame_time.h"
#include "ui/gfx/rect.h"
#include "ui/gfx/transform.h"
@@ -168,7 +169,7 @@ TEST(LayerAnimatorTest, ImplicitAnimation) {
animator->set_disable_timer_for_test(true);
TestLayerAnimationDelegate delegate;
animator->SetDelegate(&delegate);
- base::TimeTicks now = base::TimeTicks::Now();
+ base::TimeTicks now = gfx::FrameTime::Now();
animator->SetBrightness(0.5);
EXPECT_TRUE(animator->is_animating());
element->Step(now + base::TimeDelta::FromSeconds(1));
@@ -1035,7 +1036,7 @@ TEST(LayerAnimatorTest, StartTogetherSetsLastStepTime) {
// miniscule (fractions of a millisecond). If set correctly, then the delta
// should be enormous. Arbitrarily choosing 1 minute as the threshold,
// though a much smaller value would probably have sufficed.
- delta = base::TimeTicks::Now() - animator->last_step_time();
+ delta = gfx::FrameTime::Now() - animator->last_step_time();
EXPECT_GT(60.0, delta.InSecondsF());
}
diff --git a/ui/compositor/test/layer_animator_test_controller.cc b/ui/compositor/test/layer_animator_test_controller.cc
index 2b686cc..b7b8c40 100644
--- a/ui/compositor/test/layer_animator_test_controller.cc
+++ b/ui/compositor/test/layer_animator_test_controller.cc
@@ -5,6 +5,8 @@
#include "cc/animation/animation.h"
#include "ui/compositor/layer_animation_sequence.h"
#include "ui/compositor/test/layer_animator_test_controller.h"
+#include "ui/gfx/frame_time.h"
+#include "ui/gfx/rect.h"
namespace ui {
@@ -52,7 +54,7 @@ void LayerAnimatorTestController::StartThreadedAnimationsIfNeeded() {
0,
element->animation_group_id(),
threaded_properties[i],
- (base::TimeTicks::Now() - base::TimeTicks()).InSecondsF()));
+ (gfx::FrameTime::Now() - base::TimeTicks()).InSecondsF()));
}
}
diff --git a/ui/gfx/animation/animation_container.cc b/ui/gfx/animation/animation_container.cc
index c76f1bb..d8290b2 100644
--- a/ui/gfx/animation/animation_container.cc
+++ b/ui/gfx/animation/animation_container.cc
@@ -6,6 +6,7 @@
#include "ui/gfx/animation/animation_container_element.h"
#include "ui/gfx/animation/animation_container_observer.h"
+#include "ui/gfx/frame_time.h"
using base::TimeDelta;
using base::TimeTicks;
@@ -13,7 +14,7 @@ using base::TimeTicks;
namespace gfx {
AnimationContainer::AnimationContainer()
- : last_tick_time_(TimeTicks::Now()),
+ : last_tick_time_(gfx::FrameTime::Now()),
observer_(NULL) {
}
@@ -28,7 +29,7 @@ void AnimationContainer::Start(AnimationContainerElement* element) {
// element isn't running.
if (elements_.empty()) {
- last_tick_time_ = TimeTicks::Now();
+ last_tick_time_ = gfx::FrameTime::Now();
SetMinTimerInterval(element->GetTimerInterval());
} else if (element->GetTimerInterval() < min_timer_interval_) {
SetMinTimerInterval(element->GetTimerInterval());
@@ -61,7 +62,7 @@ void AnimationContainer::Run() {
// ourself here to make sure we're still valid after running all the elements.
scoped_refptr<AnimationContainer> this_ref(this);
- TimeTicks current_time = TimeTicks::Now();
+ TimeTicks current_time = gfx::FrameTime::Now();
last_tick_time_ = current_time;
diff --git a/ui/gfx/frame_time.h b/ui/gfx/frame_time.h
new file mode 100644
index 0000000..8d143ee
--- /dev/null
+++ b/ui/gfx/frame_time.h
@@ -0,0 +1,37 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_GFX_FRAME_TIME_H
+#define UI_GFX_FRAME_TIME_H
+
+#include "base/time/time.h"
+#include "base/logging.h"
+
+namespace gfx {
+
+// FrameTime::Now() should be used to get timestamps with a timebase that
+// is consistent across the graphics stack.
+class FrameTime {
+ public:
+ static base::TimeTicks Now() {
+ if (TimestampsAreHighRes())
+ return base::TimeTicks::HighResNow();
+ return base::TimeTicks::Now();
+ }
+
+#if defined(OS_WIN)
+ static base::TimeTicks FromQPCValue(LONGLONG qpc_value) {
+ DCHECK(TimestampsAreHighRes());
+ return base::TimeTicks::FromQPCValue(qpc_value);
+ }
+#endif
+
+ static bool TimestampsAreHighRes() {
+ return base::TimeTicks::IsHighResNowFastAndReliable();
+ }
+};
+
+}
+
+#endif // UI_GFX_FRAME_TIME_H
diff --git a/ui/gfx/gfx.gyp b/ui/gfx/gfx.gyp
index 66d4adb..56c4d64 100644
--- a/ui/gfx/gfx.gyp
+++ b/ui/gfx/gfx.gyp
@@ -86,6 +86,7 @@
'display_observer.h',
'favicon_size.cc',
'favicon_size.h',
+ 'frame_time.h',
'font.cc',
'font.h',
'font_fallback_win.cc',
diff --git a/ui/gl/gl_surface_win.cc b/ui/gl/gl_surface_win.cc
index d535c06..ff2ed84 100644
--- a/ui/gl/gl_surface_win.cc
+++ b/ui/gl/gl_surface_win.cc
@@ -11,6 +11,7 @@
#include "base/memory/scoped_ptr.h"
#include "base/win/windows_version.h"
#include "third_party/mesa/src/include/GL/osmesa.h"
+#include "ui/gfx/frame_time.h"
#include "ui/gl/gl_bindings.h"
#include "ui/gl/gl_implementation.h"
#include "ui/gl/gl_surface_egl.h"
@@ -56,8 +57,16 @@ class DWMVSyncProvider : public VSyncProvider {
if (result != S_OK)
return;
- base::TimeTicks timebase = base::TimeTicks::FromQPCValue(
- static_cast<LONGLONG>(timing_info.qpcVBlank));
+ base::TimeTicks timebase;
+ // If FrameTime is not high resolution, we do not want to translate the
+ // QPC value provided by DWM into the low-resolution timebase, which
+ // would be error prone and jittery. As a fallback, we assume the timebase
+ // is zero.
+ if (gfx::FrameTime::TimestampsAreHighRes()) {
+ timebase = gfx::FrameTime::FromQPCValue(
+ static_cast<LONGLONG>(timing_info.qpcVBlank));
+ }
+
// Swap the numerator/denominator to convert frequency to period.
if (timing_info.rateRefresh.uiDenominator > 0 &&
timing_info.rateRefresh.uiNumerator > 0) {
diff --git a/ui/surface/accelerated_surface_win.cc b/ui/surface/accelerated_surface_win.cc
index f346dbe..a8b57c5 100644
--- a/ui/surface/accelerated_surface_win.cc
+++ b/ui/surface/accelerated_surface_win.cc
@@ -28,6 +28,7 @@
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/base/win/shell.h"
#include "ui/events/latency_info.h"
+#include "ui/gfx/frame_time.h"
#include "ui/gfx/rect.h"
#include "ui/gfx/win/dpi.h"
#include "ui/gfx/win/hwnd_util.h"
@@ -877,18 +878,22 @@ void AcceleratedPresenter::DoPresentAndAcknowledge(
if (raster_status.InVBlank)
clamped_scanline = display_mode.Height;
- base::TimeTicks current_time = base::TimeTicks::HighResNow();
-
// Figure out approximately how far back in time the last vsync was based on
// the ratio of the raster scanline to the display height.
base::TimeTicks last_vsync_time;
base::TimeDelta refresh_period;
+
if (display_mode.Height) {
+ refresh_period = base::TimeDelta::FromMicroseconds(
+ 1000000 / display_mode.RefreshRate);
+ // If FrameTime is not high resolution, we use a timebase of zero to avoid
+ // introducing jitter into our frame start times.
+ if (gfx::FrameTime::TimestampsAreHighRes()) {
+ base::TimeTicks current_time = gfx::FrameTime::Now();
last_vsync_time = current_time -
base::TimeDelta::FromMilliseconds((clamped_scanline * 1000) /
(display_mode.RefreshRate * display_mode.Height));
- refresh_period = base::TimeDelta::FromMicroseconds(
- 1000000 / display_mode.RefreshRate);
+ }
}
// Wait for the StretchRect to complete before notifying the GPU process