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

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

Issue 23796002: cc: Implement deadine scheduling disabled by default (Closed) Base URL: http://git.chromium.org/chromium/src.git@schedReadback4
Patch Set: disable by default everywhere Created 7 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
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 "base/auto_reset.h" 8 #include "base/auto_reset.h"
8 #include "base/debug/trace_event.h" 9 #include "base/debug/trace_event.h"
9 #include "base/logging.h" 10 #include "base/logging.h"
10 #include "cc/debug/traced_value.h" 11 #include "cc/debug/traced_value.h"
11 12
12 namespace cc { 13 namespace cc {
13 14
14 Scheduler::Scheduler(SchedulerClient* client, 15 Scheduler::Scheduler(SchedulerClient* client,
15 const SchedulerSettings& scheduler_settings) 16 const SchedulerSettings& scheduler_settings)
16 : settings_(scheduler_settings), 17 : settings_(scheduler_settings),
17 client_(client), 18 client_(client),
18 weak_factory_(this), 19 weak_factory_(this),
19 last_set_needs_begin_frame_(false), 20 last_set_needs_begin_frame_(false),
20 state_machine_(scheduler_settings), 21 state_machine_(scheduler_settings),
21 inside_process_scheduled_actions_(false), 22 inside_process_scheduled_actions_(false),
22 inside_action_(SchedulerStateMachine::ACTION_NONE) { 23 inside_action_(SchedulerStateMachine::ACTION_NONE) {
23 DCHECK(client_); 24 DCHECK(client_);
24 DCHECK(!state_machine_.BeginFrameNeededToDrawByImplThread()); 25 DCHECK(!state_machine_.BeginFrameNeededByImplThread());
25 } 26 }
26 27
27 Scheduler::~Scheduler() { 28 Scheduler::~Scheduler() {}
28 client_->SetNeedsBeginFrameOnImplThread(false);
29 }
30 29
31 void Scheduler::SetCanStart() { 30 void Scheduler::SetCanStart() {
32 state_machine_.SetCanStart(); 31 state_machine_.SetCanStart();
33 ProcessScheduledActions(); 32 ProcessScheduledActions();
34 } 33 }
35 34
36 void Scheduler::SetVisible(bool visible) { 35 void Scheduler::SetVisible(bool visible) {
37 state_machine_.SetVisible(visible); 36 state_machine_.SetVisible(visible);
38 ProcessScheduledActions(); 37 ProcessScheduledActions();
39 } 38 }
40 39
41 void Scheduler::SetCanDraw(bool can_draw) { 40 void Scheduler::SetCanDraw(bool can_draw) {
42 state_machine_.SetCanDraw(can_draw); 41 state_machine_.SetCanDraw(can_draw);
43 ProcessScheduledActions(); 42 ProcessScheduledActions();
44 } 43 }
45 44
46 void Scheduler::NotifyReadyToActivate() { 45 void Scheduler::NotifyReadyToActivate() {
47 state_machine_.NotifyReadyToActivate(); 46 state_machine_.NotifyReadyToActivate();
48 ProcessScheduledActions(); 47 ProcessScheduledActions();
49 } 48 }
50 49
50 void Scheduler::ActivatePendingTree() {
51 client_->ScheduledActionActivatePendingTree();
52 if (state_machine_.ShouldTriggerBeginFrameDeadlineEarly())
53 PostBeginFrameDeadline(base::TimeTicks());
54 }
55
51 void Scheduler::SetNeedsCommit() { 56 void Scheduler::SetNeedsCommit() {
52 state_machine_.SetNeedsCommit(); 57 state_machine_.SetNeedsCommit();
53 ProcessScheduledActions(); 58 ProcessScheduledActions();
54 } 59 }
55 60
56 void Scheduler::SetNeedsForcedCommitForReadback() { 61 void Scheduler::SetNeedsForcedCommitForReadback() {
57 state_machine_.SetNeedsCommit(); 62 state_machine_.SetNeedsCommit();
58 state_machine_.SetNeedsForcedCommitForReadback(); 63 state_machine_.SetNeedsForcedCommitForReadback();
59 ProcessScheduledActions(); 64 ProcessScheduledActions();
60 } 65 }
(...skipping 16 matching lines...) Expand all
77 82
78 void Scheduler::SetMainThreadNeedsLayerTextures() { 83 void Scheduler::SetMainThreadNeedsLayerTextures() {
79 state_machine_.SetMainThreadNeedsLayerTextures(); 84 state_machine_.SetMainThreadNeedsLayerTextures();
80 ProcessScheduledActions(); 85 ProcessScheduledActions();
81 } 86 }
82 87
83 void Scheduler::FinishCommit() { 88 void Scheduler::FinishCommit() {
84 TRACE_EVENT0("cc", "Scheduler::FinishCommit"); 89 TRACE_EVENT0("cc", "Scheduler::FinishCommit");
85 state_machine_.FinishCommit(); 90 state_machine_.FinishCommit();
86 ProcessScheduledActions(); 91 ProcessScheduledActions();
92
93 if (state_machine_.ShouldTriggerBeginFrameDeadlineEarly())
94 PostBeginFrameDeadline(base::TimeTicks());
87 } 95 }
88 96
89 void Scheduler::BeginFrameAbortedByMainThread(bool did_handle) { 97 void Scheduler::BeginFrameAbortedByMainThread(bool did_handle) {
90 TRACE_EVENT0("cc", "Scheduler::BeginFrameAbortedByMainThread"); 98 TRACE_EVENT0("cc", "Scheduler::BeginFrameAbortedByMainThread");
91 state_machine_.BeginFrameAbortedByMainThread(did_handle); 99 state_machine_.BeginFrameAbortedByMainThread(did_handle);
92 ProcessScheduledActions(); 100 ProcessScheduledActions();
93 } 101 }
94 102
95 void Scheduler::DidLoseOutputSurface() { 103 void Scheduler::DidLoseOutputSurface() {
96 TRACE_EVENT0("cc", "Scheduler::DidLoseOutputSurface"); 104 TRACE_EVENT0("cc", "Scheduler::DidLoseOutputSurface");
105 last_set_needs_begin_frame_ = false;
106 begin_frame_deadline_closure_.Cancel();
97 state_machine_.DidLoseOutputSurface(); 107 state_machine_.DidLoseOutputSurface();
98 ProcessScheduledActions(); 108 ProcessScheduledActions();
99 } 109 }
100 110
101 void Scheduler::DidCreateAndInitializeOutputSurface() { 111 void Scheduler::DidCreateAndInitializeOutputSurface() {
102 TRACE_EVENT0("cc", "Scheduler::DidCreateAndInitializeOutputSurface"); 112 TRACE_EVENT0("cc", "Scheduler::DidCreateAndInitializeOutputSurface");
113 DCHECK(!last_set_needs_begin_frame_);
114 DCHECK(begin_frame_deadline_closure_.IsCancelled());
103 state_machine_.DidCreateAndInitializeOutputSurface(); 115 state_machine_.DidCreateAndInitializeOutputSurface();
104 last_set_needs_begin_frame_ = false;
105 ProcessScheduledActions(); 116 ProcessScheduledActions();
106 } 117 }
107 118
108 base::TimeTicks Scheduler::AnticipatedDrawTime() { 119 base::TimeTicks Scheduler::AnticipatedDrawTime() {
109 TRACE_EVENT0("cc", "Scheduler::AnticipatedDrawTime"); 120 TRACE_EVENT0("cc", "Scheduler::AnticipatedDrawTime");
110 121
111 if (!last_set_needs_begin_frame_ || 122 if (!last_set_needs_begin_frame_ ||
112 last_begin_frame_args_.interval <= base::TimeDelta()) 123 last_begin_frame_args_.interval <= base::TimeDelta())
113 return base::TimeTicks(); 124 return base::TimeTicks();
114 125
115 // TODO(brianderson): Express this in terms of the deadline.
116 base::TimeTicks now = base::TimeTicks::Now(); 126 base::TimeTicks now = base::TimeTicks::Now();
117 int64 intervals = 1 + ((now - last_begin_frame_args_.frame_time) / 127 base::TimeTicks timebase = std::max(last_begin_frame_args_.frame_time,
118 last_begin_frame_args_.interval); 128 last_begin_frame_args_.deadline);
119 return last_begin_frame_args_.frame_time + 129 int64 intervals = 1 + ((now - timebase) / last_begin_frame_args_.interval);
120 (last_begin_frame_args_.interval * intervals); 130 return timebase + (last_begin_frame_args_.interval * intervals);
121 } 131 }
122 132
123 base::TimeTicks Scheduler::LastBeginFrameOnImplThreadTime() { 133 base::TimeTicks Scheduler::LastBeginFrameOnImplThreadTime() {
124 return last_begin_frame_args_.frame_time; 134 return last_begin_frame_args_.frame_time;
125 } 135 }
126 136
127 void Scheduler::SetupNextBeginFrameIfNeeded() { 137 void Scheduler::SetupNextBeginFrameIfNeeded() {
128 bool needs_begin_frame_to_draw = 138 bool needs_begin_frame =
129 state_machine_.BeginFrameNeededToDrawByImplThread(); 139 state_machine_.BeginFrameNeededByImplThread();
130 // We want to avoid proactive begin frames with the synchronous compositor
131 // because every SetNeedsBeginFrame will force a redraw.
132 bool proactive_begin_frame_wanted =
133 state_machine_.ProactiveBeginFrameWantedByImplThread() &&
134 !settings_.using_synchronous_renderer_compositor &&
135 settings_.throttle_frame_production;
136 bool needs_begin_frame = needs_begin_frame_to_draw ||
137 proactive_begin_frame_wanted;
138 140
139 bool should_call_set_needs_begin_frame = 141 bool should_call_set_needs_begin_frame =
140 // Always request the BeginFrame immediately if it wasn't needed before. 142 // Always request the BeginFrame immediately if it wasn't needed before.
141 (needs_begin_frame && !last_set_needs_begin_frame_) || 143 (needs_begin_frame && !last_set_needs_begin_frame_) ||
142 // We always need to explicitly request our next BeginFrame. 144 // We always need to explicitly request our next BeginFrame.
143 state_machine_.inside_begin_frame(); 145 (state_machine_.begin_frame_state() ==
danakj 2013/09/17 20:26:19 bool at_end_of_deadline = "this thing" might help
brianderson 2013/09/17 21:08:24 Good suggestion. Done.
146 SchedulerStateMachine::BEGIN_FRAME_STATE_INSIDE_DEADLINE);
144 147
145 if (should_call_set_needs_begin_frame) { 148 if (should_call_set_needs_begin_frame) {
146 client_->SetNeedsBeginFrameOnImplThread(needs_begin_frame); 149 client_->SetNeedsBeginFrameOnImplThread(needs_begin_frame);
147 last_set_needs_begin_frame_ = needs_begin_frame; 150 last_set_needs_begin_frame_ = needs_begin_frame;
148 } 151 }
149 152
150 // Setup PollForAnticipatedDrawTriggers for cases where we want a proactive 153 // Setup PollForAnticipatedDrawTriggers for cases where we want a proactive
151 // BeginFrame but aren't requesting one. 154 // BeginFrame but aren't requesting one.
152 if (!needs_begin_frame && 155 if (!last_set_needs_begin_frame_ &&
153 state_machine_.ProactiveBeginFrameWantedByImplThread()) { 156 state_machine_.ShouldPollForAnticipatedDrawTriggers()) {
154 if (poll_for_draw_triggers_closure_.IsCancelled()) { 157 if (poll_for_draw_triggers_closure_.IsCancelled()) {
danakj 2013/09/17 20:26:19 As discussed, DCHECK(!needs_begin_frame) with a co
brianderson 2013/09/17 21:08:24 Done.
155 poll_for_draw_triggers_closure_.Reset( 158 poll_for_draw_triggers_closure_.Reset(
156 base::Bind(&Scheduler::PollForAnticipatedDrawTriggers, 159 base::Bind(&Scheduler::PollForAnticipatedDrawTriggers,
157 weak_factory_.GetWeakPtr())); 160 weak_factory_.GetWeakPtr()));
158 base::MessageLoop::current()->PostDelayedTask( 161 base::MessageLoop::current()->PostDelayedTask(
159 FROM_HERE, 162 FROM_HERE,
160 poll_for_draw_triggers_closure_.callback(), 163 poll_for_draw_triggers_closure_.callback(),
161 last_begin_frame_args_.interval); 164 last_begin_frame_args_.interval);
162 } 165 }
163 } else { 166 } else {
164 poll_for_draw_triggers_closure_.Cancel(); 167 poll_for_draw_triggers_closure_.Cancel();
165 } 168 }
166 } 169 }
167 170
168 void Scheduler::BeginFrame(const BeginFrameArgs& args) { 171 void Scheduler::BeginFrame(const BeginFrameArgs& args) {
169 TRACE_EVENT0("cc", "Scheduler::BeginFrame"); 172 TRACE_EVENT0("cc", "Scheduler::BeginFrame");
170 DCHECK(!state_machine_.inside_begin_frame());
danakj 2013/09/17 20:26:19 Can we dcheck against the begin_frame_state() inst
brianderson 2013/09/17 21:08:24 I moved DCHECKS to OnBeginFrame, OnBeginFrameDeadl
171 last_begin_frame_args_ = args; 173 last_begin_frame_args_ = args;
172 state_machine_.DidEnterBeginFrame(args); 174 last_begin_frame_args_.deadline -= client_->DrawDurationEstimate();
175 state_machine_.OnBeginFrame(last_begin_frame_args_);
173 ProcessScheduledActions(); 176 ProcessScheduledActions();
174 state_machine_.DidLeaveBeginFrame(); 177 state_machine_.OnBeginFrameDeadlinePending();
178
179 if (settings_.using_synchronous_renderer_compositor) {
180 // The synchronous renderer compositor has to make its GL calls
181 // within this call to BeginFrame.
182 // TODO(brianderson): Have the OutputSurface initiate the deadline tasks
183 // so the sychronous renderer compoistor can take advantage of splitting
184 // up the BeginFrame and deadline as well.
185 OnBeginFrameDeadline();
186 } else if (!settings_.deadline_scheduling_enabled) {
187 // We emulate the old non-deadline scheduler here by posting the
188 // deadline task without any delay.
189 PostBeginFrameDeadline(base::TimeTicks());
190 } else if (state_machine_.ShouldTriggerBeginFrameDeadlineEarly()) {
191 // We are ready to draw a new active tree immediately.
192 PostBeginFrameDeadline(base::TimeTicks());
193 } else if (state_machine_.needs_redraw()) {
194 // We have an animation or fast input path on the impl thread that wants
195 // to draw, so don't wait too long for a new active tree.
196 PostBeginFrameDeadline(last_begin_frame_args_.deadline);
197 } else {
198 // The impl thread doesn't have anything it wants to draw and we are just
199 // waiting for a new active tree, so post the deadline for the next
200 // expected BeginFrame start. This allows us to draw immediately when
201 // there is a new active tree, instead of waiting for the next BeginFrame.
202 // TODO(brianderson): Handle long deadlines (that are past the next frame's
203 // frame time) properly instead of using this hack.
204 PostBeginFrameDeadline(last_begin_frame_args_.frame_time +
205 last_begin_frame_args_.interval);
206 }
207 }
208
209 void Scheduler::PostBeginFrameDeadline(base::TimeTicks deadline) {
210 begin_frame_deadline_closure_.Cancel();
211 begin_frame_deadline_closure_.Reset(
212 base::Bind(&Scheduler::OnBeginFrameDeadline, weak_factory_.GetWeakPtr()));
213 client_->PostBeginFrameDeadline(begin_frame_deadline_closure_.callback(),
214 deadline);
215 }
216
217 void Scheduler::OnBeginFrameDeadline() {
218 TRACE_EVENT0("cc", "Scheduler::OnBeginFrameDeadline");
219 begin_frame_deadline_closure_.Cancel();
220 state_machine_.OnBeginFrameDeadline();
221 ProcessScheduledActions();
222 // We only transition out of BEGIN_FRAME_STATE_INSIDE_DEADLINE when all
223 // actions that occur back-to-back in response to entering
224 // BEGIN_FRAME_STATE_INSIDE_DEADLINE have completed. This is important
225 // because sending the BeginFrame to the main thread will not occur if
226 // we transition to BEGIN_FRAME_STATE_IDLE too early.
227 state_machine_.OnBeginFrameIdle();
228 client_->DidBeginFrameDeadlineOnImplThread();
175 } 229 }
176 230
177 void Scheduler::PollForAnticipatedDrawTriggers() { 231 void Scheduler::PollForAnticipatedDrawTriggers() {
178 TRACE_EVENT0("cc", "Scheduler::PollForAnticipatedDrawTriggers"); 232 TRACE_EVENT0("cc", "Scheduler::PollForAnticipatedDrawTriggers");
179 state_machine_.DidEnterPollForAnticipatedDrawTriggers(); 233 state_machine_.DidEnterPollForAnticipatedDrawTriggers();
180 ProcessScheduledActions(); 234 ProcessScheduledActions();
181 state_machine_.DidLeavePollForAnticipatedDrawTriggers(); 235 state_machine_.DidLeavePollForAnticipatedDrawTriggers();
182 } 236 }
183 237
184 void Scheduler::DrawAndSwapIfPossible() { 238 void Scheduler::DrawAndSwapIfPossible() {
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
221 case SchedulerStateMachine::ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD: 275 case SchedulerStateMachine::ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD:
222 client_->ScheduledActionSendBeginFrameToMainThread(); 276 client_->ScheduledActionSendBeginFrameToMainThread();
223 break; 277 break;
224 case SchedulerStateMachine::ACTION_COMMIT: 278 case SchedulerStateMachine::ACTION_COMMIT:
225 client_->ScheduledActionCommit(); 279 client_->ScheduledActionCommit();
226 break; 280 break;
227 case SchedulerStateMachine::ACTION_UPDATE_VISIBLE_TILES: 281 case SchedulerStateMachine::ACTION_UPDATE_VISIBLE_TILES:
228 client_->ScheduledActionUpdateVisibleTiles(); 282 client_->ScheduledActionUpdateVisibleTiles();
229 break; 283 break;
230 case SchedulerStateMachine::ACTION_ACTIVATE_PENDING_TREE: 284 case SchedulerStateMachine::ACTION_ACTIVATE_PENDING_TREE:
231 client_->ScheduledActionActivatePendingTree(); 285 ActivatePendingTree();
232 break; 286 break;
233 case SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE: 287 case SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE:
234 DrawAndSwapIfPossible(); 288 DrawAndSwapIfPossible();
235 break; 289 break;
236 case SchedulerStateMachine::ACTION_DRAW_AND_SWAP_FORCED: 290 case SchedulerStateMachine::ACTION_DRAW_AND_SWAP_FORCED:
237 DrawAndSwapForced(); 291 DrawAndSwapForced();
238 break; 292 break;
239 case SchedulerStateMachine::ACTION_DRAW_AND_SWAP_ABORT: 293 case SchedulerStateMachine::ACTION_DRAW_AND_SWAP_ABORT:
240 // No action is actually performed, but this allows the state machine to 294 // No action is actually performed, but this allows the state machine to
241 // advance out of its waiting to draw state without actually drawing. 295 // advance out of its waiting to draw state without actually drawing.
(...skipping 15 matching lines...) Expand all
257 311
258 SetupNextBeginFrameIfNeeded(); 312 SetupNextBeginFrameIfNeeded();
259 client_->DidAnticipatedDrawTimeChange(AnticipatedDrawTime()); 313 client_->DidAnticipatedDrawTimeChange(AnticipatedDrawTime());
260 } 314 }
261 315
262 bool Scheduler::WillDrawIfNeeded() const { 316 bool Scheduler::WillDrawIfNeeded() const {
263 return !state_machine_.PendingDrawsShouldBeAborted(); 317 return !state_machine_.PendingDrawsShouldBeAborted();
264 } 318 }
265 319
266 } // namespace cc 320 } // namespace cc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698