Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(201)

Unified Diff: cc/scheduler/scheduler.cc

Issue 794293002: cc: Unify BeginRetroFrames and non-RetroFrame paths in scheduler. [WIP] (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | cc/scheduler/scheduler_state_machine.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: cc/scheduler/scheduler.cc
diff --git a/cc/scheduler/scheduler.cc b/cc/scheduler/scheduler.cc
index 7f0232d3d306a9c9ca51ab198c5b37b61db66561..1df91bb60412c8cb28ed69a5047d97c1bb625ed6 100644
--- a/cc/scheduler/scheduler.cc
+++ b/cc/scheduler/scheduler.cc
@@ -90,7 +90,7 @@ Scheduler::Scheduler(
layer_tree_host_id_(layer_tree_host_id),
task_runner_(task_runner),
power_monitor_(power_monitor),
- begin_retro_frame_posted_(false),
+ begin_frame_process_posted_(false),
state_machine_(scheduler_settings),
inside_process_scheduled_actions_(false),
inside_action_(SchedulerStateMachine::ACTION_NONE),
@@ -102,8 +102,8 @@ Scheduler::Scheduler(
DCHECK(client_);
DCHECK(!state_machine_.BeginFrameNeeded());
- begin_retro_frame_closure_ =
- base::Bind(&Scheduler::BeginRetroFrame, weak_factory_.GetWeakPtr());
+ begin_frame_process_closure_ =
+ base::Bind(&Scheduler::ProcessBeginFrames, weak_factory_.GetWeakPtr());
begin_impl_frame_deadline_closure_ = base::Bind(
&Scheduler::OnBeginImplFrameDeadline, weak_factory_.GetWeakPtr());
poll_for_draw_triggers_closure_ = base::Bind(
@@ -159,11 +159,6 @@ void Scheduler::TeardownPowerMonitoring() {
}
}
-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,
base::TimeDelta interval) {
// TODO(brianderson): We should not be receiving 0 intervals.
@@ -249,11 +244,6 @@ void Scheduler::DidSwapBuffersComplete() {
ProcessScheduledActions();
}
-void Scheduler::SetImplLatencyTakesPriority(bool impl_latency_takes_priority) {
- state_machine_.SetImplLatencyTakesPriority(impl_latency_takes_priority);
- ProcessScheduledActions();
-}
-
void Scheduler::NotifyReadyToCommit() {
TRACE_EVENT0("cc", "Scheduler::NotifyReadyToCommit");
state_machine_.NotifyReadyToCommit();
@@ -275,7 +265,7 @@ void Scheduler::DidLoseOutputSurface() {
state_machine_.DidLoseOutputSurface();
if (frame_source_->NeedsBeginFrames())
frame_source_->SetNeedsBeginFrames(false);
- begin_retro_frame_args_.clear();
+ pending_begin_frame_args_.clear();
ProcessScheduledActions();
}
@@ -283,8 +273,17 @@ void Scheduler::DidCreateAndInitializeOutputSurface() {
TRACE_EVENT0("cc", "Scheduler::DidCreateAndInitializeOutputSurface");
DCHECK(!frame_source_->NeedsBeginFrames());
DCHECK(begin_impl_frame_deadline_task_.IsCancelled());
+
state_machine_.DidCreateAndInitializeOutputSurface();
ProcessScheduledActions();
+
+ // We want to start the first commit ASAP, so we post the LastBeginFrameArgs
+ // onto the retro queue and process it.
+ BeginFrameArgs missed = frame_source_->LastBeginFrameArgs();
+ missed.type = BeginFrameArgs::MISSED;
+ // Adjust the deadline
+ //missed.deadline = XXXXX
+ OnBeginFrame(missed);
}
void Scheduler::NotifyBeginMainFrameStarted() {
@@ -292,22 +291,6 @@ void Scheduler::NotifyBeginMainFrameStarted() {
state_machine_.NotifyBeginMainFrameStarted();
}
-base::TimeTicks Scheduler::AnticipatedDrawTime() const {
- if (!frame_source_->NeedsBeginFrames() ||
- begin_impl_frame_args_.interval <= base::TimeDelta())
- return base::TimeTicks();
-
- 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);
- return timebase + (begin_impl_frame_args_.interval * intervals);
-}
-
-base::TimeTicks Scheduler::LastBeginImplFrameTime() {
- return begin_impl_frame_args_.frame_time;
-}
-
void Scheduler::SetupNextBeginFrameIfNeeded() {
if (!task_runner_.get())
return;
@@ -330,10 +313,9 @@ void Scheduler::SetupNextBeginFrameIfNeeded() {
}
if (at_end_of_deadline) {
- frame_source_->DidFinishFrame(begin_retro_frame_args_.size());
+ frame_source_->DidFinishFrame(pending_begin_frame_args_.size());
}
- PostBeginRetroFrameIfNeeded();
SetupPollingMechanisms(needs_begin_frame);
}
@@ -386,240 +368,137 @@ void Scheduler::SetupPollingMechanisms(bool needs_begin_frame) {
}
}
-// BeginFrame is the mechanism that tells us that now is a good time to start
-// 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.
-bool Scheduler::OnBeginFrameMixInDelegate(const BeginFrameArgs& args) {
- TRACE_EVENT1("cc", "Scheduler::BeginFrame", "args", args.AsValue());
+base::TimeDelta Scheduler::TimeForDrawing() {
+ return EstimatedParentDrawTime() + client_->DrawDurationEstimate();
+}
- // Deliver BeginFrames to children.
- if (settings_.forward_begin_frames_to_children &&
- state_machine_.children_need_begin_frames()) {
- BeginFrameArgs adjusted_args_for_children(args);
- // Adjust a deadline for child schedulers.
- // TODO(simonhong): Once we have commitless update, we can get rid of
- // BeginMainFrameToCommitDurationEstimate() +
- // CommitToActivateDurationEstimate().
- adjusted_args_for_children.deadline -=
- (client_->BeginMainFrameToCommitDurationEstimate() +
- client_->CommitToActivateDurationEstimate() +
- client_->DrawDurationEstimate() + EstimatedParentDrawTime());
- client_->SendBeginFramesToChildren(adjusted_args_for_children);
+base::TimeTicks Scheduler::CalculateDeadline(base::TimeTicks now, const BeginFrameArgs& args) {
+ // Synchronous renderer should doesn't use deadlines.
+ if (settings_.using_synchronous_renderer_compositor) {
+ return base::TimeTicks();
}
- // 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;
+ base::TimeTicks deadline = args.deadline;
+
+ // Decrease the deadline enough to give drawing enough time to happen.
+ deadline -= TimeForDrawing();
+
+ if (false) { //is_low_end()) {
+ // On low end devices, if we start main thread rendering it can stave us
+ // of CPU. Hence, if we don't think the main will make this frame we should
+ // run the impl tasks right now.
+ base::TimeTicks main_thread_time =
+ client_->BeginMainFrameToCommitDurationEstimate() +
+ client_->CommitToActivateDurationEstimate();
+
+ if (now + main_thread_time > deadline) {
+ deadline = now;
+ }
}
+
+ return deadline;
+}
- BeginFrameArgs adjusted_args(args);
- adjusted_args.deadline -= EstimatedParentDrawTime();
+// BeginFrame is the mechanism that tells us that now is a good time to start
+// making a frame. Usually this means that user input for the frame is complete.
+bool Scheduler::OnBeginFrameMixInDelegate(const BeginFrameArgs& args) {
+ TRACE_EVENT1("cc", "Scheduler::BeginFrame", "args", args.AsValue());
- bool should_defer_begin_frame;
- if (settings_.using_synchronous_renderer_compositor) {
- should_defer_begin_frame = false;
- } else {
- should_defer_begin_frame =
- !begin_retro_frame_args_.empty() || begin_retro_frame_posted_ ||
- !frame_source_->NeedsBeginFrames() ||
- (state_machine_.begin_impl_frame_state() !=
- SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE);
+ // Push the BeginFrame onto a queue for processing.
+ begin_retro_frame_args.push_back(args);
+
+ // If we aren't already processing frames, start processing now.
+ if (state_machine_.begin_impl_frame_state() == SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE) {
+ ProcessBeginFrames(nullptr);
+ // Otherwise, post a task to process the frames after the current processing
+ // is finished.
+ } else if (!begin_frame_process_posted_) {
+ begin_frame_process_posted_ = true;
+ task_runner_->PostTask(FROM_HERE, begin_frame_process_closure_, &begin_frame_process_posted_);
}
- if (should_defer_begin_frame) {
- begin_retro_frame_args_.push_back(adjusted_args);
- TRACE_EVENT_INSTANT0(
- "cc", "Scheduler::BeginFrame deferred", TRACE_EVENT_SCOPE_THREAD);
- // Queuing the frame counts as "using it", so we need to return true.
- } else {
- BeginImplFrame(adjusted_args);
- }
return true;
}
-void Scheduler::SetChildrenNeedBeginFrames(bool children_need_begin_frames) {
- DCHECK(settings_.forward_begin_frames_to_children);
- state_machine_.SetChildrenNeedBeginFrames(children_need_begin_frames);
- DCHECK_EQ(state_machine_.NextAction(), SchedulerStateMachine::ACTION_NONE);
-}
-
-// BeginRetroFrame is called for BeginFrames that we've deferred because
-// the scheduler was in the middle of processing a previous BeginFrame.
-void Scheduler::BeginRetroFrame() {
- TRACE_EVENT0("cc", "Scheduler::BeginRetroFrame");
- DCHECK(!settings_.using_synchronous_renderer_compositor);
- DCHECK(begin_retro_frame_posted_);
- begin_retro_frame_posted_ = false;
+void Scheduler::ProcessBeginFrames(bool* clear_posted) {
+ DCHECK(!begin_retro_frame_args.empty());
- // If there aren't any retroactive BeginFrames, then we've lost the
- // OutputSurface and should abort.
- if (begin_retro_frame_args_.empty())
- return;
+ if (clear_posted) {
+ *clear_posted = false;
+ }
- // Discard expired BeginRetroFrames
- // Today, we should always end up with at most one un-expired BeginRetroFrame
- // because deadlines will not be greater than the next frame time. We don't
- // DCHECK though because some systems don't always have monotonic timestamps.
- // 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.
+ // Capture now to use for all the deadline calculations
base::TimeTicks now = Now();
- while (!begin_retro_frame_args_.empty()) {
- const BeginFrameArgs& args = begin_retro_frame_args_.front();
- base::TimeTicks expiration_time = args.frame_time + args.interval;
- if (now <= expiration_time)
- break;
- TRACE_EVENT_INSTANT2(
- "cc", "Scheduler::BeginRetroFrame discarding", TRACE_EVENT_SCOPE_THREAD,
- "expiration_time - now", (expiration_time - now).InMillisecondsF(),
- "BeginFrameArgs", begin_retro_frame_args_.front().AsValue());
- begin_retro_frame_args_.pop_front();
- frame_source_->DidFinishFrame(begin_retro_frame_args_.size());
+ // If we have multiple frames to process, discard anything which we can't
+ // make it's deadline.
+ while (pending_begin_frame_args_.size() > 1) {
+ const BeginFrameArgs& args = pending_begin_frame_args_.front();
+
+ base::TimeTicks deadline = CalculateDeadline(now, args);
+ if (now >= deadline) {
+ TRACE_EVENT_INSTANT2(
+ "cc", "Scheduler::BeginFrame discarding", TRACE_EVENT_SCOPE_THREAD,
+ "expiration_time - now", (deadline - now).InMillisecondsF(),
+ "BeginFrameArgs", args.AsValue());
+ pending_begin_frame_args_.pop_front();
+ frame_source_->DidFinishFrame(pending_begin_frame_args_.size());
+ }
}
- if (begin_retro_frame_args_.empty()) {
- TRACE_EVENT_INSTANT0("cc",
- "Scheduler::BeginRetroFrames all expired",
- TRACE_EVENT_SCOPE_THREAD);
- } else {
- BeginFrameArgs front = begin_retro_frame_args_.front();
- begin_retro_frame_args_.pop_front();
- BeginImplFrame(front);
- }
+ // Process the head of the queue.
+ BeginFrameArgs front_args = pending_begin_frame_args_.front();
+ pending_begin_frame_args_.pop_front();
+ front_args.deadline = CalculateDeadline(now, front_args);
+ BeginImplFrame(now, front_args);
}
-// There could be a race between the posted BeginRetroFrame and a new
-// BeginFrame arriving via the normal mechanism. Scheduler::BeginFrame
-// will check if there is a pending BeginRetroFrame to ensure we handle
-// BeginFrames in FIFO order.
-void Scheduler::PostBeginRetroFrameIfNeeded() {
- 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_args_ should always be empty for the
- // synchronous compositor.
- DCHECK(!settings_.using_synchronous_renderer_compositor);
- if (state_machine_.begin_impl_frame_state() !=
- SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE)
- return;
-
- begin_retro_frame_posted_ = true;
- 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) {
- 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();
-
- base::TimeDelta draw_duration_estimate = client_->DrawDurationEstimate();
- begin_impl_frame_args_ = args;
- begin_impl_frame_args_.deadline -= draw_duration_estimate;
+void Scheduler::BeginImplFrame(base::TimeTicks now, const BeginFrameArgs& args) {
+ // Clear any pending impl frame deadline
+ begin_impl_frame_deadline_task_.Cancel();
+ begin_impl_frame_deadline_task_.Reset(begin_impl_frame_deadline_closure_);
- if (!state_machine_.impl_latency_takes_priority() &&
- main_thread_is_in_high_latency_mode &&
- CanCommitAndActivateBeforeDeadline()) {
- state_machine_.SetSkipNextBeginMainFrameToReduceLatency();
+ // TODO(mithro): ?????
+ // Deliver BeginFrames to children.
+ if (settings_.forward_begin_frames_to_children &&
+ state_machine_.children_need_begin_frames()) {
+ BeginFrameArgs adjusted_args_for_children(args);
+ // Adjust a deadline for child schedulers.
+ // TODO(simonhong): Once we have commitless update, we can get rid of
+ // BeginMainFrameToCommitDurationEstimate() +
+ // CommitToActivateDurationEstimate().
+ adjusted_args_for_children.deadline -=
+ (client_->BeginMainFrameToCommitDurationEstimate() +
+ client_->CommitToActivateDurationEstimate() +
+ TimeForDrawing());
+ client_->SendBeginFramesToChildren(adjusted_args_for_children);
}
- client_->WillBeginImplFrame(begin_impl_frame_args_);
- state_machine_.OnBeginImplFrame(begin_impl_frame_args_);
- devtools_instrumentation::DidBeginFrame(layer_tree_host_id_);
-
- ProcessScheduledActions();
-
- state_machine_.OnBeginImplFrameDeadlinePending();
+ // Start the ImplFrame
+ client_->BeginImplFrame(args);
- if (settings_.using_synchronous_renderer_compositor) {
- // The synchronous renderer compositor has to make its GL calls
- // within this call.
- // TODO(brianderson): Have the OutputSurface initiate the deadline tasks
- // so the synchronous renderer compositor can take advantage of splitting
- // up the BeginImplFrame and deadline as well.
+ // If we are asked to schedule a deadline in the past, just run the deadline
+ // right now.
+ if (now >= args.deadline) {
OnBeginImplFrameDeadline();
- } else {
- ScheduleBeginImplFrameDeadline(
- AdjustedBeginImplFrameDeadline(args, draw_duration_estimate));
- }
-}
-
-base::TimeTicks Scheduler::AdjustedBeginImplFrameDeadline(
- const BeginFrameArgs& args,
- base::TimeDelta draw_duration_estimate) const {
- // The synchronous compositor does not post a deadline task.
- DCHECK(!settings_.using_synchronous_renderer_compositor);
- if (state_machine_.ShouldTriggerBeginImplFrameDeadlineEarly()) {
- // We are ready to draw a new active tree immediately.
- // We don't use Now() here because it's somewhat expensive to call.
- return base::TimeTicks();
- } else if (state_machine_.needs_redraw()) {
- // We have an animation or fast input path on the impl thread that wants
- // to draw, so don't wait too long for a new active tree.
- return args.deadline - draw_duration_estimate;
- } else {
- // The impl thread doesn't have anything it wants to draw and we are just
- // waiting for a new active tree, so post the deadline for the next
- // expected BeginImplFrame start. This allows us to draw immediately when
- // there is a new active tree, instead of waiting for the next
- // BeginImplFrame.
- // TODO(brianderson): Handle long deadlines (that are past the next frame's
- // frame time) properly instead of using this hack.
- return args.frame_time + args.interval;
+ return;
}
-}
-
-void Scheduler::ScheduleBeginImplFrameDeadline(base::TimeTicks deadline) {
- TRACE_EVENT1(
- "cc", "Scheduler::ScheduleBeginImplFrameDeadline", "deadline", deadline);
-
- begin_impl_frame_deadline_task_.Cancel();
- begin_impl_frame_deadline_task_.Reset(begin_impl_frame_deadline_closure_);
-
- base::TimeDelta delta = deadline - Now();
- if (delta <= base::TimeDelta())
- delta = base::TimeDelta();
+
+ // Else post a task for the deadline
task_runner_->PostDelayedTask(
- FROM_HERE, begin_impl_frame_deadline_task_.callback(), delta);
+ FROM_HERE, begin_impl_frame_deadline_task_.callback(), now - deadline);
}
void Scheduler::OnBeginImplFrameDeadline() {
TRACE_EVENT0("cc", "Scheduler::OnBeginImplFrameDeadline");
begin_impl_frame_deadline_task_.Cancel();
+ last_begin_impl_frame_args_ = current_begin_impl_frame_args_;
+
// We split the deadline actions up into two phases so the state machine
- // has a chance to trigger actions that should occur durring and after
- // the deadline separately. For example:
+ // has a chance to trigger actions that should occur during and after the
+ // deadline separately. For example:
// * Sending the BeginMainFrame will not occur after the deadline in
// order to wait for more user-input before starting the next commit.
// * Creating a new OuputSurface will not occur during the deadline in
@@ -632,6 +511,120 @@ void Scheduler::OnBeginImplFrameDeadline() {
client_->DidBeginImplFrameDeadline();
}
+void Scheduler::DidActivateSyncTree() {
+ // Main frame is committed and activated
+ last_main_frame_args_ = current_main_frame_args_;
+ current_main_frame_args_ = BeginFrameArgs();
+}
+
+BeginFrameArgs Scheduler::GetBeginMainFrameArgs() {
+ // Did the previous main frame meet the deadline?
+ bool last_main_frame_meet_deadline = (last_main_frame_args_.frame_time == last_impl_frame_args_.frame_time);
+
+ BeginFrameArgs args(current_impl_frame_args_);
+ // We aren't inside an active impl frame deadline, so we use the values of
+ // the last impl frame.
+ // TODO(mithro): This includes deadline adjustment for draw time which could
+ // instead be given to the main frame.
+ if (!args.is_valid()) {
+ args = last_impl_frame_args_;
+ }
+
+ // Do we think the main frame can make the deadline?
+ base::TimeDelta main_thread_time =
+ client_->BeginMainFrameToCommitDurationEstimate() +
+ client_->CommitToActivateDurationEstimate();
+ if (now + main_thread_time <= args.deadline) {
+ // If we think the BeginMainFrame will make the deadline, we should
+ // definitely go ahead.
+ return args;
+ }
+
+ base::TimeDelta will_missed_deadline_by = now + main_thread_time - args.deadline;
+
+/*
+ // If we think the BeginMainFrame will only miss by a little and we made the
+ // last deadline, we are going to give it a go and see if we actually miss.
+ // This exists because our estimates are rough and there is jitter in the
+ // system.
+ bool close_deadline_miss = (will_missed_deadline_by / base::TimeDelta::FromMilliseconds(1)) == 0;
+ if (last_main_frame_meet_deadline && close_deadline_miss) {
+ return args;
+ }
+*/
+
+ // Otherwise, we don't think the BeginMainFrame will make the deadline and
+ // have already missed the last frame. What we do depends on if we think
+ // sending a BeginMainFrame now will effect the next frame's ability to meet
+ // the deadline.
+
+ // Work out what percentage of an normal interval the main thread rendering
+ // will take.
+ base::TimeDelta time_for_rendering = args.interval - (EstimatedParentDrawTime() + client_->DrawDurationEstimate());
+ double main_percentage_of_rendering_time = main_thread_time.InMillisecondsF() / time_for_rendering.InMillisecondsF();
+
+ if (main_percentage_of_rendering_time < 0.5) {
+ // As the main thread can render twice a frame, starting rendering is
+ // unlikely to cause us to miss the next frame. Let's try and catch the
+ // main thread up to the impl thread to help with latency.
+ // We keep the expired deadline so main thread knows it not to run any
+ // unimportant tasks. It will have time after we catch back up.
+ return args;
+ }
+
+ if (main_percentage_of_rendering_time > 1.0) {
+ // Values greater than 1.0 mean the main thread will never make a normal
+ // deadline.
+
+ // If we could meet 50% of the interval, then we assume that we will do
+ // that and start rendering ASAP.
+ if (main_percentage_of_rendering_time < 2.0) {
+ // Adjust the deadline to the next deadline we think the main thread will
+ // probably make.
+ while (args.deadline + time_for_rendering >= now) {
+ args.deadline += args.interval;
+ }
+ return args;
+ }
+
+ // If the main thread isn't even going to make 50% frame rate, just target
+ // throughput and render as fast as we can. We clear the deadline to inform
+ // the main thread that we are targeting throughput and want to minimize
+ // context switches.
+ args.deadline = base::TimeTicks();
+ return args;
+ }
+
+ // If main_percentage_of_rendering_time is between 0.5 and 1.0, then if we
+ // start rendering too late it will break the next frame too. However, we
+ // have to be careful we don't drop *every* main frame on the floor.
+
+ // If we are missing the deadline by the "slack" in the next frame, then we
+ // should go ahead.
+ base::TimeDelta slack_in_next_frame = time_for_rendering - main_thread_time;
+ if (will_miss_deadline_by < slack_in_next_frame) {
+ // We don't adjust the deadline because we want this main frame to return
+ // as early as possible to give the next main frame as much chance as
+ // possible.
+ return args;
+ }
+
+ if (last_main_frame_meet_deadline == DROPPED) {
+ // Drop this main frame to allow the next main frame to start as soon as
+ // the BeginFrame message occurs.
+ return args;
+ } else {
+ return BeginFrameArgs();
+ }
+}
+
+void Scheduler::SetChildrenNeedBeginFrames(bool children_need_begin_frames) {
+ DCHECK(settings_.forward_begin_frames_to_children);
+ state_machine_.SetChildrenNeedBeginFrames(children_need_begin_frames);
+ DCHECK_EQ(state_machine_.NextAction(), SchedulerStateMachine::ACTION_NONE);
+}
+
+
void Scheduler::PollForAnticipatedDrawTriggers() {
TRACE_EVENT0("cc", "Scheduler::PollForAnticipatedDrawTriggers");
poll_for_draw_triggers_task_.Cancel();
@@ -679,6 +672,14 @@ void Scheduler::ProcessScheduledActions() {
client_->ScheduledActionAnimate();
break;
case SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME:
+
+ // FIXME:!!!!!!!
+ BeginFrameArgs args = GetBeginMainFrameArgs();
+ if (!args.IsValid())
+ continue;
+ current_main_frame_args_ = args;
+ // FIXME:!!!!!!!
+
client_->ScheduledActionSendBeginMainFrame();
break;
case SchedulerStateMachine::ACTION_COMMIT:
@@ -707,11 +708,9 @@ void Scheduler::ProcessScheduledActions() {
} while (action != SchedulerStateMachine::ACTION_NONE);
SetupNextBeginFrameIfNeeded();
- client_->DidAnticipatedDrawTimeChange(AnticipatedDrawTime());
-
if (state_machine_.ShouldTriggerBeginImplFrameDeadlineEarly()) {
DCHECK(!settings_.using_synchronous_renderer_compositor);
- ScheduleBeginImplFrameDeadline(base::TimeTicks());
+ OnBeginImplFrameDeadline();
}
}
@@ -750,8 +749,8 @@ void Scheduler::AsValueInto(base::debug::TracedValue* state) const {
estimated_parent_draw_time_.InMillisecondsF());
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_frame_process_posted_", begin_frame_process_posted_);
+ state->SetInteger("pending_begin_frame_args_", pending_begin_frame_args_.size());
state->SetBoolean("begin_impl_frame_deadline_task_",
!begin_impl_frame_deadline_task_.IsCancelled());
state->SetBoolean("poll_for_draw_triggers_task_",
@@ -776,25 +775,6 @@ void Scheduler::AsValueInto(base::debug::TracedValue* state) const {
state->EndDictionary();
}
-bool Scheduler::CanCommitAndActivateBeforeDeadline() const {
- // Check if the main thread computation and commit can be finished before the
- // impl thread's deadline.
- base::TimeTicks estimated_draw_time =
- begin_impl_frame_args_.frame_time +
- client_->BeginMainFrameToCommitDurationEstimate() +
- client_->CommitToActivateDurationEstimate();
-
- TRACE_EVENT2(
- TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler"),
- "CanCommitAndActivateBeforeDeadline",
- "time_left_after_drawing_ms",
- (begin_impl_frame_args_.deadline - estimated_draw_time).InMillisecondsF(),
- "state",
- AsValue());
-
- return estimated_draw_time < begin_impl_frame_args_.deadline;
-}
-
bool Scheduler::IsBeginMainFrameSentOrStarted() const {
return (state_machine_.commit_state() ==
SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT ||
« no previous file with comments | « no previous file | cc/scheduler/scheduler_state_machine.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698