OLD | NEW |
| (Empty) |
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 | |
3 // found in the LICENSE file. | |
4 | |
5 #include "config.h" | |
6 | |
7 #include "CCSchedulerStateMachine.h" | |
8 #include "base/stringprintf.h" | |
9 | |
10 | |
11 namespace cc { | |
12 | |
13 CCSchedulerStateMachine::CCSchedulerStateMachine() | |
14 : m_commitState(COMMIT_STATE_IDLE) | |
15 , m_currentFrameNumber(0) | |
16 , m_lastFrameNumberWhereDrawWasCalled(-1) | |
17 , m_consecutiveFailedDraws(0) | |
18 , m_maximumNumberOfFailedDrawsBeforeDrawIsForced(3) | |
19 , m_needsRedraw(false) | |
20 , m_needsForcedRedraw(false) | |
21 , m_needsForcedRedrawAfterNextCommit(false) | |
22 , m_needsCommit(false) | |
23 , m_needsForcedCommit(false) | |
24 , m_mainThreadNeedsLayerTextures(false) | |
25 , m_insideVSync(false) | |
26 , m_visible(false) | |
27 , m_canBeginFrame(false) | |
28 , m_canDraw(false) | |
29 , m_drawIfPossibleFailed(false) | |
30 , m_textureState(LAYER_TEXTURE_STATE_UNLOCKED) | |
31 , m_contextState(CONTEXT_ACTIVE) | |
32 { | |
33 } | |
34 | |
35 std::string CCSchedulerStateMachine::toString() | |
36 { | |
37 std::string str; | |
38 base::StringAppendF(&str, "m_commitState = %d; ", m_commitState); | |
39 base::StringAppendF(&str, "m_currentFrameNumber = %d; ", m_currentFrameNumbe
r); | |
40 base::StringAppendF(&str, "m_lastFrameNumberWhereDrawWasCalled = %d; ", m_la
stFrameNumberWhereDrawWasCalled); | |
41 base::StringAppendF(&str, "m_consecutiveFailedDraws = %d; ", m_consecutiveFa
iledDraws); | |
42 base::StringAppendF(&str, "m_maximumNumberOfFailedDrawsBeforeDrawIsForced =
%d; ", m_maximumNumberOfFailedDrawsBeforeDrawIsForced); | |
43 base::StringAppendF(&str, "m_needsRedraw = %d; ", m_needsRedraw); | |
44 base::StringAppendF(&str, "m_needsForcedRedraw = %d; ", m_needsForcedRedraw)
; | |
45 base::StringAppendF(&str, "m_needsForcedRedrawAfterNextCommit = %d; ", m_nee
dsForcedRedrawAfterNextCommit); | |
46 base::StringAppendF(&str, "m_needsCommit = %d; ", m_needsCommit); | |
47 base::StringAppendF(&str, "m_needsForcedCommit = %d; ", m_needsForcedCommit)
; | |
48 base::StringAppendF(&str, "m_mainThreadNeedsLayerTextures = %d; ", m_mainThr
eadNeedsLayerTextures); | |
49 base::StringAppendF(&str, "m_insideVSync = %d; ", m_insideVSync); | |
50 base::StringAppendF(&str, "m_visible = %d; ", m_visible); | |
51 base::StringAppendF(&str, "m_canBeginFrame = %d; ", m_canBeginFrame); | |
52 base::StringAppendF(&str, "m_canDraw = %d; ", m_canDraw); | |
53 base::StringAppendF(&str, "m_drawIfPossibleFailed = %d; ", m_drawIfPossibleF
ailed); | |
54 base::StringAppendF(&str, "m_textureState = %d; ", m_textureState); | |
55 base::StringAppendF(&str, "m_contextState = %d; ", m_contextState); | |
56 return str; | |
57 } | |
58 | |
59 bool CCSchedulerStateMachine::hasDrawnThisFrame() const | |
60 { | |
61 return m_currentFrameNumber == m_lastFrameNumberWhereDrawWasCalled; | |
62 } | |
63 | |
64 bool CCSchedulerStateMachine::drawSuspendedUntilCommit() const | |
65 { | |
66 if (!m_canDraw) | |
67 return true; | |
68 if (!m_visible) | |
69 return true; | |
70 if (m_textureState == LAYER_TEXTURE_STATE_ACQUIRED_BY_MAIN_THREAD) | |
71 return true; | |
72 return false; | |
73 } | |
74 | |
75 bool CCSchedulerStateMachine::scheduledToDraw() const | |
76 { | |
77 if (!m_needsRedraw) | |
78 return false; | |
79 if (drawSuspendedUntilCommit()) | |
80 return false; | |
81 return true; | |
82 } | |
83 | |
84 bool CCSchedulerStateMachine::shouldDraw() const | |
85 { | |
86 if (m_needsForcedRedraw) | |
87 return true; | |
88 | |
89 if (!scheduledToDraw()) | |
90 return false; | |
91 if (!m_insideVSync) | |
92 return false; | |
93 if (hasDrawnThisFrame()) | |
94 return false; | |
95 if (m_contextState != CONTEXT_ACTIVE) | |
96 return false; | |
97 return true; | |
98 } | |
99 | |
100 bool CCSchedulerStateMachine::shouldAcquireLayerTexturesForMainThread() const | |
101 { | |
102 if (!m_mainThreadNeedsLayerTextures) | |
103 return false; | |
104 if (m_textureState == LAYER_TEXTURE_STATE_UNLOCKED) | |
105 return true; | |
106 ASSERT(m_textureState == LAYER_TEXTURE_STATE_ACQUIRED_BY_IMPL_THREAD); | |
107 // Transfer the lock from impl thread to main thread immediately if the | |
108 // impl thread is not even scheduled to draw. Guards against deadlocking. | |
109 if (!scheduledToDraw()) | |
110 return true; | |
111 if (!vsyncCallbackNeeded()) | |
112 return true; | |
113 return false; | |
114 } | |
115 | |
116 CCSchedulerStateMachine::Action CCSchedulerStateMachine::nextAction() const | |
117 { | |
118 if (shouldAcquireLayerTexturesForMainThread()) | |
119 return ACTION_ACQUIRE_LAYER_TEXTURES_FOR_MAIN_THREAD; | |
120 switch (m_commitState) { | |
121 case COMMIT_STATE_IDLE: | |
122 if (m_contextState != CONTEXT_ACTIVE && m_needsForcedRedraw) | |
123 return ACTION_DRAW_FORCED; | |
124 if (m_contextState != CONTEXT_ACTIVE && m_needsForcedCommit) | |
125 return ACTION_BEGIN_FRAME; | |
126 if (m_contextState == CONTEXT_LOST) | |
127 return ACTION_BEGIN_CONTEXT_RECREATION; | |
128 if (m_contextState == CONTEXT_RECREATING) | |
129 return ACTION_NONE; | |
130 if (shouldDraw()) | |
131 return m_needsForcedRedraw ? ACTION_DRAW_FORCED : ACTION_DRAW_IF_POS
SIBLE; | |
132 if (m_needsCommit && ((m_visible && m_canBeginFrame) || m_needsForcedCom
mit)) | |
133 return ACTION_BEGIN_FRAME; | |
134 return ACTION_NONE; | |
135 | |
136 case COMMIT_STATE_FRAME_IN_PROGRESS: | |
137 if (shouldDraw()) | |
138 return m_needsForcedRedraw ? ACTION_DRAW_FORCED : ACTION_DRAW_IF_POS
SIBLE; | |
139 return ACTION_NONE; | |
140 | |
141 case COMMIT_STATE_READY_TO_COMMIT: | |
142 return ACTION_COMMIT; | |
143 | |
144 case COMMIT_STATE_WAITING_FOR_FIRST_DRAW: | |
145 if (shouldDraw() || m_contextState == CONTEXT_LOST) | |
146 return m_needsForcedRedraw ? ACTION_DRAW_FORCED : ACTION_DRAW_IF_POS
SIBLE; | |
147 // COMMIT_STATE_WAITING_FOR_FIRST_DRAW wants to enforce a draw. If m_can
Draw is false | |
148 // or textures are not available, proceed to the next step (similar as i
n COMMIT_STATE_IDLE). | |
149 bool canCommit = m_visible || m_needsForcedCommit; | |
150 if (m_needsCommit && canCommit && drawSuspendedUntilCommit()) | |
151 return ACTION_BEGIN_FRAME; | |
152 return ACTION_NONE; | |
153 } | |
154 ASSERT_NOT_REACHED(); | |
155 return ACTION_NONE; | |
156 } | |
157 | |
158 void CCSchedulerStateMachine::updateState(Action action) | |
159 { | |
160 switch (action) { | |
161 case ACTION_NONE: | |
162 return; | |
163 | |
164 case ACTION_BEGIN_FRAME: | |
165 ASSERT(m_visible || m_needsForcedCommit); | |
166 m_commitState = COMMIT_STATE_FRAME_IN_PROGRESS; | |
167 m_needsCommit = false; | |
168 m_needsForcedCommit = false; | |
169 return; | |
170 | |
171 case ACTION_COMMIT: | |
172 m_commitState = COMMIT_STATE_WAITING_FOR_FIRST_DRAW; | |
173 m_needsRedraw = true; | |
174 if (m_drawIfPossibleFailed) | |
175 m_lastFrameNumberWhereDrawWasCalled = -1; | |
176 | |
177 if (m_needsForcedRedrawAfterNextCommit) { | |
178 m_needsForcedRedrawAfterNextCommit = false; | |
179 m_needsForcedRedraw = true; | |
180 } | |
181 | |
182 m_textureState = LAYER_TEXTURE_STATE_ACQUIRED_BY_IMPL_THREAD; | |
183 return; | |
184 | |
185 case ACTION_DRAW_FORCED: | |
186 case ACTION_DRAW_IF_POSSIBLE: | |
187 m_needsRedraw = false; | |
188 m_needsForcedRedraw = false; | |
189 m_drawIfPossibleFailed = false; | |
190 if (m_insideVSync) | |
191 m_lastFrameNumberWhereDrawWasCalled = m_currentFrameNumber; | |
192 if (m_commitState == COMMIT_STATE_WAITING_FOR_FIRST_DRAW) | |
193 m_commitState = COMMIT_STATE_IDLE; | |
194 if (m_textureState == LAYER_TEXTURE_STATE_ACQUIRED_BY_IMPL_THREAD) | |
195 m_textureState = LAYER_TEXTURE_STATE_UNLOCKED; | |
196 return; | |
197 | |
198 case ACTION_BEGIN_CONTEXT_RECREATION: | |
199 ASSERT(m_commitState == COMMIT_STATE_IDLE); | |
200 ASSERT(m_contextState == CONTEXT_LOST); | |
201 m_contextState = CONTEXT_RECREATING; | |
202 return; | |
203 | |
204 case ACTION_ACQUIRE_LAYER_TEXTURES_FOR_MAIN_THREAD: | |
205 m_textureState = LAYER_TEXTURE_STATE_ACQUIRED_BY_MAIN_THREAD; | |
206 m_mainThreadNeedsLayerTextures = false; | |
207 if (m_commitState != COMMIT_STATE_FRAME_IN_PROGRESS) | |
208 m_needsCommit = true; | |
209 return; | |
210 } | |
211 } | |
212 | |
213 void CCSchedulerStateMachine::setMainThreadNeedsLayerTextures() | |
214 { | |
215 ASSERT(!m_mainThreadNeedsLayerTextures); | |
216 ASSERT(m_textureState != LAYER_TEXTURE_STATE_ACQUIRED_BY_MAIN_THREAD); | |
217 m_mainThreadNeedsLayerTextures = true; | |
218 } | |
219 | |
220 bool CCSchedulerStateMachine::vsyncCallbackNeeded() const | |
221 { | |
222 // If we can't draw, don't tick until we are notified that we can draw again
. | |
223 if (!m_canDraw) | |
224 return false; | |
225 | |
226 if (m_needsForcedRedraw) | |
227 return true; | |
228 | |
229 return m_needsRedraw && m_visible && m_contextState == CONTEXT_ACTIVE; | |
230 } | |
231 | |
232 void CCSchedulerStateMachine::didEnterVSync() | |
233 { | |
234 m_insideVSync = true; | |
235 } | |
236 | |
237 void CCSchedulerStateMachine::didLeaveVSync() | |
238 { | |
239 m_currentFrameNumber++; | |
240 m_insideVSync = false; | |
241 } | |
242 | |
243 void CCSchedulerStateMachine::setVisible(bool visible) | |
244 { | |
245 m_visible = visible; | |
246 } | |
247 | |
248 void CCSchedulerStateMachine::setNeedsRedraw() | |
249 { | |
250 m_needsRedraw = true; | |
251 } | |
252 | |
253 void CCSchedulerStateMachine::setNeedsForcedRedraw() | |
254 { | |
255 m_needsForcedRedraw = true; | |
256 } | |
257 | |
258 void CCSchedulerStateMachine::didDrawIfPossibleCompleted(bool success) | |
259 { | |
260 m_drawIfPossibleFailed = !success; | |
261 if (m_drawIfPossibleFailed) { | |
262 m_needsRedraw = true; | |
263 m_needsCommit = true; | |
264 m_consecutiveFailedDraws++; | |
265 if (m_consecutiveFailedDraws >= m_maximumNumberOfFailedDrawsBeforeDrawIs
Forced) { | |
266 m_consecutiveFailedDraws = 0; | |
267 // We need to force a draw, but it doesn't make sense to do this unt
il | |
268 // we've committed and have new textures. | |
269 m_needsForcedRedrawAfterNextCommit = true; | |
270 } | |
271 } else | |
272 m_consecutiveFailedDraws = 0; | |
273 } | |
274 | |
275 void CCSchedulerStateMachine::setNeedsCommit() | |
276 { | |
277 m_needsCommit = true; | |
278 } | |
279 | |
280 void CCSchedulerStateMachine::setNeedsForcedCommit() | |
281 { | |
282 m_needsForcedCommit = true; | |
283 } | |
284 | |
285 void CCSchedulerStateMachine::beginFrameComplete() | |
286 { | |
287 ASSERT(m_commitState == COMMIT_STATE_FRAME_IN_PROGRESS); | |
288 m_commitState = COMMIT_STATE_READY_TO_COMMIT; | |
289 } | |
290 | |
291 void CCSchedulerStateMachine::beginFrameAborted() | |
292 { | |
293 ASSERT(m_commitState == COMMIT_STATE_FRAME_IN_PROGRESS); | |
294 m_commitState = COMMIT_STATE_IDLE; | |
295 setNeedsCommit(); | |
296 } | |
297 | |
298 void CCSchedulerStateMachine::didLoseContext() | |
299 { | |
300 if (m_contextState == CONTEXT_LOST || m_contextState == CONTEXT_RECREATING) | |
301 return; | |
302 m_contextState = CONTEXT_LOST; | |
303 } | |
304 | |
305 void CCSchedulerStateMachine::didRecreateContext() | |
306 { | |
307 ASSERT(m_contextState == CONTEXT_RECREATING); | |
308 m_contextState = CONTEXT_ACTIVE; | |
309 setNeedsCommit(); | |
310 } | |
311 | |
312 void CCSchedulerStateMachine::setMaximumNumberOfFailedDrawsBeforeDrawIsForced(in
t numDraws) | |
313 { | |
314 m_maximumNumberOfFailedDrawsBeforeDrawIsForced = numDraws; | |
315 } | |
316 | |
317 } | |
OLD | NEW |