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

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

Issue 16871016: cc: Use BeginFrameArgs (Closed) Base URL: http://git.chromium.org/chromium/src.git@bfargs2
Patch Set: Rebase; Avoid double activate; Fix OutputSurface init and page scroll delta; Created 7 years, 4 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 11
11 namespace cc { 12 namespace cc {
12 13
13 Scheduler::Scheduler(SchedulerClient* client, 14 Scheduler::Scheduler(SchedulerClient* client,
14 const SchedulerSettings& scheduler_settings) 15 const SchedulerSettings& scheduler_settings)
15 : settings_(scheduler_settings), 16 : settings_(scheduler_settings),
16 client_(client), 17 client_(client),
17 weak_factory_(this), 18 weak_factory_(this),
18 last_set_needs_begin_frame_(false), 19 last_set_needs_begin_frame_(false),
19 has_pending_begin_frame_(false), 20 has_pending_begin_frame_(false),
20 safe_to_expect_begin_frame_(false), 21 safe_to_expect_begin_frame_(
22 !scheduler_settings.use_begin_frame_workaround_for_crbug_249806),
21 state_machine_(scheduler_settings), 23 state_machine_(scheduler_settings),
22 inside_process_scheduled_actions_(false) { 24 inside_process_scheduled_actions_(false) {
23 DCHECK(client_); 25 DCHECK(client_);
24 DCHECK(!state_machine_.BeginFrameNeededToDrawByImplThread()); 26 DCHECK(!state_machine_.BeginFrameNeededByImplThread());
25 } 27 }
26 28
27 Scheduler::~Scheduler() { 29 Scheduler::~Scheduler() {
28 client_->SetNeedsBeginFrameOnImplThread(false); 30 client_->SetNeedsBeginFrameOnImplThread(false);
29 } 31 }
30 32
31 void Scheduler::SetCanStart() { 33 void Scheduler::SetCanStart() {
32 state_machine_.SetCanStart(); 34 state_machine_.SetCanStart();
33 ProcessScheduledActions(); 35 ProcessScheduledActions();
34 } 36 }
35 37
36 void Scheduler::SetVisible(bool visible) { 38 void Scheduler::SetVisible(bool visible) {
37 state_machine_.SetVisible(visible); 39 state_machine_.SetVisible(visible);
38 ProcessScheduledActions(); 40 ProcessScheduledActions();
39 } 41 }
40 42
41 void Scheduler::SetCanDraw(bool can_draw) { 43 void Scheduler::SetCanDraw(bool can_draw) {
42 state_machine_.SetCanDraw(can_draw); 44 state_machine_.SetCanDraw(can_draw);
43 ProcessScheduledActions(); 45 ProcessScheduledActions();
44 } 46 }
45 47
46 void Scheduler::SetHasPendingTree(bool has_pending_tree) { 48 void Scheduler::NotifyReadyToActivate() {
47 state_machine_.SetHasPendingTree(has_pending_tree); 49 state_machine_.NotifyReadyToActivate();
48 ProcessScheduledActions(); 50 ProcessScheduledActions();
49 } 51 }
50 52
53 void Scheduler::SetHasTrees(bool has_pending_tree, bool active_tree_is_null) {
54 state_machine_.SetHasTrees(has_pending_tree, active_tree_is_null);
55 ProcessScheduledActions();
56
57 if (state_machine_.ShouldTriggerBeginFrameDeadlineEarly())
58 PostBeginFrameDeadline(base::TimeTicks());
59 }
60
51 void Scheduler::SetNeedsCommit() { 61 void Scheduler::SetNeedsCommit() {
52 state_machine_.SetNeedsCommit(); 62 state_machine_.SetNeedsCommit();
53 ProcessScheduledActions(); 63 ProcessScheduledActions();
54 } 64 }
55 65
56 void Scheduler::SetNeedsForcedCommit() { 66 void Scheduler::SetNeedsForcedCommitForReadback() {
57 state_machine_.SetNeedsCommit(); 67 state_machine_.SetNeedsCommit();
58 state_machine_.SetNeedsForcedCommit(); 68 state_machine_.SetNeedsForcedCommitForReadback();
59 ProcessScheduledActions(); 69 ProcessScheduledActions();
60 } 70 }
61 71
62 void Scheduler::SetNeedsRedraw() { 72 void Scheduler::SetNeedsRedraw() {
63 state_machine_.SetNeedsRedraw(); 73 state_machine_.SetNeedsRedraw();
64 ProcessScheduledActions(); 74 ProcessScheduledActions();
65 } 75 }
66 76
67 void Scheduler::DidSwapUseIncompleteTile() { 77 void Scheduler::DidSwapUseIncompleteTile() {
68 state_machine_.DidSwapUseIncompleteTile(); 78 state_machine_.DidSwapUseIncompleteTile();
69 ProcessScheduledActions(); 79 ProcessScheduledActions();
70 } 80 }
71 81
72 void Scheduler::SetNeedsForcedRedraw() {
73 state_machine_.SetNeedsForcedRedraw();
74 ProcessScheduledActions();
75 }
76
77 void Scheduler::SetMainThreadNeedsLayerTextures() { 82 void Scheduler::SetMainThreadNeedsLayerTextures() {
78 state_machine_.SetMainThreadNeedsLayerTextures(); 83 state_machine_.SetMainThreadNeedsLayerTextures();
79 ProcessScheduledActions(); 84 ProcessScheduledActions();
80 } 85 }
81 86
82 void Scheduler::FinishCommit() { 87 void Scheduler::FinishCommit() {
83 TRACE_EVENT0("cc", "Scheduler::FinishCommit"); 88 TRACE_EVENT0("cc", "Scheduler::FinishCommit");
84 state_machine_.FinishCommit(); 89 state_machine_.FinishCommit();
85 ProcessScheduledActions(); 90 ProcessScheduledActions();
91
92 if (state_machine_.ShouldTriggerBeginFrameDeadlineEarly())
93 PostBeginFrameDeadline(base::TimeTicks());
86 } 94 }
87 95
88 void Scheduler::BeginFrameAbortedByMainThread(bool did_handle) { 96 void Scheduler::BeginFrameAbortedByMainThread(bool did_handle) {
89 TRACE_EVENT0("cc", "Scheduler::BeginFrameAbortedByMainThread"); 97 TRACE_EVENT0("cc", "Scheduler::BeginFrameAbortedByMainThread");
90 state_machine_.BeginFrameAbortedByMainThread(did_handle); 98 state_machine_.BeginFrameAbortedByMainThread(did_handle);
91 ProcessScheduledActions(); 99 ProcessScheduledActions();
92 } 100 }
93 101
94 void Scheduler::DidLoseOutputSurface() { 102 void Scheduler::DidLoseOutputSurface() {
95 TRACE_EVENT0("cc", "Scheduler::DidLoseOutputSurface"); 103 TRACE_EVENT0("cc", "Scheduler::DidLoseOutputSurface");
104 begin_frame_deadline_closure_.Cancel();
105 has_pending_begin_frame_ = false;
96 state_machine_.DidLoseOutputSurface(); 106 state_machine_.DidLoseOutputSurface();
97 ProcessScheduledActions(); 107 ProcessScheduledActions();
98 } 108 }
99 109
100 void Scheduler::DidCreateAndInitializeOutputSurface() { 110 void Scheduler::DidCreateAndInitializeOutputSurface() {
101 TRACE_EVENT0("cc", "Scheduler::DidCreateAndInitializeOutputSurface"); 111 TRACE_EVENT0("cc", "Scheduler::DidCreateAndInitializeOutputSurface");
102 state_machine_.DidCreateAndInitializeOutputSurface(); 112 state_machine_.DidCreateAndInitializeOutputSurface();
113 begin_frame_deadline_closure_.Cancel();
103 has_pending_begin_frame_ = false; 114 has_pending_begin_frame_ = false;
104 last_set_needs_begin_frame_ = false; 115 last_set_needs_begin_frame_ = false;
105 safe_to_expect_begin_frame_ = false; 116 safe_to_expect_begin_frame_ =
117 !settings_.use_begin_frame_workaround_for_crbug_249806;
106 ProcessScheduledActions(); 118 ProcessScheduledActions();
107 } 119 }
108 120
109 base::TimeTicks Scheduler::AnticipatedDrawTime() { 121 base::TimeTicks Scheduler::AnticipatedDrawTime() {
110 TRACE_EVENT0("cc", "Scheduler::AnticipatedDrawTime"); 122 TRACE_EVENT0("cc", "Scheduler::AnticipatedDrawTime");
111 123
112 if (!last_set_needs_begin_frame_ || 124 if (!last_set_needs_begin_frame_ ||
113 last_begin_frame_args_.interval <= base::TimeDelta()) 125 last_begin_frame_args_.interval <= base::TimeDelta())
114 return base::TimeTicks(); 126 return base::TimeTicks();
115 127
116 // TODO(brianderson): Express this in terms of the deadline.
117 base::TimeTicks now = base::TimeTicks::Now(); 128 base::TimeTicks now = base::TimeTicks::Now();
118 int64 intervals = 1 + ((now - last_begin_frame_args_.frame_time) / 129 base::TimeTicks timebase = std::max(last_begin_frame_args_.frame_time,
119 last_begin_frame_args_.interval); 130 last_begin_frame_args_.deadline);
120 return last_begin_frame_args_.frame_time + 131 int64 intervals = 1 + ((now - timebase) / last_begin_frame_args_.interval);
121 (last_begin_frame_args_.interval * intervals); 132 return timebase + (last_begin_frame_args_.interval * intervals);
122 } 133 }
123 134
124 base::TimeTicks Scheduler::LastBeginFrameOnImplThreadTime() { 135 base::TimeTicks Scheduler::LastBeginFrameOnImplThreadTime() {
125 return last_begin_frame_args_.frame_time; 136 return last_begin_frame_args_.frame_time;
126 } 137 }
127 138
128 void Scheduler::SetupNextBeginFrameIfNeeded() { 139 void Scheduler::SetupNextBeginFrameIfNeeded() {
129 bool needs_begin_frame_to_draw = 140 bool needs_begin_frame_to_draw =
130 state_machine_.BeginFrameNeededToDrawByImplThread(); 141 state_machine_.BeginFrameNeededToDrawByImplThread();
131 // We want to avoid proactive begin frames with the synchronous compositor
132 // because every SetNeedsBeginFrame will force a redraw.
133 bool proactive_begin_frame_wanted = 142 bool proactive_begin_frame_wanted =
134 state_machine_.ProactiveBeginFrameWantedByImplThread() && 143 state_machine_.BeginFrameProactivelyNeededByImplThread();
135 !settings_.using_synchronous_renderer_compositor && 144
136 settings_.throttle_frame_production; 145 // We want to avoid proactive begin frames with the synchronous
146 // compositor because every SetNeedsBeginFrame will force a redraw.
137 bool needs_begin_frame = needs_begin_frame_to_draw || 147 bool needs_begin_frame = needs_begin_frame_to_draw ||
138 proactive_begin_frame_wanted; 148 proactive_begin_frame_wanted;
139 bool immediate_disables_needed = 149
140 settings_.using_synchronous_renderer_compositor; 150 bool should_call_set_needs_begin_frame =
151 // The synchronous renderer compositor needs immediate enables/disables.
152 (settings_.using_synchronous_renderer_compositor &&
153 needs_begin_frame != last_set_needs_begin_frame_) ||
154 // Always request the BeginFrame immediately if it wasn't needed before.
155 (needs_begin_frame && !last_set_needs_begin_frame_) ||
156 // Only disable the BeginFrame after a BeginFrame where we didn't swap.
157 (!needs_begin_frame && last_set_needs_begin_frame_ &&
158 has_pending_begin_frame_ && !state_machine_.InsideBeginFrame()) ||
159 // We did not draw and swap this BeginFrame,
160 // so we need to explicitly request another BeginFrame.
161 (needs_begin_frame && has_pending_begin_frame_ &&
162 !state_machine_.InsideBeginFrame());
141 163
142 if (needs_begin_frame_to_draw) 164 if (needs_begin_frame_to_draw)
143 safe_to_expect_begin_frame_ = true; 165 safe_to_expect_begin_frame_ = true;
144 166
145 // Determine if we need BeginFrame notifications. 167 if (should_call_set_needs_begin_frame) {
146 // If we do, always request the BeginFrame immediately.
147 // If not, only disable on the next BeginFrame to avoid unnecessary toggles.
148 // The synchronous renderer compositor requires immediate disables though.
149 if ((needs_begin_frame ||
150 state_machine_.inside_begin_frame() ||
151 immediate_disables_needed) &&
152 (needs_begin_frame != last_set_needs_begin_frame_)) {
153 has_pending_begin_frame_ = false; 168 has_pending_begin_frame_ = false;
154 client_->SetNeedsBeginFrameOnImplThread(needs_begin_frame); 169 client_->SetNeedsBeginFrameOnImplThread(needs_begin_frame);
155 if (safe_to_expect_begin_frame_) 170 if (safe_to_expect_begin_frame_)
156 last_set_needs_begin_frame_ = needs_begin_frame; 171 last_set_needs_begin_frame_ = needs_begin_frame;
157 } 172 }
158
159 // Request another BeginFrame if we haven't drawn for now until we have
160 // deadlines implemented.
161 if (state_machine_.inside_begin_frame() && has_pending_begin_frame_) {
162 has_pending_begin_frame_ = false;
163 client_->SetNeedsBeginFrameOnImplThread(true);
164 return;
165 }
166 } 173 }
167 174
168 void Scheduler::BeginFrame(const BeginFrameArgs& args) { 175 void Scheduler::BeginFrame(const BeginFrameArgs& args) {
169 TRACE_EVENT0("cc", "Scheduler::BeginFrame"); 176 TRACE_EVENT0("cc", "Scheduler::BeginFrame");
170 DCHECK(!has_pending_begin_frame_); 177 DCHECK(!has_pending_begin_frame_);
171 has_pending_begin_frame_ = true; 178 has_pending_begin_frame_ = true;
172 safe_to_expect_begin_frame_ = true; 179 safe_to_expect_begin_frame_ = true;
173 last_begin_frame_args_ = args; 180 last_begin_frame_args_ = args;
174 state_machine_.DidEnterBeginFrame(args); 181 last_begin_frame_args_.AdjustDeadline(-client_->DrawDurationEstimate());
182 state_machine_.OnBeginFrame(last_begin_frame_args_);
175 ProcessScheduledActions(); 183 ProcessScheduledActions();
176 state_machine_.DidLeaveBeginFrame(); 184
185 if (settings_.using_synchronous_renderer_compositor)
186 OnBeginFrameDeadline();
187 else if (state_machine_.ShouldTriggerBeginFrameDeadlineEarly())
188 PostBeginFrameDeadline(base::TimeTicks());
189 else
190 PostBeginFrameDeadline(last_begin_frame_args_.deadline);
191 }
192
193 void Scheduler::PostBeginFrameDeadline(base::TimeTicks deadline) {
194 begin_frame_deadline_closure_.Cancel();
195 begin_frame_deadline_closure_.Reset(
196 base::Bind(&Scheduler::OnBeginFrameDeadline, weak_factory_.GetWeakPtr()));
197 client_->PostBeginFrameDeadline(
198 begin_frame_deadline_closure_.callback(), deadline);
199 }
200
201 void Scheduler::OnBeginFrameDeadline() {
202 TRACE_EVENT0("cc", "Scheduler::OnBeginFrameDeadline");
203 begin_frame_deadline_closure_.Cancel();
204 state_machine_.OnBeginFrameDeadline();
205 ProcessScheduledActions();
206 client_->DidBeginFrameDeadlineOnImplThread();
177 } 207 }
178 208
179 void Scheduler::DrawAndSwapIfPossible() { 209 void Scheduler::DrawAndSwapIfPossible() {
180 ScheduledActionDrawAndSwapResult result = 210 DrawSwapReadbackResult result =
181 client_->ScheduledActionDrawAndSwapIfPossible(); 211 client_->ScheduledActionDrawAndSwapIfPossible();
182 state_machine_.DidDrawIfPossibleCompleted(result.did_draw); 212 state_machine_.DidDrawIfPossibleCompleted(result.did_draw);
183 if (result.did_swap) 213 if (result.did_swap)
184 has_pending_begin_frame_ = false; 214 has_pending_begin_frame_ = false;
185 } 215 }
186 216
187 void Scheduler::DrawAndSwapForced() { 217 void Scheduler::DrawAndSwapForced() {
188 ScheduledActionDrawAndSwapResult result = 218 DrawSwapReadbackResult result =
189 client_->ScheduledActionDrawAndSwapForced(); 219 client_->ScheduledActionDrawAndSwapForced();
190 if (result.did_swap) 220 if (result.did_swap)
191 has_pending_begin_frame_ = false; 221 has_pending_begin_frame_ = false;
192 } 222 }
193 223
194 void Scheduler::ProcessScheduledActions() { 224 void Scheduler::ProcessScheduledActions() {
195 // We do not allow ProcessScheduledActions to be recursive. 225 // We do not allow ProcessScheduledActions to be recursive.
196 // The top-level call will iteratively execute the next action for us anyway. 226 // The top-level call will iteratively execute the next action for us anyway.
197 if (inside_process_scheduled_actions_) 227 if (inside_process_scheduled_actions_)
198 return; 228 return;
199 229
200 base::AutoReset<bool> mark_inside(&inside_process_scheduled_actions_, true); 230 base::AutoReset<bool> mark_inside(&inside_process_scheduled_actions_, true);
201 231
202 SchedulerStateMachine::Action action = state_machine_.NextAction(); 232 SchedulerStateMachine::Action action;
203 while (action != SchedulerStateMachine::ACTION_NONE) { 233 do {
234 action = state_machine_.NextAction();
235 TRACE_EVENT2("cc", "SchedulerStateMachine",
236 "action", action,
237 "state", state_machine_.ToString());
204 state_machine_.UpdateState(action); 238 state_machine_.UpdateState(action);
205 switch (action) { 239 switch (action) {
206 case SchedulerStateMachine::ACTION_NONE: 240 case SchedulerStateMachine::ACTION_NONE:
207 break; 241 break;
208 case SchedulerStateMachine::ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD: 242 case SchedulerStateMachine::ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD:
209 client_->ScheduledActionSendBeginFrameToMainThread(); 243 client_->ScheduledActionSendBeginFrameToMainThread();
210 break; 244 break;
211 case SchedulerStateMachine::ACTION_COMMIT: 245 case SchedulerStateMachine::ACTION_COMMIT:
212 client_->ScheduledActionCommit(); 246 client_->ScheduledActionCommit();
213 break; 247 break;
214 case SchedulerStateMachine::ACTION_UPDATE_VISIBLE_TILES: 248 case SchedulerStateMachine::ACTION_UPDATE_VISIBLE_TILES:
215 client_->ScheduledActionUpdateVisibleTiles(); 249 client_->ScheduledActionUpdateVisibleTiles();
216 break; 250 break;
217 case SchedulerStateMachine::ACTION_ACTIVATE_PENDING_TREE_IF_NEEDED: 251 case SchedulerStateMachine::ACTION_ACTIVATE_PENDING_TREE:
218 client_->ScheduledActionActivatePendingTreeIfNeeded(); 252 client_->ScheduledActionActivatePendingTree();
219 break; 253 break;
220 case SchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE: 254 case SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE:
221 DrawAndSwapIfPossible(); 255 DrawAndSwapIfPossible();
222 break; 256 break;
223 case SchedulerStateMachine::ACTION_DRAW_FORCED: 257 case SchedulerStateMachine::ACTION_DRAW_AND_SWAP_FORCED:
224 DrawAndSwapForced(); 258 DrawAndSwapForced();
225 break; 259 break;
260 case SchedulerStateMachine::ACTION_DRAW_AND_SWAP_ABORT:
261 // No action is actually performed, but this allows the state machine to
262 // advance out of its waiting to draw state without actually drawing.
263 break;
264 case SchedulerStateMachine::ACTION_DRAW_AND_READBACK:
265 client_->ScheduledActionDrawAndReadback();
266 break;
226 case SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION: 267 case SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION:
227 client_->ScheduledActionBeginOutputSurfaceCreation(); 268 client_->ScheduledActionBeginOutputSurfaceCreation();
228 break; 269 break;
229 case SchedulerStateMachine::ACTION_ACQUIRE_LAYER_TEXTURES_FOR_MAIN_THREAD: 270 case SchedulerStateMachine::ACTION_ACQUIRE_LAYER_TEXTURES_FOR_MAIN_THREAD:
230 client_->ScheduledActionAcquireLayerTexturesForMainThread(); 271 client_->ScheduledActionAcquireLayerTexturesForMainThread();
231 break; 272 break;
232 } 273 }
233 action = state_machine_.NextAction(); 274 } while (action != SchedulerStateMachine::ACTION_NONE);
enne (OOO) 2013/08/02 19:41:25 This is a much-needed scheduler change.
234 }
235 275
276 state_machine_.AdvanceBeginFrameStateWhenNoActionsRemain();
236 SetupNextBeginFrameIfNeeded(); 277 SetupNextBeginFrameIfNeeded();
237 client_->DidAnticipatedDrawTimeChange(AnticipatedDrawTime()); 278 client_->DidAnticipatedDrawTimeChange(AnticipatedDrawTime());
238 } 279 }
239 280
240 bool Scheduler::WillDrawIfNeeded() const { 281 bool Scheduler::WillDrawIfNeeded() const {
241 return !state_machine_.DrawSuspendedUntilCommit(); 282 return !state_machine_.DrawSuspendedUntilCommit();
242 } 283 }
243 284
244 } // namespace cc 285 } // namespace cc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698