Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(233)

Side by Side Diff: cc/surfaces/display_scheduler.cc

Issue 2527283003: cc: Introduce BeginFrame sequence numbers and acknowledgements.
Patch Set: Address Brian's comments. Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « cc/surfaces/display_scheduler.h ('k') | cc/surfaces/display_scheduler_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
OLDNEW
« no previous file with comments | « cc/surfaces/display_scheduler.h ('k') | cc/surfaces/display_scheduler_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698