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

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: Very minor fixes. Created 6 years, 2 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
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( 20 BeginFrameSource* SchedulerFrameSourcesConstructor::ConstructPrimaryFrameSource(
21 Scheduler* scheduler, 21 Scheduler* scheduler) {
22 scoped_refptr<DelayBasedTimeSource> time_source) 22 if (!scheduler->settings_.throttle_frame_production) {
23 : scheduler_(scheduler), time_source_(time_source) { 23 TRACE_EVENT1("cc",
24 time_source_->SetClient(this); 24 "Scheduler::Scheduler()",
25 } 25 "PrimaryFrameSource",
26 "BackToBackBeginFrameSource");
27 DCHECK(!scheduler->primary_frame_source_internal_);
28 scheduler->primary_frame_source_internal_ =
29 BackToBackBeginFrameSource::Create(scheduler->task_runner_.get());
30 return scheduler->primary_frame_source_internal_.get();
31 } else if (scheduler->settings_.begin_frame_scheduling_enabled) {
32 TRACE_EVENT1("cc",
33 "Scheduler::Scheduler()",
34 "PrimaryFrameSource",
35 "SchedulerClient");
36 return scheduler->client_->ExternalBeginFrameSource();
37 } else {
38 TRACE_EVENT1("cc",
39 "Scheduler::Scheduler()",
40 "PrimaryFrameSource",
41 "SyntheticBeginFrameSource");
42 scoped_ptr<SyntheticBeginFrameSource> synthetic_source =
43 SyntheticBeginFrameSource::Create(scheduler->task_runner_.get(),
44 scheduler->Now(),
45 BeginFrameArgs::DefaultInterval());
26 46
27 Scheduler::SyntheticBeginFrameSource::~SyntheticBeginFrameSource() { 47 DCHECK(!scheduler->vsync_observer_);
28 } 48 scheduler->vsync_observer_ = synthetic_source.get();
29 49
30 void Scheduler::SyntheticBeginFrameSource::CommitVSyncParameters( 50 DCHECK(!scheduler->primary_frame_source_internal_);
31 base::TimeTicks timebase, 51 scheduler->primary_frame_source_internal_ = synthetic_source.Pass();
32 base::TimeDelta interval) { 52 return scheduler->primary_frame_source_internal_.get();
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 } 53 }
46 } 54 }
47 55
48 bool Scheduler::SyntheticBeginFrameSource::IsActive() const { 56 BeginFrameSource*
49 return time_source_->Active(); 57 SchedulerFrameSourcesConstructor::ConstructBackgroundFrameSource(
50 } 58 Scheduler* scheduler) {
51 59 TRACE_EVENT1("cc",
52 void Scheduler::SyntheticBeginFrameSource::OnTimerTick() { 60 "Scheduler::Scheduler()",
53 BeginFrameArgs begin_frame_args( 61 "BackgroundFrameSource",
54 CreateSyntheticBeginFrameArgs(time_source_->LastTickTime())); 62 "SyntheticBeginFrameSource");
55 scheduler_->BeginFrame(begin_frame_args); 63 DCHECK(!(scheduler->background_frame_source_internal_));
56 } 64 scheduler->background_frame_source_internal_ =
57 65 SyntheticBeginFrameSource::Create(scheduler->task_runner_.get(),
58 void Scheduler::SyntheticBeginFrameSource::AsValueInto( 66 scheduler->Now(),
59 base::debug::TracedValue* state) const { 67 base::TimeDelta::FromSeconds(1));
60 time_source_->AsValueInto(state); 68 return scheduler->background_frame_source_internal_.get();
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 } 69 }
70 70
71 Scheduler::Scheduler( 71 Scheduler::Scheduler(
72 SchedulerClient* client, 72 SchedulerClient* client,
73 const SchedulerSettings& scheduler_settings, 73 const SchedulerSettings& scheduler_settings,
74 int layer_tree_host_id, 74 int layer_tree_host_id,
75 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) 75 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
76 : settings_(scheduler_settings), 76 SchedulerFrameSourcesConstructor* frame_sources_constructor)
77 : frame_source_(),
78 primary_frame_source_(NULL),
79 background_frame_source_(NULL),
80 primary_frame_source_internal_(),
81 background_frame_source_internal_(),
82 vsync_observer_(NULL),
83 settings_(scheduler_settings),
77 client_(client), 84 client_(client),
78 layer_tree_host_id_(layer_tree_host_id), 85 layer_tree_host_id_(layer_tree_host_id),
79 task_runner_(task_runner), 86 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), 87 begin_retro_frame_posted_(false),
84 state_machine_(scheduler_settings), 88 state_machine_(scheduler_settings),
85 inside_process_scheduled_actions_(false), 89 inside_process_scheduled_actions_(false),
86 inside_action_(SchedulerStateMachine::ACTION_NONE), 90 inside_action_(SchedulerStateMachine::ACTION_NONE),
87 weak_factory_(this) { 91 weak_factory_(this) {
88 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler"), 92 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler"),
89 "Scheduler::Scheduler", 93 "Scheduler::Scheduler",
90 "settings", 94 "settings",
91 settings_.AsValue()); 95 settings_.AsValue());
92 DCHECK(client_); 96 DCHECK(client_);
93 DCHECK(!state_machine_.BeginFrameNeeded()); 97 DCHECK(!state_machine_.BeginFrameNeeded());
94 98
95 begin_retro_frame_closure_ = 99 begin_retro_frame_closure_ =
96 base::Bind(&Scheduler::BeginRetroFrame, weak_factory_.GetWeakPtr()); 100 base::Bind(&Scheduler::BeginRetroFrame, weak_factory_.GetWeakPtr());
97 begin_unthrottled_frame_closure_ =
98 base::Bind(&Scheduler::BeginUnthrottledFrame, weak_factory_.GetWeakPtr());
99 begin_impl_frame_deadline_closure_ = base::Bind( 101 begin_impl_frame_deadline_closure_ = base::Bind(
100 &Scheduler::OnBeginImplFrameDeadline, weak_factory_.GetWeakPtr()); 102 &Scheduler::OnBeginImplFrameDeadline, weak_factory_.GetWeakPtr());
101 poll_for_draw_triggers_closure_ = base::Bind( 103 poll_for_draw_triggers_closure_ = base::Bind(
102 &Scheduler::PollForAnticipatedDrawTriggers, weak_factory_.GetWeakPtr()); 104 &Scheduler::PollForAnticipatedDrawTriggers, weak_factory_.GetWeakPtr());
103 advance_commit_state_closure_ = base::Bind( 105 advance_commit_state_closure_ = base::Bind(
104 &Scheduler::PollToAdvanceCommitState, weak_factory_.GetWeakPtr()); 106 &Scheduler::PollToAdvanceCommitState, weak_factory_.GetWeakPtr());
105 107
106 if (!settings_.begin_frame_scheduling_enabled) { 108 frame_source_ = BeginFrameSourceMultiplexer::Create();
107 SetupSyntheticBeginFrames(); 109 frame_source_->AddObserver(this);
108 } 110
111 // Primary frame source
112 primary_frame_source_ =
113 frame_sources_constructor->ConstructPrimaryFrameSource(this);
114 frame_source_->AddSource(primary_frame_source_);
115
116 // Background ticking frame source
117 background_frame_source_ =
118 frame_sources_constructor->ConstructBackgroundFrameSource(this);
119 frame_source_->AddSource(background_frame_source_);
109 } 120 }
110 121
111 Scheduler::~Scheduler() { 122 Scheduler::~Scheduler() {
112 if (synthetic_begin_frame_source_) {
113 synthetic_begin_frame_source_->SetNeedsBeginFrame(false,
114 &begin_retro_frame_args_);
115 }
116 }
117
118 void Scheduler::SetupSyntheticBeginFrames() {
119 scoped_refptr<DelayBasedTimeSource> time_source;
120 if (gfx::FrameTime::TimestampsAreHighRes()) {
121 time_source = DelayBasedTimeSourceHighRes::Create(VSyncInterval(),
122 task_runner_.get());
123 } else {
124 time_source =
125 DelayBasedTimeSource::Create(VSyncInterval(), task_runner_.get());
126 }
127 DCHECK(!synthetic_begin_frame_source_);
128 synthetic_begin_frame_source_.reset(
129 new SyntheticBeginFrameSource(this, time_source));
130 } 123 }
131 124
132 base::TimeTicks Scheduler::Now() const { 125 base::TimeTicks Scheduler::Now() const {
133 return gfx::FrameTime::Now(); 126 base::TimeTicks now = gfx::FrameTime::Now();
127 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler.now"),
128 "Scheduler::Now",
129 "now",
130 now);
131 return now;
134 } 132 }
135 133
136 void Scheduler::CommitVSyncParameters(base::TimeTicks timebase, 134 void Scheduler::CommitVSyncParameters(base::TimeTicks timebase,
137 base::TimeDelta interval) { 135 base::TimeDelta interval) {
138 // TODO(brianderson): We should not be receiving 0 intervals. 136 // TODO(brianderson): We should not be receiving 0 intervals.
139 if (interval == base::TimeDelta()) 137 if (interval == base::TimeDelta())
140 interval = BeginFrameArgs::DefaultInterval(); 138 interval = BeginFrameArgs::DefaultInterval();
141 vsync_interval_ = interval; 139
142 if (!settings_.begin_frame_scheduling_enabled) 140 if (vsync_observer_)
143 synthetic_begin_frame_source_->CommitVSyncParameters(timebase, interval); 141 vsync_observer_->OnUpdateVSyncParameters(timebase, interval);
144 } 142 }
145 143
146 void Scheduler::SetEstimatedParentDrawTime(base::TimeDelta draw_time) { 144 void Scheduler::SetEstimatedParentDrawTime(base::TimeDelta draw_time) {
147 DCHECK_GE(draw_time.ToInternalValue(), 0); 145 DCHECK_GE(draw_time.ToInternalValue(), 0);
148 estimated_parent_draw_time_ = draw_time; 146 estimated_parent_draw_time_ = draw_time;
149 } 147 }
150 148
151 void Scheduler::SetCanStart() { 149 void Scheduler::SetCanStart() {
152 state_machine_.SetCanStart(); 150 state_machine_.SetCanStart();
153 ProcessScheduledActions(); 151 ProcessScheduledActions();
154 } 152 }
155 153
156 void Scheduler::SetVisible(bool visible) { 154 void Scheduler::SetVisible(bool visible) {
157 state_machine_.SetVisible(visible); 155 state_machine_.SetVisible(visible);
156 if (visible) {
157 frame_source_->SetActiveSource(primary_frame_source_);
158 } else {
159 frame_source_->SetActiveSource(background_frame_source_);
160 }
158 ProcessScheduledActions(); 161 ProcessScheduledActions();
159 } 162 }
160 163
161 void Scheduler::SetCanDraw(bool can_draw) { 164 void Scheduler::SetCanDraw(bool can_draw) {
162 state_machine_.SetCanDraw(can_draw); 165 state_machine_.SetCanDraw(can_draw);
163 ProcessScheduledActions(); 166 ProcessScheduledActions();
164 } 167 }
165 168
166 void Scheduler::NotifyReadyToActivate() { 169 void Scheduler::NotifyReadyToActivate() {
167 state_machine_.NotifyReadyToActivate(); 170 state_machine_.NotifyReadyToActivate();
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
230 ProcessScheduledActions(); 233 ProcessScheduledActions();
231 } 234 }
232 235
233 void Scheduler::DidManageTiles() { 236 void Scheduler::DidManageTiles() {
234 state_machine_.DidManageTiles(); 237 state_machine_.DidManageTiles();
235 } 238 }
236 239
237 void Scheduler::DidLoseOutputSurface() { 240 void Scheduler::DidLoseOutputSurface() {
238 TRACE_EVENT0("cc", "Scheduler::DidLoseOutputSurface"); 241 TRACE_EVENT0("cc", "Scheduler::DidLoseOutputSurface");
239 state_machine_.DidLoseOutputSurface(); 242 state_machine_.DidLoseOutputSurface();
240 last_set_needs_begin_frame_ = false; 243 if (frame_source_->NeedsBeginFrames())
241 if (!settings_.begin_frame_scheduling_enabled) { 244 frame_source_->SetNeedsBeginFrames(false);
242 synthetic_begin_frame_source_->SetNeedsBeginFrame(false,
243 &begin_retro_frame_args_);
244 }
245 begin_retro_frame_args_.clear(); 245 begin_retro_frame_args_.clear();
246 ProcessScheduledActions(); 246 ProcessScheduledActions();
247 } 247 }
248 248
249 void Scheduler::DidCreateAndInitializeOutputSurface() { 249 void Scheduler::DidCreateAndInitializeOutputSurface() {
250 TRACE_EVENT0("cc", "Scheduler::DidCreateAndInitializeOutputSurface"); 250 TRACE_EVENT0("cc", "Scheduler::DidCreateAndInitializeOutputSurface");
251 DCHECK(!last_set_needs_begin_frame_); 251 DCHECK(!frame_source_->NeedsBeginFrames());
252 DCHECK(begin_impl_frame_deadline_task_.IsCancelled()); 252 DCHECK(begin_impl_frame_deadline_task_.IsCancelled());
253 state_machine_.DidCreateAndInitializeOutputSurface(); 253 state_machine_.DidCreateAndInitializeOutputSurface();
254 ProcessScheduledActions(); 254 ProcessScheduledActions();
255 } 255 }
256 256
257 void Scheduler::NotifyBeginMainFrameStarted() { 257 void Scheduler::NotifyBeginMainFrameStarted() {
258 TRACE_EVENT0("cc", "Scheduler::NotifyBeginMainFrameStarted"); 258 TRACE_EVENT0("cc", "Scheduler::NotifyBeginMainFrameStarted");
259 state_machine_.NotifyBeginMainFrameStarted(); 259 state_machine_.NotifyBeginMainFrameStarted();
260 } 260 }
261 261
262 base::TimeTicks Scheduler::AnticipatedDrawTime() const { 262 base::TimeTicks Scheduler::AnticipatedDrawTime() const {
263 if (!last_set_needs_begin_frame_ || 263 if (!frame_source_->NeedsBeginFrames() ||
264 begin_impl_frame_args_.interval <= base::TimeDelta()) 264 begin_impl_frame_args_.interval <= base::TimeDelta())
265 return base::TimeTicks(); 265 return base::TimeTicks();
266 266
267 base::TimeTicks now = Now(); 267 base::TimeTicks now = Now();
268 base::TimeTicks timebase = std::max(begin_impl_frame_args_.frame_time, 268 base::TimeTicks timebase = std::max(begin_impl_frame_args_.frame_time,
269 begin_impl_frame_args_.deadline); 269 begin_impl_frame_args_.deadline);
270 int64 intervals = 1 + ((now - timebase) / begin_impl_frame_args_.interval); 270 int64 intervals = 1 + ((now - timebase) / begin_impl_frame_args_.interval);
271 return timebase + (begin_impl_frame_args_.interval * intervals); 271 return timebase + (begin_impl_frame_args_.interval * intervals);
272 } 272 }
273 273
274 base::TimeTicks Scheduler::LastBeginImplFrameTime() { 274 base::TimeTicks Scheduler::LastBeginImplFrameTime() {
275 return begin_impl_frame_args_.frame_time; 275 return begin_impl_frame_args_.frame_time;
276 } 276 }
277 277
278 void Scheduler::SetupNextBeginFrameIfNeeded() { 278 void Scheduler::SetupNextBeginFrameIfNeeded() {
279 if (!task_runner_.get()) 279 if (!task_runner_.get())
280 return; 280 return;
281 281
282 bool needs_begin_frame = state_machine_.BeginFrameNeeded(); 282 bool needs_begin_frame = state_machine_.BeginFrameNeeded();
283 283
284 if (settings_.throttle_frame_production) { 284 bool at_end_of_deadline =
285 SetupNextBeginFrameWhenVSyncThrottlingEnabled(needs_begin_frame); 285 (state_machine_.begin_impl_frame_state() ==
286 } else { 286 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE);
287 SetupNextBeginFrameWhenVSyncThrottlingDisabled(needs_begin_frame); 287
288 bool should_call_set_needs_begin_frame =
289 // Always request the BeginFrame immediately if it wasn't needed before.
290 (needs_begin_frame && !frame_source_->NeedsBeginFrames()) ||
291 // Only stop requesting BeginFrames after a deadline.
292 (!needs_begin_frame && frame_source_->NeedsBeginFrames() &&
293 at_end_of_deadline);
294
295 if (should_call_set_needs_begin_frame) {
296 frame_source_->SetNeedsBeginFrames(needs_begin_frame);
288 } 297 }
298
299 if (at_end_of_deadline) {
300 frame_source_->DidFinishFrame(begin_retro_frame_args_.size());
301 }
302
303 PostBeginRetroFrameIfNeeded();
289 SetupPollingMechanisms(needs_begin_frame); 304 SetupPollingMechanisms(needs_begin_frame);
290 } 305 }
291 306
292 // When we are throttling frame production, we request BeginFrames
293 // from the OutputSurface.
294 void Scheduler::SetupNextBeginFrameWhenVSyncThrottlingEnabled(
295 bool needs_begin_frame) {
296 bool at_end_of_deadline =
297 state_machine_.begin_impl_frame_state() ==
298 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE;
299
300 bool should_call_set_needs_begin_frame =
301 // Always request the BeginFrame immediately if it wasn't needed before.
302 (needs_begin_frame && !last_set_needs_begin_frame_) ||
303 // Only stop requesting BeginFrames after a deadline.
304 (!needs_begin_frame && last_set_needs_begin_frame_ && at_end_of_deadline);
305
306 if (should_call_set_needs_begin_frame) {
307 if (settings_.begin_frame_scheduling_enabled) {
308 client_->SetNeedsBeginFrame(needs_begin_frame);
309 } else {
310 synthetic_begin_frame_source_->SetNeedsBeginFrame(
311 needs_begin_frame, &begin_retro_frame_args_);
312 }
313 last_set_needs_begin_frame_ = needs_begin_frame;
314 }
315
316 PostBeginRetroFrameIfNeeded();
317 }
318
319 // When we aren't throttling frame production, we initiate a BeginFrame
320 // as soon as one is needed.
321 void Scheduler::SetupNextBeginFrameWhenVSyncThrottlingDisabled(
322 bool needs_begin_frame) {
323 last_set_needs_begin_frame_ = needs_begin_frame;
324
325 if (!needs_begin_frame || begin_unthrottled_frame_posted_)
326 return;
327
328 if (state_machine_.begin_impl_frame_state() !=
329 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE &&
330 state_machine_.begin_impl_frame_state() !=
331 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE) {
332 return;
333 }
334
335 begin_unthrottled_frame_posted_ = true;
336 task_runner_->PostTask(FROM_HERE, begin_unthrottled_frame_closure_);
337 }
338
339 // BeginUnthrottledFrame is used when we aren't throttling frame production.
340 // This will usually be because VSync is disabled.
341 void Scheduler::BeginUnthrottledFrame() {
342 DCHECK(!settings_.throttle_frame_production);
343 DCHECK(begin_retro_frame_args_.empty());
344
345 base::TimeTicks now = Now();
346 base::TimeTicks deadline = now + vsync_interval_;
347
348 BeginFrameArgs begin_frame_args =
349 BeginFrameArgs::Create(now, deadline, vsync_interval_);
350 BeginImplFrame(begin_frame_args);
351
352 begin_unthrottled_frame_posted_ = false;
353 }
354
355 // We may need to poll when we can't rely on BeginFrame to advance certain 307 // We may need to poll when we can't rely on BeginFrame to advance certain
356 // state or to avoid deadlock. 308 // state or to avoid deadlock.
357 void Scheduler::SetupPollingMechanisms(bool needs_begin_frame) { 309 void Scheduler::SetupPollingMechanisms(bool needs_begin_frame) {
358 bool needs_advance_commit_state_timer = false; 310 bool needs_advance_commit_state_timer = false;
359 // Setup PollForAnticipatedDrawTriggers if we need to monitor state but 311 // Setup PollForAnticipatedDrawTriggers if we need to monitor state but
360 // aren't expecting any more BeginFrames. This should only be needed by 312 // aren't expecting any more BeginFrames. This should only be needed by
361 // the synchronous compositor when BeginFrameNeeded is false. 313 // the synchronous compositor when BeginFrameNeeded is false.
362 if (state_machine_.ShouldPollForAnticipatedDrawTriggers()) { 314 if (state_machine_.ShouldPollForAnticipatedDrawTriggers()) {
363 DCHECK(!state_machine_.SupportsProactiveBeginFrame()); 315 DCHECK(!state_machine_.SupportsProactiveBeginFrame());
364 DCHECK(!needs_begin_frame); 316 DCHECK(!needs_begin_frame);
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
398 } 350 }
399 } else { 351 } else {
400 advance_commit_state_task_.Cancel(); 352 advance_commit_state_task_.Cancel();
401 } 353 }
402 } 354 }
403 355
404 // BeginFrame is the mechanism that tells us that now is a good time to start 356 // BeginFrame is the mechanism that tells us that now is a good time to start
405 // making a frame. Usually this means that user input for the frame is complete. 357 // making a frame. Usually this means that user input for the frame is complete.
406 // If the scheduler is busy, we queue the BeginFrame to be handled later as 358 // If the scheduler is busy, we queue the BeginFrame to be handled later as
407 // a BeginRetroFrame. 359 // a BeginRetroFrame.
408 void Scheduler::BeginFrame(const BeginFrameArgs& args) { 360 bool Scheduler::OnBeginFrameMixInDelegate(const BeginFrameArgs& args) {
409 TRACE_EVENT1("cc", "Scheduler::BeginFrame", "args", args.AsValue()); 361 TRACE_EVENT1("cc", "Scheduler::BeginFrame", "args", args.AsValue());
410 DCHECK(settings_.throttle_frame_production); 362
363 // We have just called SetNeedsBeginFrame(true) and the BeginFrameSource has
364 // sent us the last BeginFrame we have missed. As we might not be able to
365 // actually make rendering for this call, handle it like a "retro frame".
366 // TODO(brainderson): Add a test for this functionality ASAP!
367 if (args.type == BeginFrameArgs::MISSED) {
368 begin_retro_frame_args_.push_back(args);
369 PostBeginRetroFrameIfNeeded();
370 return true;
371 }
411 372
412 BeginFrameArgs adjusted_args(args); 373 BeginFrameArgs adjusted_args(args);
413 adjusted_args.deadline -= EstimatedParentDrawTime(); 374 adjusted_args.deadline -= EstimatedParentDrawTime();
414 375
415 bool should_defer_begin_frame; 376 bool should_defer_begin_frame;
416 if (settings_.using_synchronous_renderer_compositor) { 377 if (settings_.using_synchronous_renderer_compositor) {
417 should_defer_begin_frame = false; 378 should_defer_begin_frame = false;
418 } else { 379 } else {
419 should_defer_begin_frame = 380 should_defer_begin_frame =
420 !begin_retro_frame_args_.empty() || begin_retro_frame_posted_ || 381 !begin_retro_frame_args_.empty() || begin_retro_frame_posted_ ||
421 !last_set_needs_begin_frame_ || 382 !frame_source_->NeedsBeginFrames() ||
422 (state_machine_.begin_impl_frame_state() != 383 (state_machine_.begin_impl_frame_state() !=
423 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE); 384 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE);
424 } 385 }
425 386
426 if (should_defer_begin_frame) { 387 if (should_defer_begin_frame) {
427 begin_retro_frame_args_.push_back(adjusted_args); 388 begin_retro_frame_args_.push_back(adjusted_args);
428 TRACE_EVENT_INSTANT0( 389 TRACE_EVENT_INSTANT0(
429 "cc", "Scheduler::BeginFrame deferred", TRACE_EVENT_SCOPE_THREAD); 390 "cc", "Scheduler::BeginFrame deferred", TRACE_EVENT_SCOPE_THREAD);
430 return; 391 // Queuing the frame counts as "using it", so we need to return true.
392 } else {
393 BeginImplFrame(adjusted_args);
431 } 394 }
432 395 return true;
433 BeginImplFrame(adjusted_args);
434 } 396 }
435 397
436 // BeginRetroFrame is called for BeginFrames that we've deferred because 398 // BeginRetroFrame is called for BeginFrames that we've deferred because
437 // the scheduler was in the middle of processing a previous BeginFrame. 399 // the scheduler was in the middle of processing a previous BeginFrame.
438 void Scheduler::BeginRetroFrame() { 400 void Scheduler::BeginRetroFrame() {
439 TRACE_EVENT0("cc", "Scheduler::BeginRetroFrame"); 401 TRACE_EVENT0("cc", "Scheduler::BeginRetroFrame");
440 DCHECK(!settings_.using_synchronous_renderer_compositor); 402 DCHECK(!settings_.using_synchronous_renderer_compositor);
441 DCHECK(begin_retro_frame_posted_); 403 DCHECK(begin_retro_frame_posted_);
442 begin_retro_frame_posted_ = false; 404 begin_retro_frame_posted_ = false;
443 405
(...skipping 18 matching lines...) Expand all
462 break; 424 break;
463 425
464 TRACE_EVENT_INSTANT2("cc", 426 TRACE_EVENT_INSTANT2("cc",
465 "Scheduler::BeginRetroFrame discarding", 427 "Scheduler::BeginRetroFrame discarding",
466 TRACE_EVENT_SCOPE_THREAD, 428 TRACE_EVENT_SCOPE_THREAD,
467 "deadline - now", 429 "deadline - now",
468 (adjusted_deadline - now).InMicroseconds(), 430 (adjusted_deadline - now).InMicroseconds(),
469 "BeginFrameArgs", 431 "BeginFrameArgs",
470 begin_retro_frame_args_.front().AsValue()); 432 begin_retro_frame_args_.front().AsValue());
471 begin_retro_frame_args_.pop_front(); 433 begin_retro_frame_args_.pop_front();
434 frame_source_->DidFinishFrame(begin_retro_frame_args_.size());
472 } 435 }
473 436
474 if (begin_retro_frame_args_.empty()) { 437 if (begin_retro_frame_args_.empty()) {
475 DCHECK(settings_.throttle_frame_production);
476 TRACE_EVENT_INSTANT0("cc", 438 TRACE_EVENT_INSTANT0("cc",
477 "Scheduler::BeginRetroFrames all expired", 439 "Scheduler::BeginRetroFrames all expired",
478 TRACE_EVENT_SCOPE_THREAD); 440 TRACE_EVENT_SCOPE_THREAD);
479 } else { 441 } else {
480 BeginImplFrame(begin_retro_frame_args_.front()); 442 BeginImplFrame(begin_retro_frame_args_.front());
481 begin_retro_frame_args_.pop_front(); 443 begin_retro_frame_args_.pop_front();
482 } 444 }
483 } 445 }
484 446
485 // There could be a race between the posted BeginRetroFrame and a new 447 // There could be a race between the posted BeginRetroFrame and a new
486 // BeginFrame arriving via the normal mechanism. Scheduler::BeginFrame 448 // BeginFrame arriving via the normal mechanism. Scheduler::BeginFrame
487 // will check if there is a pending BeginRetroFrame to ensure we handle 449 // will check if there is a pending BeginRetroFrame to ensure we handle
488 // BeginFrames in FIFO order. 450 // BeginFrames in FIFO order.
489 void Scheduler::PostBeginRetroFrameIfNeeded() { 451 void Scheduler::PostBeginRetroFrameIfNeeded() {
490 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler"), 452 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler"),
491 "Scheduler::PostBeginRetroFrameIfNeeded", 453 "Scheduler::PostBeginRetroFrameIfNeeded",
492 "state", 454 "state",
493 AsValue()); 455 AsValue());
494 if (!last_set_needs_begin_frame_) 456 if (!frame_source_->NeedsBeginFrames())
495 return; 457 return;
496 458
497 if (begin_retro_frame_args_.empty() || begin_retro_frame_posted_) 459 if (begin_retro_frame_args_.empty() || begin_retro_frame_posted_)
498 return; 460 return;
499 461
500 // begin_retro_frame_args_ should always be empty for the 462 // begin_retro_frame_args_ should always be empty for the
501 // synchronous compositor. 463 // synchronous compositor.
502 DCHECK(!settings_.using_synchronous_renderer_compositor); 464 DCHECK(!settings_.using_synchronous_renderer_compositor);
503 465
504 if (state_machine_.begin_impl_frame_state() != 466 if (state_machine_.begin_impl_frame_state() !=
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after
712 scoped_refptr<base::debug::TracedValue> state = 674 scoped_refptr<base::debug::TracedValue> state =
713 new base::debug::TracedValue(); 675 new base::debug::TracedValue();
714 AsValueInto(state.get()); 676 AsValueInto(state.get());
715 return state; 677 return state;
716 } 678 }
717 679
718 void Scheduler::AsValueInto(base::debug::TracedValue* state) const { 680 void Scheduler::AsValueInto(base::debug::TracedValue* state) const {
719 state->BeginDictionary("state_machine"); 681 state->BeginDictionary("state_machine");
720 state_machine_.AsValueInto(state, Now()); 682 state_machine_.AsValueInto(state, Now());
721 state->EndDictionary(); 683 state->EndDictionary();
722 if (synthetic_begin_frame_source_) { 684
723 state->BeginDictionary("synthetic_begin_frame_source_"); 685 state->BeginDictionary("frame_source_");
724 synthetic_begin_frame_source_->AsValueInto(state); 686 frame_source_->AsValueInto(state);
725 state->EndDictionary(); 687 state->EndDictionary();
726 }
727 688
728 state->BeginDictionary("scheduler_state"); 689 state->BeginDictionary("scheduler_state");
729 state->SetDouble("time_until_anticipated_draw_time_ms", 690 state->SetDouble("time_until_anticipated_draw_time_ms",
730 (AnticipatedDrawTime() - Now()).InMillisecondsF()); 691 (AnticipatedDrawTime() - Now()).InMillisecondsF());
731 state->SetDouble("vsync_interval_ms", vsync_interval_.InMillisecondsF());
732 state->SetDouble("estimated_parent_draw_time_ms", 692 state->SetDouble("estimated_parent_draw_time_ms",
733 estimated_parent_draw_time_.InMillisecondsF()); 693 estimated_parent_draw_time_.InMillisecondsF());
734 state->SetBoolean("last_set_needs_begin_frame_", last_set_needs_begin_frame_); 694 state->SetBoolean("last_set_needs_begin_frame_",
735 state->SetBoolean("begin_unthrottled_frame_posted_", 695 frame_source_->NeedsBeginFrames());
736 begin_unthrottled_frame_posted_);
737 state->SetBoolean("begin_retro_frame_posted_", begin_retro_frame_posted_); 696 state->SetBoolean("begin_retro_frame_posted_", begin_retro_frame_posted_);
738 state->SetInteger("begin_retro_frame_args_", begin_retro_frame_args_.size()); 697 state->SetInteger("begin_retro_frame_args_", begin_retro_frame_args_.size());
739 state->SetBoolean("begin_impl_frame_deadline_task_", 698 state->SetBoolean("begin_impl_frame_deadline_task_",
740 !begin_impl_frame_deadline_task_.IsCancelled()); 699 !begin_impl_frame_deadline_task_.IsCancelled());
741 state->SetBoolean("poll_for_draw_triggers_task_", 700 state->SetBoolean("poll_for_draw_triggers_task_",
742 !poll_for_draw_triggers_task_.IsCancelled()); 701 !poll_for_draw_triggers_task_.IsCancelled());
743 state->SetBoolean("advance_commit_state_task_", 702 state->SetBoolean("advance_commit_state_task_",
744 !advance_commit_state_task_.IsCancelled()); 703 !advance_commit_state_task_.IsCancelled());
745 state->BeginDictionary("begin_impl_frame_args"); 704 state->BeginDictionary("begin_impl_frame_args");
746 begin_impl_frame_args_.AsValueInto(state); 705 begin_impl_frame_args_.AsValueInto(state);
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
780 } 739 }
781 740
782 bool Scheduler::IsBeginMainFrameSentOrStarted() const { 741 bool Scheduler::IsBeginMainFrameSentOrStarted() const {
783 return (state_machine_.commit_state() == 742 return (state_machine_.commit_state() ==
784 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT || 743 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT ||
785 state_machine_.commit_state() == 744 state_machine_.commit_state() ==
786 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED); 745 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED);
787 } 746 }
788 747
789 } // namespace cc 748 } // namespace cc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698