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

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

Powered by Google App Engine
This is Rietveld 408576698