Index: cc/scheduler/begin_frame_source.cc |
diff --git a/cc/scheduler/begin_frame_source.cc b/cc/scheduler/begin_frame_source.cc |
index 4c859a7b53c89c81a0aa8ee738ecc0d806607600..a7ba684d934c6ca5564ce6181d00fd18768c959c 100644 |
--- a/cc/scheduler/begin_frame_source.cc |
+++ b/cc/scheduler/begin_frame_source.cc |
@@ -6,6 +6,7 @@ |
#include <stddef.h> |
+#include "base/atomic_sequence_num.h" |
#include "base/auto_reset.h" |
#include "base/location.h" |
#include "base/logging.h" |
@@ -25,7 +26,7 @@ namespace { |
static const double kDoubleTickDivisor = 2.0; |
} |
-// BeginFrameObserverBase ----------------------------------------------- |
+// BeginFrameObserverBase ------------------------------------------------- |
BeginFrameObserverBase::BeginFrameObserverBase() |
: last_begin_frame_args_(), dropped_begin_frame_args_(0) { |
} |
@@ -33,9 +34,12 @@ BeginFrameObserverBase::BeginFrameObserverBase() |
const BeginFrameArgs& BeginFrameObserverBase::LastUsedBeginFrameArgs() const { |
return last_begin_frame_args_; |
} |
+ |
void BeginFrameObserverBase::OnBeginFrame(const BeginFrameArgs& args) { |
DCHECK(args.IsValid()); |
DCHECK(args.frame_time >= last_begin_frame_args_.frame_time); |
+ DCHECK(args.sequence_number > last_begin_frame_args_.sequence_number || |
+ args.source_id != last_begin_frame_args_.source_id); |
bool used = OnBeginFrameDerivedImpl(args); |
if (used) { |
last_begin_frame_args_ = args; |
@@ -44,17 +48,31 @@ void BeginFrameObserverBase::OnBeginFrame(const BeginFrameArgs& args) { |
} |
} |
+// BeginFrameSource ------------------------------------------------------- |
+namespace { |
+static base::StaticAtomicSequenceNumber g_next_source_id; |
+} // namespace |
+ |
+BeginFrameSource::BeginFrameSource() : source_id_(g_next_source_id.GetNext()) {} |
+ |
+uint32_t BeginFrameSource::source_id() const { |
+ return source_id_; |
+} |
+ |
+// StubBeginFrameSource --------------------------------------------------- |
bool StubBeginFrameSource::IsThrottled() const { |
return true; |
} |
-// SyntheticBeginFrameSource --------------------------------------------- |
+// SyntheticBeginFrameSource ---------------------------------------------- |
SyntheticBeginFrameSource::~SyntheticBeginFrameSource() = default; |
-// BackToBackBeginFrameSource -------------------------------------------- |
+// BackToBackBeginFrameSource --------------------------------------------- |
BackToBackBeginFrameSource::BackToBackBeginFrameSource( |
std::unique_ptr<DelayBasedTimeSource> time_source) |
- : time_source_(std::move(time_source)), weak_factory_(this) { |
+ : time_source_(std::move(time_source)), |
+ next_sequence_number_(BeginFrameArgs::kStartingFrameNumber), |
+ weak_factory_(this) { |
time_source_->SetClient(this); |
// The time_source_ ticks immediately, so we SetActive(true) for a single |
// tick when we need it, and keep it as SetActive(false) otherwise. |
@@ -97,8 +115,9 @@ void BackToBackBeginFrameSource::OnTimerTick() { |
base::TimeTicks frame_time = time_source_->LastTickTime(); |
base::TimeDelta default_interval = BeginFrameArgs::DefaultInterval(); |
BeginFrameArgs args = BeginFrameArgs::Create( |
- BEGINFRAME_FROM_HERE, frame_time, frame_time + default_interval, |
- default_interval, BeginFrameArgs::NORMAL); |
+ BEGINFRAME_FROM_HERE, source_id(), next_sequence_number_, frame_time, |
+ frame_time + default_interval, default_interval, BeginFrameArgs::NORMAL); |
+ next_sequence_number_++; |
// This must happen after getting the LastTickTime() from the time source. |
time_source_->SetActive(false); |
@@ -113,7 +132,8 @@ void BackToBackBeginFrameSource::OnTimerTick() { |
// DelayBasedBeginFrameSource --------------------------------------------- |
DelayBasedBeginFrameSource::DelayBasedBeginFrameSource( |
std::unique_ptr<DelayBasedTimeSource> time_source) |
- : time_source_(std::move(time_source)) { |
+ : time_source_(std::move(time_source)), |
+ next_sequence_number_(BeginFrameArgs::kStartingFrameNumber) { |
time_source_->SetClient(this); |
} |
@@ -142,9 +162,10 @@ void DelayBasedBeginFrameSource::SetAuthoritativeVSyncInterval( |
BeginFrameArgs DelayBasedBeginFrameSource::CreateBeginFrameArgs( |
base::TimeTicks frame_time, |
BeginFrameArgs::BeginFrameArgsType type) { |
- return BeginFrameArgs::Create(BEGINFRAME_FROM_HERE, frame_time, |
- time_source_->NextTickTime(), |
- time_source_->Interval(), type); |
+ uint64_t sequence_number = next_sequence_number_++; |
+ return BeginFrameArgs::Create( |
+ BEGINFRAME_FROM_HERE, source_id(), sequence_number, frame_time, |
+ time_source_->NextTickTime(), time_source_->Interval(), type); |
} |
void DelayBasedBeginFrameSource::AddObserver(BeginFrameObserver* obs) { |
@@ -154,14 +175,33 @@ void DelayBasedBeginFrameSource::AddObserver(BeginFrameObserver* obs) { |
observers_.insert(obs); |
obs->OnBeginFrameSourcePausedChanged(false); |
time_source_->SetActive(true); |
- BeginFrameArgs args = CreateBeginFrameArgs( |
- time_source_->NextTickTime() - time_source_->Interval(), |
- BeginFrameArgs::MISSED); |
+ |
+ // Missed args should correspond to |current_begin_frame_args_| (particularly, |
+ // have the same sequence number) if |current_begin_frame_args_| still |
+ // correspond to the last time the time source should have ticked. This may |
+ // not be the case if OnTimerTick() has never run yet, the time source was |
+ // inactive before AddObserver() was called, or the interval changed. In such |
+ // a case, we create new args with a new sequence number. |
+ base::TimeTicks last_or_missed_tick_time = |
+ time_source_->NextTickTime() - time_source_->Interval(); |
+ if (current_begin_frame_args_.IsValid() && |
+ current_begin_frame_args_.frame_time == last_or_missed_tick_time && |
+ current_begin_frame_args_.interval == time_source_->Interval()) { |
+ // Ensure that the args have the right type. |
+ current_begin_frame_args_.type = BeginFrameArgs::MISSED; |
+ } else { |
+ // The args are not up to date and we need to create new ones with the |
+ // missed tick's time and a new sequence number. |
+ current_begin_frame_args_ = |
+ CreateBeginFrameArgs(last_or_missed_tick_time, BeginFrameArgs::MISSED); |
+ } |
+ |
BeginFrameArgs last_args = obs->LastUsedBeginFrameArgs(); |
if (!last_args.IsValid() || |
- (args.frame_time > |
- last_args.frame_time + args.interval / kDoubleTickDivisor)) { |
- obs->OnBeginFrame(args); |
+ (current_begin_frame_args_.frame_time > |
+ last_args.frame_time + |
+ current_begin_frame_args_.interval / kDoubleTickDivisor)) { |
+ obs->OnBeginFrame(current_begin_frame_args_); |
} |
} |
@@ -179,18 +219,21 @@ bool DelayBasedBeginFrameSource::IsThrottled() const { |
} |
void DelayBasedBeginFrameSource::OnTimerTick() { |
- BeginFrameArgs args = CreateBeginFrameArgs(time_source_->LastTickTime(), |
- BeginFrameArgs::NORMAL); |
+ current_begin_frame_args_ = CreateBeginFrameArgs(time_source_->LastTickTime(), |
+ BeginFrameArgs::NORMAL); |
std::unordered_set<BeginFrameObserver*> observers(observers_); |
for (auto* obs : observers) { |
BeginFrameArgs last_args = obs->LastUsedBeginFrameArgs(); |
if (!last_args.IsValid() || |
- (args.frame_time > |
- last_args.frame_time + args.interval / kDoubleTickDivisor)) |
- obs->OnBeginFrame(args); |
+ (current_begin_frame_args_.frame_time > |
+ last_args.frame_time + |
+ current_begin_frame_args_.interval / kDoubleTickDivisor)) { |
+ obs->OnBeginFrame(current_begin_frame_args_); |
+ } |
} |
} |
+// ExternalBeginFrameSource ----------------------------------------------- |
ExternalBeginFrameSource::ExternalBeginFrameSource( |
ExternalBeginFrameSourceClient* client) |
: client_(client) { |
@@ -214,6 +257,9 @@ void ExternalBeginFrameSource::AddObserver(BeginFrameObserver* obs) { |
BeginFrameArgs last_args = obs->LastUsedBeginFrameArgs(); |
if (!last_args.IsValid() || |
(missed_begin_frame_args_.frame_time > last_args.frame_time)) { |
+ DCHECK((missed_begin_frame_args_.source_id != last_args.source_id) || |
+ (missed_begin_frame_args_.sequence_number > |
+ last_args.sequence_number)); |
obs->OnBeginFrame(missed_begin_frame_args_); |
} |
} |