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

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: rebase? 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 has_pending_begin_frame_(false), 21 has_pending_begin_frame_(false),
21 safe_to_expect_begin_frame_(false), 22 safe_to_expect_begin_frame_(
23 !scheduler_settings.use_begin_frame_workaround_for_crbug_249806),
22 state_machine_(scheduler_settings), 24 state_machine_(scheduler_settings),
23 inside_process_scheduled_actions_(false) { 25 inside_process_scheduled_actions_(false) {
24 DCHECK(client_); 26 DCHECK(client_);
25 DCHECK(!state_machine_.BeginFrameNeededToDrawByImplThread()); 27 DCHECK(!state_machine_.BeginFrameNeededByImplThread());
26 } 28 }
27 29
28 Scheduler::~Scheduler() { 30 Scheduler::~Scheduler() {
29 client_->SetNeedsBeginFrameOnImplThread(false);
30 } 31 }
31 32
32 void Scheduler::SetCanStart() { 33 void Scheduler::SetCanStart() {
33 state_machine_.SetCanStart(); 34 state_machine_.SetCanStart();
34 ProcessScheduledActions(); 35 ProcessScheduledActions();
35 } 36 }
36 37
37 void Scheduler::SetVisible(bool visible) { 38 void Scheduler::SetVisible(bool visible) {
38 state_machine_.SetVisible(visible); 39 state_machine_.SetVisible(visible);
39 ProcessScheduledActions(); 40 ProcessScheduledActions();
40 } 41 }
41 42
42 void Scheduler::SetCanDraw(bool can_draw) { 43 void Scheduler::SetCanDraw(bool can_draw) {
43 state_machine_.SetCanDraw(can_draw); 44 state_machine_.SetCanDraw(can_draw);
44 ProcessScheduledActions(); 45 ProcessScheduledActions();
45 } 46 }
46 47
47 void Scheduler::NotifyReadyToActivate() { 48 void Scheduler::NotifyReadyToActivate() {
48 state_machine_.NotifyReadyToActivate(); 49 state_machine_.NotifyReadyToActivate();
49 ProcessScheduledActions(); 50 ProcessScheduledActions();
50 } 51 }
51 52
53 void Scheduler::ActivatePendingTree() {
54 client_->ScheduledActionActivatePendingTree();
55 if (state_machine_.ShouldTriggerBeginFrameDeadlineEarly())
56 PostBeginFrameDeadline(base::TimeTicks());
57 }
58
52 void Scheduler::SetNeedsCommit() { 59 void Scheduler::SetNeedsCommit() {
53 state_machine_.SetNeedsCommit(); 60 state_machine_.SetNeedsCommit();
54 ProcessScheduledActions(); 61 ProcessScheduledActions();
55 } 62 }
56 63
57 void Scheduler::SetNeedsForcedCommitForReadback() { 64 void Scheduler::SetNeedsForcedCommitForReadback() {
58 state_machine_.SetNeedsCommit(); 65 state_machine_.SetNeedsCommit();
59 state_machine_.SetNeedsForcedCommitForReadback(); 66 state_machine_.SetNeedsForcedCommitForReadback();
60 ProcessScheduledActions(); 67 ProcessScheduledActions();
61 } 68 }
(...skipping 10 matching lines...) Expand all
72 79
73 void Scheduler::SetMainThreadNeedsLayerTextures() { 80 void Scheduler::SetMainThreadNeedsLayerTextures() {
74 state_machine_.SetMainThreadNeedsLayerTextures(); 81 state_machine_.SetMainThreadNeedsLayerTextures();
75 ProcessScheduledActions(); 82 ProcessScheduledActions();
76 } 83 }
77 84
78 void Scheduler::FinishCommit() { 85 void Scheduler::FinishCommit() {
79 TRACE_EVENT0("cc", "Scheduler::FinishCommit"); 86 TRACE_EVENT0("cc", "Scheduler::FinishCommit");
80 state_machine_.FinishCommit(); 87 state_machine_.FinishCommit();
81 ProcessScheduledActions(); 88 ProcessScheduledActions();
89
90 if (state_machine_.ShouldTriggerBeginFrameDeadlineEarly())
91 PostBeginFrameDeadline(base::TimeTicks());
82 } 92 }
83 93
84 void Scheduler::BeginFrameAbortedByMainThread(bool did_handle) { 94 void Scheduler::BeginFrameAbortedByMainThread(bool did_handle) {
85 TRACE_EVENT0("cc", "Scheduler::BeginFrameAbortedByMainThread"); 95 TRACE_EVENT0("cc", "Scheduler::BeginFrameAbortedByMainThread");
86 state_machine_.BeginFrameAbortedByMainThread(did_handle); 96 state_machine_.BeginFrameAbortedByMainThread(did_handle);
87 ProcessScheduledActions(); 97 ProcessScheduledActions();
88 } 98 }
89 99
90 void Scheduler::DidLoseOutputSurface() { 100 void Scheduler::DidLoseOutputSurface() {
91 TRACE_EVENT0("cc", "Scheduler::DidLoseOutputSurface"); 101 TRACE_EVENT0("cc", "Scheduler::DidLoseOutputSurface");
102 begin_frame_deadline_closure_.Cancel();
103 has_pending_begin_frame_ = false;
92 state_machine_.DidLoseOutputSurface(); 104 state_machine_.DidLoseOutputSurface();
93 ProcessScheduledActions(); 105 ProcessScheduledActions();
94 } 106 }
95 107
96 void Scheduler::DidCreateAndInitializeOutputSurface() { 108 void Scheduler::DidCreateAndInitializeOutputSurface() {
97 TRACE_EVENT0("cc", "Scheduler::DidCreateAndInitializeOutputSurface"); 109 TRACE_EVENT0("cc", "Scheduler::DidCreateAndInitializeOutputSurface");
98 state_machine_.DidCreateAndInitializeOutputSurface(); 110 state_machine_.DidCreateAndInitializeOutputSurface();
111 begin_frame_deadline_closure_.Cancel();
99 has_pending_begin_frame_ = false; 112 has_pending_begin_frame_ = false;
100 last_set_needs_begin_frame_ = false; 113 last_set_needs_begin_frame_ = false;
101 safe_to_expect_begin_frame_ = false; 114 safe_to_expect_begin_frame_ =
115 !settings_.use_begin_frame_workaround_for_crbug_249806;
102 ProcessScheduledActions(); 116 ProcessScheduledActions();
103 } 117 }
104 118
105 base::TimeTicks Scheduler::AnticipatedDrawTime() { 119 base::TimeTicks Scheduler::AnticipatedDrawTime() {
106 TRACE_EVENT0("cc", "Scheduler::AnticipatedDrawTime"); 120 TRACE_EVENT0("cc", "Scheduler::AnticipatedDrawTime");
107 121
108 if (!last_set_needs_begin_frame_ || 122 if (!last_set_needs_begin_frame_ ||
109 last_begin_frame_args_.interval <= base::TimeDelta()) 123 last_begin_frame_args_.interval <= base::TimeDelta())
110 return base::TimeTicks(); 124 return base::TimeTicks();
111 125
112 // TODO(brianderson): Express this in terms of the deadline.
113 base::TimeTicks now = base::TimeTicks::Now(); 126 base::TimeTicks now = base::TimeTicks::Now();
114 int64 intervals = 1 + ((now - last_begin_frame_args_.frame_time) / 127 base::TimeTicks timebase = std::max(last_begin_frame_args_.frame_time,
115 last_begin_frame_args_.interval); 128 last_begin_frame_args_.deadline);
116 return last_begin_frame_args_.frame_time + 129 int64 intervals = 1 + ((now - timebase) / last_begin_frame_args_.interval);
117 (last_begin_frame_args_.interval * intervals); 130 return timebase + (last_begin_frame_args_.interval * intervals);
118 } 131 }
119 132
120 base::TimeTicks Scheduler::LastBeginFrameOnImplThreadTime() { 133 base::TimeTicks Scheduler::LastBeginFrameOnImplThreadTime() {
121 return last_begin_frame_args_.frame_time; 134 return last_begin_frame_args_.frame_time;
122 } 135 }
123 136
124 void Scheduler::SetupNextBeginFrameIfNeeded() { 137 void Scheduler::SetupNextBeginFrameIfNeeded() {
125 bool needs_begin_frame_to_draw = 138 bool needs_begin_frame_to_draw =
126 state_machine_.BeginFrameNeededToDrawByImplThread(); 139 state_machine_.BeginFrameNeededToDrawByImplThread();
127 // We want to avoid proactive begin frames with the synchronous compositor
128 // because every SetNeedsBeginFrame will force a redraw.
129 bool proactive_begin_frame_wanted = 140 bool proactive_begin_frame_wanted =
130 state_machine_.ProactiveBeginFrameWantedByImplThread() && 141 state_machine_.ProactiveBeginFrameWantedByImplThread();
131 !settings_.using_synchronous_renderer_compositor && 142
132 settings_.throttle_frame_production; 143 // We want to avoid proactive begin frames with the synchronous
133 bool needs_begin_frame = needs_begin_frame_to_draw || 144 // compositor because every SetNeedsBeginFrame will force a redraw.
134 proactive_begin_frame_wanted; 145 bool needs_begin_frame =
135 bool immediate_disables_needed = 146 needs_begin_frame_to_draw || proactive_begin_frame_wanted;
136 settings_.using_synchronous_renderer_compositor; 147
148 bool should_call_set_needs_begin_frame =
149 // The synchronous renderer compositor needs immediate enables/disables.
150 (settings_.using_synchronous_renderer_compositor &&
151 needs_begin_frame != last_set_needs_begin_frame_) ||
152 // Always request the BeginFrame immediately if it wasn't needed before.
153 (needs_begin_frame && !last_set_needs_begin_frame_) ||
154 // Only disable the BeginFrame after a BeginFrame where we didn't swap.
155 (!needs_begin_frame && last_set_needs_begin_frame_ &&
156 has_pending_begin_frame_ && !state_machine_.InsideBeginFrame()) ||
157 // We did not draw and swap this BeginFrame,
158 // so we need to explicitly request another BeginFrame.
159 (needs_begin_frame && has_pending_begin_frame_ &&
160 !state_machine_.InsideBeginFrame());
137 161
138 if (needs_begin_frame_to_draw) 162 if (needs_begin_frame_to_draw)
139 safe_to_expect_begin_frame_ = true; 163 safe_to_expect_begin_frame_ = true;
140 164
141 // Determine if we need BeginFrame notifications. 165 if (should_call_set_needs_begin_frame) {
142 // If we do, always request the BeginFrame immediately.
143 // If not, only disable on the next BeginFrame to avoid unnecessary toggles.
144 // The synchronous renderer compositor requires immediate disables though.
145 if ((needs_begin_frame ||
146 state_machine_.inside_begin_frame() ||
147 immediate_disables_needed) &&
148 (needs_begin_frame != last_set_needs_begin_frame_)) {
149 has_pending_begin_frame_ = false; 166 has_pending_begin_frame_ = false;
150 client_->SetNeedsBeginFrameOnImplThread(needs_begin_frame); 167 client_->SetNeedsBeginFrameOnImplThread(needs_begin_frame);
151 if (safe_to_expect_begin_frame_) 168 if (safe_to_expect_begin_frame_)
152 last_set_needs_begin_frame_ = needs_begin_frame; 169 last_set_needs_begin_frame_ = needs_begin_frame;
153 } 170 }
154
155 // Request another BeginFrame if we haven't drawn for now until we have
156 // deadlines implemented.
157 if (state_machine_.inside_begin_frame() && has_pending_begin_frame_) {
158 has_pending_begin_frame_ = false;
159 client_->SetNeedsBeginFrameOnImplThread(true);
160 return;
161 }
162 } 171 }
163 172
164 void Scheduler::BeginFrame(const BeginFrameArgs& args) { 173 void Scheduler::BeginFrame(const BeginFrameArgs& args) {
165 TRACE_EVENT0("cc", "Scheduler::BeginFrame"); 174 TRACE_EVENT0("cc", "Scheduler::BeginFrame");
166 DCHECK(!has_pending_begin_frame_); 175 DCHECK(!has_pending_begin_frame_);
167 has_pending_begin_frame_ = true; 176 has_pending_begin_frame_ = true;
168 safe_to_expect_begin_frame_ = true; 177 safe_to_expect_begin_frame_ = true;
169 last_begin_frame_args_ = args; 178 last_begin_frame_args_ = args;
170 state_machine_.DidEnterBeginFrame(args); 179 last_begin_frame_args_.deadline -= client_->DrawDurationEstimate();
180 state_machine_.OnBeginFrame(last_begin_frame_args_);
171 ProcessScheduledActions(); 181 ProcessScheduledActions();
172 state_machine_.DidLeaveBeginFrame(); 182
183 if (settings_.using_synchronous_renderer_compositor) {
184 // The synchronous renderer compositor has to make it's GL calls
enne (OOO) 2013/09/10 03:35:44 s/'//
brianderson 2013/09/10 21:16:56 Done.
185 // within this call to BeginFrame.
186 // TODO(brianderson): Have the OutputSurface initiate the deadline tasks
187 // so the sychronous renderer compoistor can take advantage of splitting
188 // up the BeginFrame and deadline as well.
189 OnBeginFrameDeadline();
190 } else if (!settings_.deadline_scheduling_enabled) {
191 // We emulate the old non-deadline scheduler here by posting the
192 // deadline task without any delay.
193 PostBeginFrameDeadline(base::TimeTicks());
194 } else if (state_machine_.ShouldTriggerBeginFrameDeadlineEarly()) {
195 // We are ready to draw a new active tree immediately.
196 PostBeginFrameDeadline(base::TimeTicks());
197 } else if (state_machine_.needs_redraw()) {
198 // We have an animation or fast input path on the impl thread that wants
199 // to draw, so don't wait too long for a new active tree.
200 PostBeginFrameDeadline(last_begin_frame_args_.deadline);
201 } else {
202 // The impl thread doesn't have anything it wants to draw and we are just
203 // waiting for a new active tree, so post the deadline for the next
204 // expected BeginFrame start.
205 // TODO(brianderson): Handle long deadlines (that are past the next frame's
206 // frame time) properly instead of using this hack.
207 PostBeginFrameDeadline(last_begin_frame_args_.frame_time +
208 last_begin_frame_args_.interval);
209 }
210 }
211
212 void Scheduler::PostBeginFrameDeadline(base::TimeTicks deadline) {
213 begin_frame_deadline_closure_.Cancel();
214 begin_frame_deadline_closure_.Reset(
215 base::Bind(&Scheduler::OnBeginFrameDeadline, weak_factory_.GetWeakPtr()));
216 client_->PostBeginFrameDeadline(begin_frame_deadline_closure_.callback(),
217 deadline);
218 }
219
220 void Scheduler::OnBeginFrameDeadline() {
221 TRACE_EVENT0("cc", "Scheduler::OnBeginFrameDeadline");
222 begin_frame_deadline_closure_.Cancel();
223 state_machine_.OnBeginFrameDeadline();
224 ProcessScheduledActions();
225 client_->DidBeginFrameDeadlineOnImplThread();
173 } 226 }
174 227
175 void Scheduler::DrawAndSwapIfPossible() { 228 void Scheduler::DrawAndSwapIfPossible() {
176 DrawSwapReadbackResult result = 229 DrawSwapReadbackResult result =
177 client_->ScheduledActionDrawAndSwapIfPossible(); 230 client_->ScheduledActionDrawAndSwapIfPossible();
178 state_machine_.DidDrawIfPossibleCompleted(result.did_draw); 231 state_machine_.DidDrawIfPossibleCompleted(result.did_draw);
179 if (result.did_swap) 232 if (result.did_swap)
180 has_pending_begin_frame_ = false; 233 has_pending_begin_frame_ = false;
181 } 234 }
182 235
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
214 case SchedulerStateMachine::ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD: 267 case SchedulerStateMachine::ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD:
215 client_->ScheduledActionSendBeginFrameToMainThread(); 268 client_->ScheduledActionSendBeginFrameToMainThread();
216 break; 269 break;
217 case SchedulerStateMachine::ACTION_COMMIT: 270 case SchedulerStateMachine::ACTION_COMMIT:
218 client_->ScheduledActionCommit(); 271 client_->ScheduledActionCommit();
219 break; 272 break;
220 case SchedulerStateMachine::ACTION_UPDATE_VISIBLE_TILES: 273 case SchedulerStateMachine::ACTION_UPDATE_VISIBLE_TILES:
221 client_->ScheduledActionUpdateVisibleTiles(); 274 client_->ScheduledActionUpdateVisibleTiles();
222 break; 275 break;
223 case SchedulerStateMachine::ACTION_ACTIVATE_PENDING_TREE: 276 case SchedulerStateMachine::ACTION_ACTIVATE_PENDING_TREE:
224 client_->ScheduledActionActivatePendingTree(); 277 ActivatePendingTree();
225 break; 278 break;
226 case SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE: 279 case SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE:
227 DrawAndSwapIfPossible(); 280 DrawAndSwapIfPossible();
228 break; 281 break;
229 case SchedulerStateMachine::ACTION_DRAW_AND_SWAP_FORCED: 282 case SchedulerStateMachine::ACTION_DRAW_AND_SWAP_FORCED:
230 DrawAndSwapForced(); 283 DrawAndSwapForced();
231 break; 284 break;
232 case SchedulerStateMachine::ACTION_DRAW_AND_SWAP_ABORT: 285 case SchedulerStateMachine::ACTION_DRAW_AND_SWAP_ABORT:
233 // No action is actually performed, but this allows the state machine to 286 // No action is actually performed, but this allows the state machine to
234 // advance out of its waiting to draw state without actually drawing. 287 // advance out of its waiting to draw state without actually drawing.
235 break; 288 break;
236 case SchedulerStateMachine::ACTION_DRAW_AND_READBACK: 289 case SchedulerStateMachine::ACTION_DRAW_AND_READBACK:
237 DrawAndReadback(); 290 DrawAndReadback();
238 break; 291 break;
239 case SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION: 292 case SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION:
240 client_->ScheduledActionBeginOutputSurfaceCreation(); 293 client_->ScheduledActionBeginOutputSurfaceCreation();
241 break; 294 break;
242 case SchedulerStateMachine::ACTION_ACQUIRE_LAYER_TEXTURES_FOR_MAIN_THREAD: 295 case SchedulerStateMachine::ACTION_ACQUIRE_LAYER_TEXTURES_FOR_MAIN_THREAD:
243 client_->ScheduledActionAcquireLayerTexturesForMainThread(); 296 client_->ScheduledActionAcquireLayerTexturesForMainThread();
244 break; 297 break;
245 } 298 }
246 } while (action != SchedulerStateMachine::ACTION_NONE); 299 } while (action != SchedulerStateMachine::ACTION_NONE);
247 300
301 state_machine_.AdvanceBeginFrameStateWhenNoActionsRemain();
248 SetupNextBeginFrameIfNeeded(); 302 SetupNextBeginFrameIfNeeded();
249 client_->DidAnticipatedDrawTimeChange(AnticipatedDrawTime()); 303 client_->DidAnticipatedDrawTimeChange(AnticipatedDrawTime());
250 } 304 }
251 305
252 bool Scheduler::WillDrawIfNeeded() const { 306 bool Scheduler::WillDrawIfNeeded() const {
253 return !state_machine_.PendingDrawsShouldBeAborted(); 307 return !state_machine_.PendingDrawsShouldBeAborted();
254 } 308 }
255 309
256 } // namespace cc 310 } // namespace cc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698