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

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

Issue 2411793008: Adds BeginFrameControl via DevTools.
Patch Set: BFC prototype v2 with allow_latency_opts and waiting for BFOs. Created 4 years, 1 month 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/begin_frame_args.h"
12 #include "cc/output/output_surface.h" 13 #include "cc/output/output_surface.h"
13 14
14 namespace cc { 15 namespace cc {
15 16
16 DisplayScheduler::DisplayScheduler(BeginFrameSource* begin_frame_source, 17 DisplayScheduler::DisplayScheduler(base::SingleThreadTaskRunner* task_runner,
17 base::SingleThreadTaskRunner* task_runner,
18 int max_pending_swaps) 18 int max_pending_swaps)
19 : begin_frame_source_(begin_frame_source), 19 : client_(nullptr),
20 begin_frame_source_(nullptr),
20 task_runner_(task_runner), 21 task_runner_(task_runner),
21 inside_surface_damaged_(false), 22 inside_surface_damaged_(false),
22 visible_(false), 23 visible_(false),
23 output_surface_lost_(false), 24 output_surface_lost_(false),
24 root_surface_resources_locked_(true), 25 root_surface_resources_locked_(true),
25 inside_begin_frame_deadline_interval_(false), 26 inside_begin_frame_deadline_interval_(false),
26 needs_draw_(false), 27 needs_draw_(false),
27 expecting_root_surface_damage_because_of_resize_(false), 28 expecting_root_surface_damage_because_of_resize_(false),
28 all_active_child_surfaces_ready_to_draw_(false), 29 all_active_child_surfaces_ready_to_draw_(false),
29 pending_swaps_(0), 30 pending_swaps_(0),
30 max_pending_swaps_(max_pending_swaps), 31 max_pending_swaps_(max_pending_swaps),
31 observing_begin_frame_source_(false), 32 observing_begin_frame_source_(false),
32 root_surface_damaged_(false), 33 root_surface_damaged_(false),
33 expect_damage_from_root_surface_(false), 34 expect_damage_from_root_surface_(false),
34 weak_ptr_factory_(this) { 35 weak_ptr_factory_(this) {
35 begin_frame_deadline_closure_ = base::Bind( 36 begin_frame_deadline_closure_ = base::Bind(
36 &DisplayScheduler::OnBeginFrameDeadline, weak_ptr_factory_.GetWeakPtr()); 37 &DisplayScheduler::OnBeginFrameDeadline, weak_ptr_factory_.GetWeakPtr());
37 } 38 }
38 39
39 DisplayScheduler::~DisplayScheduler() { 40 DisplayScheduler::~DisplayScheduler() {
40 StopObservingBeginFrames(); 41 StopObservingBeginFrames();
41 } 42 }
42 43
43 void DisplayScheduler::SetClient(DisplaySchedulerClient* client) { 44 void DisplayScheduler::SetClient(DisplaySchedulerClient* client) {
44 client_ = client; 45 client_ = client;
45 } 46 }
46 47
48 void DisplayScheduler::SetBeginFrameSource(
49 DisplayBeginFrameSource* begin_frame_source) {
50 begin_frame_source_ = begin_frame_source;
51 begin_frame_source_->SetClient(this);
52 DCHECK(begin_frame_source_->GetTargetSource());
53 }
54
47 void DisplayScheduler::SetVisible(bool visible) { 55 void DisplayScheduler::SetVisible(bool visible) {
48 if (visible_ == visible) 56 if (visible_ == visible)
49 return; 57 return;
50 58
51 visible_ = visible; 59 visible_ = visible;
52 // If going invisible, we'll stop observing begin frames once we try 60 // If going invisible, we'll stop observing begin frames once we try
53 // to draw and fail. 61 // to draw and fail.
54 StartObservingBeginFrames(); 62 StartObservingBeginFrames();
55 ScheduleBeginFrameDeadline(); 63 ScheduleBeginFrameDeadline();
56 } 64 }
57 65
58 // If we try to draw when the root surface resources are locked, the 66 // If we try to draw when the root surface resources are locked, the
59 // draw will fail. 67 // draw will fail.
60 void DisplayScheduler::SetRootSurfaceResourcesLocked(bool locked) { 68 void DisplayScheduler::SetRootSurfaceResourcesLocked(bool locked) {
61 TRACE_EVENT1("cc", "DisplayScheduler::SetRootSurfaceResourcesLocked", 69 TRACE_EVENT1("cc", "DisplayScheduler::SetRootSurfaceResourcesLocked",
62 "locked", locked); 70 "locked", locked);
63 root_surface_resources_locked_ = locked; 71 root_surface_resources_locked_ = locked;
64 ScheduleBeginFrameDeadline(); 72 ScheduleBeginFrameDeadline();
65 } 73 }
66 74
67 // This is used to force an immediate swap before a resize. 75 // This is used to force an immediate swap before a resize.
68 void DisplayScheduler::ForceImmediateSwapIfPossible() { 76 void DisplayScheduler::ForceImmediateSwapIfPossible() {
69 TRACE_EVENT0("cc", "DisplayScheduler::ForceImmediateSwapIfPossible"); 77 TRACE_EVENT0("cc", "DisplayScheduler::ForceImmediateSwapIfPossible");
70 bool in_begin = inside_begin_frame_deadline_interval_; 78 bool in_begin = inside_begin_frame_deadline_interval_;
71 AttemptDrawAndSwap(); 79 AttemptDrawAndSwap();
72 if (in_begin) 80 if (in_begin)
73 begin_frame_source_->DidFinishFrame(this, 0); 81 begin_frame_source_->GetTargetSource()->DidFinishFrame(this, 0);
74 } 82 }
75 83
76 void DisplayScheduler::DisplayResized() { 84 void DisplayScheduler::DisplayResized() {
77 expecting_root_surface_damage_because_of_resize_ = true; 85 expecting_root_surface_damage_because_of_resize_ = true;
78 expect_damage_from_root_surface_ = true; 86 expect_damage_from_root_surface_ = true;
79 needs_draw_ = true; 87 needs_draw_ = true;
80 ScheduleBeginFrameDeadline(); 88 ScheduleBeginFrameDeadline();
81 } 89 }
82 90
83 // Notification that there was a resize or the root surface changed and 91 // Notification that there was a resize or the root surface changed and
(...skipping 17 matching lines...) Expand all
101 base::AutoReset<bool> auto_reset(&inside_surface_damaged_, true); 109 base::AutoReset<bool> auto_reset(&inside_surface_damaged_, true);
102 110
103 needs_draw_ = true; 111 needs_draw_ = true;
104 112
105 if (surface_id == root_surface_id_) { 113 if (surface_id == root_surface_id_) {
106 root_surface_damaged_ = true; 114 root_surface_damaged_ = true;
107 expecting_root_surface_damage_because_of_resize_ = false; 115 expecting_root_surface_damage_because_of_resize_ = false;
108 } else { 116 } else {
109 child_surface_ids_damaged_.insert(surface_id); 117 child_surface_ids_damaged_.insert(surface_id);
110 118
111 // TODO(mithro): Use hints from SetNeedsBeginFrames and SwapAborts. 119 if (BeginFrameForcesDamage()) {
112 all_active_child_surfaces_ready_to_draw_ = base::STLIncludes( 120 // Wait for all BeginFrameObservers to call DidFinishFrame() before
113 child_surface_ids_damaged_, child_surface_ids_to_expect_damage_from_); 121 // triggering an early deadline. We do this only if we know that the
122 // BeginFrame should cause damage on all active surfaces, because BFOs
123 // currently may not call DidFinishFrame() when the BeginFrame does not
124 // cause any damage to their surface.
125 // TODO(eseckler): Make this the default heuristic once we can guarantee
126 // observers to call DidFinishFrame() for every frame.
127 all_active_child_surfaces_ready_to_draw_ =
128 begin_frame_source_->AllObserversFinishedFrame();
129 } else {
130 // TODO(mithro): Use hints from SetNeedsBeginFrames and SwapAborts.
131 all_active_child_surfaces_ready_to_draw_ = base::STLIncludes(
132 child_surface_ids_damaged_, child_surface_ids_to_expect_damage_from_);
133 }
114 } 134 }
115 135
116 StartObservingBeginFrames(); 136 StartObservingBeginFrames();
117 ScheduleBeginFrameDeadline(); 137 ScheduleBeginFrameDeadline();
118 } 138 }
119 139
120 void DisplayScheduler::OutputSurfaceLost() { 140 void DisplayScheduler::OutputSurfaceLost() {
121 TRACE_EVENT0("cc", "DisplayScheduler::OutputSurfaceLost"); 141 TRACE_EVENT0("cc", "DisplayScheduler::OutputSurfaceLost");
122 output_surface_lost_ = true; 142 output_surface_lost_ = true;
123 ScheduleBeginFrameDeadline(); 143 ScheduleBeginFrameDeadline();
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
181 // synchronously trigger the previous deadline before progressing. 201 // synchronously trigger the previous deadline before progressing.
182 if (inside_begin_frame_deadline_interval_) { 202 if (inside_begin_frame_deadline_interval_) {
183 OnBeginFrameDeadline(); 203 OnBeginFrameDeadline();
184 } 204 }
185 205
186 // Schedule the deadline. 206 // Schedule the deadline.
187 current_begin_frame_args_ = save_args; 207 current_begin_frame_args_ = save_args;
188 current_begin_frame_args_.deadline -= 208 current_begin_frame_args_.deadline -=
189 BeginFrameArgs::DefaultEstimatedParentDrawTime(); 209 BeginFrameArgs::DefaultEstimatedParentDrawTime();
190 inside_begin_frame_deadline_interval_ = true; 210 inside_begin_frame_deadline_interval_ = true;
211
212 if (BeginFrameForcesDamage()) {
213 // We know every surface that receives the BeginFrame will be damaged, so we
214 // wait until all BeginFrameObservers have responded instead of waiting for
215 // child_surface_ids_to_expect_damage_from_.
216 expect_damage_from_root_surface_ = false;
217 all_active_child_surfaces_ready_to_draw_ =
218 begin_frame_source_->AllObserversFinishedFrame();
219 }
220
191 ScheduleBeginFrameDeadline(); 221 ScheduleBeginFrameDeadline();
192
193 return true; 222 return true;
194 } 223 }
195 224
196 void DisplayScheduler::StartObservingBeginFrames() { 225 void DisplayScheduler::StartObservingBeginFrames() {
197 if (!observing_begin_frame_source_ && ShouldDraw()) { 226 if (!observing_begin_frame_source_ && ShouldDraw()) {
198 begin_frame_source_->AddObserver(this); 227 // We don't want to wait for our own DidFinishFrame() when using
228 // begin_frame_source_->AllObserversFinishedFrame(), so we add ourselves to
229 // the target source directly.
230 begin_frame_source_->GetTargetSource()->AddObserver(this);
199 observing_begin_frame_source_ = true; 231 observing_begin_frame_source_ = true;
200 } 232 }
201 } 233 }
202 234
203 void DisplayScheduler::StopObservingBeginFrames() { 235 void DisplayScheduler::StopObservingBeginFrames() {
204 if (observing_begin_frame_source_) { 236 if (observing_begin_frame_source_) {
205 begin_frame_source_->RemoveObserver(this); 237 begin_frame_source_->GetTargetSource()->RemoveObserver(this);
206 observing_begin_frame_source_ = false; 238 observing_begin_frame_source_ = false;
207 239
208 // A missed BeginFrame may be queued, so drop that too if we're going to 240 // A missed BeginFrame may be queued, so drop that too if we're going to
209 // stop listening. 241 // stop listening.
210 missed_begin_frame_task_.Cancel(); 242 missed_begin_frame_task_.Cancel();
211 } 243 }
212 } 244 }
213 245
214 bool DisplayScheduler::ShouldDraw() { 246 bool DisplayScheduler::ShouldDraw() {
215 // Note: When any of these cases becomes true, StartObservingBeginFrames must 247 // Note: When any of these cases becomes true, StartObservingBeginFrames must
216 // be called to ensure the draw will happen. 248 // be called to ensure the draw will happen.
217 return needs_draw_ && !output_surface_lost_ && visible_; 249 return needs_draw_ && !output_surface_lost_ && visible_;
218 } 250 }
219 251
252 bool DisplayScheduler::BeginFrameForcesDamage() const {
253 return !current_begin_frame_args_.allow_latency_optimizations;
254 }
255
220 void DisplayScheduler::OnBeginFrameSourcePausedChanged(bool paused) { 256 void DisplayScheduler::OnBeginFrameSourcePausedChanged(bool paused) {
221 // BeginFrameSources used with DisplayScheduler do not make use of this 257 // BeginFrameSources used with DisplayScheduler do not make use of this
222 // feature. 258 // feature.
223 if (paused) 259 if (paused)
224 NOTIMPLEMENTED(); 260 NOTIMPLEMENTED();
225 } 261 }
226 262
263 void DisplayScheduler::ObserverStatusChanged() {
264 // If we're using the BeginFrameObservers to determine when all active
265 // surfaces have been damaged, we may need to update the deadline.
266 if (BeginFrameForcesDamage()) {
267 all_active_child_surfaces_ready_to_draw_ =
268 begin_frame_source_->AllObserversFinishedFrame();
269 ScheduleBeginFrameDeadline();
270 }
271 }
272
273 void DisplayScheduler::BeginFrameSourceSwapping(BeginFrameSource* new_source) {
274 DCHECK(new_source);
275 if (observing_begin_frame_source_) {
276 begin_frame_source_->GetTargetSource()->RemoveObserver(this);
277 new_source->AddObserver(this);
278 }
279 }
280
227 base::TimeTicks DisplayScheduler::DesiredBeginFrameDeadlineTime() { 281 base::TimeTicks DisplayScheduler::DesiredBeginFrameDeadlineTime() {
228 if (output_surface_lost_) { 282 if (output_surface_lost_) {
229 TRACE_EVENT_INSTANT0("cc", "Lost output surface", TRACE_EVENT_SCOPE_THREAD); 283 TRACE_EVENT_INSTANT0("cc", "Lost output surface", TRACE_EVENT_SCOPE_THREAD);
230 return base::TimeTicks(); 284 return base::TimeTicks();
231 } 285 }
232 286
233 if (pending_swaps_ >= max_pending_swaps_) { 287 if (pending_swaps_ >= max_pending_swaps_) {
234 TRACE_EVENT_INSTANT0("cc", "Swap throttled", TRACE_EVENT_SCOPE_THREAD); 288 TRACE_EVENT_INSTANT0("cc", "Swap throttled", TRACE_EVENT_SCOPE_THREAD);
235 return current_begin_frame_args_.frame_time + 289 return current_begin_frame_args_.frame_time +
236 current_begin_frame_args_.interval; 290 current_begin_frame_args_.interval;
237 } 291 }
238 292
239 if (!needs_draw_) { 293 // Allow an immediate deadline even if there's no damage and we know that
294 // no BeginFrameObservers are active.
295 if (!needs_draw_ &&
296 !(BeginFrameForcesDamage() && all_active_child_surfaces_ready_to_draw_)) {
240 TRACE_EVENT_INSTANT0("cc", "No damage yet", TRACE_EVENT_SCOPE_THREAD); 297 TRACE_EVENT_INSTANT0("cc", "No damage yet", TRACE_EVENT_SCOPE_THREAD);
241 return current_begin_frame_args_.frame_time + 298 return current_begin_frame_args_.frame_time +
242 current_begin_frame_args_.interval; 299 current_begin_frame_args_.interval;
243 } 300 }
244 301
245 if (root_surface_resources_locked_) { 302 if (root_surface_resources_locked_) {
246 TRACE_EVENT_INSTANT0("cc", "Root surface resources locked", 303 TRACE_EVENT_INSTANT0("cc", "Root surface resources locked",
247 TRACE_EVENT_SCOPE_THREAD); 304 TRACE_EVENT_SCOPE_THREAD);
248 return current_begin_frame_args_.frame_time + 305 return current_begin_frame_args_.frame_time +
249 current_begin_frame_args_.interval; 306 current_begin_frame_args_.interval;
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
344 expect_damage_from_root_surface_ = false; 401 expect_damage_from_root_surface_ = false;
345 402
346 StopObservingBeginFrames(); 403 StopObservingBeginFrames();
347 } 404 }
348 } 405 }
349 406
350 void DisplayScheduler::OnBeginFrameDeadline() { 407 void DisplayScheduler::OnBeginFrameDeadline() {
351 TRACE_EVENT0("cc", "DisplayScheduler::OnBeginFrameDeadline"); 408 TRACE_EVENT0("cc", "DisplayScheduler::OnBeginFrameDeadline");
352 409
353 AttemptDrawAndSwap(); 410 AttemptDrawAndSwap();
354 begin_frame_source_->DidFinishFrame(this, 0); 411 begin_frame_source_->GetTargetSource()->DidFinishFrame(this, 0);
355 } 412 }
356 413
357 void DisplayScheduler::DidSwapBuffers() { 414 void DisplayScheduler::DidSwapBuffers() {
358 pending_swaps_++; 415 pending_swaps_++;
359 TRACE_EVENT_ASYNC_BEGIN1("cc", "DisplayScheduler:pending_swaps", this, 416 TRACE_EVENT_ASYNC_BEGIN1("cc", "DisplayScheduler:pending_swaps", this,
360 "pending_frames", pending_swaps_); 417 "pending_frames", pending_swaps_);
361 } 418 }
362 419
363 void DisplayScheduler::DidReceiveSwapBuffersAck() { 420 void DisplayScheduler::DidReceiveSwapBuffersAck() {
364 pending_swaps_--; 421 pending_swaps_--;
365 TRACE_EVENT_ASYNC_END1("cc", "DisplayScheduler:pending_swaps", this, 422 TRACE_EVENT_ASYNC_END1("cc", "DisplayScheduler:pending_swaps", this,
366 "pending_frames", pending_swaps_); 423 "pending_frames", pending_swaps_);
367 ScheduleBeginFrameDeadline(); 424 ScheduleBeginFrameDeadline();
368 } 425 }
369 426
370 } // namespace cc 427 } // 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