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

Side by Side Diff: cc/scheduler/scheduler.cc

Issue 267783004: Refactoring the way begin frame sources inside scheduler work. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: I have a race condition in LayerTreeHostTestAbortedCommitDoesntStallDisabledVsync.RunMultiThread_De… Created 6 years, 3 months 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « cc/scheduler/scheduler.h ('k') | cc/scheduler/scheduler_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2011 The Chromium Authors. All rights reserved. 1 // Copyright 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "cc/scheduler/scheduler.h" 5 #include "cc/scheduler/scheduler.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include "base/auto_reset.h" 8 #include "base/auto_reset.h"
9 #include "base/debug/trace_event.h" 9 #include "base/debug/trace_event.h"
10 #include "base/debug/trace_event_argument.h" 10 #include "base/debug/trace_event_argument.h"
11 #include "base/logging.h" 11 #include "base/logging.h"
12 #include "base/single_thread_task_runner.h" 12 #include "base/single_thread_task_runner.h"
13 #include "cc/debug/devtools_instrumentation.h" 13 #include "cc/debug/devtools_instrumentation.h"
14 #include "cc/debug/traced_value.h" 14 #include "cc/debug/traced_value.h"
15 #include "cc/scheduler/delay_based_time_source.h" 15 #include "cc/scheduler/delay_based_time_source.h"
16 #include "ui/gfx/frame_time.h" 16 #include "ui/gfx/frame_time.h"
17 17
18 namespace cc { 18 namespace cc {
19 19
20 Scheduler::SyntheticBeginFrameSource::SyntheticBeginFrameSource(
21 Scheduler* scheduler,
22 scoped_refptr<DelayBasedTimeSource> time_source)
23 : scheduler_(scheduler), time_source_(time_source) {
24 time_source_->SetClient(this);
25 }
26
27 Scheduler::SyntheticBeginFrameSource::~SyntheticBeginFrameSource() {
28 }
29
30 void Scheduler::SyntheticBeginFrameSource::CommitVSyncParameters(
31 base::TimeTicks timebase,
32 base::TimeDelta interval) {
33 time_source_->SetTimebaseAndInterval(timebase, interval);
34 }
35
36 void Scheduler::SyntheticBeginFrameSource::SetNeedsBeginFrame(
37 bool needs_begin_frame,
38 std::deque<BeginFrameArgs>* begin_retro_frame_args) {
39 DCHECK(begin_retro_frame_args);
40 base::TimeTicks missed_tick_time =
41 time_source_->SetActive(needs_begin_frame);
42 if (!missed_tick_time.is_null()) {
43 begin_retro_frame_args->push_back(
44 CreateSyntheticBeginFrameArgs(missed_tick_time));
45 }
46 }
47
48 bool Scheduler::SyntheticBeginFrameSource::IsActive() const {
49 return time_source_->Active();
50 }
51
52 void Scheduler::SyntheticBeginFrameSource::OnTimerTick() {
53 BeginFrameArgs begin_frame_args(
54 CreateSyntheticBeginFrameArgs(time_source_->LastTickTime()));
55 scheduler_->BeginFrame(begin_frame_args);
56 }
57
58 void Scheduler::SyntheticBeginFrameSource::AsValueInto(
59 base::debug::TracedValue* state) const {
60 time_source_->AsValueInto(state);
61 }
62
63 BeginFrameArgs
64 Scheduler::SyntheticBeginFrameSource::CreateSyntheticBeginFrameArgs(
65 base::TimeTicks frame_time) {
66 base::TimeTicks deadline = time_source_->NextTickTime();
67 return BeginFrameArgs::Create(
68 frame_time, deadline, scheduler_->VSyncInterval());
69 }
70
71 Scheduler::Scheduler( 20 Scheduler::Scheduler(
72 SchedulerClient* client, 21 SchedulerClient* client,
73 const SchedulerSettings& scheduler_settings, 22 const SchedulerSettings& scheduler_settings,
74 int layer_tree_host_id, 23 int layer_tree_host_id,
75 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) 24 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner)
76 : settings_(scheduler_settings), 25 : settings_(scheduler_settings),
77 client_(client), 26 client_(client),
78 layer_tree_host_id_(layer_tree_host_id), 27 layer_tree_host_id_(layer_tree_host_id),
79 task_runner_(task_runner), 28 task_runner_(task_runner),
80 vsync_interval_(BeginFrameArgs::DefaultInterval()),
81 last_set_needs_begin_frame_(false),
82 begin_unthrottled_frame_posted_(false),
83 begin_retro_frame_posted_(false), 29 begin_retro_frame_posted_(false),
84 state_machine_(scheduler_settings), 30 state_machine_(scheduler_settings),
85 inside_process_scheduled_actions_(false), 31 inside_process_scheduled_actions_(false),
86 inside_action_(SchedulerStateMachine::ACTION_NONE), 32 inside_action_(SchedulerStateMachine::ACTION_NONE),
87 weak_factory_(this) { 33 weak_factory_(this) {
88 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler"), 34 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler"),
89 "Scheduler::Scheduler", 35 "Scheduler::Scheduler",
90 "settings", 36 "settings",
91 settings_.AsValue()); 37 settings_.AsValue());
92 DCHECK(client_); 38 DCHECK(client_);
93 DCHECK(!state_machine_.BeginFrameNeeded()); 39 DCHECK(!state_machine_.BeginFrameNeeded());
94 if (settings_.main_frame_before_activation_enabled) { 40 if (settings_.main_frame_before_activation_enabled) {
95 DCHECK(settings_.main_frame_before_draw_enabled); 41 DCHECK(settings_.main_frame_before_draw_enabled);
96 } 42 }
97 43
98 begin_retro_frame_closure_ = 44 begin_retro_frame_closure_ =
99 base::Bind(&Scheduler::BeginRetroFrame, weak_factory_.GetWeakPtr()); 45 base::Bind(&Scheduler::BeginRetroFrame, weak_factory_.GetWeakPtr());
100 begin_unthrottled_frame_closure_ =
101 base::Bind(&Scheduler::BeginUnthrottledFrame, weak_factory_.GetWeakPtr());
102 begin_impl_frame_deadline_closure_ = base::Bind( 46 begin_impl_frame_deadline_closure_ = base::Bind(
103 &Scheduler::OnBeginImplFrameDeadline, weak_factory_.GetWeakPtr()); 47 &Scheduler::OnBeginImplFrameDeadline, weak_factory_.GetWeakPtr());
104 poll_for_draw_triggers_closure_ = base::Bind( 48 poll_for_draw_triggers_closure_ = base::Bind(
105 &Scheduler::PollForAnticipatedDrawTriggers, weak_factory_.GetWeakPtr()); 49 &Scheduler::PollForAnticipatedDrawTriggers, weak_factory_.GetWeakPtr());
106 advance_commit_state_closure_ = base::Bind( 50 advance_commit_state_closure_ = base::Bind(
107 &Scheduler::PollToAdvanceCommitState, weak_factory_.GetWeakPtr()); 51 &Scheduler::PollToAdvanceCommitState, weak_factory_.GetWeakPtr());
52 }
108 53
109 if (!settings_.begin_frame_scheduling_enabled) { 54 BeginFrameSource* Scheduler::GetPrimaryBeginFrameSource() {
110 SetupSyntheticBeginFrames(); 55 if (!settings_.throttle_frame_production) {
56 TRACE_EVENT1("cc",
57 "Scheduler::Scheduler()",
58 "PrimaryFrameSource",
59 "BackToBackBeginFrameSource");
60 primary_frame_source_internal_ =
61 BackToBackBeginFrameSource::Create(task_runner_.get());
62 return primary_frame_source_internal_.get();
63 } else if (settings_.begin_frame_scheduling_enabled) {
64 TRACE_EVENT1("cc",
65 "Scheduler::Scheduler()",
66 "PrimaryFrameSource",
67 "SchedulerClient");
68 return client_->GetExternalBeginFrameSource();
69 } else {
70 TRACE_EVENT1("cc",
71 "Scheduler::Scheduler()",
72 "PrimaryFrameSource",
73 "SyntheticBeginFrameSource");
74 scoped_ptr<SyntheticBeginFrameSource> synthetic_source =
75 SyntheticBeginFrameSource::Create(
76 task_runner_.get(), Now(), BeginFrameArgs::DefaultInterval());
77 vsync_observer_ = synthetic_source.get();
78 primary_frame_source_internal_ = synthetic_source.Pass();
79 return primary_frame_source_internal_.get();
111 } 80 }
112 } 81 }
113 82
114 Scheduler::~Scheduler() { 83 BeginFrameSource* Scheduler::GetBackgroundBeginFrameSource() {
115 if (synthetic_begin_frame_source_) { 84 TRACE_EVENT1("cc",
116 synthetic_begin_frame_source_->SetNeedsBeginFrame(false, 85 "Scheduler::Scheduler()",
117 &begin_retro_frame_args_); 86 "BackgroundFrameSource",
118 } 87 "SyntheticBeginFrameSource");
88 background_frame_source_internal_ = SyntheticBeginFrameSource::Create(
89 task_runner_.get(), Now(), base::TimeDelta::FromSeconds(1));
90 return background_frame_source_internal_.get();
119 } 91 }
120 92
121 void Scheduler::SetupSyntheticBeginFrames() { 93 void Scheduler::FinalizeSetup() {
122 scoped_refptr<DelayBasedTimeSource> time_source; 94 frame_source_ = BeginFrameSourceMultiplexer::Create();
123 if (gfx::FrameTime::TimestampsAreHighRes()) { 95 frame_source_->AddObserver(this);
124 time_source = DelayBasedTimeSourceHighRes::Create(VSyncInterval(), 96
125 task_runner_.get()); 97 // Primary frame source
126 } else { 98 primary_frame_source_ = GetPrimaryBeginFrameSource();
127 time_source = 99 frame_source_->AddSource(primary_frame_source_);
128 DelayBasedTimeSource::Create(VSyncInterval(), task_runner_.get()); 100
129 } 101 // Background ticking frame source
130 DCHECK(!synthetic_begin_frame_source_); 102 background_frame_source_ = GetBackgroundBeginFrameSource();
131 synthetic_begin_frame_source_.reset( 103 frame_source_->AddSource(background_frame_source_);
132 new SyntheticBeginFrameSource(this, time_source)); 104 }
105
106 Scheduler::~Scheduler() {
133 } 107 }
134 108
135 base::TimeTicks Scheduler::Now() const { 109 base::TimeTicks Scheduler::Now() const {
136 return gfx::FrameTime::Now(); 110 return gfx::FrameTime::Now();
137 } 111 }
138 112
139 void Scheduler::CommitVSyncParameters(base::TimeTicks timebase, 113 void Scheduler::CommitVSyncParameters(base::TimeTicks timebase,
140 base::TimeDelta interval) { 114 base::TimeDelta interval) {
141 // TODO(brianderson): We should not be receiving 0 intervals. 115 // TODO(brianderson): We should not be receiving 0 intervals.
142 if (interval == base::TimeDelta()) 116 if (interval == base::TimeDelta())
143 interval = BeginFrameArgs::DefaultInterval(); 117 interval = BeginFrameArgs::DefaultInterval();
144 vsync_interval_ = interval; 118
145 if (!settings_.begin_frame_scheduling_enabled) 119 if (vsync_observer_)
146 synthetic_begin_frame_source_->CommitVSyncParameters(timebase, interval); 120 vsync_observer_->OnUpdateVSyncParameters(timebase, interval);
147 } 121 }
148 122
149 void Scheduler::SetEstimatedParentDrawTime(base::TimeDelta draw_time) { 123 void Scheduler::SetEstimatedParentDrawTime(base::TimeDelta draw_time) {
150 DCHECK_GE(draw_time.ToInternalValue(), 0); 124 DCHECK_GE(draw_time.ToInternalValue(), 0);
151 estimated_parent_draw_time_ = draw_time; 125 estimated_parent_draw_time_ = draw_time;
152 } 126 }
153 127
154 void Scheduler::SetCanStart() { 128 void Scheduler::SetCanStart() {
155 state_machine_.SetCanStart(); 129 state_machine_.SetCanStart();
156 ProcessScheduledActions(); 130 ProcessScheduledActions();
157 } 131 }
158 132
159 void Scheduler::SetVisible(bool visible) { 133 void Scheduler::SetVisible(bool visible) {
160 state_machine_.SetVisible(visible); 134 state_machine_.SetVisible(visible);
135 if (visible) {
136 frame_source_->SetActiveSource(primary_frame_source_);
137 } else {
138 frame_source_->SetActiveSource(background_frame_source_);
139 }
161 ProcessScheduledActions(); 140 ProcessScheduledActions();
162 } 141 }
163 142
164 void Scheduler::SetCanDraw(bool can_draw) { 143 void Scheduler::SetCanDraw(bool can_draw) {
165 state_machine_.SetCanDraw(can_draw); 144 state_machine_.SetCanDraw(can_draw);
166 ProcessScheduledActions(); 145 ProcessScheduledActions();
167 } 146 }
168 147
169 void Scheduler::NotifyReadyToActivate() { 148 void Scheduler::NotifyReadyToActivate() {
170 state_machine_.NotifyReadyToActivate(); 149 state_machine_.NotifyReadyToActivate();
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
233 ProcessScheduledActions(); 212 ProcessScheduledActions();
234 } 213 }
235 214
236 void Scheduler::DidManageTiles() { 215 void Scheduler::DidManageTiles() {
237 state_machine_.DidManageTiles(); 216 state_machine_.DidManageTiles();
238 } 217 }
239 218
240 void Scheduler::DidLoseOutputSurface() { 219 void Scheduler::DidLoseOutputSurface() {
241 TRACE_EVENT0("cc", "Scheduler::DidLoseOutputSurface"); 220 TRACE_EVENT0("cc", "Scheduler::DidLoseOutputSurface");
242 state_machine_.DidLoseOutputSurface(); 221 state_machine_.DidLoseOutputSurface();
243 last_set_needs_begin_frame_ = false; 222 if (frame_source_->NeedsBeginFrames())
244 if (!settings_.begin_frame_scheduling_enabled) { 223 frame_source_->SetNeedsBeginFrames(false);
245 synthetic_begin_frame_source_->SetNeedsBeginFrame(false,
246 &begin_retro_frame_args_);
247 }
248 begin_retro_frame_args_.clear(); 224 begin_retro_frame_args_.clear();
249 ProcessScheduledActions(); 225 ProcessScheduledActions();
250 } 226 }
251 227
252 void Scheduler::DidCreateAndInitializeOutputSurface() { 228 void Scheduler::DidCreateAndInitializeOutputSurface() {
253 TRACE_EVENT0("cc", "Scheduler::DidCreateAndInitializeOutputSurface"); 229 TRACE_EVENT0("cc", "Scheduler::DidCreateAndInitializeOutputSurface");
254 DCHECK(!last_set_needs_begin_frame_); 230 DCHECK(!frame_source_->NeedsBeginFrames());
255 DCHECK(begin_impl_frame_deadline_task_.IsCancelled()); 231 DCHECK(begin_impl_frame_deadline_task_.IsCancelled());
256 state_machine_.DidCreateAndInitializeOutputSurface(); 232 state_machine_.DidCreateAndInitializeOutputSurface();
257 ProcessScheduledActions(); 233 ProcessScheduledActions();
258 } 234 }
259 235
260 void Scheduler::NotifyBeginMainFrameStarted() { 236 void Scheduler::NotifyBeginMainFrameStarted() {
261 TRACE_EVENT0("cc", "Scheduler::NotifyBeginMainFrameStarted"); 237 TRACE_EVENT0("cc", "Scheduler::NotifyBeginMainFrameStarted");
262 state_machine_.NotifyBeginMainFrameStarted(); 238 state_machine_.NotifyBeginMainFrameStarted();
263 } 239 }
264 240
265 base::TimeTicks Scheduler::AnticipatedDrawTime() const { 241 base::TimeTicks Scheduler::AnticipatedDrawTime() const {
266 if (!last_set_needs_begin_frame_ || 242 if (!frame_source_->NeedsBeginFrames() ||
267 begin_impl_frame_args_.interval <= base::TimeDelta()) 243 begin_impl_frame_args_.interval <= base::TimeDelta())
268 return base::TimeTicks(); 244 return base::TimeTicks();
269 245
270 base::TimeTicks now = Now(); 246 base::TimeTicks now = Now();
271 base::TimeTicks timebase = std::max(begin_impl_frame_args_.frame_time, 247 base::TimeTicks timebase = std::max(begin_impl_frame_args_.frame_time,
272 begin_impl_frame_args_.deadline); 248 begin_impl_frame_args_.deadline);
273 int64 intervals = 1 + ((now - timebase) / begin_impl_frame_args_.interval); 249 int64 intervals = 1 + ((now - timebase) / begin_impl_frame_args_.interval);
274 return timebase + (begin_impl_frame_args_.interval * intervals); 250 return timebase + (begin_impl_frame_args_.interval * intervals);
275 } 251 }
276 252
253 const BeginFrameArgs& Scheduler::LastBeginFrameArgs() const {
254 return last_begin_frame_args_;
255 }
256
277 base::TimeTicks Scheduler::LastBeginImplFrameTime() { 257 base::TimeTicks Scheduler::LastBeginImplFrameTime() {
278 return begin_impl_frame_args_.frame_time; 258 return begin_impl_frame_args_.frame_time;
279 } 259 }
280 260
281 void Scheduler::SetupNextBeginFrameIfNeeded() { 261 void Scheduler::SetupNextBeginFrameIfNeeded() {
282 if (!task_runner_.get()) 262 if (!task_runner_.get())
283 return; 263 return;
284 264
285 bool needs_begin_frame = state_machine_.BeginFrameNeeded(); 265 bool needs_begin_frame = state_machine_.BeginFrameNeeded();
286 266
287 if (settings_.throttle_frame_production) { 267 bool at_end_of_deadline =
288 SetupNextBeginFrameWhenVSyncThrottlingEnabled(needs_begin_frame); 268 (state_machine_.begin_impl_frame_state() ==
289 } else { 269 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE);
290 SetupNextBeginFrameWhenVSyncThrottlingDisabled(needs_begin_frame); 270
271 bool should_call_set_needs_begin_frame =
272 // Always request the BeginFrame immediately if it wasn't needed before.
273 (needs_begin_frame && !frame_source_->NeedsBeginFrames()) ||
274 // Only stop requesting BeginFrames after a deadline.
275 (!needs_begin_frame && frame_source_->NeedsBeginFrames() &&
276 at_end_of_deadline);
277
278 if (should_call_set_needs_begin_frame) {
279 frame_source_->SetNeedsBeginFrames(needs_begin_frame);
291 } 280 }
281
282 bool at_state_idle = (state_machine_.begin_impl_frame_state() !=
283 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE);
284 if (at_end_of_deadline || at_state_idle) {
285 frame_source_->DidFinishFrame(begin_retro_frame_args_.size());
286 }
287
288 PostBeginRetroFrameIfNeeded();
292 SetupPollingMechanisms(needs_begin_frame); 289 SetupPollingMechanisms(needs_begin_frame);
293 } 290 }
294 291
295 // When we are throttling frame production, we request BeginFrames
296 // from the OutputSurface.
297 void Scheduler::SetupNextBeginFrameWhenVSyncThrottlingEnabled(
298 bool needs_begin_frame) {
299 bool at_end_of_deadline =
300 state_machine_.begin_impl_frame_state() ==
301 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE;
302
303 bool should_call_set_needs_begin_frame =
304 // Always request the BeginFrame immediately if it wasn't needed before.
305 (needs_begin_frame && !last_set_needs_begin_frame_) ||
306 // Only stop requesting BeginFrames after a deadline.
307 (!needs_begin_frame && last_set_needs_begin_frame_ && at_end_of_deadline);
308
309 if (should_call_set_needs_begin_frame) {
310 if (settings_.begin_frame_scheduling_enabled) {
311 client_->SetNeedsBeginFrame(needs_begin_frame);
312 } else {
313 synthetic_begin_frame_source_->SetNeedsBeginFrame(
314 needs_begin_frame, &begin_retro_frame_args_);
315 }
316 last_set_needs_begin_frame_ = needs_begin_frame;
317 }
318
319 PostBeginRetroFrameIfNeeded();
320 }
321
322 // When we aren't throttling frame production, we initiate a BeginFrame
323 // as soon as one is needed.
324 void Scheduler::SetupNextBeginFrameWhenVSyncThrottlingDisabled(
325 bool needs_begin_frame) {
326 last_set_needs_begin_frame_ = needs_begin_frame;
327
328 if (!needs_begin_frame || begin_unthrottled_frame_posted_)
329 return;
330
331 if (state_machine_.begin_impl_frame_state() !=
332 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE &&
333 state_machine_.begin_impl_frame_state() !=
334 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE) {
335 return;
336 }
337
338 begin_unthrottled_frame_posted_ = true;
339 task_runner_->PostTask(FROM_HERE, begin_unthrottled_frame_closure_);
340 }
341
342 // BeginUnthrottledFrame is used when we aren't throttling frame production.
343 // This will usually be because VSync is disabled.
344 void Scheduler::BeginUnthrottledFrame() {
345 DCHECK(!settings_.throttle_frame_production);
346 DCHECK(begin_retro_frame_args_.empty());
347
348 base::TimeTicks now = Now();
349 base::TimeTicks deadline = now + vsync_interval_;
350
351 BeginFrameArgs begin_frame_args =
352 BeginFrameArgs::Create(now, deadline, vsync_interval_);
353 BeginImplFrame(begin_frame_args);
354
355 begin_unthrottled_frame_posted_ = false;
356 }
357
358 // We may need to poll when we can't rely on BeginFrame to advance certain 292 // We may need to poll when we can't rely on BeginFrame to advance certain
359 // state or to avoid deadlock. 293 // state or to avoid deadlock.
360 void Scheduler::SetupPollingMechanisms(bool needs_begin_frame) { 294 void Scheduler::SetupPollingMechanisms(bool needs_begin_frame) {
361 bool needs_advance_commit_state_timer = false; 295 bool needs_advance_commit_state_timer = false;
362 // Setup PollForAnticipatedDrawTriggers if we need to monitor state but 296 // Setup PollForAnticipatedDrawTriggers if we need to monitor state but
363 // aren't expecting any more BeginFrames. This should only be needed by 297 // aren't expecting any more BeginFrames. This should only be needed by
364 // the synchronous compositor when BeginFrameNeeded is false. 298 // the synchronous compositor when BeginFrameNeeded is false.
365 if (state_machine_.ShouldPollForAnticipatedDrawTriggers()) { 299 if (state_machine_.ShouldPollForAnticipatedDrawTriggers()) {
366 DCHECK(!state_machine_.SupportsProactiveBeginFrame()); 300 DCHECK(!state_machine_.SupportsProactiveBeginFrame());
367 DCHECK(!needs_begin_frame); 301 DCHECK(!needs_begin_frame);
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
401 } 335 }
402 } else { 336 } else {
403 advance_commit_state_task_.Cancel(); 337 advance_commit_state_task_.Cancel();
404 } 338 }
405 } 339 }
406 340
407 // BeginFrame is the mechanism that tells us that now is a good time to start 341 // BeginFrame is the mechanism that tells us that now is a good time to start
408 // making a frame. Usually this means that user input for the frame is complete. 342 // making a frame. Usually this means that user input for the frame is complete.
409 // If the scheduler is busy, we queue the BeginFrame to be handled later as 343 // If the scheduler is busy, we queue the BeginFrame to be handled later as
410 // a BeginRetroFrame. 344 // a BeginRetroFrame.
411 void Scheduler::BeginFrame(const BeginFrameArgs& args) { 345 void Scheduler::OnBeginFrame(const BeginFrameArgs& args) {
412 TRACE_EVENT1("cc", "Scheduler::BeginFrame", "args", args.AsValue()); 346 TRACE_EVENT1("cc", "Scheduler::BeginFrame", "args", args.AsValue());
413 DCHECK(settings_.throttle_frame_production);
414 347
415 BeginFrameArgs adjusted_args(args); 348 BeginFrameArgs adjusted_args(args);
416 adjusted_args.deadline -= EstimatedParentDrawTime(); 349 adjusted_args.deadline -= EstimatedParentDrawTime();
417 350
418 bool should_defer_begin_frame; 351 bool should_defer_begin_frame;
419 if (settings_.using_synchronous_renderer_compositor) { 352 if (settings_.using_synchronous_renderer_compositor) {
420 should_defer_begin_frame = false; 353 should_defer_begin_frame = false;
421 } else { 354 } else {
422 should_defer_begin_frame = 355 should_defer_begin_frame =
423 !begin_retro_frame_args_.empty() || begin_retro_frame_posted_ || 356 !begin_retro_frame_args_.empty() || begin_retro_frame_posted_ ||
424 !last_set_needs_begin_frame_ || 357 !frame_source_->NeedsBeginFrames() ||
425 (state_machine_.begin_impl_frame_state() != 358 (state_machine_.begin_impl_frame_state() !=
426 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE); 359 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE);
427 } 360 }
428 361
429 if (should_defer_begin_frame) { 362 if (should_defer_begin_frame) {
430 begin_retro_frame_args_.push_back(adjusted_args); 363 begin_retro_frame_args_.push_back(adjusted_args);
431 TRACE_EVENT_INSTANT0( 364 TRACE_EVENT_INSTANT0(
432 "cc", "Scheduler::BeginFrame deferred", TRACE_EVENT_SCOPE_THREAD); 365 "cc", "Scheduler::BeginFrame deferred", TRACE_EVENT_SCOPE_THREAD);
433 return; 366 return;
434 } 367 }
(...skipping 19 matching lines...) Expand all
454 // because deadlines will not be greater than the next frame time. We don't 387 // because deadlines will not be greater than the next frame time. We don't
455 // DCHECK though because some systems don't always have monotonic timestamps. 388 // DCHECK though because some systems don't always have monotonic timestamps.
456 // TODO(brianderson): In the future, long deadlines could result in us not 389 // TODO(brianderson): In the future, long deadlines could result in us not
457 // draining the queue if we don't catch up. If we consistently can't catch 390 // draining the queue if we don't catch up. If we consistently can't catch
458 // up, our fallback should be to lower our frame rate. 391 // up, our fallback should be to lower our frame rate.
459 base::TimeTicks now = Now(); 392 base::TimeTicks now = Now();
460 base::TimeDelta draw_duration_estimate = client_->DrawDurationEstimate(); 393 base::TimeDelta draw_duration_estimate = client_->DrawDurationEstimate();
461 while (!begin_retro_frame_args_.empty() && 394 while (!begin_retro_frame_args_.empty() &&
462 now > AdjustedBeginImplFrameDeadline(begin_retro_frame_args_.front(), 395 now > AdjustedBeginImplFrameDeadline(begin_retro_frame_args_.front(),
463 draw_duration_estimate)) { 396 draw_duration_estimate)) {
464 TRACE_EVENT1("cc", 397 TRACE_EVENT2("cc",
465 "Scheduler::BeginRetroFrame discarding", 398 "Scheduler::BeginRetroFrame discarding",
399 "now",
400 Now(),
brianderson 2014/09/18 00:27:24 Now() -> now ?
mithro-old 2014/09/18 13:33:37 Done. Move this bit into https://codereview.chrom
466 "frame_time", 401 "frame_time",
467 begin_retro_frame_args_.front().frame_time); 402 begin_retro_frame_args_.front().frame_time);
brianderson 2014/09/18 00:27:24 begin_retro_frame_args_.front().AsValue()?
mithro-old 2014/09/18 13:33:37 Done. Move this bit into https://codereview.chrom
468 begin_retro_frame_args_.pop_front(); 403 begin_retro_frame_args_.pop_front();
404 frame_source_->DidFinishFrame(begin_retro_frame_args_.size());
469 } 405 }
470 406
471 if (begin_retro_frame_args_.empty()) { 407 if (begin_retro_frame_args_.empty()) {
472 DCHECK(settings_.throttle_frame_production);
473 TRACE_EVENT_INSTANT0("cc", 408 TRACE_EVENT_INSTANT0("cc",
474 "Scheduler::BeginRetroFrames all expired", 409 "Scheduler::BeginRetroFrames all expired",
475 TRACE_EVENT_SCOPE_THREAD); 410 TRACE_EVENT_SCOPE_THREAD);
476 } else { 411 } else {
477 BeginImplFrame(begin_retro_frame_args_.front()); 412 BeginImplFrame(begin_retro_frame_args_.front());
478 begin_retro_frame_args_.pop_front(); 413 begin_retro_frame_args_.pop_front();
479 } 414 }
480 } 415 }
481 416
482 // There could be a race between the posted BeginRetroFrame and a new 417 // There could be a race between the posted BeginRetroFrame and a new
483 // BeginFrame arriving via the normal mechanism. Scheduler::BeginFrame 418 // BeginFrame arriving via the normal mechanism. Scheduler::BeginFrame
484 // will check if there is a pending BeginRetroFrame to ensure we handle 419 // will check if there is a pending BeginRetroFrame to ensure we handle
485 // BeginFrames in FIFO order. 420 // BeginFrames in FIFO order.
486 void Scheduler::PostBeginRetroFrameIfNeeded() { 421 void Scheduler::PostBeginRetroFrameIfNeeded() {
487 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler"), 422 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler"),
488 "Scheduler::PostBeginRetroFrameIfNeeded", 423 "Scheduler::PostBeginRetroFrameIfNeeded",
489 "state", 424 "state",
490 AsValue()); 425 AsValue());
491 if (!last_set_needs_begin_frame_) 426 if (!frame_source_->NeedsBeginFrames())
492 return; 427 return;
493 428
494 if (begin_retro_frame_args_.empty() || begin_retro_frame_posted_) 429 if (begin_retro_frame_args_.empty() || begin_retro_frame_posted_)
495 return; 430 return;
496 431
497 // begin_retro_frame_args_ should always be empty for the 432 // begin_retro_frame_args_ should always be empty for the
498 // synchronous compositor. 433 // synchronous compositor.
499 DCHECK(!settings_.using_synchronous_renderer_compositor); 434 DCHECK(!settings_.using_synchronous_renderer_compositor);
500 435
501 if (state_machine_.begin_impl_frame_state() != 436 if (state_machine_.begin_impl_frame_state() !=
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after
691 } 626 }
692 627
693 bool Scheduler::WillDrawIfNeeded() const { 628 bool Scheduler::WillDrawIfNeeded() const {
694 return !state_machine_.PendingDrawsShouldBeAborted(); 629 return !state_machine_.PendingDrawsShouldBeAborted();
695 } 630 }
696 631
697 scoped_refptr<base::debug::ConvertableToTraceFormat> Scheduler::AsValue() 632 scoped_refptr<base::debug::ConvertableToTraceFormat> Scheduler::AsValue()
698 const { 633 const {
699 scoped_refptr<base::debug::TracedValue> state = 634 scoped_refptr<base::debug::TracedValue> state =
700 new base::debug::TracedValue(); 635 new base::debug::TracedValue();
636 AsValueInto(state.get());
637 return state;
638 }
639
640 void Scheduler::AsValueInto(base::debug::TracedValue* state) const {
701 state->BeginDictionary("state_machine"); 641 state->BeginDictionary("state_machine");
702 state_machine_.AsValueInto(state.get()); 642 state_machine_.AsValueInto(state);
703 state->EndDictionary(); 643 state->EndDictionary();
704 if (synthetic_begin_frame_source_) { 644
705 state->BeginDictionary("synthetic_begin_frame_source_"); 645 state->BeginDictionary("frame_source_");
706 synthetic_begin_frame_source_->AsValueInto(state.get()); 646 frame_source_->AsValueInto(state);
707 state->EndDictionary(); 647 state->EndDictionary();
708 }
709 648
710 state->BeginDictionary("scheduler_state"); 649 state->BeginDictionary("scheduler_state");
711 state->SetDouble("time_until_anticipated_draw_time_ms", 650 state->SetDouble("time_until_anticipated_draw_time_ms",
712 (AnticipatedDrawTime() - Now()).InMillisecondsF()); 651 (AnticipatedDrawTime() - Now()).InMillisecondsF());
713 state->SetDouble("vsync_interval_ms", vsync_interval_.InMillisecondsF());
714 state->SetDouble("estimated_parent_draw_time_ms", 652 state->SetDouble("estimated_parent_draw_time_ms",
715 estimated_parent_draw_time_.InMillisecondsF()); 653 estimated_parent_draw_time_.InMillisecondsF());
716 state->SetBoolean("last_set_needs_begin_frame_", last_set_needs_begin_frame_); 654 state->SetBoolean("last_set_needs_begin_frame_",
717 state->SetBoolean("begin_unthrottled_frame_posted_", 655 frame_source_->NeedsBeginFrames());
718 begin_unthrottled_frame_posted_);
719 state->SetBoolean("begin_retro_frame_posted_", begin_retro_frame_posted_); 656 state->SetBoolean("begin_retro_frame_posted_", begin_retro_frame_posted_);
720 state->SetInteger("begin_retro_frame_args_", begin_retro_frame_args_.size()); 657 state->SetInteger("begin_retro_frame_args_", begin_retro_frame_args_.size());
721 state->SetBoolean("begin_impl_frame_deadline_task_", 658 state->SetBoolean("begin_impl_frame_deadline_task_",
722 !begin_impl_frame_deadline_task_.IsCancelled()); 659 !begin_impl_frame_deadline_task_.IsCancelled());
723 state->SetBoolean("poll_for_draw_triggers_task_", 660 state->SetBoolean("poll_for_draw_triggers_task_",
724 !poll_for_draw_triggers_task_.IsCancelled()); 661 !poll_for_draw_triggers_task_.IsCancelled());
725 state->SetBoolean("advance_commit_state_task_", 662 state->SetBoolean("advance_commit_state_task_",
726 !advance_commit_state_task_.IsCancelled()); 663 !advance_commit_state_task_.IsCancelled());
727 state->BeginDictionary("begin_impl_frame_args"); 664 state->BeginDictionary("begin_impl_frame_args");
728 begin_impl_frame_args_.AsValueInto(state.get()); 665 begin_impl_frame_args_.AsValueInto(state);
729 state->EndDictionary(); 666 state->EndDictionary();
730 667
731 state->EndDictionary(); 668 state->EndDictionary();
732 669
733 state->BeginDictionary("client_state"); 670 state->BeginDictionary("client_state");
734 state->SetDouble("draw_duration_estimate_ms", 671 state->SetDouble("draw_duration_estimate_ms",
735 client_->DrawDurationEstimate().InMillisecondsF()); 672 client_->DrawDurationEstimate().InMillisecondsF());
736 state->SetDouble( 673 state->SetDouble(
737 "begin_main_frame_to_commit_duration_estimate_ms", 674 "begin_main_frame_to_commit_duration_estimate_ms",
738 client_->BeginMainFrameToCommitDurationEstimate().InMillisecondsF()); 675 client_->BeginMainFrameToCommitDurationEstimate().InMillisecondsF());
739 state->SetDouble( 676 state->SetDouble(
740 "commit_to_activate_duration_estimate_ms", 677 "commit_to_activate_duration_estimate_ms",
741 client_->CommitToActivateDurationEstimate().InMillisecondsF()); 678 client_->CommitToActivateDurationEstimate().InMillisecondsF());
742 state->EndDictionary(); 679 state->EndDictionary();
743 return state;
744 } 680 }
745 681
746 bool Scheduler::CanCommitAndActivateBeforeDeadline() const { 682 bool Scheduler::CanCommitAndActivateBeforeDeadline() const {
747 // Check if the main thread computation and commit can be finished before the 683 // Check if the main thread computation and commit can be finished before the
748 // impl thread's deadline. 684 // impl thread's deadline.
749 base::TimeTicks estimated_draw_time = 685 base::TimeTicks estimated_draw_time =
750 begin_impl_frame_args_.frame_time + 686 begin_impl_frame_args_.frame_time +
751 client_->BeginMainFrameToCommitDurationEstimate() + 687 client_->BeginMainFrameToCommitDurationEstimate() +
752 client_->CommitToActivateDurationEstimate(); 688 client_->CommitToActivateDurationEstimate();
753 689
754 TRACE_EVENT2( 690 TRACE_EVENT2(
755 TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler"), 691 TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler"),
756 "CanCommitAndActivateBeforeDeadline", 692 "CanCommitAndActivateBeforeDeadline",
757 "time_left_after_drawing_ms", 693 "time_left_after_drawing_ms",
758 (begin_impl_frame_args_.deadline - estimated_draw_time).InMillisecondsF(), 694 (begin_impl_frame_args_.deadline - estimated_draw_time).InMillisecondsF(),
759 "state", 695 "state",
760 AsValue()); 696 AsValue());
761 697
762 return estimated_draw_time < begin_impl_frame_args_.deadline; 698 return estimated_draw_time < begin_impl_frame_args_.deadline;
763 } 699 }
764 700
765 bool Scheduler::IsBeginMainFrameSentOrStarted() const { 701 bool Scheduler::IsBeginMainFrameSentOrStarted() const {
766 return (state_machine_.commit_state() == 702 return (state_machine_.commit_state() ==
767 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT || 703 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT ||
768 state_machine_.commit_state() == 704 state_machine_.commit_state() ==
769 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED); 705 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED);
770 } 706 }
771 707
772 } // namespace cc 708 } // namespace cc
OLDNEW
« no previous file with comments | « cc/scheduler/scheduler.h ('k') | cc/scheduler/scheduler_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698