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

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

Issue 1251693002: cc: Consider Surface active if frame received recently (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: active_child_surface_ids_ Created 5 years, 5 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/stl_util.h" 9 #include "base/stl_util.h"
10 #include "base/trace_event/trace_event.h" 10 #include "base/trace_event/trace_event.h"
(...skipping 10 matching lines...) Expand all
21 task_runner_(task_runner), 21 task_runner_(task_runner),
22 output_surface_lost_(false), 22 output_surface_lost_(false),
23 root_surface_resources_locked_(true), 23 root_surface_resources_locked_(true),
24 inside_begin_frame_deadline_interval_(false), 24 inside_begin_frame_deadline_interval_(false),
25 needs_draw_(false), 25 needs_draw_(false),
26 entire_display_damaged_(false), 26 entire_display_damaged_(false),
27 all_active_child_surfaces_ready_to_draw_(false), 27 all_active_child_surfaces_ready_to_draw_(false),
28 pending_swaps_(0), 28 pending_swaps_(0),
29 max_pending_swaps_(max_pending_swaps), 29 max_pending_swaps_(max_pending_swaps),
30 root_surface_damaged_(false), 30 root_surface_damaged_(false),
31 expect_damage_from_root_surface_(false), 31 root_surface_active_(false),
32 current_active_child_surface_ids_index_(0),
32 weak_ptr_factory_(this) { 33 weak_ptr_factory_(this) {
33 begin_frame_source_->AddObserver(this); 34 begin_frame_source_->AddObserver(this);
34 begin_frame_deadline_closure_ = base::Bind( 35 begin_frame_deadline_closure_ = base::Bind(
35 &DisplayScheduler::OnBeginFrameDeadline, weak_ptr_factory_.GetWeakPtr()); 36 &DisplayScheduler::OnBeginFrameDeadline, weak_ptr_factory_.GetWeakPtr());
36 } 37 }
37 38
38 DisplayScheduler::~DisplayScheduler() { 39 DisplayScheduler::~DisplayScheduler() {
39 begin_frame_source_->RemoveObserver(this); 40 begin_frame_source_->RemoveObserver(this);
40 } 41 }
41 42
(...skipping 30 matching lines...) Expand all
72 void DisplayScheduler::SurfaceDamaged(SurfaceId surface_id) { 73 void DisplayScheduler::SurfaceDamaged(SurfaceId surface_id) {
73 TRACE_EVENT1("cc", "DisplayScheduler::SurfaceDamaged", "surface_id", 74 TRACE_EVENT1("cc", "DisplayScheduler::SurfaceDamaged", "surface_id",
74 surface_id.id); 75 surface_id.id);
75 76
76 needs_draw_ = true; 77 needs_draw_ = true;
77 78
78 if (surface_id == root_surface_id_) { 79 if (surface_id == root_surface_id_) {
79 root_surface_damaged_ = true; 80 root_surface_damaged_ = true;
80 } else { 81 } else {
81 child_surface_ids_damaged_.insert(surface_id); 82 child_surface_ids_damaged_.insert(surface_id);
83 UpdateFutureActiveChildSurfaceIDs(surface_id);
sunnyps 2015/07/23 21:10:38 nit: Instead of a separate method, just update the
82 84
83 // TODO(mithro): Use hints from SetNeedsBeginFrames and SwapAborts. 85 // TODO(mithro): Use hints from SetNeedsBeginFrames and SwapAborts.
84 all_active_child_surfaces_ready_to_draw_ = base::STLIncludes( 86 all_active_child_surfaces_ready_to_draw_ = base::STLIncludes(
85 child_surface_ids_damaged_, child_surface_ids_to_expect_damage_from_); 87 child_surface_ids_damaged_, CurrentActiveChildSurfaceIDs());
86 } 88 }
87 89
88 begin_frame_source_->SetNeedsBeginFrames(!output_surface_lost_); 90 begin_frame_source_->SetNeedsBeginFrames(!output_surface_lost_);
89 ScheduleBeginFrameDeadline(); 91 ScheduleBeginFrameDeadline();
90 } 92 }
91 93
92 void DisplayScheduler::OutputSurfaceLost() { 94 void DisplayScheduler::OutputSurfaceLost() {
93 TRACE_EVENT0("cc", "DisplayScheduler::OutputSurfaceLost"); 95 TRACE_EVENT0("cc", "DisplayScheduler::OutputSurfaceLost");
94 output_surface_lost_ = true; 96 output_surface_lost_ = true;
95 begin_frame_source_->SetNeedsBeginFrames(false); 97 begin_frame_source_->SetNeedsBeginFrames(false);
96 ScheduleBeginFrameDeadline(); 98 ScheduleBeginFrameDeadline();
97 } 99 }
98 100
99 void DisplayScheduler::DrawAndSwap() { 101 void DisplayScheduler::DrawAndSwap() {
100 TRACE_EVENT0("cc", "DisplayScheduler::DrawAndSwap"); 102 TRACE_EVENT0("cc", "DisplayScheduler::DrawAndSwap");
101 DCHECK_LT(pending_swaps_, max_pending_swaps_); 103 DCHECK_LT(pending_swaps_, max_pending_swaps_);
102 DCHECK(!output_surface_lost_); 104 DCHECK(!output_surface_lost_);
103 105
104 bool success = client_->DrawAndSwap(); 106 bool success = client_->DrawAndSwap();
105 if (!success) 107 if (!success)
106 return; 108 return;
107 109
108 child_surface_ids_to_expect_damage_from_ = 110 UpdateActiveSurfaces();
sunnyps 2015/07/23 21:10:38 nit: No need for a separate method here. It's easi
109 base::STLSetIntersection<std::vector<SurfaceId>>(
110 child_surface_ids_damaged_, child_surface_ids_damaged_prev_);
111 111
112 child_surface_ids_damaged_prev_.swap(child_surface_ids_damaged_); 112 // Update state regarding what needs to be drawn.
113 child_surface_ids_damaged_.clear();
114
115 needs_draw_ = false; 113 needs_draw_ = false;
116 entire_display_damaged_ = false; 114 entire_display_damaged_ = false;
117 all_active_child_surfaces_ready_to_draw_ =
118 child_surface_ids_to_expect_damage_from_.empty();
119
120 expect_damage_from_root_surface_ = root_surface_damaged_;
121 root_surface_damaged_ = false; 115 root_surface_damaged_ = false;
116 child_surface_ids_damaged_.clear();
122 } 117 }
123 118
124 bool DisplayScheduler::OnBeginFrameDerivedImpl(const BeginFrameArgs& args) { 119 bool DisplayScheduler::OnBeginFrameDerivedImpl(const BeginFrameArgs& args) {
125 base::TimeTicks now = base::TimeTicks::Now(); 120 base::TimeTicks now = base::TimeTicks::Now();
126 TRACE_EVENT2("cc", "DisplayScheduler::BeginFrame", "args", args.AsValue(), 121 TRACE_EVENT2("cc", "DisplayScheduler::BeginFrame", "args", args.AsValue(),
127 "now", now); 122 "now", now);
128 123
129 // If we get another BeginFrame before the previous deadline, 124 // If we get another BeginFrame before the previous deadline,
130 // synchronously trigger the previous deadline before progressing. 125 // synchronously trigger the previous deadline before progressing.
131 if (inside_begin_frame_deadline_interval_) { 126 if (inside_begin_frame_deadline_interval_) {
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
167 current_begin_frame_args_.interval; 162 current_begin_frame_args_.interval;
168 } 163 }
169 164
170 // TODO(mithro): Be smarter about resize deadlines. 165 // TODO(mithro): Be smarter about resize deadlines.
171 if (entire_display_damaged_) { 166 if (entire_display_damaged_) {
172 TRACE_EVENT_INSTANT0("cc", "Entire display damaged", 167 TRACE_EVENT_INSTANT0("cc", "Entire display damaged",
173 TRACE_EVENT_SCOPE_THREAD); 168 TRACE_EVENT_SCOPE_THREAD);
174 return base::TimeTicks(); 169 return base::TimeTicks();
175 } 170 }
176 171
177 bool root_ready_to_draw = 172 bool root_ready_to_draw = !root_surface_active_ || root_surface_damaged_;
178 !expect_damage_from_root_surface_ || root_surface_damaged_;
179 173
180 if (all_active_child_surfaces_ready_to_draw_ && root_ready_to_draw) { 174 if (all_active_child_surfaces_ready_to_draw_ && root_ready_to_draw) {
181 TRACE_EVENT_INSTANT0("cc", "All active surfaces ready", 175 TRACE_EVENT_INSTANT0("cc", "All active surfaces ready",
182 TRACE_EVENT_SCOPE_THREAD); 176 TRACE_EVENT_SCOPE_THREAD);
183 return base::TimeTicks(); 177 return base::TimeTicks();
184 } 178 }
185 179
186 // Use an earlier deadline if we are only waiting for the root surface 180 // Use an earlier deadline if we are only waiting for the root surface
187 // in case our expect_damage_from_root_surface heuristic is incorrect. 181 // in case our expect_damage_from_root_surface heuristic is incorrect.
188 // TODO(mithro): Replace this with SetNeedsBeginFrame and SwapAbort 182 // TODO(mithro): Replace this with SetNeedsBeginFrame and SwapAbort
189 // logic. 183 // logic.
190 if (all_active_child_surfaces_ready_to_draw_ && 184 if (all_active_child_surfaces_ready_to_draw_ && root_surface_active_) {
sunnyps 2015/07/23 21:10:38 nit: Rename to child_surfaces_ready_to_draw_
brianderson 2015/07/23 22:21:48 Done.
191 expect_damage_from_root_surface_) {
192 TRACE_EVENT_INSTANT0("cc", "Waiting for damage from root surface", 185 TRACE_EVENT_INSTANT0("cc", "Waiting for damage from root surface",
193 TRACE_EVENT_SCOPE_THREAD); 186 TRACE_EVENT_SCOPE_THREAD);
194 // This adjusts the deadline by DefaultEstimatedParentDrawTime for 187 // This adjusts the deadline by DefaultEstimatedParentDrawTime for
195 // a second time. The first one represented the Surfaces draw to display 188 // a second time. The first one represented the Surfaces draw to display
196 // latency. This one represents root surface commit+raster+draw latency. 189 // latency. This one represents root surface commit+raster+draw latency.
197 // We treat the root surface differently since it lives on the same thread 190 // We treat the root surface differently since it lives on the same thread
198 // as Surfaces and waiting for it too long may push out the Surfaces draw. 191 // as Surfaces and waiting for it too long may push out the Surfaces draw.
199 // If we also assume the root surface is fast to start a commit after the 192 // If we also assume the root surface is fast to start a commit after the
200 // beginning of a frame, it'll have a chance to lock its resources, which 193 // beginning of a frame, it'll have a chance to lock its resources, which
201 // will cause us to wait for it to unlock its resources above. 194 // will cause us to wait for it to unlock its resources above.
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
242 begin_frame_deadline_task_.callback(), delta); 235 begin_frame_deadline_task_.callback(), delta);
243 TRACE_EVENT2("cc", "Using new deadline", "delta", delta.ToInternalValue(), 236 TRACE_EVENT2("cc", "Using new deadline", "delta", delta.ToInternalValue(),
244 "desired_deadline", desired_deadline); 237 "desired_deadline", desired_deadline);
245 } 238 }
246 239
247 void DisplayScheduler::AttemptDrawAndSwap() { 240 void DisplayScheduler::AttemptDrawAndSwap() {
248 inside_begin_frame_deadline_interval_ = false; 241 inside_begin_frame_deadline_interval_ = false;
249 begin_frame_deadline_task_.Cancel(); 242 begin_frame_deadline_task_.Cancel();
250 begin_frame_deadline_task_time_ = base::TimeTicks(); 243 begin_frame_deadline_task_time_ = base::TimeTicks();
251 244
252 if (needs_draw_ && !output_surface_lost_) { 245 bool stay_active =
253 if (pending_swaps_ < max_pending_swaps_ && !root_surface_resources_locked_) 246 !output_surface_lost_ && (needs_draw_ || root_surface_active_ ||
254 DrawAndSwap(); 247 !CurrentActiveChildSurfaceIDs().empty());
248
sunnyps 2015/07/23 21:10:38 nit: This could be better structured as: if (!sta
brianderson 2015/07/23 22:21:48 Done.
249 if (stay_active) {
250 if (needs_draw_) {
251 if (pending_swaps_ < max_pending_swaps_ &&
252 !root_surface_resources_locked_)
253 DrawAndSwap();
254 } else {
255 // In order to properly go idle, make sure to update expectations that
256 // will cause |stay_active| to go false even if we have nothing to draw.
257 // Verify no child surfaces are currently damaged, since
258 // UpdateSurfaceDamageExpectatations will clear that list.
259 DCHECK(child_surface_ids_damaged_.empty());
260 DCHECK(!entire_display_damaged_);
261 DCHECK(!root_surface_damaged_);
262 UpdateActiveSurfaces();
263 }
255 } else { 264 } else {
256 // We are going idle, so reset expectations. 265 // We are going idle, so reset expectations.
257 child_surface_ids_to_expect_damage_from_.clear(); 266 ClearActiveSurfaces();
sunnyps 2015/07/23 21:10:38 nit: Probably doesn't need a separate method.
258 child_surface_ids_damaged_prev_.clear();
259 child_surface_ids_damaged_.clear();
260 all_active_child_surfaces_ready_to_draw_ = true;
261 expect_damage_from_root_surface_ = false;
262
263 begin_frame_source_->SetNeedsBeginFrames(false); 267 begin_frame_source_->SetNeedsBeginFrames(false);
264 } 268 }
265 } 269 }
266 270
267 void DisplayScheduler::OnBeginFrameDeadline() { 271 void DisplayScheduler::OnBeginFrameDeadline() {
268 TRACE_EVENT0("cc", "DisplayScheduler::OnBeginFrameDeadline"); 272 TRACE_EVENT0("cc", "DisplayScheduler::OnBeginFrameDeadline");
269 273
270 AttemptDrawAndSwap(); 274 AttemptDrawAndSwap();
271 begin_frame_source_->DidFinishFrame(0); 275 begin_frame_source_->DidFinishFrame(0);
272 } 276 }
273 277
274 void DisplayScheduler::DidSwapBuffers() { 278 void DisplayScheduler::DidSwapBuffers() {
275 pending_swaps_++; 279 pending_swaps_++;
276 TRACE_EVENT1("cc", "DisplayScheduler::DidSwapBuffers", "pending_frames", 280 TRACE_EVENT1("cc", "DisplayScheduler::DidSwapBuffers", "pending_frames",
277 pending_swaps_); 281 pending_swaps_);
278 } 282 }
279 283
280 void DisplayScheduler::DidSwapBuffersComplete() { 284 void DisplayScheduler::DidSwapBuffersComplete() {
281 pending_swaps_--; 285 pending_swaps_--;
282 TRACE_EVENT1("cc", "DisplayScheduler::DidSwapBuffersComplete", 286 TRACE_EVENT1("cc", "DisplayScheduler::DidSwapBuffersComplete",
283 "pending_frames", pending_swaps_); 287 "pending_frames", pending_swaps_);
284 ScheduleBeginFrameDeadline(); 288 ScheduleBeginFrameDeadline();
285 } 289 }
286 290
291 std::set<SurfaceId>& DisplayScheduler::CurrentActiveChildSurfaceIDs() {
sunnyps 2015/07/23 21:10:38 nit: inline this
292 return active_child_surface_ids_[current_active_child_surface_ids_index_];
293 }
294
295 void DisplayScheduler::UpdateFutureActiveChildSurfaceIDs(SurfaceId surface_id) {
296 for (int i = 0; i < kActiveChildSurfaceIdsSize; i++)
297 active_child_surface_ids_[i].insert(surface_id);
298 }
299
300 void DisplayScheduler::ClearActiveSurfaces() {
301 root_surface_active_ = false;
302
303 current_active_child_surface_ids_index_ = 0;
304 for (int i = 0; i < kActiveChildSurfaceIdsSize; i++)
305 active_child_surface_ids_[i].clear();
306
307 all_active_child_surfaces_ready_to_draw_ = true;
308 }
309
310 void DisplayScheduler::UpdateActiveSurfaces() {
311 root_surface_active_ = root_surface_damaged_;
312
313 CurrentActiveChildSurfaceIDs().clear();
314
315 current_active_child_surface_ids_index_++;
sunnyps 2015/07/23 21:10:38 nit: index = (index + 1) % N
brianderson 2015/07/23 22:21:49 Done.
316 if (current_active_child_surface_ids_index_ >= kActiveChildSurfaceIdsSize)
317 current_active_child_surface_ids_index_ = 0;
318
319 all_active_child_surfaces_ready_to_draw_ =
sunnyps 2015/07/23 21:10:38 nit: This could be an inline function.
brianderson 2015/07/23 22:21:48 My goal in writing all the helper methods was to p
320 CurrentActiveChildSurfaceIDs().empty();
321 }
322
287 } // namespace cc 323 } // namespace cc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698