namespace cc {
-Scheduler::SyntheticBeginFrameSource::SyntheticBeginFrameSource(
- Scheduler* scheduler,
- base::SingleThreadTaskRunner* task_runner)
- : scheduler_(scheduler) {
- if (gfx::FrameTime::TimestampsAreHighRes()) {
- time_source_ = DelayBasedTimeSourceHighRes::Create(
- scheduler_->VSyncInterval(), task_runner);
+BeginFrameSource* SchedulerFrameSourcesConstructor::ConstructPrimaryFrameSource(
+ Scheduler* scheduler) {
+ if (!scheduler->settings_.throttle_frame_production) {
+ TRACE_EVENT1("cc",
+ "Scheduler::Scheduler()",
+ "PrimaryFrameSource",
+ "BackToBackBeginFrameSource");
+ DCHECK(!scheduler->primary_frame_source_internal_);
+ scheduler->primary_frame_source_internal_ =
+ BackToBackBeginFrameSource::Create(scheduler->task_runner_.get());
+ return scheduler->primary_frame_source_internal_.get();
+ } else if (scheduler->settings_.begin_frame_scheduling_enabled) {
+ TRACE_EVENT1("cc",
+ "Scheduler::Scheduler()",
+ "PrimaryFrameSource",
+ "SchedulerClient");
+ return scheduler->client_->ExternalBeginFrameSource();
} else {
- time_source_ = DelayBasedTimeSource::Create(scheduler_->VSyncInterval(),
- task_runner);
- }
- time_source_->SetClient(this);
-}
-
-Scheduler::SyntheticBeginFrameSource::~SyntheticBeginFrameSource() {
-}
-
-void Scheduler::SyntheticBeginFrameSource::CommitVSyncParameters(
- base::TimeTicks timebase,
- base::TimeDelta interval) {
- time_source_->SetTimebaseAndInterval(timebase, interval);
-}
-
-void Scheduler::SyntheticBeginFrameSource::SetNeedsBeginFrame(
- bool needs_begin_frame,
- std::deque<BeginFrameArgs>* begin_retro_frame_args) {
- DCHECK(begin_retro_frame_args);
- base::TimeTicks missed_tick_time =
- time_source_->SetActive(needs_begin_frame);
- if (!missed_tick_time.is_null()) {
- begin_retro_frame_args->push_back(
- CreateSyntheticBeginFrameArgs(missed_tick_time));
+ TRACE_EVENT1("cc",
+ "Scheduler::Scheduler()",
+ "PrimaryFrameSource",
+ "SyntheticBeginFrameSource");
+ scoped_ptr<SyntheticBeginFrameSource> synthetic_source =
+ SyntheticBeginFrameSource::Create(scheduler->task_runner_.get(),
+ scheduler->Now(),
+ BeginFrameArgs::DefaultInterval());
+
+ DCHECK(!scheduler->vsync_observer_);
+ scheduler->vsync_observer_ = synthetic_source.get();
+
+ DCHECK(!scheduler->primary_frame_source_internal_);
+ scheduler->primary_frame_source_internal_ = synthetic_source.Pass();
+ return scheduler->primary_frame_source_internal_.get();
}
}
-bool Scheduler::SyntheticBeginFrameSource::IsActive() const {
- return time_source_->Active();
-}
-
-void Scheduler::SyntheticBeginFrameSource::OnTimerTick() {
- BeginFrameArgs begin_frame_args(
- CreateSyntheticBeginFrameArgs(time_source_->LastTickTime()));
- scheduler_->BeginFrame(begin_frame_args);
-}
-
-void Scheduler::SyntheticBeginFrameSource::AsValueInto(
- base::debug::TracedValue* state) const {
- time_source_->AsValueInto(state);
-}
-
-BeginFrameArgs
-Scheduler::SyntheticBeginFrameSource::CreateSyntheticBeginFrameArgs(
- base::TimeTicks frame_time) {
- base::TimeTicks deadline = time_source_->NextTickTime();
- return BeginFrameArgs::Create(
- frame_time, deadline, scheduler_->VSyncInterval());
+BeginFrameSource*
+SchedulerFrameSourcesConstructor::ConstructBackgroundFrameSource(
+ Scheduler* scheduler) {
+ TRACE_EVENT1("cc",
+ "Scheduler::Scheduler()",
+ "BackgroundFrameSource",
+ "SyntheticBeginFrameSource");
+ DCHECK(!(scheduler->background_frame_source_internal_));
+ scheduler->background_frame_source_internal_ =
+ SyntheticBeginFrameSource::Create(scheduler->task_runner_.get(),
+ scheduler->Now(),
+ base::TimeDelta::FromSeconds(1));
+ return scheduler->background_frame_source_internal_.get();
}
Scheduler::Scheduler(
SchedulerClient* client,
const SchedulerSettings& scheduler_settings,
int layer_tree_host_id,
- const scoped_refptr<base::SingleThreadTaskRunner>& impl_task_runner)
- : settings_(scheduler_settings),
+ const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
+ base::PowerMonitor* power_monitor,
+ SchedulerFrameSourcesConstructor* frame_sources_constructor)
+ : frame_source_(),
+ primary_frame_source_(NULL),
+ background_frame_source_(NULL),
+ primary_frame_source_internal_(),
+ background_frame_source_internal_(),
+ vsync_observer_(NULL),
+ settings_(scheduler_settings),
client_(client),
layer_tree_host_id_(layer_tree_host_id),
- impl_task_runner_(impl_task_runner),
- vsync_interval_(BeginFrameArgs::DefaultInterval()),
- last_set_needs_begin_frame_(false),
- begin_unthrottled_frame_posted_(false),
+ task_runner_(task_runner),
+ power_monitor_(power_monitor),
begin_retro_frame_posted_(false),
state_machine_(scheduler_settings),
inside_process_scheduled_actions_(false),
settings_.AsValue());
DCHECK(client_);
DCHECK(!state_machine_.BeginFrameNeeded());
- if (settings_.main_frame_before_activation_enabled) {
- DCHECK(settings_.main_frame_before_draw_enabled);
- }
begin_retro_frame_closure_ =
base::Bind(&Scheduler::BeginRetroFrame, weak_factory_.GetWeakPtr());
- begin_unthrottled_frame_closure_ =
- base::Bind(&Scheduler::BeginUnthrottledFrame, weak_factory_.GetWeakPtr());
begin_impl_frame_deadline_closure_ = base::Bind(
&Scheduler::OnBeginImplFrameDeadline, weak_factory_.GetWeakPtr());
poll_for_draw_triggers_closure_ = base::Bind(
advance_commit_state_closure_ = base::Bind(
&Scheduler::PollToAdvanceCommitState, weak_factory_.GetWeakPtr());
- if (!settings_.begin_frame_scheduling_enabled) {
- SetupSyntheticBeginFrames();
- }
+ frame_source_ = BeginFrameSourceMultiplexer::Create();
+ frame_source_->AddObserver(this);
+
+ // Primary frame source
+ primary_frame_source_ =
+ frame_sources_constructor->ConstructPrimaryFrameSource(this);
+ frame_source_->AddSource(primary_frame_source_);
+
+ // Background ticking frame source
+ background_frame_source_ =
+ frame_sources_constructor->ConstructBackgroundFrameSource(this);
+ frame_source_->AddSource(background_frame_source_);
+
+ SetupPowerMonitoring();
}
Scheduler::~Scheduler() {
- if (synthetic_begin_frame_source_) {
- synthetic_begin_frame_source_->SetNeedsBeginFrame(false,
- &begin_retro_frame_args_);
+ TeardownPowerMonitoring();
+}
+
+base::TimeTicks Scheduler::Now() const {
+ base::TimeTicks now = gfx::FrameTime::Now();
+ TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler.now"),
+ "Scheduler::Now",
+ "now",
+ now);
+ return now;
+}
+
+void Scheduler::SetupPowerMonitoring() {
+ if (settings_.disable_hi_res_timer_tasks_on_battery) {
+ DCHECK(power_monitor_);
+ power_monitor_->AddObserver(this);
+ state_machine_.SetImplLatencyTakesPriorityOnBattery(
+ power_monitor_->IsOnBatteryPower());
}
}
-void Scheduler::SetupSyntheticBeginFrames() {
- DCHECK(!synthetic_begin_frame_source_);
- synthetic_begin_frame_source_.reset(
- new SyntheticBeginFrameSource(this, impl_task_runner_.get()));
+void Scheduler::TeardownPowerMonitoring() {
+ if (settings_.disable_hi_res_timer_tasks_on_battery) {
+ DCHECK(power_monitor_);
+ power_monitor_->RemoveObserver(this);
+ }
+}
+
+void Scheduler::OnPowerStateChange(bool on_battery_power) {
+ DCHECK(settings_.disable_hi_res_timer_tasks_on_battery);
+ state_machine_.SetImplLatencyTakesPriorityOnBattery(on_battery_power);
}
void Scheduler::CommitVSyncParameters(base::TimeTicks timebase,
// TODO(brianderson): We should not be receiving 0 intervals.
if (interval == base::TimeDelta())
interval = BeginFrameArgs::DefaultInterval();
- vsync_interval_ = interval;
- if (!settings_.begin_frame_scheduling_enabled)
- synthetic_begin_frame_source_->CommitVSyncParameters(timebase, interval);
+
+ if (vsync_observer_)
+ vsync_observer_->OnUpdateVSyncParameters(timebase, interval);
}
void Scheduler::SetEstimatedParentDrawTime(base::TimeDelta draw_time) {
void Scheduler::SetVisible(bool visible) {
state_machine_.SetVisible(visible);
+ if (visible) {
+ frame_source_->SetActiveSource(primary_frame_source_);
+ } else {
+ frame_source_->SetActiveSource(background_frame_source_);
+ }
ProcessScheduledActions();
}
ProcessScheduledActions();
}
-void Scheduler::SetSmoothnessTakesPriority(bool smoothness_takes_priority) {
- state_machine_.SetSmoothnessTakesPriority(smoothness_takes_priority);
+void Scheduler::SetImplLatencyTakesPriority(bool impl_latency_takes_priority) {
+ state_machine_.SetImplLatencyTakesPriority(impl_latency_takes_priority);
ProcessScheduledActions();
}
void Scheduler::DidLoseOutputSurface() {
TRACE_EVENT0("cc", "Scheduler::DidLoseOutputSurface");
state_machine_.DidLoseOutputSurface();
- last_set_needs_begin_frame_ = false;
- if (!settings_.begin_frame_scheduling_enabled) {
- synthetic_begin_frame_source_->SetNeedsBeginFrame(false,
- &begin_retro_frame_args_);
- }
+ if (frame_source_->NeedsBeginFrames())
+ frame_source_->SetNeedsBeginFrames(false);
begin_retro_frame_args_.clear();
ProcessScheduledActions();
}
void Scheduler::DidCreateAndInitializeOutputSurface() {
TRACE_EVENT0("cc", "Scheduler::DidCreateAndInitializeOutputSurface");
- DCHECK(!last_set_needs_begin_frame_);
+ DCHECK(!frame_source_->NeedsBeginFrames());
DCHECK(begin_impl_frame_deadline_task_.IsCancelled());
state_machine_.DidCreateAndInitializeOutputSurface();
ProcessScheduledActions();
}
base::TimeTicks Scheduler::AnticipatedDrawTime() const {
- if (!last_set_needs_begin_frame_ ||
+ if (!frame_source_->NeedsBeginFrames() ||
begin_impl_frame_args_.interval <= base::TimeDelta())
return base::TimeTicks();
- base::TimeTicks now = gfx::FrameTime::Now();
+ base::TimeTicks now = Now();
base::TimeTicks timebase = std::max(begin_impl_frame_args_.frame_time,
begin_impl_frame_args_.deadline);
int64 intervals = 1 + ((now - timebase) / begin_impl_frame_args_.interval);
}
void Scheduler::SetupNextBeginFrameIfNeeded() {
- bool needs_begin_frame = state_machine_.BeginFrameNeeded();
+ if (!task_runner_.get())
+ return;
- if (settings_.throttle_frame_production) {
- SetupNextBeginFrameWhenVSyncThrottlingEnabled(needs_begin_frame);
- } else {
- SetupNextBeginFrameWhenVSyncThrottlingDisabled(needs_begin_frame);
- }
- SetupPollingMechanisms(needs_begin_frame);
-}
+ bool needs_begin_frame = state_machine_.BeginFrameNeeded();
-// When we are throttling frame production, we request BeginFrames
-// from the OutputSurface.
-void Scheduler::SetupNextBeginFrameWhenVSyncThrottlingEnabled(
- bool needs_begin_frame) {
bool at_end_of_deadline =
- state_machine_.begin_impl_frame_state() ==
- SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE;
+ (state_machine_.begin_impl_frame_state() ==
+ SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE);
bool should_call_set_needs_begin_frame =
// Always request the BeginFrame immediately if it wasn't needed before.
- (needs_begin_frame && !last_set_needs_begin_frame_) ||
+ (needs_begin_frame && !frame_source_->NeedsBeginFrames()) ||
// Only stop requesting BeginFrames after a deadline.
- (!needs_begin_frame && last_set_needs_begin_frame_ && at_end_of_deadline);
+ (!needs_begin_frame && frame_source_->NeedsBeginFrames() &&
+ at_end_of_deadline);
if (should_call_set_needs_begin_frame) {
- if (settings_.begin_frame_scheduling_enabled) {
- client_->SetNeedsBeginFrame(needs_begin_frame);
- } else {
- synthetic_begin_frame_source_->SetNeedsBeginFrame(
- needs_begin_frame, &begin_retro_frame_args_);
- }
- last_set_needs_begin_frame_ = needs_begin_frame;
+ frame_source_->SetNeedsBeginFrames(needs_begin_frame);
}
- PostBeginRetroFrameIfNeeded();
-}
-
-// When we aren't throttling frame production, we initiate a BeginFrame
-// as soon as one is needed.
-void Scheduler::SetupNextBeginFrameWhenVSyncThrottlingDisabled(
- bool needs_begin_frame) {
- last_set_needs_begin_frame_ = needs_begin_frame;
-
- if (!needs_begin_frame || begin_unthrottled_frame_posted_)
- return;
-
- if (state_machine_.begin_impl_frame_state() !=
- SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE &&
- state_machine_.begin_impl_frame_state() !=
- SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE) {
- return;
+ if (at_end_of_deadline) {
+ frame_source_->DidFinishFrame(begin_retro_frame_args_.size());
}
- begin_unthrottled_frame_posted_ = true;
- impl_task_runner_->PostTask(FROM_HERE, begin_unthrottled_frame_closure_);
-}
-
-// BeginUnthrottledFrame is used when we aren't throttling frame production.
-// This will usually be because VSync is disabled.
-void Scheduler::BeginUnthrottledFrame() {
- DCHECK(!settings_.throttle_frame_production);
- DCHECK(begin_retro_frame_args_.empty());
-
- base::TimeTicks now = gfx::FrameTime::Now();
- base::TimeTicks deadline = now + vsync_interval_;
-
- BeginFrameArgs begin_frame_args =
- BeginFrameArgs::Create(now, deadline, vsync_interval_);
- BeginImplFrame(begin_frame_args);
-
- begin_unthrottled_frame_posted_ = false;
+ PostBeginRetroFrameIfNeeded();
+ SetupPollingMechanisms(needs_begin_frame);
}
// We may need to poll when we can't rely on BeginFrame to advance certain
base::TimeDelta delay = begin_impl_frame_args_.IsValid()
? begin_impl_frame_args_.interval
: BeginFrameArgs::DefaultInterval();
- impl_task_runner_->PostDelayedTask(
+ task_runner_->PostDelayedTask(
FROM_HERE, poll_for_draw_triggers_task_.callback(), delay);
}
} else {
// Since we'd rather get a BeginImplFrame by the normal mechanism, we
// set the interval to twice the interval from the previous frame.
advance_commit_state_task_.Reset(advance_commit_state_closure_);
- impl_task_runner_->PostDelayedTask(FROM_HERE,
- advance_commit_state_task_.callback(),
- begin_impl_frame_args_.interval * 2);
+ task_runner_->PostDelayedTask(FROM_HERE,
+ advance_commit_state_task_.callback(),
+ begin_impl_frame_args_.interval * 2);
}
} else {
advance_commit_state_task_.Cancel();
// making a frame. Usually this means that user input for the frame is complete.
// If the scheduler is busy, we queue the BeginFrame to be handled later as
// a BeginRetroFrame.
-void Scheduler::BeginFrame(const BeginFrameArgs& args) {
+bool Scheduler::OnBeginFrameMixInDelegate(const BeginFrameArgs& args) {
TRACE_EVENT1("cc", "Scheduler::BeginFrame", "args", args.AsValue());
- DCHECK(settings_.throttle_frame_production);
+
+ // We have just called SetNeedsBeginFrame(true) and the BeginFrameSource has
+ // sent us the last BeginFrame we have missed. As we might not be able to
+ // actually make rendering for this call, handle it like a "retro frame".
+ // TODO(brainderson): Add a test for this functionality ASAP!
+ if (args.type == BeginFrameArgs::MISSED) {
+ begin_retro_frame_args_.push_back(args);
+ PostBeginRetroFrameIfNeeded();
+ return true;
+ }
BeginFrameArgs adjusted_args(args);
adjusted_args.deadline -= EstimatedParentDrawTime();
} else {
should_defer_begin_frame =
!begin_retro_frame_args_.empty() || begin_retro_frame_posted_ ||
- !last_set_needs_begin_frame_ ||
+ !frame_source_->NeedsBeginFrames() ||
(state_machine_.begin_impl_frame_state() !=
SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE);
}
begin_retro_frame_args_.push_back(adjusted_args);
TRACE_EVENT_INSTANT0(
"cc", "Scheduler::BeginFrame deferred", TRACE_EVENT_SCOPE_THREAD);
- return;
+ // Queuing the frame counts as "using it", so we need to return true.
+ } else {
+ BeginImplFrame(adjusted_args);
}
-
- BeginImplFrame(adjusted_args);
+ return true;
}
// BeginRetroFrame is called for BeginFrames that we've deferred because
// TODO(brianderson): In the future, long deadlines could result in us not
// draining the queue if we don't catch up. If we consistently can't catch
// up, our fallback should be to lower our frame rate.
- base::TimeTicks now = gfx::FrameTime::Now();
+ base::TimeTicks now = Now();
base::TimeDelta draw_duration_estimate = client_->DrawDurationEstimate();
- while (!begin_retro_frame_args_.empty() &&
- now > AdjustedBeginImplFrameDeadline(begin_retro_frame_args_.front(),
- draw_duration_estimate)) {
- TRACE_EVENT1("cc",
- "Scheduler::BeginRetroFrame discarding",
- "frame_time",
- begin_retro_frame_args_.front().frame_time);
+ while (!begin_retro_frame_args_.empty()) {
+ base::TimeTicks adjusted_deadline = AdjustedBeginImplFrameDeadline(
+ begin_retro_frame_args_.front(), draw_duration_estimate);
+ if (now <= adjusted_deadline)
+ break;
+
+ TRACE_EVENT_INSTANT2("cc",
+ "Scheduler::BeginRetroFrame discarding",
+ TRACE_EVENT_SCOPE_THREAD,
+ "deadline - now",
+ (adjusted_deadline - now).InMicroseconds(),
+ "BeginFrameArgs",
+ begin_retro_frame_args_.front().AsValue());
begin_retro_frame_args_.pop_front();
+ frame_source_->DidFinishFrame(begin_retro_frame_args_.size());
}
if (begin_retro_frame_args_.empty()) {
- DCHECK(settings_.throttle_frame_production);
TRACE_EVENT_INSTANT0("cc",
"Scheduler::BeginRetroFrames all expired",
TRACE_EVENT_SCOPE_THREAD);
// will check if there is a pending BeginRetroFrame to ensure we handle
// BeginFrames in FIFO order.
void Scheduler::PostBeginRetroFrameIfNeeded() {
- if (!last_set_needs_begin_frame_)
+ TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler"),
+ "Scheduler::PostBeginRetroFrameIfNeeded",
+ "state",
+ AsValue());
+ if (!frame_source_->NeedsBeginFrames())
return;
if (begin_retro_frame_args_.empty() || begin_retro_frame_posted_)
return;
begin_retro_frame_posted_ = true;
- impl_task_runner_->PostTask(FROM_HERE, begin_retro_frame_closure_);
+ task_runner_->PostTask(FROM_HERE, begin_retro_frame_closure_);
}
// BeginImplFrame starts a compositor frame that will wait up until a deadline
// for a BeginMainFrame+activation to complete before it times out and draws
// any asynchronous animation and scroll/pinch updates.
void Scheduler::BeginImplFrame(const BeginFrameArgs& args) {
- TRACE_EVENT1("cc", "Scheduler::BeginImplFrame", "args", args.AsValue());
- DCHECK(state_machine_.begin_impl_frame_state() ==
- SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE);
+ bool main_thread_is_in_high_latency_mode =
+ state_machine_.MainThreadIsInHighLatencyMode();
+ TRACE_EVENT2("cc",
+ "Scheduler::BeginImplFrame",
+ "args",
+ args.AsValue(),
+ "main_thread_is_high_latency",
+ main_thread_is_in_high_latency_mode);
+ TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler"),
+ "MainThreadLatency",
+ main_thread_is_in_high_latency_mode);
+ DCHECK_EQ(state_machine_.begin_impl_frame_state(),
+ SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE);
DCHECK(state_machine_.HasInitializedOutputSurface());
advance_commit_state_task_.Cancel();
begin_impl_frame_args_ = args;
begin_impl_frame_args_.deadline -= draw_duration_estimate;
- if (!state_machine_.smoothness_takes_priority() &&
- state_machine_.MainThreadIsInHighLatencyMode() &&
+ if (!state_machine_.impl_latency_takes_priority() &&
+ main_thread_is_in_high_latency_mode &&
CanCommitAndActivateBeforeDeadline()) {
state_machine_.SetSkipNextBeginMainFrameToReduceLatency();
}
}
void Scheduler::ScheduleBeginImplFrameDeadline(base::TimeTicks deadline) {
+ TRACE_EVENT1(
+ "cc", "Scheduler::ScheduleBeginImplFrameDeadline", "deadline", deadline);
if (settings_.using_synchronous_renderer_compositor) {
// The synchronous renderer compositor has to make its GL calls
// within this call.
begin_impl_frame_deadline_task_.Cancel();
begin_impl_frame_deadline_task_.Reset(begin_impl_frame_deadline_closure_);
- base::TimeDelta delta = deadline - gfx::FrameTime::Now();
+ base::TimeDelta delta = deadline - Now();
if (delta <= base::TimeDelta())
delta = base::TimeDelta();
- impl_task_runner_->PostDelayedTask(
+ task_runner_->PostDelayedTask(
FROM_HERE, begin_impl_frame_deadline_task_.callback(), delta);
}
ProcessScheduledActions();
}
-bool Scheduler::IsBeginMainFrameSent() const {
- return state_machine_.commit_state() ==
- SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT;
-}
-
void Scheduler::DrawAndSwapIfPossible() {
DrawResult result = client_->ScheduledActionDrawAndSwapIfPossible();
state_machine_.DidDrawIfPossibleCompleted(result);
"SchedulerStateMachine",
"state",
AsValue());
+ VLOG(2) << "Scheduler::ProcessScheduledActions: "
+ << SchedulerStateMachine::ActionToString(action) << " "
+ << state_machine_.GetStatesForDebugging();
state_machine_.UpdateState(action);
base::AutoReset<SchedulerStateMachine::Action>
mark_inside_action(&inside_action_, action);
const {
scoped_refptr<base::debug::TracedValue> state =
new base::debug::TracedValue();
+ AsValueInto(state.get());
+ return state;
+}
+
+void Scheduler::AsValueInto(base::debug::TracedValue* state) const {
state->BeginDictionary("state_machine");
- state_machine_.AsValueInto(state);
+ state_machine_.AsValueInto(state, Now());
state->EndDictionary();
- if (synthetic_begin_frame_source_) {
- state->BeginDictionary("synthetic_begin_frame_source_");
- synthetic_begin_frame_source_->AsValueInto(state);
+
+ // Only trace frame sources when explicitly enabled - http://crbug.com/420607
+ bool frame_tracing_enabled = false;
+ TRACE_EVENT_CATEGORY_GROUP_ENABLED(
+ TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler.frames"),
+ &frame_tracing_enabled);
+ if (frame_tracing_enabled) {
+ state->BeginDictionary("frame_source_");
+ frame_source_->AsValueInto(state);
state->EndDictionary();
}
state->BeginDictionary("scheduler_state");
- state->SetDouble(
- "time_until_anticipated_draw_time_ms",
- (AnticipatedDrawTime() - base::TimeTicks::Now()).InMillisecondsF());
- state->SetDouble("vsync_interval_ms", vsync_interval_.InMillisecondsF());
+ state->SetDouble("time_until_anticipated_draw_time_ms",
+ (AnticipatedDrawTime() - Now()).InMillisecondsF());
state->SetDouble("estimated_parent_draw_time_ms",
estimated_parent_draw_time_.InMillisecondsF());
- state->SetBoolean("last_set_needs_begin_frame_", last_set_needs_begin_frame_);
- state->SetBoolean("begin_unthrottled_frame_posted_",
- begin_unthrottled_frame_posted_);
+ state->SetBoolean("last_set_needs_begin_frame_",
+ frame_source_->NeedsBeginFrames());
state->SetBoolean("begin_retro_frame_posted_", begin_retro_frame_posted_);
state->SetInteger("begin_retro_frame_args_", begin_retro_frame_args_.size());
state->SetBoolean("begin_impl_frame_deadline_task_",
"commit_to_activate_duration_estimate_ms",
client_->CommitToActivateDurationEstimate().InMillisecondsF());
state->EndDictionary();
- return state;
}
bool Scheduler::CanCommitAndActivateBeforeDeadline() const {