| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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/surfaces/display_scheduler.h" | 5 #include "cc/surfaces/display_scheduler.h" |
| 6 | 6 |
| 7 #include <vector> | 7 #include <vector> |
| 8 | 8 |
| 9 #include "base/auto_reset.h" | 9 #include "base/auto_reset.h" |
| 10 #include "base/stl_util.h" | 10 #include "base/stl_util.h" |
| 11 #include "base/trace_event/trace_event.h" | 11 #include "base/trace_event/trace_event.h" |
| 12 #include "cc/output/output_surface.h" | 12 #include "cc/output/output_surface.h" |
| 13 | 13 |
| 14 namespace cc { | 14 namespace cc { |
| 15 | 15 |
| 16 DisplayScheduler::DisplayScheduler(BeginFrameSource* begin_frame_source, | 16 DisplayScheduler::DisplayScheduler(base::SingleThreadTaskRunner* task_runner, |
| 17 base::SingleThreadTaskRunner* task_runner, | |
| 18 int max_pending_swaps) | 17 int max_pending_swaps) |
| 19 : begin_frame_source_(begin_frame_source), | 18 : client_(nullptr), |
| 19 begin_frame_source_(nullptr), |
| 20 task_runner_(task_runner), | 20 task_runner_(task_runner), |
| 21 inside_surface_damaged_(false), | 21 inside_surface_damaged_(false), |
| 22 visible_(false), | 22 visible_(false), |
| 23 output_surface_lost_(false), | 23 output_surface_lost_(false), |
| 24 root_surface_resources_locked_(true), | 24 root_surface_resources_locked_(true), |
| 25 inside_begin_frame_deadline_interval_(false), | 25 inside_begin_frame_deadline_interval_(false), |
| 26 needs_draw_(false), | 26 needs_draw_(false), |
| 27 expecting_root_surface_damage_because_of_resize_(false), | 27 expecting_root_surface_damage_because_of_resize_(false), |
| 28 all_active_child_surfaces_ready_to_draw_(false), | |
| 29 pending_swaps_(0), | 28 pending_swaps_(0), |
| 30 max_pending_swaps_(max_pending_swaps), | 29 max_pending_swaps_(max_pending_swaps), |
| 31 observing_begin_frame_source_(false), | 30 observing_begin_frames_(false), |
| 32 root_surface_damaged_(false), | |
| 33 expect_damage_from_root_surface_(false), | |
| 34 weak_ptr_factory_(this) { | 31 weak_ptr_factory_(this) { |
| 35 begin_frame_deadline_closure_ = base::Bind( | 32 begin_frame_deadline_closure_ = base::Bind( |
| 36 &DisplayScheduler::OnBeginFrameDeadline, weak_ptr_factory_.GetWeakPtr()); | 33 &DisplayScheduler::OnBeginFrameDeadline, weak_ptr_factory_.GetWeakPtr()); |
| 37 } | 34 } |
| 38 | 35 |
| 39 DisplayScheduler::~DisplayScheduler() { | 36 DisplayScheduler::~DisplayScheduler() { |
| 40 StopObservingBeginFrames(); | 37 StopObservingBeginFrames(); |
| 41 } | 38 } |
| 42 | 39 |
| 43 void DisplayScheduler::SetClient(DisplaySchedulerClient* client) { | 40 void DisplayScheduler::SetClient(DisplaySchedulerClient* client) { |
| 44 client_ = client; | 41 client_ = client; |
| 45 } | 42 } |
| 46 | 43 |
| 44 void DisplayScheduler::SetBeginFrameSource( |
| 45 DisplayBeginFrameSource* begin_frame_source) { |
| 46 begin_frame_source_ = begin_frame_source; |
| 47 begin_frame_source_->SetClient(this); |
| 48 } |
| 49 |
| 47 void DisplayScheduler::SetVisible(bool visible) { | 50 void DisplayScheduler::SetVisible(bool visible) { |
| 48 if (visible_ == visible) | 51 if (visible_ == visible) |
| 49 return; | 52 return; |
| 50 | 53 |
| 51 visible_ = visible; | 54 visible_ = visible; |
| 52 // If going invisible, we'll stop observing begin frames once we try | 55 // If going invisible, we'll stop observing begin frames once we try |
| 53 // to draw and fail. | 56 // to draw and fail. |
| 54 StartObservingBeginFrames(); | 57 StartObservingBeginFrames(); |
| 55 ScheduleBeginFrameDeadline(); | 58 ScheduleBeginFrameDeadline(); |
| 56 } | 59 } |
| 57 | 60 |
| 58 // If we try to draw when the root surface resources are locked, the | 61 // If we try to draw when the root surface resources are locked, the |
| 59 // draw will fail. | 62 // draw will fail. |
| 60 void DisplayScheduler::SetRootSurfaceResourcesLocked(bool locked) { | 63 void DisplayScheduler::SetRootSurfaceResourcesLocked(bool locked) { |
| 61 TRACE_EVENT1("cc", "DisplayScheduler::SetRootSurfaceResourcesLocked", | 64 TRACE_EVENT1("cc", "DisplayScheduler::SetRootSurfaceResourcesLocked", |
| 62 "locked", locked); | 65 "locked", locked); |
| 63 root_surface_resources_locked_ = locked; | 66 root_surface_resources_locked_ = locked; |
| 64 ScheduleBeginFrameDeadline(); | 67 ScheduleBeginFrameDeadline(); |
| 65 } | 68 } |
| 66 | 69 |
| 67 // This is used to force an immediate swap before a resize. | 70 // This is used to force an immediate swap before a resize. |
| 68 void DisplayScheduler::ForceImmediateSwapIfPossible() { | 71 void DisplayScheduler::ForceImmediateSwapIfPossible() { |
| 69 TRACE_EVENT0("cc", "DisplayScheduler::ForceImmediateSwapIfPossible"); | 72 TRACE_EVENT0("cc", "DisplayScheduler::ForceImmediateSwapIfPossible"); |
| 70 bool in_begin = inside_begin_frame_deadline_interval_; | 73 bool in_begin = inside_begin_frame_deadline_interval_; |
| 71 AttemptDrawAndSwap(); | 74 bool did_draw = AttemptDrawAndSwap(); |
| 72 if (in_begin) | 75 if (in_begin) |
| 73 begin_frame_source_->DidFinishFrame(this, 0); | 76 begin_frame_source_->FinishClientFrame(did_draw, needs_draw_); |
| 74 } | 77 } |
| 75 | 78 |
| 76 void DisplayScheduler::DisplayResized() { | 79 void DisplayScheduler::DisplayResized() { |
| 77 expecting_root_surface_damage_because_of_resize_ = true; | 80 expecting_root_surface_damage_because_of_resize_ = true; |
| 78 expect_damage_from_root_surface_ = true; | |
| 79 needs_draw_ = true; | 81 needs_draw_ = true; |
| 80 ScheduleBeginFrameDeadline(); | 82 ScheduleBeginFrameDeadline(); |
| 81 } | 83 } |
| 82 | 84 |
| 83 // Notification that there was a resize or the root surface changed and | 85 // Notification that there was a resize or the root surface changed and |
| 84 // that we should just draw immediately. | 86 // that we should just draw immediately. |
| 85 void DisplayScheduler::SetNewRootSurface(const SurfaceId& root_surface_id) { | 87 void DisplayScheduler::SetNewRootSurface(const SurfaceId& root_surface_id) { |
| 86 TRACE_EVENT0("cc", "DisplayScheduler::SetNewRootSurface"); | 88 TRACE_EVENT0("cc", "DisplayScheduler::SetNewRootSurface"); |
| 87 root_surface_id_ = root_surface_id; | 89 root_surface_id_ = root_surface_id; |
| 88 SurfaceDamaged(root_surface_id); | 90 SurfaceDamaged(root_surface_id); |
| 89 } | 91 } |
| 90 | 92 |
| 91 // Indicates that there was damage to one of the surfaces. | 93 // Indicates that there was damage to one of the surfaces. |
| 92 // Has some logic to wait for multiple active surfaces before | 94 // Has some logic to wait for multiple active surfaces before |
| 93 // triggering the deadline. | 95 // triggering the deadline. |
| 94 void DisplayScheduler::SurfaceDamaged(const SurfaceId& surface_id) { | 96 void DisplayScheduler::SurfaceDamaged(const SurfaceId& surface_id) { |
| 95 TRACE_EVENT1("cc", "DisplayScheduler::SurfaceDamaged", "surface_id", | 97 TRACE_EVENT1("cc", "DisplayScheduler::SurfaceDamaged", "surface_id", |
| 96 surface_id.ToString()); | 98 surface_id.ToString()); |
| 97 | 99 |
| 98 // We may cause a new BeginFrame to be run inside this method, but to help | 100 // We may cause a new BeginFrame to be run inside this method, but to help |
| 99 // avoid being reentrant to the caller of SurfaceDamaged, track when this is | 101 // avoid being reentrant to the caller of SurfaceDamaged, track when this is |
| 100 // happening with |inside_surface_damaged_|. | 102 // happening with |inside_surface_damaged_|. |
| 101 base::AutoReset<bool> auto_reset(&inside_surface_damaged_, true); | 103 base::AutoReset<bool> auto_reset(&inside_surface_damaged_, true); |
| 102 | 104 |
| 103 needs_draw_ = true; | 105 needs_draw_ = true; |
| 104 | 106 |
| 105 if (surface_id == root_surface_id_) { | 107 if (surface_id == root_surface_id_) |
| 106 root_surface_damaged_ = true; | |
| 107 expecting_root_surface_damage_because_of_resize_ = false; | 108 expecting_root_surface_damage_because_of_resize_ = false; |
| 108 } else { | |
| 109 child_surface_ids_damaged_.insert(surface_id); | |
| 110 | |
| 111 // TODO(mithro): Use hints from SetNeedsBeginFrames and SwapAborts. | |
| 112 all_active_child_surfaces_ready_to_draw_ = base::STLIncludes( | |
| 113 child_surface_ids_damaged_, child_surface_ids_to_expect_damage_from_); | |
| 114 } | |
| 115 | 109 |
| 116 StartObservingBeginFrames(); | 110 StartObservingBeginFrames(); |
| 117 ScheduleBeginFrameDeadline(); | 111 ScheduleBeginFrameDeadline(); |
| 118 } | 112 } |
| 119 | 113 |
| 120 void DisplayScheduler::OutputSurfaceLost() { | 114 void DisplayScheduler::OutputSurfaceLost() { |
| 121 TRACE_EVENT0("cc", "DisplayScheduler::OutputSurfaceLost"); | 115 TRACE_EVENT0("cc", "DisplayScheduler::OutputSurfaceLost"); |
| 122 output_surface_lost_ = true; | 116 output_surface_lost_ = true; |
| 123 ScheduleBeginFrameDeadline(); | 117 ScheduleBeginFrameDeadline(); |
| 124 } | 118 } |
| 125 | 119 |
| 126 void DisplayScheduler::DrawAndSwap() { | 120 bool DisplayScheduler::DrawAndSwap() { |
| 127 TRACE_EVENT0("cc", "DisplayScheduler::DrawAndSwap"); | 121 TRACE_EVENT0("cc", "DisplayScheduler::DrawAndSwap"); |
| 128 DCHECK_LT(pending_swaps_, max_pending_swaps_); | 122 DCHECK_LT(pending_swaps_, max_pending_swaps_); |
| 129 DCHECK(!output_surface_lost_); | 123 DCHECK(!output_surface_lost_); |
| 130 | 124 |
| 131 bool success = client_->DrawAndSwap(); | 125 bool success = client_->DrawAndSwap(); |
| 132 if (!success) | 126 if (!success) |
| 133 return; | 127 return false; |
| 134 | |
| 135 child_surface_ids_to_expect_damage_from_ = | |
| 136 base::STLSetIntersection<std::vector<SurfaceId>>( | |
| 137 child_surface_ids_damaged_, child_surface_ids_damaged_prev_); | |
| 138 | |
| 139 child_surface_ids_damaged_prev_.swap(child_surface_ids_damaged_); | |
| 140 child_surface_ids_damaged_.clear(); | |
| 141 | 128 |
| 142 needs_draw_ = false; | 129 needs_draw_ = false; |
| 143 all_active_child_surfaces_ready_to_draw_ = | 130 return true; |
| 144 child_surface_ids_to_expect_damage_from_.empty(); | |
| 145 | |
| 146 expect_damage_from_root_surface_ = root_surface_damaged_; | |
| 147 root_surface_damaged_ = false; | |
| 148 } | 131 } |
| 149 | 132 |
| 150 bool DisplayScheduler::OnBeginFrameDerivedImpl(const BeginFrameArgs& args) { | 133 void DisplayScheduler::OnBeginFrame(const BeginFrameArgs& args) { |
| 151 base::TimeTicks now = base::TimeTicks::Now(); | 134 base::TimeTicks now = base::TimeTicks::Now(); |
| 152 TRACE_EVENT2("cc", "DisplayScheduler::BeginFrame", "args", args.AsValue(), | 135 TRACE_EVENT2("cc", "DisplayScheduler::BeginFrame", "args", args.AsValue(), |
| 153 "now", now); | 136 "now", now); |
| 154 | 137 |
| 138 // We always use the args, even if we post a missing_begin_frame_task. |
| 139 last_used_begin_frame_args_ = args; |
| 140 |
| 155 if (inside_surface_damaged_) { | 141 if (inside_surface_damaged_) { |
| 156 // Repost this so that we don't run a missed BeginFrame on the same | 142 // Repost this so that we don't run a missed BeginFrame on the same |
| 157 // callstack. Otherwise we end up running unexpected scheduler actions | 143 // callstack. Otherwise we end up running unexpected scheduler actions |
| 158 // immediately while inside some other action (such as submitting a | 144 // immediately while inside some other action (such as submitting a |
| 159 // CompositorFrame for a SurfaceFactory). | 145 // CompositorFrame for a SurfaceFactory). |
| 160 DCHECK_EQ(args.type, BeginFrameArgs::MISSED); | 146 DCHECK_EQ(args.type, BeginFrameArgs::MISSED); |
| 161 DCHECK(missed_begin_frame_task_.IsCancelled()); | 147 DCHECK(missed_begin_frame_task_.IsCancelled()); |
| 162 missed_begin_frame_task_.Reset(base::Bind( | 148 missed_begin_frame_task_.Reset(base::Bind( |
| 163 base::IgnoreResult(&DisplayScheduler::OnBeginFrameDerivedImpl), | 149 base::IgnoreResult(&DisplayScheduler::OnBeginFrame), |
| 164 // The CancelableCallback will not run after it is destroyed, which | 150 // The CancelableCallback will not run after it is destroyed, which |
| 165 // happens when |this| is destroyed. | 151 // happens when |this| is destroyed. |
| 166 base::Unretained(this), args)); | 152 base::Unretained(this), args)); |
| 167 task_runner_->PostTask(FROM_HERE, missed_begin_frame_task_.callback()); | 153 task_runner_->PostTask(FROM_HERE, missed_begin_frame_task_.callback()); |
| 168 return true; | 154 return; |
| 169 } | 155 } |
| 170 | 156 |
| 171 // Save the |BeginFrameArgs| as the callback (missed_begin_frame_task_) can be | 157 // Save the |BeginFrameArgs| as the callback (missed_begin_frame_task_) can be |
| 172 // destroyed if we StopObservingBeginFrames(), and it would take the |args| | 158 // destroyed if we StopObservingBeginFrames(), and it would take the |args| |
| 173 // with it. Instead save the args and cancel the |missed_begin_frame_task_|. | 159 // with it. Instead save the args and cancel the |missed_begin_frame_task_|. |
| 174 BeginFrameArgs save_args = args; | 160 BeginFrameArgs save_args = args; |
| 175 // If we get another BeginFrame before a posted missed frame, just drop the | 161 // If we get another BeginFrame before a posted missed frame, just drop the |
| 176 // missed frame. Also if this was the missed frame, drop the Callback inside | 162 // missed frame. Also if this was the missed frame, drop the Callback inside |
| 177 // it. | 163 // it. |
| 178 missed_begin_frame_task_.Cancel(); | 164 missed_begin_frame_task_.Cancel(); |
| 179 | 165 |
| 180 // If we get another BeginFrame before the previous deadline, | 166 // If we get another BeginFrame before the previous deadline, |
| 181 // synchronously trigger the previous deadline before progressing. | 167 // synchronously trigger the previous deadline before progressing. |
| 182 if (inside_begin_frame_deadline_interval_) { | 168 if (inside_begin_frame_deadline_interval_) { |
| 183 OnBeginFrameDeadline(); | 169 OnBeginFrameDeadline(); |
| 184 } | 170 } |
| 185 | 171 |
| 186 // Schedule the deadline. | 172 // Schedule the deadline. |
| 187 current_begin_frame_args_ = save_args; | 173 current_begin_frame_args_ = save_args; |
| 188 current_begin_frame_args_.deadline -= | 174 current_begin_frame_args_.deadline -= |
| 189 BeginFrameArgs::DefaultEstimatedParentDrawTime(); | 175 BeginFrameArgs::DefaultEstimatedParentDrawTime(); |
| 190 inside_begin_frame_deadline_interval_ = true; | 176 inside_begin_frame_deadline_interval_ = true; |
| 191 ScheduleBeginFrameDeadline(); | 177 ScheduleBeginFrameDeadline(); |
| 178 } |
| 192 | 179 |
| 193 return true; | 180 const BeginFrameArgs& DisplayScheduler::LastUsedBeginFrameArgs() const { |
| 181 return last_used_begin_frame_args_; |
| 194 } | 182 } |
| 195 | 183 |
| 196 void DisplayScheduler::StartObservingBeginFrames() { | 184 void DisplayScheduler::StartObservingBeginFrames() { |
| 197 if (!observing_begin_frame_source_ && ShouldDraw()) { | 185 if (!observing_begin_frames_ && |
| 198 begin_frame_source_->AddObserver(this); | 186 (ShouldDraw() || begin_frame_source_->HasObservers())) { |
| 199 observing_begin_frame_source_ = true; | 187 begin_frame_source_->SetClientNeedsBeginFrames(true); |
| 188 observing_begin_frames_ = true; |
| 200 } | 189 } |
| 201 } | 190 } |
| 202 | 191 |
| 203 void DisplayScheduler::StopObservingBeginFrames() { | 192 void DisplayScheduler::StopObservingBeginFrames() { |
| 204 if (observing_begin_frame_source_) { | 193 if (observing_begin_frames_) { |
| 205 begin_frame_source_->RemoveObserver(this); | 194 begin_frame_source_->SetClientNeedsBeginFrames(false); |
| 206 observing_begin_frame_source_ = false; | 195 observing_begin_frames_ = false; |
| 207 | 196 |
| 208 // A missed BeginFrame may be queued, so drop that too if we're going to | 197 // A missed BeginFrame may be queued, so drop that too if we're going to |
| 209 // stop listening. | 198 // stop listening. |
| 210 missed_begin_frame_task_.Cancel(); | 199 missed_begin_frame_task_.Cancel(); |
| 211 } | 200 } |
| 212 } | 201 } |
| 213 | 202 |
| 214 bool DisplayScheduler::ShouldDraw() { | 203 bool DisplayScheduler::ShouldDraw() { |
| 215 // Note: When any of these cases becomes true, StartObservingBeginFrames must | 204 // Note: When any of these cases becomes true, StartObservingBeginFrames must |
| 216 // be called to ensure the draw will happen. | 205 // be called to ensure the draw will happen. |
| 217 return needs_draw_ && !output_surface_lost_ && visible_; | 206 return needs_draw_ && !output_surface_lost_ && visible_; |
| 218 } | 207 } |
| 219 | 208 |
| 220 void DisplayScheduler::OnBeginFrameSourcePausedChanged(bool paused) { | 209 void DisplayScheduler::BeginFrameObserverStatusChanged() { |
| 221 // BeginFrameSources used with DisplayScheduler do not make use of this | 210 // We proactively start observing if any observer requests BeginFrames to |
| 222 // feature. | 211 // ensure that we call FinishClientFrame() for all of the source's frames. |
| 223 if (paused) | 212 StartObservingBeginFrames(); |
| 224 NOTIMPLEMENTED(); | 213 // Schedules an immediate deadline if all observers have responded. |
| 214 ScheduleBeginFrameDeadline(); |
| 225 } | 215 } |
| 226 | 216 |
| 227 base::TimeTicks DisplayScheduler::DesiredBeginFrameDeadlineTime() { | 217 base::TimeTicks DisplayScheduler::DesiredBeginFrameDeadlineTime() { |
| 228 if (output_surface_lost_) { | 218 if (output_surface_lost_) { |
| 229 TRACE_EVENT_INSTANT0("cc", "Lost output surface", TRACE_EVENT_SCOPE_THREAD); | 219 TRACE_EVENT_INSTANT0("cc", "Lost output surface", TRACE_EVENT_SCOPE_THREAD); |
| 230 return base::TimeTicks(); | 220 return base::TimeTicks(); |
| 231 } | 221 } |
| 232 | 222 |
| 233 if (pending_swaps_ >= max_pending_swaps_) { | 223 if (pending_swaps_ >= max_pending_swaps_) { |
| 234 TRACE_EVENT_INSTANT0("cc", "Swap throttled", TRACE_EVENT_SCOPE_THREAD); | 224 TRACE_EVENT_INSTANT0("cc", "Swap throttled", TRACE_EVENT_SCOPE_THREAD); |
| 235 return current_begin_frame_args_.frame_time + | 225 return current_begin_frame_args_.frame_time + |
| 236 current_begin_frame_args_.interval; | 226 current_begin_frame_args_.interval; |
| 237 } | 227 } |
| 238 | 228 |
| 239 if (!needs_draw_) { | 229 bool observers_finished_frame = |
| 230 begin_frame_source_->AllObserversFinishedFrame(); |
| 231 |
| 232 if (!needs_draw_ && !observers_finished_frame) { |
| 240 TRACE_EVENT_INSTANT0("cc", "No damage yet", TRACE_EVENT_SCOPE_THREAD); | 233 TRACE_EVENT_INSTANT0("cc", "No damage yet", TRACE_EVENT_SCOPE_THREAD); |
| 241 return current_begin_frame_args_.frame_time + | 234 return current_begin_frame_args_.frame_time + |
| 242 current_begin_frame_args_.interval; | 235 current_begin_frame_args_.interval; |
| 243 } | 236 } |
| 244 | 237 |
| 245 if (root_surface_resources_locked_) { | 238 if (root_surface_resources_locked_) { |
| 246 TRACE_EVENT_INSTANT0("cc", "Root surface resources locked", | 239 TRACE_EVENT_INSTANT0("cc", "Root surface resources locked", |
| 247 TRACE_EVENT_SCOPE_THREAD); | 240 TRACE_EVENT_SCOPE_THREAD); |
| 248 return current_begin_frame_args_.frame_time + | 241 return current_begin_frame_args_.frame_time + |
| 249 current_begin_frame_args_.interval; | 242 current_begin_frame_args_.interval; |
| 250 } | 243 } |
| 251 | 244 |
| 252 bool root_ready_to_draw = | 245 if (observers_finished_frame && |
| 253 !expect_damage_from_root_surface_ || root_surface_damaged_; | 246 !expecting_root_surface_damage_because_of_resize_) { |
| 254 | |
| 255 if (all_active_child_surfaces_ready_to_draw_ && root_ready_to_draw) { | |
| 256 TRACE_EVENT_INSTANT0("cc", "All active surfaces ready", | 247 TRACE_EVENT_INSTANT0("cc", "All active surfaces ready", |
| 257 TRACE_EVENT_SCOPE_THREAD); | 248 TRACE_EVENT_SCOPE_THREAD); |
| 258 return base::TimeTicks(); | 249 return base::TimeTicks(); |
| 259 } | 250 } |
| 260 | 251 |
| 261 // TODO(mithro): Be smarter about resize deadlines. | 252 // TODO(mithro): Be smarter about resize deadlines. |
| 262 if (expecting_root_surface_damage_because_of_resize_) { | 253 if (expecting_root_surface_damage_because_of_resize_) { |
| 263 TRACE_EVENT_INSTANT0("cc", "Entire display damaged", | 254 TRACE_EVENT_INSTANT0("cc", "Entire display damaged", |
| 264 TRACE_EVENT_SCOPE_THREAD); | 255 TRACE_EVENT_SCOPE_THREAD); |
| 265 return current_begin_frame_args_.frame_time + | 256 return current_begin_frame_args_.frame_time + |
| 266 current_begin_frame_args_.interval; | 257 current_begin_frame_args_.interval; |
| 267 } | 258 } |
| 268 | 259 |
| 269 // Use an earlier deadline if we are only waiting for the root surface | |
| 270 // in case our expect_damage_from_root_surface heuristic is incorrect. | |
| 271 // TODO(mithro): Replace this with SetNeedsBeginFrame and SwapAbort | |
| 272 // logic. | |
| 273 if (all_active_child_surfaces_ready_to_draw_ && | |
| 274 expect_damage_from_root_surface_) { | |
| 275 TRACE_EVENT_INSTANT0("cc", "Waiting for damage from root surface", | |
| 276 TRACE_EVENT_SCOPE_THREAD); | |
| 277 // This adjusts the deadline by DefaultEstimatedParentDrawTime for | |
| 278 // a second time. The first one represented the Surfaces draw to display | |
| 279 // latency. This one represents root surface commit+raster+draw latency. | |
| 280 // We treat the root surface differently since it lives on the same thread | |
| 281 // as Surfaces and waiting for it too long may push out the Surfaces draw. | |
| 282 // If we also assume the root surface is fast to start a commit after the | |
| 283 // beginning of a frame, it'll have a chance to lock its resources, which | |
| 284 // will cause us to wait for it to unlock its resources above. | |
| 285 // TODO(mithro): Replace hard coded estimates. | |
| 286 return current_begin_frame_args_.deadline - | |
| 287 BeginFrameArgs::DefaultEstimatedParentDrawTime(); | |
| 288 } | |
| 289 | |
| 290 TRACE_EVENT_INSTANT0("cc", "More damage expected soon", | 260 TRACE_EVENT_INSTANT0("cc", "More damage expected soon", |
| 291 TRACE_EVENT_SCOPE_THREAD); | 261 TRACE_EVENT_SCOPE_THREAD); |
| 292 return current_begin_frame_args_.deadline; | 262 return current_begin_frame_args_.deadline; |
| 293 } | 263 } |
| 294 | 264 |
| 295 void DisplayScheduler::ScheduleBeginFrameDeadline() { | 265 void DisplayScheduler::ScheduleBeginFrameDeadline() { |
| 296 TRACE_EVENT0("cc", "DisplayScheduler::ScheduleBeginFrameDeadline"); | 266 TRACE_EVENT0("cc", "DisplayScheduler::ScheduleBeginFrameDeadline"); |
| 297 | 267 |
| 298 // We need to wait for the next BeginFrame before scheduling a deadline. | 268 // We need to wait for the next BeginFrame before scheduling a deadline. |
| 299 if (!inside_begin_frame_deadline_interval_) { | 269 if (!inside_begin_frame_deadline_interval_) { |
| (...skipping 20 matching lines...) Expand all Loading... |
| 320 begin_frame_deadline_task_.Reset(begin_frame_deadline_closure_); | 290 begin_frame_deadline_task_.Reset(begin_frame_deadline_closure_); |
| 321 | 291 |
| 322 base::TimeDelta delta = | 292 base::TimeDelta delta = |
| 323 std::max(base::TimeDelta(), desired_deadline - base::TimeTicks::Now()); | 293 std::max(base::TimeDelta(), desired_deadline - base::TimeTicks::Now()); |
| 324 task_runner_->PostDelayedTask(FROM_HERE, | 294 task_runner_->PostDelayedTask(FROM_HERE, |
| 325 begin_frame_deadline_task_.callback(), delta); | 295 begin_frame_deadline_task_.callback(), delta); |
| 326 TRACE_EVENT2("cc", "Using new deadline", "delta", delta.ToInternalValue(), | 296 TRACE_EVENT2("cc", "Using new deadline", "delta", delta.ToInternalValue(), |
| 327 "desired_deadline", desired_deadline); | 297 "desired_deadline", desired_deadline); |
| 328 } | 298 } |
| 329 | 299 |
| 330 void DisplayScheduler::AttemptDrawAndSwap() { | 300 bool DisplayScheduler::AttemptDrawAndSwap() { |
| 331 inside_begin_frame_deadline_interval_ = false; | 301 inside_begin_frame_deadline_interval_ = false; |
| 332 begin_frame_deadline_task_.Cancel(); | 302 begin_frame_deadline_task_.Cancel(); |
| 333 begin_frame_deadline_task_time_ = base::TimeTicks(); | 303 begin_frame_deadline_task_time_ = base::TimeTicks(); |
| 334 | 304 |
| 335 if (ShouldDraw()) { | 305 if (ShouldDraw()) { |
| 336 if (pending_swaps_ < max_pending_swaps_ && !root_surface_resources_locked_) | 306 if (pending_swaps_ < max_pending_swaps_ && !root_surface_resources_locked_) |
| 337 DrawAndSwap(); | 307 return DrawAndSwap(); |
| 338 } else { | 308 } else if (!begin_frame_source_->HasObservers()) { |
| 339 // We are going idle, so reset expectations. | 309 // We are going idle, so reset expectations. |
| 340 child_surface_ids_to_expect_damage_from_.clear(); | 310 // TODO(eseckler): Should we avoid going idle if |
| 341 child_surface_ids_damaged_prev_.clear(); | 311 // expecting_root_surface_damage_because_of_resize_ is true? |
| 342 child_surface_ids_damaged_.clear(); | 312 expecting_root_surface_damage_because_of_resize_ = false; |
| 343 all_active_child_surfaces_ready_to_draw_ = true; | |
| 344 expect_damage_from_root_surface_ = false; | |
| 345 | 313 |
| 346 StopObservingBeginFrames(); | 314 StopObservingBeginFrames(); |
| 347 } | 315 } |
| 316 |
| 317 return false; |
| 348 } | 318 } |
| 349 | 319 |
| 350 void DisplayScheduler::OnBeginFrameDeadline() { | 320 void DisplayScheduler::OnBeginFrameDeadline() { |
| 351 TRACE_EVENT0("cc", "DisplayScheduler::OnBeginFrameDeadline"); | 321 TRACE_EVENT0("cc", "DisplayScheduler::OnBeginFrameDeadline"); |
| 322 DCHECK(inside_begin_frame_deadline_interval_); |
| 352 | 323 |
| 353 AttemptDrawAndSwap(); | 324 bool did_draw = AttemptDrawAndSwap(); |
| 354 begin_frame_source_->DidFinishFrame(this, 0); | 325 begin_frame_source_->FinishClientFrame(did_draw, needs_draw_); |
| 355 } | 326 } |
| 356 | 327 |
| 357 void DisplayScheduler::DidSwapBuffers() { | 328 void DisplayScheduler::DidSwapBuffers() { |
| 358 pending_swaps_++; | 329 pending_swaps_++; |
| 359 TRACE_EVENT_ASYNC_BEGIN1("cc", "DisplayScheduler:pending_swaps", this, | 330 TRACE_EVENT_ASYNC_BEGIN1("cc", "DisplayScheduler:pending_swaps", this, |
| 360 "pending_frames", pending_swaps_); | 331 "pending_frames", pending_swaps_); |
| 361 } | 332 } |
| 362 | 333 |
| 363 void DisplayScheduler::DidReceiveSwapBuffersAck() { | 334 void DisplayScheduler::DidReceiveSwapBuffersAck() { |
| 364 pending_swaps_--; | 335 pending_swaps_--; |
| 365 TRACE_EVENT_ASYNC_END1("cc", "DisplayScheduler:pending_swaps", this, | 336 TRACE_EVENT_ASYNC_END1("cc", "DisplayScheduler:pending_swaps", this, |
| 366 "pending_frames", pending_swaps_); | 337 "pending_frames", pending_swaps_); |
| 367 ScheduleBeginFrameDeadline(); | 338 ScheduleBeginFrameDeadline(); |
| 368 } | 339 } |
| 369 | 340 |
| 370 } // namespace cc | 341 } // namespace cc |
| OLD | NEW |