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 | 11 |
| 11 namespace cc { | 12 namespace cc { |
| 12 | 13 |
| 13 Scheduler::Scheduler(SchedulerClient* client, | 14 Scheduler::Scheduler(SchedulerClient* client, |
| 14 scoped_ptr<FrameRateController> frame_rate_controller, | 15 const SchedulerSettings& scheduler_settings, |
| 15 const SchedulerSettings& scheduler_settings) | 16 Thread *thread) |
| 16 : settings_(scheduler_settings), | 17 : settings_(scheduler_settings), |
| 17 client_(client), | 18 client_(client), |
| 18 frame_rate_controller_(frame_rate_controller.Pass()), | 19 weak_factory_(this), |
| 20 thread_(thread), | |
| 21 last_set_needs_begin_frame_(false), | |
| 22 pending_begin_frames_(0), | |
| 23 incomplete_swaps_(0), | |
| 24 last_begin_frame_time_(base::TimeTicks()), | |
| 25 anticipated_draw_time_(base::TimeTicks::Now()), | |
| 26 //TODO(brianderson): Pass with BeginFrame in the near future. | |
| 27 interval_(base::TimeDelta::FromMicroseconds(16666)), | |
| 19 state_machine_(scheduler_settings), | 28 state_machine_(scheduler_settings), |
| 20 inside_process_scheduled_actions_(false) { | 29 inside_process_scheduled_actions_(false) { |
| 21 DCHECK(client_); | 30 DCHECK(client_); |
| 22 frame_rate_controller_->SetClient(this); | |
| 23 DCHECK(!state_machine_.BeginFrameNeededByImplThread()); | 31 DCHECK(!state_machine_.BeginFrameNeededByImplThread()); |
| 24 } | 32 } |
| 25 | 33 |
| 26 Scheduler::~Scheduler() { frame_rate_controller_->SetActive(false); } | 34 Scheduler::~Scheduler() { |
| 35 client_->SetNeedsBeginFrameOnImplThread(false); | |
| 36 } | |
| 27 | 37 |
| 28 void Scheduler::SetCanStart() { | 38 void Scheduler::SetCanStart() { |
| 29 state_machine_.SetCanStart(); | 39 state_machine_.SetCanStart(); |
| 30 ProcessScheduledActions(); | 40 ProcessScheduledActions(); |
| 31 } | 41 } |
| 32 | 42 |
| 33 void Scheduler::SetVisible(bool visible) { | 43 void Scheduler::SetVisible(bool visible) { |
| 34 state_machine_.SetVisible(visible); | 44 state_machine_.SetVisible(visible); |
| 35 ProcessScheduledActions(); | 45 ProcessScheduledActions(); |
| 36 } | 46 } |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 81 state_machine_.FinishCommit(); | 91 state_machine_.FinishCommit(); |
| 82 ProcessScheduledActions(); | 92 ProcessScheduledActions(); |
| 83 } | 93 } |
| 84 | 94 |
| 85 void Scheduler::BeginFrameAbortedByMainThread() { | 95 void Scheduler::BeginFrameAbortedByMainThread() { |
| 86 TRACE_EVENT0("cc", "Scheduler::BeginFrameAbortedByMainThread"); | 96 TRACE_EVENT0("cc", "Scheduler::BeginFrameAbortedByMainThread"); |
| 87 state_machine_.BeginFrameAbortedByMainThread(); | 97 state_machine_.BeginFrameAbortedByMainThread(); |
| 88 ProcessScheduledActions(); | 98 ProcessScheduledActions(); |
| 89 } | 99 } |
| 90 | 100 |
| 91 void Scheduler::SetMaxFramesPending(int max_frames_pending) { | |
| 92 frame_rate_controller_->SetMaxFramesPending(max_frames_pending); | |
| 93 } | |
| 94 | |
| 95 int Scheduler::MaxFramesPending() const { | |
| 96 return frame_rate_controller_->MaxFramesPending(); | |
| 97 } | |
| 98 | |
| 99 int Scheduler::NumFramesPendingForTesting() const { | |
| 100 return frame_rate_controller_->NumFramesPendingForTesting(); | |
| 101 } | |
| 102 | |
| 103 void Scheduler::SetSwapBuffersCompleteSupported(bool supported) { | |
| 104 frame_rate_controller_->SetSwapBuffersCompleteSupported(supported); | |
| 105 } | |
| 106 | |
| 107 void Scheduler::DidSwapBuffersComplete() { | |
| 108 TRACE_EVENT0("cc", "Scheduler::DidSwapBuffersComplete"); | |
| 109 frame_rate_controller_->DidSwapBuffersComplete(); | |
| 110 } | |
| 111 | |
| 112 void Scheduler::DidLoseOutputSurface() { | 101 void Scheduler::DidLoseOutputSurface() { |
| 113 TRACE_EVENT0("cc", "Scheduler::DidLoseOutputSurface"); | 102 TRACE_EVENT0("cc", "Scheduler::DidLoseOutputSurface"); |
| 114 state_machine_.DidLoseOutputSurface(); | 103 state_machine_.DidLoseOutputSurface(); |
| 115 ProcessScheduledActions(); | 104 ProcessScheduledActions(); |
| 116 } | 105 } |
| 117 | 106 |
| 118 void Scheduler::DidCreateAndInitializeOutputSurface() { | 107 void Scheduler::DidCreateAndInitializeOutputSurface() { |
| 119 TRACE_EVENT0("cc", "Scheduler::DidCreateAndInitializeOutputSurface"); | 108 TRACE_EVENT0("cc", "Scheduler::DidCreateAndInitializeOutputSurface"); |
| 120 frame_rate_controller_->DidAbortAllPendingFrames(); | |
| 121 state_machine_.DidCreateAndInitializeOutputSurface(); | 109 state_machine_.DidCreateAndInitializeOutputSurface(); |
| 110 last_set_needs_begin_frame_ = false; | |
| 122 ProcessScheduledActions(); | 111 ProcessScheduledActions(); |
| 123 } | 112 } |
| 124 | 113 |
| 125 void Scheduler::SetTimebaseAndInterval(base::TimeTicks timebase, | 114 base::TimeTicks Scheduler::AnticipatedDrawTime() { |
| 126 base::TimeDelta interval) { | 115 TRACE_EVENT0("cc", "Scheduler::AnticipatedDrawTime"); |
| 127 frame_rate_controller_->SetTimebaseAndInterval(timebase, interval); | 116 base::TimeTicks now = base::TimeTicks::Now(); |
| 128 } | 117 while (anticipated_draw_time_ < now) { |
|
nduca
2013/06/04 04:53:59
i think delay based timesource has some crap in it
brianderson
2013/06/04 18:33:27
Will change this.
| |
| 118 anticipated_draw_time_ += interval_; | |
| 119 } | |
| 129 | 120 |
| 130 base::TimeTicks Scheduler::AnticipatedDrawTime() { | 121 return anticipated_draw_time_; |
| 131 return frame_rate_controller_->NextTickTime(); | |
| 132 } | 122 } |
| 133 | 123 |
| 134 base::TimeTicks Scheduler::LastBeginFrameOnImplThreadTime() { | 124 base::TimeTicks Scheduler::LastBeginFrameOnImplThreadTime() { |
| 135 return frame_rate_controller_->LastTickTime(); | 125 return last_begin_frame_time_; |
| 136 } | 126 } |
| 137 | 127 |
| 138 void Scheduler::BeginFrame(bool throttled) { | 128 void Scheduler::SetupNextBeginFrameIfNeeded() { |
| 139 TRACE_EVENT1("cc", "Scheduler::BeginFrame", "throttled", throttled); | 129 // Determine if we need BeginFrame notifications. |
| 140 if (!throttled) | 130 // If we do, always request the BeginFrame immediately. |
| 141 state_machine_.DidEnterBeginFrame(); | 131 // If not, only disable on the next BeginFrame to avoid unnecessary toggles. |
| 132 // The synchronous renderer compositor requires immediate disables though. | |
| 133 bool needs_begin_frame = state_machine_.BeginFrameNeededByImplThread(); | |
| 134 if ((needs_begin_frame || | |
| 135 state_machine_.inside_begin_frame() || | |
| 136 settings_.using_synchronous_renderer_compositor) && | |
| 137 (needs_begin_frame != last_set_needs_begin_frame_)) { | |
| 138 client_->SetNeedsBeginFrameOnImplThread(needs_begin_frame); | |
| 139 last_set_needs_begin_frame_ = needs_begin_frame; | |
| 140 } | |
| 141 | |
| 142 if (state_machine_.inside_begin_frame() && pending_begin_frames_) { | |
| 143 // Self tick to retry a BeginFrame where we did not draw. | |
| 144 // TODO(brianderson): Implement smarter polling when deadlines are added. | |
| 145 thread_->PostDelayedTask( | |
| 146 base::Bind(&Scheduler::BeginFrameRetry, weak_factory_.GetWeakPtr()), | |
| 147 interval_); | |
| 148 } | |
| 149 } | |
| 150 | |
| 151 void Scheduler::BeginFrame(base::TimeTicks frame_time) { | |
| 152 TRACE_EVENT0("cc", "Scheduler::BeginFrame"); | |
| 153 pending_begin_frames_++; | |
|
nduca
2013/06/04 04:53:59
okay this bit i dont get. why would we ever have t
brianderson
2013/06/04 18:33:27
In this patch, pending_begin_frames_ will only eve
| |
| 154 last_begin_frame_time_ = frame_time; | |
| 155 anticipated_draw_time_ = frame_time + interval_; | |
| 156 state_machine_.DidEnterBeginFrame(); | |
| 142 ProcessScheduledActions(); | 157 ProcessScheduledActions(); |
| 143 if (!throttled) | 158 state_machine_.DidLeaveBeginFrame(); |
| 144 state_machine_.DidLeaveBeginFrame(); | 159 } |
| 160 | |
| 161 void Scheduler::BeginFrameRetry() { | |
| 162 TRACE_EVENT0("cc", "Scheduler::BeginFrameRetry"); | |
| 163 state_machine_.DidEnterBeginFrame(); | |
| 164 ProcessScheduledActions(); | |
| 165 state_machine_.DidLeaveBeginFrame(); | |
| 166 } | |
| 167 | |
| 168 void Scheduler::DrawAndSwapIfPossible() { | |
| 169 ScheduledActionDrawAndSwapResult result = | |
| 170 client_->ScheduledActionDrawAndSwapIfPossible(); | |
| 171 state_machine_.DidDrawIfPossibleCompleted(result.did_draw); | |
| 172 if (result.did_swap) | |
| 173 pending_begin_frames_--; | |
| 174 } | |
| 175 | |
| 176 void Scheduler::DrawAndSwapForced() { | |
| 177 ScheduledActionDrawAndSwapResult result = | |
| 178 client_->ScheduledActionDrawAndSwapForced(); | |
| 179 if (result.did_swap) | |
| 180 pending_begin_frames_--; | |
| 145 } | 181 } |
| 146 | 182 |
| 147 void Scheduler::ProcessScheduledActions() { | 183 void Scheduler::ProcessScheduledActions() { |
| 148 // We do not allow ProcessScheduledActions to be recursive. | 184 // We do not allow ProcessScheduledActions to be recursive. |
| 149 // The top-level call will iteratively execute the next action for us anyway. | 185 // The top-level call will iteratively execute the next action for us anyway. |
| 150 if (inside_process_scheduled_actions_) | 186 if (inside_process_scheduled_actions_) |
| 151 return; | 187 return; |
| 152 | 188 |
| 153 base::AutoReset<bool> mark_inside(&inside_process_scheduled_actions_, true); | 189 base::AutoReset<bool> mark_inside(&inside_process_scheduled_actions_, true); |
| 154 | 190 |
| 155 SchedulerStateMachine::Action action = state_machine_.NextAction(); | 191 SchedulerStateMachine::Action action = state_machine_.NextAction(); |
| 156 while (action != SchedulerStateMachine::ACTION_NONE) { | 192 while (action != SchedulerStateMachine::ACTION_NONE) { |
| 157 state_machine_.UpdateState(action); | 193 state_machine_.UpdateState(action); |
| 158 TRACE_EVENT1( | 194 TRACE_EVENT2( |
| 159 "cc", "Scheduler::ProcessScheduledActions()", "action", action); | 195 "cc", "Scheduler::ProcessScheduledActions()", |
| 196 "action", action, | |
| 197 "state", state_machine_.ToString()); | |
| 160 | 198 |
| 161 switch (action) { | 199 switch (action) { |
| 162 case SchedulerStateMachine::ACTION_NONE: | 200 case SchedulerStateMachine::ACTION_NONE: |
| 163 break; | 201 break; |
| 164 case SchedulerStateMachine::ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD: | 202 case SchedulerStateMachine::ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD: |
| 165 client_->ScheduledActionSendBeginFrameToMainThread(); | 203 client_->ScheduledActionSendBeginFrameToMainThread(); |
| 166 break; | 204 break; |
| 167 case SchedulerStateMachine::ACTION_COMMIT: | 205 case SchedulerStateMachine::ACTION_COMMIT: |
| 168 client_->ScheduledActionCommit(); | 206 client_->ScheduledActionCommit(); |
| 169 break; | 207 break; |
| 170 case SchedulerStateMachine::ACTION_CHECK_FOR_COMPLETED_TILE_UPLOADS: | 208 case SchedulerStateMachine::ACTION_CHECK_FOR_COMPLETED_TILE_UPLOADS: |
| 171 client_->ScheduledActionCheckForCompletedTileUploads(); | 209 client_->ScheduledActionCheckForCompletedTileUploads(); |
| 172 break; | 210 break; |
| 173 case SchedulerStateMachine::ACTION_ACTIVATE_PENDING_TREE_IF_NEEDED: | 211 case SchedulerStateMachine::ACTION_ACTIVATE_PENDING_TREE_IF_NEEDED: |
| 174 client_->ScheduledActionActivatePendingTreeIfNeeded(); | 212 client_->ScheduledActionActivatePendingTreeIfNeeded(); |
| 175 break; | 213 break; |
| 176 case SchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE: { | 214 case SchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE: |
| 177 ScheduledActionDrawAndSwapResult result = | 215 DrawAndSwapIfPossible(); |
| 178 client_->ScheduledActionDrawAndSwapIfPossible(); | |
| 179 state_machine_.DidDrawIfPossibleCompleted(result.did_draw); | |
| 180 if (result.did_swap) | |
| 181 frame_rate_controller_->DidSwapBuffers(); | |
| 182 break; | 216 break; |
| 183 } | 217 case SchedulerStateMachine::ACTION_DRAW_FORCED: |
| 184 case SchedulerStateMachine::ACTION_DRAW_FORCED: { | 218 DrawAndSwapForced(); |
| 185 ScheduledActionDrawAndSwapResult result = | |
| 186 client_->ScheduledActionDrawAndSwapForced(); | |
| 187 if (result.did_swap) | |
| 188 frame_rate_controller_->DidSwapBuffers(); | |
| 189 break; | 219 break; |
| 190 } | |
| 191 case SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION: | 220 case SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION: |
| 192 client_->ScheduledActionBeginOutputSurfaceCreation(); | 221 client_->ScheduledActionBeginOutputSurfaceCreation(); |
| 193 break; | 222 break; |
| 194 case SchedulerStateMachine::ACTION_ACQUIRE_LAYER_TEXTURES_FOR_MAIN_THREAD: | 223 case SchedulerStateMachine::ACTION_ACQUIRE_LAYER_TEXTURES_FOR_MAIN_THREAD: |
| 195 client_->ScheduledActionAcquireLayerTexturesForMainThread(); | 224 client_->ScheduledActionAcquireLayerTexturesForMainThread(); |
| 196 break; | 225 break; |
| 197 } | 226 } |
| 198 action = state_machine_.NextAction(); | 227 action = state_machine_.NextAction(); |
| 199 } | 228 } |
| 200 | 229 |
| 201 // Activate or deactivate the frame rate controller. | 230 SetupNextBeginFrameIfNeeded(); |
|
nduca
2013/06/04 04:53:59
This feels like more data suggesting that the task
brianderson
2013/06/04 18:33:27
I will revisit this idea in future patches that ad
| |
| 202 frame_rate_controller_->SetActive( | 231 client_->DidAnticipatedDrawTimeChange(AnticipatedDrawTime()); |
|
nduca
2013/06/04 04:53:59
so, if you actually look at who needs this, its th
brianderson
2013/06/04 18:33:27
This patch is already pretty big, so I opened anot
| |
| 203 state_machine_.BeginFrameNeededByImplThread()); | |
| 204 client_->DidAnticipatedDrawTimeChange(frame_rate_controller_->NextTickTime()); | |
| 205 } | 232 } |
| 206 | 233 |
| 207 bool Scheduler::WillDrawIfNeeded() const { | 234 bool Scheduler::WillDrawIfNeeded() const { |
| 208 return !state_machine_.DrawSuspendedUntilCommit(); | 235 return !state_machine_.DrawSuspendedUntilCommit(); |
| 209 } | 236 } |
| 210 | 237 |
| 211 } // namespace cc | 238 } // namespace cc |
| OLD | NEW |