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

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

Issue 2854163003: [cc] Plumb BeginFrameAcks through SurfaceManager to DisplayScheduler. (Closed)
Patch Set: Track state per surface. Created 3 years, 7 months 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
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 #include "cc/surfaces/surface_manager.h"
13 14
14 namespace cc { 15 namespace cc {
15 16
16 DisplayScheduler::DisplayScheduler(base::SingleThreadTaskRunner* task_runner, 17 DisplayScheduler::DisplayScheduler(base::SingleThreadTaskRunner* task_runner,
17 int max_pending_swaps) 18 int max_pending_swaps)
18 : client_(nullptr), 19 : client_(nullptr),
19 begin_frame_source_(nullptr), 20 begin_frame_source_(nullptr),
21 surface_manager_(nullptr),
20 task_runner_(task_runner), 22 task_runner_(task_runner),
21 inside_surface_damaged_(false), 23 inside_surface_damaged_(false),
22 visible_(false), 24 visible_(false),
23 output_surface_lost_(false), 25 output_surface_lost_(false),
24 root_surface_resources_locked_(true), 26 root_surface_resources_locked_(true),
25 inside_begin_frame_deadline_interval_(false), 27 inside_begin_frame_deadline_interval_(false),
26 needs_draw_(false), 28 needs_draw_(false),
27 expecting_root_surface_damage_because_of_resize_(false), 29 expecting_root_surface_damage_because_of_resize_(false),
28 all_active_child_surfaces_ready_to_draw_(false), 30 has_pending_surfaces_(false),
29 next_swap_id_(1), 31 next_swap_id_(1),
30 pending_swaps_(0), 32 pending_swaps_(0),
31 max_pending_swaps_(max_pending_swaps), 33 max_pending_swaps_(max_pending_swaps),
32 observing_begin_frame_source_(false), 34 observing_begin_frame_source_(false),
33 root_surface_damaged_(false),
34 expect_damage_from_root_surface_(false),
35 weak_ptr_factory_(this) { 35 weak_ptr_factory_(this) {
36 begin_frame_deadline_closure_ = base::Bind( 36 begin_frame_deadline_closure_ = base::Bind(
37 &DisplayScheduler::OnBeginFrameDeadline, weak_ptr_factory_.GetWeakPtr()); 37 &DisplayScheduler::OnBeginFrameDeadline, weak_ptr_factory_.GetWeakPtr());
38 } 38 }
39 39
40 DisplayScheduler::~DisplayScheduler() { 40 DisplayScheduler::~DisplayScheduler() {
41 StopObservingBeginFrames(); 41 StopObservingBeginFrames();
42 } 42 }
43 43
44 void DisplayScheduler::SetClient(DisplaySchedulerClient* client) { 44 void DisplayScheduler::SetClient(DisplaySchedulerClient* client) {
45 client_ = client; 45 client_ = client;
46 } 46 }
47 47
48 void DisplayScheduler::SetBeginFrameSource( 48 void DisplayScheduler::SetBeginFrameSource(
49 BeginFrameSource* begin_frame_source) { 49 BeginFrameSource* begin_frame_source) {
50 begin_frame_source_ = begin_frame_source; 50 begin_frame_source_ = begin_frame_source;
51 } 51 }
52 52
53 void DisplayScheduler::SetSurfaceManager(SurfaceManager* surface_manager) {
54 surface_manager_ = surface_manager;
55 }
56
53 void DisplayScheduler::SetVisible(bool visible) { 57 void DisplayScheduler::SetVisible(bool visible) {
54 if (visible_ == visible) 58 if (visible_ == visible)
55 return; 59 return;
56 60
57 visible_ = visible; 61 visible_ = visible;
58 // If going invisible, we'll stop observing begin frames once we try 62 // If going invisible, we'll stop observing begin frames once we try
59 // to draw and fail. 63 // to draw and fail.
60 StartObservingBeginFrames(); 64 StartObservingBeginFrames();
61 ScheduleBeginFrameDeadline(); 65 ScheduleBeginFrameDeadline();
62 } 66 }
(...skipping 11 matching lines...) Expand all
74 void DisplayScheduler::ForceImmediateSwapIfPossible() { 78 void DisplayScheduler::ForceImmediateSwapIfPossible() {
75 TRACE_EVENT0("cc", "DisplayScheduler::ForceImmediateSwapIfPossible"); 79 TRACE_EVENT0("cc", "DisplayScheduler::ForceImmediateSwapIfPossible");
76 bool in_begin = inside_begin_frame_deadline_interval_; 80 bool in_begin = inside_begin_frame_deadline_interval_;
77 bool did_draw = AttemptDrawAndSwap(); 81 bool did_draw = AttemptDrawAndSwap();
78 if (in_begin) 82 if (in_begin)
79 DidFinishFrame(did_draw); 83 DidFinishFrame(did_draw);
80 } 84 }
81 85
82 void DisplayScheduler::DisplayResized() { 86 void DisplayScheduler::DisplayResized() {
83 expecting_root_surface_damage_because_of_resize_ = true; 87 expecting_root_surface_damage_because_of_resize_ = true;
84 expect_damage_from_root_surface_ = true;
85 needs_draw_ = true; 88 needs_draw_ = true;
86 ScheduleBeginFrameDeadline(); 89 ScheduleBeginFrameDeadline();
87 } 90 }
88 91
89 // Notification that there was a resize or the root surface changed and 92 // Notification that there was a resize or the root surface changed and
90 // that we should just draw immediately. 93 // that we should just draw immediately.
91 void DisplayScheduler::SetNewRootSurface(const SurfaceId& root_surface_id) { 94 void DisplayScheduler::SetNewRootSurface(const SurfaceId& root_surface_id) {
92 TRACE_EVENT0("cc", "DisplayScheduler::SetNewRootSurface"); 95 TRACE_EVENT0("cc", "DisplayScheduler::SetNewRootSurface");
93 root_surface_id_ = root_surface_id; 96 root_surface_id_ = root_surface_id;
94 SurfaceDamaged(root_surface_id); 97 SurfaceDamaged(root_surface_id);
95 } 98 }
96 99
97 // Indicates that there was damage to one of the surfaces. 100 // Indicates that there was damage to one of the surfaces.
98 // Has some logic to wait for multiple active surfaces before 101 // Has some logic to wait for multiple active surfaces before
99 // triggering the deadline. 102 // triggering the deadline.
100 void DisplayScheduler::SurfaceDamaged(const SurfaceId& surface_id) { 103 void DisplayScheduler::SurfaceDamaged(const SurfaceId& surface_id) {
101 TRACE_EVENT1("cc", "DisplayScheduler::SurfaceDamaged", "surface_id", 104 TRACE_EVENT1("cc", "DisplayScheduler::SurfaceDamaged", "surface_id",
102 surface_id.ToString()); 105 surface_id.ToString());
103 106
104 // We may cause a new BeginFrame to be run inside this method, but to help 107 // We may cause a new BeginFrame to be run inside this method, but to help
105 // avoid being reentrant to the caller of SurfaceDamaged, track when this is 108 // avoid being reentrant to the caller of SurfaceDamaged, track when this is
106 // happening with |inside_surface_damaged_|. 109 // happening with |inside_surface_damaged_|.
107 base::AutoReset<bool> auto_reset(&inside_surface_damaged_, true); 110 base::AutoReset<bool> auto_reset(&inside_surface_damaged_, true);
108 111
109 needs_draw_ = true; 112 needs_draw_ = true;
110 113
111 if (surface_id == root_surface_id_) { 114 if (surface_id == root_surface_id_)
112 root_surface_damaged_ = true;
113 expecting_root_surface_damage_because_of_resize_ = false; 115 expecting_root_surface_damage_because_of_resize_ = false;
114 } else {
115 child_surface_ids_damaged_.insert(surface_id);
116
117 // TODO(mithro): Use hints from SetNeedsBeginFrames and SwapAborts.
118 all_active_child_surfaces_ready_to_draw_ = base::STLIncludes(
119 child_surface_ids_damaged_, child_surface_ids_to_expect_damage_from_);
120 }
121 116
122 StartObservingBeginFrames(); 117 StartObservingBeginFrames();
123 ScheduleBeginFrameDeadline(); 118 ScheduleBeginFrameDeadline();
124 } 119 }
125 120
121 void DisplayScheduler::OnSurfaceProducerStateChanged(
122 const SurfaceId& surface_id) {
123 UpdateHasPendingSurfaces();
124 TRACE_EVENT1("cc", "DisplayScheduler::OnSurfaceProducerStateChanged",
125 "has_pending_surfaces", has_pending_surfaces_);
126 ScheduleBeginFrameDeadline();
127 }
128
129 void DisplayScheduler::UpdateHasPendingSurfaces() {
130 if (!surface_manager_)
131 return;
132
133 // We only need to check for the state of previously referenced surfaced, as
134 // newly referenced child surfaces will already have damage. (An exception to
135 // this are surfaces referenced by a CompositorFrame that is activated because
136 // of a surface synchronization deadline. By activating the parent frame,
137 // however, we decided not to wait for these child surfaces.)
138 for (std::pair<SurfaceId, int> entry :
139 client_->GetPreviousContainedSurfaces()) {
140 Surface* surface = surface_manager_->GetSurfaceForId(entry.first);
141 if (surface && surface->GetProducerState() == Surface::PENDING) {
142 TRACE_EVENT2("cc", "DisplayScheduler::UpdateHasPendingSurfaces()",
143 "pending_surface_id", entry.first.ToString(),
144 "pending_surface_producer_state",
145 surface->GetProducerState());
146 has_pending_surfaces_ = true;
147 return;
148 }
149 }
150 has_pending_surfaces_ = false;
151 }
152
126 void DisplayScheduler::OutputSurfaceLost() { 153 void DisplayScheduler::OutputSurfaceLost() {
127 TRACE_EVENT0("cc", "DisplayScheduler::OutputSurfaceLost"); 154 TRACE_EVENT0("cc", "DisplayScheduler::OutputSurfaceLost");
128 output_surface_lost_ = true; 155 output_surface_lost_ = true;
129 ScheduleBeginFrameDeadline(); 156 ScheduleBeginFrameDeadline();
130 } 157 }
131 158
132 bool DisplayScheduler::DrawAndSwap() { 159 bool DisplayScheduler::DrawAndSwap() {
133 TRACE_EVENT0("cc", "DisplayScheduler::DrawAndSwap"); 160 TRACE_EVENT0("cc", "DisplayScheduler::DrawAndSwap");
134 DCHECK_LT(pending_swaps_, max_pending_swaps_); 161 DCHECK_LT(pending_swaps_, max_pending_swaps_);
135 DCHECK(!output_surface_lost_); 162 DCHECK(!output_surface_lost_);
136 163
137 bool success = client_->DrawAndSwap(); 164 bool success = client_->DrawAndSwap();
138 if (!success) 165 if (!success)
139 return false; 166 return false;
140 167
141 child_surface_ids_to_expect_damage_from_ =
142 base::STLSetIntersection<std::vector<SurfaceId>>(
143 child_surface_ids_damaged_, child_surface_ids_damaged_prev_);
144
145 child_surface_ids_damaged_prev_.swap(child_surface_ids_damaged_);
146 child_surface_ids_damaged_.clear();
147
148 needs_draw_ = false; 168 needs_draw_ = false;
149 all_active_child_surfaces_ready_to_draw_ =
150 child_surface_ids_to_expect_damage_from_.empty();
151
152 expect_damage_from_root_surface_ = root_surface_damaged_;
153 root_surface_damaged_ = false;
154 return true; 169 return true;
155 } 170 }
156 171
157 bool DisplayScheduler::OnBeginFrameDerivedImpl(const BeginFrameArgs& args) { 172 bool DisplayScheduler::OnBeginFrameDerivedImpl(const BeginFrameArgs& args) {
158 base::TimeTicks now = base::TimeTicks::Now(); 173 base::TimeTicks now = base::TimeTicks::Now();
159 TRACE_EVENT2("cc", "DisplayScheduler::BeginFrame", "args", args.AsValue(), 174 TRACE_EVENT2("cc", "DisplayScheduler::BeginFrame", "args", args.AsValue(),
160 "now", now); 175 "now", now);
161 176
162 if (inside_surface_damaged_) { 177 if (inside_surface_damaged_) {
163 // Repost this so that we don't run a missed BeginFrame on the same 178 // Repost this so that we don't run a missed BeginFrame on the same
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
236 TRACE_EVENT_INSTANT0("cc", "Lost output surface", TRACE_EVENT_SCOPE_THREAD); 251 TRACE_EVENT_INSTANT0("cc", "Lost output surface", TRACE_EVENT_SCOPE_THREAD);
237 return base::TimeTicks(); 252 return base::TimeTicks();
238 } 253 }
239 254
240 if (pending_swaps_ >= max_pending_swaps_) { 255 if (pending_swaps_ >= max_pending_swaps_) {
241 TRACE_EVENT_INSTANT0("cc", "Swap throttled", TRACE_EVENT_SCOPE_THREAD); 256 TRACE_EVENT_INSTANT0("cc", "Swap throttled", TRACE_EVENT_SCOPE_THREAD);
242 return current_begin_frame_args_.frame_time + 257 return current_begin_frame_args_.frame_time +
243 current_begin_frame_args_.interval; 258 current_begin_frame_args_.interval;
244 } 259 }
245 260
246 if (!needs_draw_) { 261 bool all_surfaces_ready =
262 !has_pending_surfaces_ && root_surface_id_.is_valid();
263 if (!needs_draw_ && !all_surfaces_ready) {
247 TRACE_EVENT_INSTANT0("cc", "No damage yet", TRACE_EVENT_SCOPE_THREAD); 264 TRACE_EVENT_INSTANT0("cc", "No damage yet", TRACE_EVENT_SCOPE_THREAD);
248 return current_begin_frame_args_.frame_time + 265 return current_begin_frame_args_.frame_time +
249 current_begin_frame_args_.interval; 266 current_begin_frame_args_.interval;
250 } 267 }
251 268
252 if (root_surface_resources_locked_) { 269 if (root_surface_resources_locked_) {
253 TRACE_EVENT_INSTANT0("cc", "Root surface resources locked", 270 TRACE_EVENT_INSTANT0("cc", "Root surface resources locked",
254 TRACE_EVENT_SCOPE_THREAD); 271 TRACE_EVENT_SCOPE_THREAD);
255 return current_begin_frame_args_.frame_time + 272 return current_begin_frame_args_.frame_time +
256 current_begin_frame_args_.interval; 273 current_begin_frame_args_.interval;
257 } 274 }
258 275
259 bool root_ready_to_draw = 276 if (all_surfaces_ready && !expecting_root_surface_damage_because_of_resize_) {
260 !expect_damage_from_root_surface_ || root_surface_damaged_;
261
262 if (all_active_child_surfaces_ready_to_draw_ && root_ready_to_draw) {
263 TRACE_EVENT_INSTANT0("cc", "All active surfaces ready", 277 TRACE_EVENT_INSTANT0("cc", "All active surfaces ready",
264 TRACE_EVENT_SCOPE_THREAD); 278 TRACE_EVENT_SCOPE_THREAD);
265 return base::TimeTicks(); 279 return base::TimeTicks();
266 } 280 }
267 281
268 // TODO(mithro): Be smarter about resize deadlines. 282 // TODO(mithro): Be smarter about resize deadlines.
269 if (expecting_root_surface_damage_because_of_resize_) { 283 if (expecting_root_surface_damage_because_of_resize_) {
270 TRACE_EVENT_INSTANT0("cc", "Entire display damaged", 284 TRACE_EVENT_INSTANT0("cc", "Entire display damaged",
271 TRACE_EVENT_SCOPE_THREAD); 285 TRACE_EVENT_SCOPE_THREAD);
272 return current_begin_frame_args_.frame_time + 286 return current_begin_frame_args_.frame_time +
273 current_begin_frame_args_.interval; 287 current_begin_frame_args_.interval;
274 } 288 }
275 289
276 // Use an earlier deadline if we are only waiting for the root surface
277 // in case our expect_damage_from_root_surface heuristic is incorrect.
278 // TODO(mithro): Replace this with SetNeedsBeginFrame and SwapAbort
279 // logic.
280 if (all_active_child_surfaces_ready_to_draw_ &&
281 expect_damage_from_root_surface_) {
282 TRACE_EVENT_INSTANT0("cc", "Waiting for damage from root surface",
283 TRACE_EVENT_SCOPE_THREAD);
284 // This adjusts the deadline by DefaultEstimatedParentDrawTime for
285 // a second time. The first one represented the Surfaces draw to display
286 // latency. This one represents root surface commit+raster+draw latency.
287 // We treat the root surface differently since it lives on the same thread
288 // as Surfaces and waiting for it too long may push out the Surfaces draw.
289 // If we also assume the root surface is fast to start a commit after the
290 // beginning of a frame, it'll have a chance to lock its resources, which
291 // will cause us to wait for it to unlock its resources above.
292 // TODO(mithro): Replace hard coded estimates.
293 return current_begin_frame_args_.deadline -
294 BeginFrameArgs::DefaultEstimatedParentDrawTime();
295 }
296
297 TRACE_EVENT_INSTANT0("cc", "More damage expected soon", 290 TRACE_EVENT_INSTANT0("cc", "More damage expected soon",
298 TRACE_EVENT_SCOPE_THREAD); 291 TRACE_EVENT_SCOPE_THREAD);
299 return current_begin_frame_args_.deadline; 292 return current_begin_frame_args_.deadline;
300 } 293 }
301 294
302 void DisplayScheduler::ScheduleBeginFrameDeadline() { 295 void DisplayScheduler::ScheduleBeginFrameDeadline() {
303 TRACE_EVENT0("cc", "DisplayScheduler::ScheduleBeginFrameDeadline"); 296 TRACE_EVENT0("cc", "DisplayScheduler::ScheduleBeginFrameDeadline");
304 297
305 // We need to wait for the next BeginFrame before scheduling a deadline. 298 // We need to wait for the next BeginFrame before scheduling a deadline.
306 if (!inside_begin_frame_deadline_interval_) { 299 if (!inside_begin_frame_deadline_interval_) {
(...skipping 30 matching lines...) Expand all
337 bool DisplayScheduler::AttemptDrawAndSwap() { 330 bool DisplayScheduler::AttemptDrawAndSwap() {
338 inside_begin_frame_deadline_interval_ = false; 331 inside_begin_frame_deadline_interval_ = false;
339 begin_frame_deadline_task_.Cancel(); 332 begin_frame_deadline_task_.Cancel();
340 begin_frame_deadline_task_time_ = base::TimeTicks(); 333 begin_frame_deadline_task_time_ = base::TimeTicks();
341 334
342 if (ShouldDraw()) { 335 if (ShouldDraw()) {
343 if (pending_swaps_ < max_pending_swaps_ && !root_surface_resources_locked_) 336 if (pending_swaps_ < max_pending_swaps_ && !root_surface_resources_locked_)
344 return DrawAndSwap(); 337 return DrawAndSwap();
345 } else { 338 } else {
346 // We are going idle, so reset expectations. 339 // We are going idle, so reset expectations.
347 child_surface_ids_to_expect_damage_from_.clear(); 340 // TODO(eseckler): Should we avoid going idle if
348 child_surface_ids_damaged_prev_.clear(); 341 // |expecting_root_surface_damage_because_of_resize_| is true?
349 child_surface_ids_damaged_.clear(); 342 expecting_root_surface_damage_because_of_resize_ = false;
350 all_active_child_surfaces_ready_to_draw_ = true;
351 expect_damage_from_root_surface_ = false;
352 343
353 StopObservingBeginFrames(); 344 StopObservingBeginFrames();
354 } 345 }
355 return false; 346 return false;
356 } 347 }
357 348
358 void DisplayScheduler::OnBeginFrameDeadline() { 349 void DisplayScheduler::OnBeginFrameDeadline() {
359 TRACE_EVENT0("cc", "DisplayScheduler::OnBeginFrameDeadline"); 350 TRACE_EVENT0("cc", "DisplayScheduler::OnBeginFrameDeadline");
360 DCHECK(inside_begin_frame_deadline_interval_); 351 DCHECK(inside_begin_frame_deadline_interval_);
361 352
(...skipping 16 matching lines...) Expand all
378 } 369 }
379 370
380 void DisplayScheduler::DidReceiveSwapBuffersAck() { 371 void DisplayScheduler::DidReceiveSwapBuffersAck() {
381 uint32_t swap_id = next_swap_id_ - pending_swaps_; 372 uint32_t swap_id = next_swap_id_ - pending_swaps_;
382 pending_swaps_--; 373 pending_swaps_--;
383 TRACE_EVENT_ASYNC_END0("cc", "DisplayScheduler:pending_swaps", swap_id); 374 TRACE_EVENT_ASYNC_END0("cc", "DisplayScheduler:pending_swaps", swap_id);
384 ScheduleBeginFrameDeadline(); 375 ScheduleBeginFrameDeadline();
385 } 376 }
386 377
387 } // namespace cc 378 } // namespace cc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698