| 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 |