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

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: Fixed all existing tests! New tests pending... Created 7 years, 5 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::SetHasTrees(bool has_pending_tree, bool active_tree_is_null) {
47 state_machine_.SetHasPendingTree(has_pending_tree); 49 state_machine_.SetHasTrees(has_pending_tree, active_tree_is_null);
48 ProcessScheduledActions(); 50 ProcessScheduledActions();
51
52 if (state_machine_.ShouldTriggerBeginFrameDeadlineEarly())
53 PostBeginFrameDeadline(base::TimeTicks());
49 } 54 }
50 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::SetNeedsForcedCommit() { 61 void Scheduler::SetNeedsForcedCommitForReadback() {
57 state_machine_.SetNeedsCommit(); 62 state_machine_.SetNeedsCommit();
58 state_machine_.SetNeedsForcedCommit(); 63 state_machine_.SetNeedsForcedCommitForReadback();
59 ProcessScheduledActions(); 64 ProcessScheduledActions();
60 } 65 }
61 66
62 void Scheduler::SetNeedsRedraw() { 67 void Scheduler::SetNeedsRedraw() {
63 state_machine_.SetNeedsRedraw(); 68 state_machine_.SetNeedsRedraw();
64 ProcessScheduledActions(); 69 ProcessScheduledActions();
65 } 70 }
66 71
67 void Scheduler::DidSwapUseIncompleteTile() { 72 void Scheduler::DidSwapUseIncompleteTile() {
68 state_machine_.DidSwapUseIncompleteTile(); 73 state_machine_.DidSwapUseIncompleteTile();
69 ProcessScheduledActions(); 74 ProcessScheduledActions();
70 } 75 }
71 76
72 void Scheduler::SetNeedsForcedRedraw() {
73 state_machine_.SetNeedsForcedRedraw();
74 ProcessScheduledActions();
75 }
76
77 void Scheduler::SetMainThreadNeedsLayerTextures() { 77 void Scheduler::SetMainThreadNeedsLayerTextures() {
78 state_machine_.SetMainThreadNeedsLayerTextures(); 78 state_machine_.SetMainThreadNeedsLayerTextures();
79 ProcessScheduledActions(); 79 ProcessScheduledActions();
80 } 80 }
81 81
82 void Scheduler::FinishCommit() { 82 void Scheduler::FinishCommit() {
83 TRACE_EVENT0("cc", "Scheduler::FinishCommit"); 83 TRACE_EVENT0("cc", "Scheduler::FinishCommit");
84 state_machine_.FinishCommit(); 84 state_machine_.FinishCommit();
85 ProcessScheduledActions(); 85 ProcessScheduledActions();
86
87 if (state_machine_.ShouldTriggerBeginFrameDeadlineEarly())
88 PostBeginFrameDeadline(base::TimeTicks());
86 } 89 }
87 90
88 void Scheduler::BeginFrameAbortedByMainThread() { 91 void Scheduler::BeginFrameAbortedByMainThread() {
89 TRACE_EVENT0("cc", "Scheduler::BeginFrameAbortedByMainThread"); 92 TRACE_EVENT0("cc", "Scheduler::BeginFrameAbortedByMainThread");
90 state_machine_.BeginFrameAbortedByMainThread(); 93 state_machine_.BeginFrameAbortedByMainThread();
91 ProcessScheduledActions(); 94 ProcessScheduledActions();
92 } 95 }
93 96
94 void Scheduler::DidLoseOutputSurface() { 97 void Scheduler::DidLoseOutputSurface() {
95 TRACE_EVENT0("cc", "Scheduler::DidLoseOutputSurface"); 98 TRACE_EVENT0("cc", "Scheduler::DidLoseOutputSurface");
96 state_machine_.DidLoseOutputSurface(); 99 state_machine_.DidLoseOutputSurface();
97 ProcessScheduledActions(); 100 ProcessScheduledActions();
98 } 101 }
99 102
100 void Scheduler::DidCreateAndInitializeOutputSurface() { 103 void Scheduler::DidCreateAndInitializeOutputSurface() {
101 TRACE_EVENT0("cc", "Scheduler::DidCreateAndInitializeOutputSurface"); 104 TRACE_EVENT0("cc", "Scheduler::DidCreateAndInitializeOutputSurface");
102 state_machine_.DidCreateAndInitializeOutputSurface(); 105 state_machine_.DidCreateAndInitializeOutputSurface();
103 has_pending_begin_frame_ = false; 106 has_pending_begin_frame_ = false;
104 last_set_needs_begin_frame_ = false; 107 last_set_needs_begin_frame_ = false;
105 safe_to_expect_begin_frame_ = false; 108 safe_to_expect_begin_frame_ =
109 !settings_.use_begin_frame_workaround_for_crbug_249806;
106 ProcessScheduledActions(); 110 ProcessScheduledActions();
107 } 111 }
108 112
109 base::TimeTicks Scheduler::AnticipatedDrawTime() { 113 base::TimeTicks Scheduler::AnticipatedDrawTime() {
110 TRACE_EVENT0("cc", "Scheduler::AnticipatedDrawTime"); 114 TRACE_EVENT0("cc", "Scheduler::AnticipatedDrawTime");
111 115
112 if (!last_set_needs_begin_frame_ || 116 if (!last_set_needs_begin_frame_ ||
113 last_begin_frame_args_.interval <= base::TimeDelta()) 117 last_begin_frame_args_.interval <= base::TimeDelta())
114 return base::TimeTicks(); 118 return base::TimeTicks();
115 119
116 // TODO(brianderson): Express this in terms of the deadline.
117 base::TimeTicks now = base::TimeTicks::Now(); 120 base::TimeTicks now = base::TimeTicks::Now();
118 int64 intervals = 1 + ((now - last_begin_frame_args_.frame_time) / 121 base::TimeTicks timebase = std::max(last_begin_frame_args_.frame_time,
119 last_begin_frame_args_.interval); 122 last_begin_frame_args_.deadline);
120 return last_begin_frame_args_.frame_time + 123 int64 intervals = 1 + ((now - timebase) / last_begin_frame_args_.interval);
121 (last_begin_frame_args_.interval * intervals); 124 return timebase + (last_begin_frame_args_.interval * intervals);
122 } 125 }
123 126
124 base::TimeTicks Scheduler::LastBeginFrameOnImplThreadTime() { 127 base::TimeTicks Scheduler::LastBeginFrameOnImplThreadTime() {
125 return last_begin_frame_args_.frame_time; 128 return last_begin_frame_args_.frame_time;
126 } 129 }
127 130
128 void Scheduler::SetupNextBeginFrameIfNeeded() { 131 void Scheduler::SetupNextBeginFrameIfNeeded() {
129 bool needs_begin_frame_to_draw = 132 bool needs_begin_frame_to_draw =
130 state_machine_.BeginFrameNeededToDrawByImplThread(); 133 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 = 134 bool proactive_begin_frame_wanted =
134 state_machine_.ProactiveBeginFrameWantedByImplThread() && 135 state_machine_.BeginFrameProactivelyNeededByImplThread();
135 !settings_.using_synchronous_renderer_compositor && 136
136 settings_.throttle_frame_production; 137 // We want to avoid proactive begin frames with the synchronous
138 // compositor because every SetNeedsBeginFrame will force a redraw.
137 bool needs_begin_frame = needs_begin_frame_to_draw || 139 bool needs_begin_frame = needs_begin_frame_to_draw ||
138 proactive_begin_frame_wanted; 140 proactive_begin_frame_wanted;
139 bool immediate_disables_needed = 141
140 settings_.using_synchronous_renderer_compositor; 142 bool should_call_set_needs_begin_frame =
143 // The synchronous renderer compositor needs immediate enables/disables.
144 (settings_.using_synchronous_renderer_compositor &&
145 needs_begin_frame != last_set_needs_begin_frame_) ||
146 // Always request the BeginFrame immediately if it wasn't needed before.
147 (needs_begin_frame && !last_set_needs_begin_frame_) ||
148 // Only disable the BeginFrame after a BeginFrame where we didn't swap.
149 (!needs_begin_frame && last_set_needs_begin_frame_ &&
150 has_pending_begin_frame_ && !state_machine_.InsideBeginFrame()) ||
151 // We did not draw and swap this BeginFrame,
152 // so we need to explicitly request another BeginFrame.
153 (needs_begin_frame && has_pending_begin_frame_ &&
154 !state_machine_.InsideBeginFrame());
141 155
142 if (needs_begin_frame_to_draw) 156 if (needs_begin_frame_to_draw)
143 safe_to_expect_begin_frame_ = true; 157 safe_to_expect_begin_frame_ = true;
144 158
145 // Determine if we need BeginFrame notifications. 159 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; 160 has_pending_begin_frame_ = false;
154 client_->SetNeedsBeginFrameOnImplThread(needs_begin_frame); 161 client_->SetNeedsBeginFrameOnImplThread(needs_begin_frame);
155 if (safe_to_expect_begin_frame_) 162 if (safe_to_expect_begin_frame_)
156 last_set_needs_begin_frame_ = needs_begin_frame; 163 last_set_needs_begin_frame_ = needs_begin_frame;
157 } 164 }
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 } 165 }
167 166
168 void Scheduler::BeginFrame(const BeginFrameArgs& args) { 167 void Scheduler::BeginFrame(const BeginFrameArgs& args) {
169 TRACE_EVENT0("cc", "Scheduler::BeginFrame"); 168 TRACE_EVENT0("cc", "Scheduler::BeginFrame");
170 DCHECK(!has_pending_begin_frame_); 169 DCHECK(!has_pending_begin_frame_);
171 has_pending_begin_frame_ = true; 170 has_pending_begin_frame_ = true;
172 safe_to_expect_begin_frame_ = true; 171 safe_to_expect_begin_frame_ = true;
173 last_begin_frame_args_ = args; 172 last_begin_frame_args_ = args;
174 state_machine_.DidEnterBeginFrame(args); 173 last_begin_frame_args_.AdjustDeadline(-client_->DrawDurationEstimate());
174 state_machine_.OnBeginFrame(last_begin_frame_args_);
175 ProcessScheduledActions(); 175 ProcessScheduledActions();
176 state_machine_.DidLeaveBeginFrame(); 176
177 if (settings_.using_synchronous_renderer_compositor)
178 OnBeginFrameDeadline();
179 else if (state_machine_.ShouldTriggerBeginFrameDeadlineEarly())
180 PostBeginFrameDeadline(base::TimeTicks());
181 else
182 PostBeginFrameDeadline(last_begin_frame_args_.deadline);
183 }
184
185 void Scheduler::PostBeginFrameDeadline(base::TimeTicks deadline) {
186 begin_frame_deadline_closure_.Cancel();
187 begin_frame_deadline_closure_.Reset(
188 base::Bind(&Scheduler::OnBeginFrameDeadline, weak_factory_.GetWeakPtr()));
189 client_->PostBeginFrameDeadline(
190 begin_frame_deadline_closure_.callback(), deadline);
191 }
192
193 void Scheduler::OnBeginFrameDeadline() {
194 TRACE_EVENT0("cc", "Scheduler::OnBeginFrameDeadline");
195 begin_frame_deadline_closure_.Cancel();
196 state_machine_.OnBeginFrameDeadline();
197 ProcessScheduledActions();
198 client_->DidBeginFrameDeadlineOnImplThread();
177 } 199 }
178 200
179 void Scheduler::DrawAndSwapIfPossible() { 201 void Scheduler::DrawAndSwapIfPossible() {
180 ScheduledActionDrawAndSwapResult result = 202 DrawSwapReadbackResult result =
181 client_->ScheduledActionDrawAndSwapIfPossible(); 203 client_->ScheduledActionDrawAndSwapIfPossible();
182 state_machine_.DidDrawIfPossibleCompleted(result.did_draw); 204 state_machine_.DidDrawIfPossibleCompleted(result.did_draw);
183 if (result.did_swap) 205 if (result.did_swap)
184 has_pending_begin_frame_ = false; 206 has_pending_begin_frame_ = false;
185 } 207 }
186 208
187 void Scheduler::DrawAndSwapForced() { 209 void Scheduler::DrawAndSwapForced() {
188 ScheduledActionDrawAndSwapResult result = 210 DrawSwapReadbackResult result =
189 client_->ScheduledActionDrawAndSwapForced(); 211 client_->ScheduledActionDrawAndSwapForced();
190 if (result.did_swap) 212 if (result.did_swap)
191 has_pending_begin_frame_ = false; 213 has_pending_begin_frame_ = false;
192 } 214 }
193 215
216 void Scheduler::DrawAndReadback() {
217 client_->ScheduledActionDrawAndReadback();
218 }
219
194 void Scheduler::ProcessScheduledActions() { 220 void Scheduler::ProcessScheduledActions() {
195 // We do not allow ProcessScheduledActions to be recursive. 221 // We do not allow ProcessScheduledActions to be recursive.
196 // The top-level call will iteratively execute the next action for us anyway. 222 // The top-level call will iteratively execute the next action for us anyway.
197 if (inside_process_scheduled_actions_) 223 if (inside_process_scheduled_actions_)
198 return; 224 return;
199 225
200 base::AutoReset<bool> mark_inside(&inside_process_scheduled_actions_, true); 226 base::AutoReset<bool> mark_inside(&inside_process_scheduled_actions_, true);
201 227
202 SchedulerStateMachine::Action action = state_machine_.NextAction(); 228 SchedulerStateMachine::Action action;
203 while (action != SchedulerStateMachine::ACTION_NONE) { 229 do {
230 TRACE_EVENT1("cc", "SchedulerStateMachine",
231 "state", state_machine_.ToString());
232 action = state_machine_.NextAction();
204 state_machine_.UpdateState(action); 233 state_machine_.UpdateState(action);
205 switch (action) { 234 switch (action) {
206 case SchedulerStateMachine::ACTION_NONE: 235 case SchedulerStateMachine::ACTION_NONE:
207 break; 236 break;
208 case SchedulerStateMachine::ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD: 237 case SchedulerStateMachine::ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD:
209 client_->ScheduledActionSendBeginFrameToMainThread(); 238 client_->ScheduledActionSendBeginFrameToMainThread();
210 break; 239 break;
211 case SchedulerStateMachine::ACTION_COMMIT: 240 case SchedulerStateMachine::ACTION_COMMIT:
212 client_->ScheduledActionCommit(); 241 client_->ScheduledActionCommit();
213 break; 242 break;
214 case SchedulerStateMachine::ACTION_CHECK_FOR_COMPLETED_TILE_UPLOADS: 243 case SchedulerStateMachine::ACTION_CHECK_FOR_COMPLETED_TILE_UPLOADS:
215 client_->ScheduledActionCheckForCompletedTileUploads(); 244 client_->ScheduledActionCheckForCompletedTileUploads();
216 break; 245 break;
217 case SchedulerStateMachine::ACTION_ACTIVATE_PENDING_TREE_IF_NEEDED: 246 case SchedulerStateMachine::ACTION_ACTIVATE_PENDING_TREE_IF_NEEDED:
218 client_->ScheduledActionActivatePendingTreeIfNeeded(); 247 client_->ScheduledActionActivatePendingTreeIfNeeded();
219 break; 248 break;
220 case SchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE: 249 case SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE:
221 DrawAndSwapIfPossible(); 250 DrawAndSwapIfPossible();
222 break; 251 break;
223 case SchedulerStateMachine::ACTION_DRAW_FORCED: 252 case SchedulerStateMachine::ACTION_DRAW_AND_SWAP_FORCED:
224 DrawAndSwapForced(); 253 DrawAndSwapForced();
225 break; 254 break;
255 case SchedulerStateMachine::ACTION_DRAW_AND_READBACK:
256 DrawAndReadback();
257 break;
226 case SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION: 258 case SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION:
227 client_->ScheduledActionBeginOutputSurfaceCreation(); 259 client_->ScheduledActionBeginOutputSurfaceCreation();
228 break; 260 break;
229 case SchedulerStateMachine::ACTION_ACQUIRE_LAYER_TEXTURES_FOR_MAIN_THREAD: 261 case SchedulerStateMachine::ACTION_ACQUIRE_LAYER_TEXTURES_FOR_MAIN_THREAD:
230 client_->ScheduledActionAcquireLayerTexturesForMainThread(); 262 client_->ScheduledActionAcquireLayerTexturesForMainThread();
231 break; 263 break;
232 } 264 }
233 action = state_machine_.NextAction(); 265 } while (action != SchedulerStateMachine::ACTION_NONE);
234 }
235 266
267 state_machine_.AdvanceBeginFrameStateWhenNoActionsRemain();
236 SetupNextBeginFrameIfNeeded(); 268 SetupNextBeginFrameIfNeeded();
237 client_->DidAnticipatedDrawTimeChange(AnticipatedDrawTime()); 269 client_->DidAnticipatedDrawTimeChange(AnticipatedDrawTime());
238 } 270 }
239 271
240 bool Scheduler::WillDrawIfNeeded() const { 272 bool Scheduler::WillDrawIfNeeded() const {
241 return !state_machine_.DrawSuspendedUntilCommit(); 273 return !state_machine_.DrawSuspendedUntilCommit();
242 } 274 }
243 275
244 } // namespace cc 276 } // namespace cc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698