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

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: rebase on resize logging patch 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
« 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/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"
11 #include "cc/output/output_surface.h" 11 #include "cc/output/output_surface.h"
12 12
13 namespace cc { 13 namespace cc {
14 14
15 DisplayScheduler::DisplayScheduler(DisplaySchedulerClient* client, 15 DisplayScheduler::DisplayScheduler(DisplaySchedulerClient* client,
16 BeginFrameSource* begin_frame_source, 16 BeginFrameSource* begin_frame_source,
17 base::SingleThreadTaskRunner* task_runner, 17 base::SingleThreadTaskRunner* task_runner,
18 int max_pending_swaps) 18 int max_pending_swaps)
19 : client_(client), 19 : client_(client),
20 begin_frame_source_(begin_frame_source), 20 begin_frame_source_(begin_frame_source),
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 expecting_root_surface_damage_because_of_resize_(false), 26 child_surfaces_ready_to_draw_(false),
27 all_active_child_surfaces_ready_to_draw_(false),
28 pending_swaps_(0), 27 pending_swaps_(0),
29 max_pending_swaps_(max_pending_swaps), 28 max_pending_swaps_(max_pending_swaps),
30 root_surface_damaged_(false), 29 root_surface_damaged_(false),
31 expect_damage_from_root_surface_(false), 30 root_surface_active_(false),
31 expecting_root_surface_damage_because_of_resize_(false),
32 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 10 matching lines...) Expand all
52 void DisplayScheduler::ForceImmediateSwapIfPossible() { 53 void DisplayScheduler::ForceImmediateSwapIfPossible() {
53 TRACE_EVENT0("cc", "DisplayScheduler::ForceImmediateSwapIfPossible"); 54 TRACE_EVENT0("cc", "DisplayScheduler::ForceImmediateSwapIfPossible");
54 bool in_begin = inside_begin_frame_deadline_interval_; 55 bool in_begin = inside_begin_frame_deadline_interval_;
55 AttemptDrawAndSwap(); 56 AttemptDrawAndSwap();
56 if (in_begin) 57 if (in_begin)
57 begin_frame_source_->DidFinishFrame(0); 58 begin_frame_source_->DidFinishFrame(0);
58 } 59 }
59 60
60 void DisplayScheduler::DisplayResized() { 61 void DisplayScheduler::DisplayResized() {
61 expecting_root_surface_damage_because_of_resize_ = true; 62 expecting_root_surface_damage_because_of_resize_ = true;
62 expect_damage_from_root_surface_ = true; 63 root_surface_active_ = true;
63 ScheduleBeginFrameDeadline(); 64 ScheduleBeginFrameDeadline();
64 } 65 }
65 66
66 // Notification that there was a resize or the root surface changed and 67 // Notification that there was a resize or the root surface changed and
67 // that we should just draw immediately. 68 // that we should just draw immediately.
68 void DisplayScheduler::SetNewRootSurface(SurfaceId root_surface_id) { 69 void DisplayScheduler::SetNewRootSurface(SurfaceId root_surface_id) {
69 TRACE_EVENT0("cc", "DisplayScheduler::SetNewRootSurface"); 70 TRACE_EVENT0("cc", "DisplayScheduler::SetNewRootSurface");
70 root_surface_id_ = root_surface_id; 71 root_surface_id_ = root_surface_id;
71 SurfaceDamaged(root_surface_id); 72 SurfaceDamaged(root_surface_id);
72 } 73 }
73 74
74 // Indicates that there was damage to one of the surfaces. 75 // Indicates that there was damage to one of the surfaces.
75 // Has some logic to wait for multiple active surfaces before 76 // Has some logic to wait for multiple active surfaces before
76 // triggering the deadline. 77 // triggering the deadline.
77 void DisplayScheduler::SurfaceDamaged(SurfaceId surface_id) { 78 void DisplayScheduler::SurfaceDamaged(SurfaceId surface_id) {
78 TRACE_EVENT1("cc", "DisplayScheduler::SurfaceDamaged", "surface_id", 79 TRACE_EVENT1("cc", "DisplayScheduler::SurfaceDamaged", "surface_id",
79 surface_id.id); 80 surface_id.id);
80 81
81 needs_draw_ = true; 82 needs_draw_ = true;
82 83
83 if (surface_id == root_surface_id_) { 84 if (surface_id == root_surface_id_) {
84 root_surface_damaged_ = true; 85 root_surface_damaged_ = true;
85 expecting_root_surface_damage_because_of_resize_ = false; 86 expecting_root_surface_damage_because_of_resize_ = false;
86 } else { 87 } else {
87 child_surface_ids_damaged_.insert(surface_id); 88 child_surface_ids_damaged_.insert(surface_id);
88 89
90 // Update future expectations for active child surfaces.
91 for (int i = 0; i < kNumFramesSurfaceIsActive; i++)
92 active_child_surface_ids_[i].insert(surface_id);
93
89 // TODO(mithro): Use hints from SetNeedsBeginFrames and SwapAborts. 94 // TODO(mithro): Use hints from SetNeedsBeginFrames and SwapAborts.
90 all_active_child_surfaces_ready_to_draw_ = base::STLIncludes( 95 child_surfaces_ready_to_draw_ = base::STLIncludes(
91 child_surface_ids_damaged_, child_surface_ids_to_expect_damage_from_); 96 child_surface_ids_damaged_,
97 active_child_surface_ids_[active_child_surface_ids_index_]);
92 } 98 }
93 99
94 begin_frame_source_->SetNeedsBeginFrames(!output_surface_lost_); 100 begin_frame_source_->SetNeedsBeginFrames(!output_surface_lost_);
95 ScheduleBeginFrameDeadline(); 101 ScheduleBeginFrameDeadline();
96 } 102 }
97 103
98 void DisplayScheduler::OutputSurfaceLost() { 104 void DisplayScheduler::OutputSurfaceLost() {
99 TRACE_EVENT0("cc", "DisplayScheduler::OutputSurfaceLost"); 105 TRACE_EVENT0("cc", "DisplayScheduler::OutputSurfaceLost");
100 output_surface_lost_ = true; 106 output_surface_lost_ = true;
101 begin_frame_source_->SetNeedsBeginFrames(false); 107 begin_frame_source_->SetNeedsBeginFrames(false);
102 ScheduleBeginFrameDeadline(); 108 ScheduleBeginFrameDeadline();
103 } 109 }
104 110
105 void DisplayScheduler::DrawAndSwap() { 111 void DisplayScheduler::DrawAndSwap() {
106 TRACE_EVENT0("cc", "DisplayScheduler::DrawAndSwap"); 112 TRACE_EVENT0("cc", "DisplayScheduler::DrawAndSwap");
107 DCHECK_LT(pending_swaps_, max_pending_swaps_); 113 DCHECK_LT(pending_swaps_, max_pending_swaps_);
108 DCHECK(!output_surface_lost_); 114 DCHECK(!output_surface_lost_);
109 115
110 bool success = client_->DrawAndSwap(); 116 bool success = client_->DrawAndSwap();
111 if (!success) 117 if (!success)
112 return; 118 return;
113 119
114 child_surface_ids_to_expect_damage_from_ = 120 UpdateActiveSurfaces();
115 base::STLSetIntersection<std::vector<SurfaceId>>(
116 child_surface_ids_damaged_, child_surface_ids_damaged_prev_);
117 121
118 child_surface_ids_damaged_prev_.swap(child_surface_ids_damaged_); 122 // Update state regarding what needs to be drawn.
123 needs_draw_ = false;
124 root_surface_damaged_ = false;
119 child_surface_ids_damaged_.clear(); 125 child_surface_ids_damaged_.clear();
120
121 needs_draw_ = false;
122 all_active_child_surfaces_ready_to_draw_ =
123 child_surface_ids_to_expect_damage_from_.empty();
124
125 expect_damage_from_root_surface_ = root_surface_damaged_;
126 root_surface_damaged_ = false;
127 } 126 }
128 127
129 bool DisplayScheduler::OnBeginFrameDerivedImpl(const BeginFrameArgs& args) { 128 bool DisplayScheduler::OnBeginFrameDerivedImpl(const BeginFrameArgs& args) {
130 base::TimeTicks now = base::TimeTicks::Now(); 129 base::TimeTicks now = base::TimeTicks::Now();
131 TRACE_EVENT2("cc", "DisplayScheduler::BeginFrame", "args", args.AsValue(), 130 TRACE_EVENT2("cc", "DisplayScheduler::BeginFrame", "args", args.AsValue(),
132 "now", now); 131 "now", now);
133 132
134 // If we get another BeginFrame before the previous deadline, 133 // If we get another BeginFrame before the previous deadline,
135 // synchronously trigger the previous deadline before progressing. 134 // synchronously trigger the previous deadline before progressing.
136 if (inside_begin_frame_deadline_interval_) { 135 if (inside_begin_frame_deadline_interval_) {
(...skipping 28 matching lines...) Expand all
165 current_begin_frame_args_.interval; 164 current_begin_frame_args_.interval;
166 } 165 }
167 166
168 if (root_surface_resources_locked_) { 167 if (root_surface_resources_locked_) {
169 TRACE_EVENT_INSTANT0("cc", "Root surface resources locked", 168 TRACE_EVENT_INSTANT0("cc", "Root surface resources locked",
170 TRACE_EVENT_SCOPE_THREAD); 169 TRACE_EVENT_SCOPE_THREAD);
171 return current_begin_frame_args_.frame_time + 170 return current_begin_frame_args_.frame_time +
172 current_begin_frame_args_.interval; 171 current_begin_frame_args_.interval;
173 } 172 }
174 173
175 bool root_ready_to_draw = 174 bool root_ready_to_draw = !root_surface_active_ || root_surface_damaged_;
176 !expect_damage_from_root_surface_ || root_surface_damaged_;
177 175
178 if (all_active_child_surfaces_ready_to_draw_ && root_ready_to_draw) { 176 if (child_surfaces_ready_to_draw_ && root_ready_to_draw) {
179 TRACE_EVENT_INSTANT0("cc", "All active surfaces ready", 177 TRACE_EVENT_INSTANT0("cc", "All active surfaces ready",
180 TRACE_EVENT_SCOPE_THREAD); 178 TRACE_EVENT_SCOPE_THREAD);
181 return base::TimeTicks(); 179 return base::TimeTicks();
182 } 180 }
183 181
184 // TODO(mithro): Be smarter about resize deadlines. 182 // TODO(mithro): Be smarter about resize deadlines.
185 if (expecting_root_surface_damage_because_of_resize_) { 183 if (expecting_root_surface_damage_because_of_resize_) {
186 TRACE_EVENT_INSTANT0("cc", "Entire display damaged", 184 TRACE_EVENT_INSTANT0("cc", "Entire display damaged",
187 TRACE_EVENT_SCOPE_THREAD); 185 TRACE_EVENT_SCOPE_THREAD);
188 return current_begin_frame_args_.frame_time + 186 return current_begin_frame_args_.frame_time +
189 current_begin_frame_args_.interval; 187 current_begin_frame_args_.interval;
190 } 188 }
191 189
192 // Use an earlier deadline if we are only waiting for the root surface 190 // Use an earlier deadline if we are only waiting for the root surface
193 // in case our expect_damage_from_root_surface heuristic is incorrect. 191 // in case our expect_damage_from_root_surface heuristic is incorrect.
194 // TODO(mithro): Replace this with SetNeedsBeginFrame and SwapAbort 192 // TODO(mithro): Replace this with SetNeedsBeginFrame and SwapAbort
195 // logic. 193 // logic.
196 if (all_active_child_surfaces_ready_to_draw_ && 194 if (child_surfaces_ready_to_draw_ && root_surface_active_) {
197 expect_damage_from_root_surface_) {
198 TRACE_EVENT_INSTANT0("cc", "Waiting for damage from root surface", 195 TRACE_EVENT_INSTANT0("cc", "Waiting for damage from root surface",
199 TRACE_EVENT_SCOPE_THREAD); 196 TRACE_EVENT_SCOPE_THREAD);
200 // This adjusts the deadline by DefaultEstimatedParentDrawTime for 197 // This adjusts the deadline by DefaultEstimatedParentDrawTime for
201 // a second time. The first one represented the Surfaces draw to display 198 // a second time. The first one represented the Surfaces draw to display
202 // latency. This one represents root surface commit+raster+draw latency. 199 // latency. This one represents root surface commit+raster+draw latency.
203 // We treat the root surface differently since it lives on the same thread 200 // We treat the root surface differently since it lives on the same thread
204 // as Surfaces and waiting for it too long may push out the Surfaces draw. 201 // as Surfaces and waiting for it too long may push out the Surfaces draw.
205 // If we also assume the root surface is fast to start a commit after the 202 // If we also assume the root surface is fast to start a commit after the
206 // beginning of a frame, it'll have a chance to lock its resources, which 203 // beginning of a frame, it'll have a chance to lock its resources, which
207 // will cause us to wait for it to unlock its resources above. 204 // will cause us to wait for it to unlock its resources above.
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
248 begin_frame_deadline_task_.callback(), delta); 245 begin_frame_deadline_task_.callback(), delta);
249 TRACE_EVENT2("cc", "Using new deadline", "delta", delta.ToInternalValue(), 246 TRACE_EVENT2("cc", "Using new deadline", "delta", delta.ToInternalValue(),
250 "desired_deadline", desired_deadline); 247 "desired_deadline", desired_deadline);
251 } 248 }
252 249
253 void DisplayScheduler::AttemptDrawAndSwap() { 250 void DisplayScheduler::AttemptDrawAndSwap() {
254 inside_begin_frame_deadline_interval_ = false; 251 inside_begin_frame_deadline_interval_ = false;
255 begin_frame_deadline_task_.Cancel(); 252 begin_frame_deadline_task_.Cancel();
256 begin_frame_deadline_task_time_ = base::TimeTicks(); 253 begin_frame_deadline_task_time_ = base::TimeTicks();
257 254
258 if (needs_draw_ && !output_surface_lost_) { 255 bool stay_active =
259 if (pending_swaps_ < max_pending_swaps_ && !root_surface_resources_locked_) 256 !output_surface_lost_ &&
260 DrawAndSwap(); 257 (needs_draw_ || root_surface_active_ ||
261 } else { 258 !active_child_surface_ids_[active_child_surface_ids_index_].empty());
259
260 if (!stay_active) {
262 // We are going idle, so reset expectations. 261 // We are going idle, so reset expectations.
263 child_surface_ids_to_expect_damage_from_.clear(); 262 root_surface_active_ = false;
264 child_surface_ids_damaged_prev_.clear(); 263 child_surfaces_ready_to_draw_ = true;
265 child_surface_ids_damaged_.clear(); 264 active_child_surface_ids_index_ = 0;
266 all_active_child_surfaces_ready_to_draw_ = true; 265 for (int i = 0; i < kNumFramesSurfaceIsActive; i++)
267 expect_damage_from_root_surface_ = false; 266 active_child_surface_ids_[i].clear();
267 begin_frame_source_->SetNeedsBeginFrames(false);
268 return;
269 }
268 270
269 begin_frame_source_->SetNeedsBeginFrames(false); 271 if (!needs_draw_) {
272 // In order to properly go idle, make sure to update expectations that
273 // will cause |stay_active| to go false even if we have nothing to draw.
274 // Verify no child surfaces are currently damaged, since
275 // UpdateSurfaceDamageExpectatations will clear that list.
276 DCHECK(child_surface_ids_damaged_.empty());
277 DCHECK(!root_surface_damaged_);
278 UpdateActiveSurfaces();
279 return;
270 } 280 }
281
282 if (pending_swaps_ >= max_pending_swaps_ || root_surface_resources_locked_)
283 return;
284
285 DrawAndSwap();
271 } 286 }
272 287
273 void DisplayScheduler::OnBeginFrameDeadline() { 288 void DisplayScheduler::OnBeginFrameDeadline() {
274 TRACE_EVENT0("cc", "DisplayScheduler::OnBeginFrameDeadline"); 289 TRACE_EVENT0("cc", "DisplayScheduler::OnBeginFrameDeadline");
275 290
276 AttemptDrawAndSwap(); 291 AttemptDrawAndSwap();
277 begin_frame_source_->DidFinishFrame(0); 292 begin_frame_source_->DidFinishFrame(0);
278 } 293 }
279 294
280 void DisplayScheduler::DidSwapBuffers() { 295 void DisplayScheduler::DidSwapBuffers() {
281 pending_swaps_++; 296 pending_swaps_++;
282 TRACE_EVENT1("cc", "DisplayScheduler::DidSwapBuffers", "pending_frames", 297 TRACE_EVENT1("cc", "DisplayScheduler::DidSwapBuffers", "pending_frames",
283 pending_swaps_); 298 pending_swaps_);
284 } 299 }
285 300
286 void DisplayScheduler::DidSwapBuffersComplete() { 301 void DisplayScheduler::DidSwapBuffersComplete() {
287 pending_swaps_--; 302 pending_swaps_--;
288 TRACE_EVENT1("cc", "DisplayScheduler::DidSwapBuffersComplete", 303 TRACE_EVENT1("cc", "DisplayScheduler::DidSwapBuffersComplete",
289 "pending_frames", pending_swaps_); 304 "pending_frames", pending_swaps_);
290 ScheduleBeginFrameDeadline(); 305 ScheduleBeginFrameDeadline();
291 } 306 }
292 307
308 void DisplayScheduler::UpdateActiveSurfaces() {
309 root_surface_active_ = root_surface_damaged_;
310 active_child_surface_ids_[active_child_surface_ids_index_].clear();
311 active_child_surface_ids_index_ =
312 (active_child_surface_ids_index_ + 1) % kNumFramesSurfaceIsActive;
313 child_surfaces_ready_to_draw_ =
314 active_child_surface_ids_[active_child_surface_ids_index_].empty();
315 }
316
293 } // namespace cc 317 } // 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