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/base/thread.h" | |
| 5 #include "cc/scheduler/scheduler.h" | 6 #include "cc/scheduler/scheduler.h" |
| 7 #include "cc/trees/proxy.h" | |
| 6 | 8 |
| 7 #include "base/auto_reset.h" | 9 #include "base/auto_reset.h" |
| 8 #include "base/debug/trace_event.h" | 10 #include "base/debug/trace_event.h" |
| 9 #include "base/logging.h" | 11 #include "base/logging.h" |
| 10 | 12 |
| 11 namespace cc { | 13 namespace cc { |
| 12 | 14 |
| 13 Scheduler::Scheduler(SchedulerClient* client, | 15 Scheduler::Scheduler(SchedulerClient* client, |
| 14 scoped_ptr<FrameRateController> frame_rate_controller, | 16 const SchedulerSettings& scheduler_settings, |
| 15 const SchedulerSettings& scheduler_settings) | 17 Thread *thread) |
| 16 : settings_(scheduler_settings), | 18 : settings_(scheduler_settings), |
| 17 client_(client), | 19 client_(client), |
| 18 frame_rate_controller_(frame_rate_controller.Pass()), | 20 weak_factory_(this), |
| 21 thread_(thread), | |
| 22 last_set_needs_begin_frame_(false), | |
| 23 pending_begin_frames_(0), | |
| 24 last_begin_frame_time_(base::TimeTicks::Now()), | |
| 25 //TODO(brianderson): Pass with BeginFrame in the near future. | |
| 26 interval_(base::TimeDelta::FromMicroseconds(16666)), | |
| 19 state_machine_(scheduler_settings), | 27 state_machine_(scheduler_settings), |
| 20 inside_process_scheduled_actions_(false) { | 28 inside_process_scheduled_actions_(false) { |
| 21 DCHECK(client_); | 29 DCHECK(client_); |
| 22 frame_rate_controller_->SetClient(this); | |
| 23 DCHECK(!state_machine_.BeginFrameNeededByImplThread()); | 30 DCHECK(!state_machine_.BeginFrameNeededByImplThread()); |
| 24 } | 31 } |
| 25 | 32 |
| 26 Scheduler::~Scheduler() { frame_rate_controller_->SetActive(false); } | 33 Scheduler::~Scheduler() { |
| 34 client_->SetNeedsBeginFrameOnImplThread(false); | |
| 35 } | |
| 27 | 36 |
| 28 void Scheduler::SetCanStart() { | 37 void Scheduler::SetCanStart() { |
| 29 state_machine_.SetCanStart(); | 38 state_machine_.SetCanStart(); |
| 30 ProcessScheduledActions(); | 39 ProcessScheduledActions(); |
| 31 } | 40 } |
| 32 | 41 |
| 33 void Scheduler::SetVisible(bool visible) { | 42 void Scheduler::SetVisible(bool visible) { |
| 34 state_machine_.SetVisible(visible); | 43 state_machine_.SetVisible(visible); |
| 35 ProcessScheduledActions(); | 44 ProcessScheduledActions(); |
| 36 } | 45 } |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 81 state_machine_.FinishCommit(); | 90 state_machine_.FinishCommit(); |
| 82 ProcessScheduledActions(); | 91 ProcessScheduledActions(); |
| 83 } | 92 } |
| 84 | 93 |
| 85 void Scheduler::BeginFrameAbortedByMainThread() { | 94 void Scheduler::BeginFrameAbortedByMainThread() { |
| 86 TRACE_EVENT0("cc", "Scheduler::BeginFrameAbortedByMainThread"); | 95 TRACE_EVENT0("cc", "Scheduler::BeginFrameAbortedByMainThread"); |
| 87 state_machine_.BeginFrameAbortedByMainThread(); | 96 state_machine_.BeginFrameAbortedByMainThread(); |
| 88 ProcessScheduledActions(); | 97 ProcessScheduledActions(); |
| 89 } | 98 } |
| 90 | 99 |
| 91 void Scheduler::SetMaxFramesPending(int max_frames_pending) { | 100 void Scheduler::DidSwapBuffers() { |
| 92 frame_rate_controller_->SetMaxFramesPending(max_frames_pending); | 101 pending_begin_frames_--; |
| 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 } | 102 } |
| 111 | 103 |
| 112 void Scheduler::DidLoseOutputSurface() { | 104 void Scheduler::DidLoseOutputSurface() { |
| 113 TRACE_EVENT0("cc", "Scheduler::DidLoseOutputSurface"); | 105 TRACE_EVENT0("cc", "Scheduler::DidLoseOutputSurface"); |
| 114 state_machine_.DidLoseOutputSurface(); | 106 state_machine_.DidLoseOutputSurface(); |
| 115 ProcessScheduledActions(); | 107 ProcessScheduledActions(); |
| 116 } | 108 } |
| 117 | 109 |
| 118 void Scheduler::DidCreateAndInitializeOutputSurface() { | 110 void Scheduler::DidCreateAndInitializeOutputSurface() { |
| 119 TRACE_EVENT0("cc", "Scheduler::DidCreateAndInitializeOutputSurface"); | 111 TRACE_EVENT0("cc", "Scheduler::DidCreateAndInitializeOutputSurface"); |
| 120 frame_rate_controller_->DidAbortAllPendingFrames(); | |
| 121 state_machine_.DidCreateAndInitializeOutputSurface(); | 112 state_machine_.DidCreateAndInitializeOutputSurface(); |
| 113 last_set_needs_begin_frame_ = false; | |
| 122 ProcessScheduledActions(); | 114 ProcessScheduledActions(); |
| 123 } | 115 } |
| 124 | 116 |
| 125 void Scheduler::SetTimebaseAndInterval(base::TimeTicks timebase, | 117 base::TimeTicks Scheduler::AnticipatedDrawTime() { |
| 126 base::TimeDelta interval) { | 118 TRACE_EVENT0("cc", "Scheduler::AnticipatedDrawTime"); |
| 127 frame_rate_controller_->SetTimebaseAndInterval(timebase, interval); | 119 base::TimeTicks now = base::TimeTicks::Now(); |
| 128 } | 120 base::TimeTicks draw_time = last_begin_frame_time_; |
| 121 while (draw_time < now) { | |
| 122 draw_time += interval_; | |
| 123 } | |
|
brianderson
2013/06/01 04:30:29
This is way hacky, but will be hard to improve unt
Sami
2013/06/03 17:30:33
Is this the only instance where we're requesting a
brianderson
2013/06/03 18:51:40
Later we'll want to request a new BeginFrame anyti
| |
| 129 | 124 |
| 130 base::TimeTicks Scheduler::AnticipatedDrawTime() { | 125 return draw_time; |
| 131 return frame_rate_controller_->NextTickTime(); | |
| 132 } | 126 } |
| 133 | 127 |
| 134 base::TimeTicks Scheduler::LastBeginFrameOnImplThreadTime() { | 128 base::TimeTicks Scheduler::LastBeginFrameOnImplThreadTime() { |
| 135 return frame_rate_controller_->LastTickTime(); | 129 return last_begin_frame_time_; |
| 136 } | 130 } |
| 137 | 131 |
| 138 void Scheduler::BeginFrame(bool throttled) { | 132 void Scheduler::SetNeedsBeginFrameIfNeeded() { |
| 139 TRACE_EVENT1("cc", "Scheduler::BeginFrame", "throttled", throttled); | 133 // Determine if we need BeginFrame notifications. |
| 140 if (!throttled) | 134 // If we do, always request the BeginFrame immediately. |
| 141 state_machine_.DidEnterBeginFrame(); | 135 // If not, only disable on the next BeginFrame to avoid unnecessary toggles. |
| 136 // The synchronous renderer compositor requires immediate disables though. | |
| 137 bool needs_begin_frame = state_machine_.BeginFrameNeededByImplThread(); | |
| 138 if ((needs_begin_frame || | |
| 139 state_machine_.inside_begin_frame() || | |
| 140 settings_.using_synchronous_renderer_compositor) && | |
| 141 (needs_begin_frame != last_set_needs_begin_frame_)) { | |
|
brianderson
2013/06/01 04:30:29
I'll need someone working on the synchronous compo
| |
| 142 client_->SetNeedsBeginFrameOnImplThread(needs_begin_frame); | |
| 143 last_set_needs_begin_frame_ = needs_begin_frame; | |
| 144 } | |
| 145 | |
| 146 if (state_machine_.inside_begin_frame()) { | |
| 147 if (pending_begin_frames_ && !needs_begin_frame) { | |
| 148 // Balance out the unhandled BeginFrames with Swaps. | |
| 149 // TODO(brianderson): Replace this duplicate swap with a "SwapSkip". | |
|
brianderson
2013/06/01 04:30:29
I should move this into a function; it's duplicate
| |
| 150 ScheduledActionDrawAndSwapResult result = | |
| 151 client_->ScheduledActionDrawAndSwapForced(); | |
| 152 if (result.did_swap) | |
| 153 DidSwapBuffers(); | |
| 154 } | |
| 155 if (pending_begin_frames_) { | |
| 156 // Self tick to retry a failed BeginFrame | |
| 157 // TODO(brianderson): Implement smarter polling when deadlines are added. | |
| 158 thread_->PostDelayedTask( | |
| 159 base::Bind(&Scheduler::BeginFrameRetry, weak_factory_.GetWeakPtr()), | |
| 160 interval_); | |
| 161 } | |
| 162 } | |
| 163 } | |
| 164 | |
| 165 void Scheduler::BeginFrame(base::TimeTicks frame_time) { | |
| 166 TRACE_EVENT0("cc", "Scheduler::BeginFrame"); | |
| 167 pending_begin_frames_++; | |
| 168 last_begin_frame_time_ = frame_time; | |
| 169 state_machine_.DidEnterBeginFrame(); | |
| 142 ProcessScheduledActions(); | 170 ProcessScheduledActions(); |
| 143 if (!throttled) | 171 state_machine_.DidLeaveBeginFrame(); |
| 144 state_machine_.DidLeaveBeginFrame(); | 172 } |
| 173 | |
| 174 void Scheduler::BeginFrameRetry() { | |
| 175 TRACE_EVENT0("cc", "Scheduler::BeginFrameRetry"); | |
| 176 state_machine_.DidEnterBeginFrame(); | |
| 177 ProcessScheduledActions(); | |
| 178 state_machine_.DidLeaveBeginFrame(); | |
| 145 } | 179 } |
| 146 | 180 |
| 147 void Scheduler::ProcessScheduledActions() { | 181 void Scheduler::ProcessScheduledActions() { |
| 148 // We do not allow ProcessScheduledActions to be recursive. | 182 // We do not allow ProcessScheduledActions to be recursive. |
| 149 // The top-level call will iteratively execute the next action for us anyway. | 183 // The top-level call will iteratively execute the next action for us anyway. |
| 150 if (inside_process_scheduled_actions_) | 184 if (inside_process_scheduled_actions_) |
| 151 return; | 185 return; |
| 152 | 186 |
| 153 base::AutoReset<bool> mark_inside(&inside_process_scheduled_actions_, true); | 187 base::AutoReset<bool> mark_inside(&inside_process_scheduled_actions_, true); |
| 154 | 188 |
| 155 SchedulerStateMachine::Action action = state_machine_.NextAction(); | 189 SchedulerStateMachine::Action action = state_machine_.NextAction(); |
| 156 while (action != SchedulerStateMachine::ACTION_NONE) { | 190 while (action != SchedulerStateMachine::ACTION_NONE) { |
| 157 state_machine_.UpdateState(action); | 191 state_machine_.UpdateState(action); |
| 158 TRACE_EVENT1( | 192 TRACE_EVENT2( |
| 159 "cc", "Scheduler::ProcessScheduledActions()", "action", action); | 193 "cc", "Scheduler::ProcessScheduledActions()", |
| 194 "action", action, | |
| 195 "state", state_machine_.ToString()); | |
| 160 | 196 |
| 161 switch (action) { | 197 switch (action) { |
| 162 case SchedulerStateMachine::ACTION_NONE: | 198 case SchedulerStateMachine::ACTION_NONE: |
| 163 break; | 199 break; |
| 164 case SchedulerStateMachine::ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD: | 200 case SchedulerStateMachine::ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD: |
| 165 client_->ScheduledActionSendBeginFrameToMainThread(); | 201 client_->ScheduledActionSendBeginFrameToMainThread(); |
| 166 break; | 202 break; |
| 167 case SchedulerStateMachine::ACTION_COMMIT: | 203 case SchedulerStateMachine::ACTION_COMMIT: |
| 168 client_->ScheduledActionCommit(); | 204 client_->ScheduledActionCommit(); |
| 169 break; | 205 break; |
| 170 case SchedulerStateMachine::ACTION_CHECK_FOR_COMPLETED_TILE_UPLOADS: | 206 case SchedulerStateMachine::ACTION_CHECK_FOR_COMPLETED_TILE_UPLOADS: |
| 171 client_->ScheduledActionCheckForCompletedTileUploads(); | 207 client_->ScheduledActionCheckForCompletedTileUploads(); |
| 172 break; | 208 break; |
| 173 case SchedulerStateMachine::ACTION_ACTIVATE_PENDING_TREE_IF_NEEDED: | 209 case SchedulerStateMachine::ACTION_ACTIVATE_PENDING_TREE_IF_NEEDED: |
| 174 client_->ScheduledActionActivatePendingTreeIfNeeded(); | 210 client_->ScheduledActionActivatePendingTreeIfNeeded(); |
| 175 break; | 211 break; |
| 176 case SchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE: { | 212 case SchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE: { |
| 177 ScheduledActionDrawAndSwapResult result = | 213 ScheduledActionDrawAndSwapResult result = |
| 178 client_->ScheduledActionDrawAndSwapIfPossible(); | 214 client_->ScheduledActionDrawAndSwapIfPossible(); |
| 179 state_machine_.DidDrawIfPossibleCompleted(result.did_draw); | 215 state_machine_.DidDrawIfPossibleCompleted(result.did_draw); |
| 180 if (result.did_swap) | 216 if (result.did_swap) |
| 181 frame_rate_controller_->DidSwapBuffers(); | 217 DidSwapBuffers(); |
| 182 break; | 218 break; |
| 183 } | 219 } |
| 184 case SchedulerStateMachine::ACTION_DRAW_FORCED: { | 220 case SchedulerStateMachine::ACTION_DRAW_FORCED: { |
| 185 ScheduledActionDrawAndSwapResult result = | 221 ScheduledActionDrawAndSwapResult result = |
| 186 client_->ScheduledActionDrawAndSwapForced(); | 222 client_->ScheduledActionDrawAndSwapForced(); |
| 187 if (result.did_swap) | 223 if (result.did_swap) |
| 188 frame_rate_controller_->DidSwapBuffers(); | 224 DidSwapBuffers(); |
| 189 break; | 225 break; |
| 190 } | 226 } |
| 191 case SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION: | 227 case SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION: |
| 192 client_->ScheduledActionBeginOutputSurfaceCreation(); | 228 client_->ScheduledActionBeginOutputSurfaceCreation(); |
| 193 break; | 229 break; |
| 194 case SchedulerStateMachine::ACTION_ACQUIRE_LAYER_TEXTURES_FOR_MAIN_THREAD: | 230 case SchedulerStateMachine::ACTION_ACQUIRE_LAYER_TEXTURES_FOR_MAIN_THREAD: |
| 195 client_->ScheduledActionAcquireLayerTexturesForMainThread(); | 231 client_->ScheduledActionAcquireLayerTexturesForMainThread(); |
| 196 break; | 232 break; |
| 197 } | 233 } |
| 198 action = state_machine_.NextAction(); | 234 action = state_machine_.NextAction(); |
| 199 } | 235 } |
| 200 | 236 |
| 201 // Activate or deactivate the frame rate controller. | 237 SetNeedsBeginFrameIfNeeded(); |
| 202 frame_rate_controller_->SetActive( | 238 client_->DidAnticipatedDrawTimeChange(AnticipatedDrawTime()); |
| 203 state_machine_.BeginFrameNeededByImplThread()); | |
| 204 client_->DidAnticipatedDrawTimeChange(frame_rate_controller_->NextTickTime()); | |
| 205 } | 239 } |
| 206 | 240 |
| 207 bool Scheduler::WillDrawIfNeeded() const { | 241 bool Scheduler::WillDrawIfNeeded() const { |
| 208 return !state_machine_.DrawSuspendedUntilCommit(); | 242 return !state_machine_.DrawSuspendedUntilCommit(); |
| 209 } | 243 } |
| 210 | 244 |
| 211 } // namespace cc | 245 } // namespace cc |
| OLD | NEW |