Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 "base/auto_reset.h" | 7 #include "base/auto_reset.h" |
| 8 #include "base/debug/trace_event.h" | 8 #include "base/debug/trace_event.h" |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "cc/base/thread.h" | 10 #include "cc/base/thread.h" |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 119 return last_begin_frame_args_.frame_time() + | 119 return last_begin_frame_args_.frame_time() + |
| 120 (last_begin_frame_args_.interval() * intervals); | 120 (last_begin_frame_args_.interval() * intervals); |
| 121 } | 121 } |
| 122 | 122 |
| 123 base::TimeTicks Scheduler::LastBeginFrameOnImplThreadTime() { | 123 base::TimeTicks Scheduler::LastBeginFrameOnImplThreadTime() { |
| 124 return last_begin_frame_args_.frame_time(); | 124 return last_begin_frame_args_.frame_time(); |
| 125 } | 125 } |
| 126 | 126 |
| 127 void Scheduler::SetupNextBeginFrameIfNeeded() { | 127 void Scheduler::SetupNextBeginFrameIfNeeded() { |
| 128 // Determine if we need BeginFrame notifications. | 128 // Determine if we need BeginFrame notifications. |
| 129 // If we do, always request the BeginFrame immediately. | |
| 130 // If not, only disable on the next BeginFrame to avoid unnecessary toggles. | |
| 131 // The synchronous renderer compositor requires immediate disables though. | |
| 132 bool needs_begin_frame = state_machine_.BeginFrameNeededByImplThread(); | 129 bool needs_begin_frame = state_machine_.BeginFrameNeededByImplThread(); |
| 133 if ((needs_begin_frame || | 130 if (settings_.using_synchronous_renderer_compositor) { |
| 134 state_machine_.inside_begin_frame() || | 131 // The synchronous renderer compositor needs immediate enables/disables. |
| 135 settings_.using_synchronous_renderer_compositor) && | 132 if (needs_begin_frame != last_set_needs_begin_frame_) { |
| 136 (needs_begin_frame != last_set_needs_begin_frame_)) { | 133 client_->SetNeedsBeginFrameOnImplThread(needs_begin_frame); |
| 137 client_->SetNeedsBeginFrameOnImplThread(needs_begin_frame); | 134 last_set_needs_begin_frame_ = needs_begin_frame; |
| 138 last_set_needs_begin_frame_ = needs_begin_frame; | 135 } |
| 139 } | 136 } else { |
| 140 | 137 // The non-synchronous renderer compositor is a bit more complicated: |
| 141 // Request another BeginFrame if we haven't drawn for now until we have | 138 if (needs_begin_frame && !last_set_needs_begin_frame_) { |
| 142 // deadlines implemented. | 139 // Always request the BeginFrame immediately if it wasn't needed before. |
| 143 if (state_machine_.inside_begin_frame() && has_pending_begin_frame_) { | 140 client_->SetNeedsBeginFrameOnImplThread(needs_begin_frame); |
|
Sami
2013/06/14 15:59:20
nit: This function might be a little easier to rea
brianderson
2013/06/14 18:42:36
Ok. This could definitely be simplified.
| |
| 144 has_pending_begin_frame_ = false; | 141 last_set_needs_begin_frame_ = needs_begin_frame; |
| 145 client_->SetNeedsBeginFrameOnImplThread(true); | 142 } else if (!needs_begin_frame && last_set_needs_begin_frame_ && |
| 143 has_pending_begin_frame_ && | |
| 144 state_machine_.begin_frame_state() == | |
| 145 SchedulerStateMachine::BEGIN_FRAME_IDLE) { | |
| 146 // Only disable the BeginFrame after a BeginFrame where we didn't swap. | |
| 147 client_->SetNeedsBeginFrameOnImplThread(needs_begin_frame); | |
| 148 last_set_needs_begin_frame_ = needs_begin_frame; | |
| 149 has_pending_begin_frame_ = false; | |
| 150 } else if (needs_begin_frame && has_pending_begin_frame_ && | |
| 151 state_machine_.begin_frame_state() == | |
| 152 SchedulerStateMachine::BEGIN_FRAME_IDLE) { | |
| 153 // We did not draw and swap this BeginFrame, | |
| 154 // so we need to explicitly request another BeginFrame. | |
| 155 client_->SetNeedsBeginFrameOnImplThread(needs_begin_frame); | |
| 156 last_set_needs_begin_frame_ = needs_begin_frame; | |
| 157 has_pending_begin_frame_ = false; | |
| 158 } | |
| 146 } | 159 } |
| 147 } | 160 } |
| 148 | 161 |
| 149 void Scheduler::BeginFrame(BeginFrameArgs args) { | 162 void Scheduler::BeginFrame(BeginFrameArgs args) { |
| 150 TRACE_EVENT0("cc", "Scheduler::BeginFrame"); | 163 TRACE_EVENT0("cc", "Scheduler::BeginFrame"); |
| 151 last_begin_frame_args_ = args; | |
| 152 DCHECK(!has_pending_begin_frame_); | 164 DCHECK(!has_pending_begin_frame_); |
| 153 has_pending_begin_frame_ = true; | 165 has_pending_begin_frame_ = true; |
| 154 last_begin_frame_args_ = args; | 166 last_begin_frame_args_ = args.CreateBeginFrameWithAdjustedDeadline( |
| 155 state_machine_.DidEnterBeginFrame(args); | 167 BeginFrameArgs::DefaultDeadlineAdjustment()); |
| 168 state_machine_.StartBeginFrame(args); | |
| 156 ProcessScheduledActions(); | 169 ProcessScheduledActions(); |
| 157 state_machine_.DidLeaveBeginFrame(); | 170 if (state_machine_.begin_frame_state() == |
| 171 SchedulerStateMachine::BEGIN_FRAME_WAITING) { | |
| 172 client_->PostBeginFrameDeadlineTask(last_begin_frame_args_.deadline()); | |
| 173 } else { | |
| 174 DCHECK_EQ(state_machine_.begin_frame_state(), | |
| 175 SchedulerStateMachine::BEGIN_FRAME_IDLE); | |
| 176 } | |
| 177 } | |
| 178 | |
| 179 void Scheduler::OnBeginFrameDeadline() { | |
| 180 TRACE_EVENT0("cc", "Scheduler::OnBeginFrameDeadline"); | |
| 181 state_machine_.OnBeginFrameDeadline(); | |
| 182 ProcessScheduledActions(); | |
| 158 } | 183 } |
| 159 | 184 |
| 160 void Scheduler::DrawAndSwapIfPossible() { | 185 void Scheduler::DrawAndSwapIfPossible() { |
| 161 ScheduledActionDrawAndSwapResult result = | 186 ScheduledActionDrawAndSwapResult result = |
| 162 client_->ScheduledActionDrawAndSwapIfPossible(); | 187 client_->ScheduledActionDrawAndSwapIfPossible(); |
| 163 state_machine_.DidDrawIfPossibleCompleted(result.did_draw); | 188 state_machine_.DidDrawIfPossibleCompleted(result.did_draw); |
| 164 if (result.did_swap) | 189 if (result.did_swap) |
| 165 has_pending_begin_frame_ = false; | 190 has_pending_begin_frame_ = false; |
| 166 } | 191 } |
| 167 | 192 |
| 168 void Scheduler::DrawAndSwapForced() { | 193 void Scheduler::DrawAndSwapForced() { |
| 169 ScheduledActionDrawAndSwapResult result = | 194 ScheduledActionDrawAndSwapResult result = |
| 170 client_->ScheduledActionDrawAndSwapForced(); | 195 client_->ScheduledActionDrawAndSwapForced(); |
| 171 if (result.did_swap) | 196 if (result.did_swap) |
| 172 has_pending_begin_frame_ = false; | 197 has_pending_begin_frame_ = false; |
| 173 } | 198 } |
| 174 | 199 |
| 175 void Scheduler::ProcessScheduledActions() { | 200 void Scheduler::ProcessScheduledActions() { |
| 176 // We do not allow ProcessScheduledActions to be recursive. | 201 // We do not allow ProcessScheduledActions to be recursive. |
| 177 // The top-level call will iteratively execute the next action for us anyway. | 202 // The top-level call will iteratively execute the next action for us anyway. |
| 178 if (inside_process_scheduled_actions_) | 203 if (inside_process_scheduled_actions_) |
| 179 return; | 204 return; |
| 180 | 205 |
| 181 base::AutoReset<bool> mark_inside(&inside_process_scheduled_actions_, true); | 206 base::AutoReset<bool> mark_inside(&inside_process_scheduled_actions_, true); |
| 182 | 207 |
| 183 SchedulerStateMachine::Action action = state_machine_.NextAction(); | 208 SchedulerStateMachine::Action action; |
| 184 while (action != SchedulerStateMachine::ACTION_NONE) { | 209 do { |
|
brianderson
2013/06/14 04:16:29
Changing to a do-while loop allows UpdateState to
Sami
2013/06/14 15:59:20
Advancing the begin frame state on ACTION_NONE see
brianderson
2013/06/14 18:42:36
It is a bit fishy, but I couldn't think of a simpl
| |
| 210 TRACE_EVENT1("cc", "SchedulerStateMachine", | |
| 211 "state", state_machine_.ToString()); | |
| 212 action = state_machine_.NextAction(); | |
| 185 state_machine_.UpdateState(action); | 213 state_machine_.UpdateState(action); |
| 186 switch (action) { | 214 switch (action) { |
| 187 case SchedulerStateMachine::ACTION_NONE: | 215 case SchedulerStateMachine::ACTION_NONE: |
| 188 break; | 216 break; |
| 189 case SchedulerStateMachine::ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD: | 217 case SchedulerStateMachine::ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD: |
| 190 client_->ScheduledActionSendBeginFrameToMainThread(); | 218 client_->ScheduledActionSendBeginFrameToMainThread(); |
| 191 break; | 219 break; |
| 192 case SchedulerStateMachine::ACTION_COMMIT: | 220 case SchedulerStateMachine::ACTION_COMMIT: |
| 193 client_->ScheduledActionCommit(); | 221 client_->ScheduledActionCommit(); |
| 194 break; | 222 break; |
| 195 case SchedulerStateMachine::ACTION_CHECK_FOR_COMPLETED_TILE_UPLOADS: | 223 case SchedulerStateMachine::ACTION_CHECK_FOR_COMPLETED_TILE_UPLOADS: |
| 196 client_->ScheduledActionCheckForCompletedTileUploads(); | 224 client_->ScheduledActionCheckForCompletedTileUploads(); |
| 197 break; | 225 break; |
| 198 case SchedulerStateMachine::ACTION_ACTIVATE_PENDING_TREE_IF_NEEDED: | 226 case SchedulerStateMachine::ACTION_ACTIVATE_PENDING_TREE_IF_NEEDED: |
| 199 client_->ScheduledActionActivatePendingTreeIfNeeded(); | 227 client_->ScheduledActionActivatePendingTreeIfNeeded(); |
| 200 break; | 228 break; |
| 201 case SchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE: | 229 case SchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE: |
| 202 DrawAndSwapIfPossible(); | 230 DrawAndSwapIfPossible(); |
| 203 break; | 231 break; |
| 204 case SchedulerStateMachine::ACTION_DRAW_FORCED: | 232 case SchedulerStateMachine::ACTION_DRAW_FORCED: |
| 205 DrawAndSwapForced(); | 233 DrawAndSwapForced(); |
| 206 break; | 234 break; |
| 207 case SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION: | 235 case SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION: |
| 208 client_->ScheduledActionBeginOutputSurfaceCreation(); | 236 client_->ScheduledActionBeginOutputSurfaceCreation(); |
| 209 break; | 237 break; |
| 210 case SchedulerStateMachine::ACTION_ACQUIRE_LAYER_TEXTURES_FOR_MAIN_THREAD: | 238 case SchedulerStateMachine::ACTION_ACQUIRE_LAYER_TEXTURES_FOR_MAIN_THREAD: |
| 211 client_->ScheduledActionAcquireLayerTexturesForMainThread(); | 239 client_->ScheduledActionAcquireLayerTexturesForMainThread(); |
| 212 break; | 240 break; |
| 213 } | 241 } |
| 214 action = state_machine_.NextAction(); | 242 } while (action != SchedulerStateMachine::ACTION_NONE); |
| 215 } | |
| 216 | 243 |
| 217 SetupNextBeginFrameIfNeeded(); | 244 SetupNextBeginFrameIfNeeded(); |
| 218 client_->DidAnticipatedDrawTimeChange(AnticipatedDrawTime()); | 245 client_->DidAnticipatedDrawTimeChange(AnticipatedDrawTime()); |
| 219 } | 246 } |
| 220 | 247 |
| 221 bool Scheduler::WillDrawIfNeeded() const { | 248 bool Scheduler::WillDrawIfNeeded() const { |
| 222 return !state_machine_.DrawSuspendedUntilCommit(); | 249 return !state_machine_.DrawSuspendedUntilCommit(); |
| 223 } | 250 } |
| 224 | 251 |
| 225 } // namespace cc | 252 } // namespace cc |
| OLD | NEW |