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

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

Issue 1012853003: Add DisplayScheduler for Surfaces (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: actually add unit tests Created 5 years, 8 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
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "cc/surfaces/display_scheduler.h"
6
7 #include <vector>
8
9 #include "base/stl_util.h"
10 #include "base/trace_event/trace_event.h"
11 #include "cc/output/output_surface.h"
12 #include "ui/gfx/frame_time.h"
13
14 namespace cc {
15
16 DisplayScheduler::DisplayScheduler(
17 DisplaySchedulerClient* client,
18 BeginFrameSource* begin_frame_source,
19 scoped_refptr<base::SingleThreadTaskRunner> task_runner,
20 int max_pending_swaps)
21 : client_(client),
22 begin_frame_source_(begin_frame_source),
23 task_runner_(task_runner),
24 output_surface_lost_(false),
25 resources_locked_by_browser_(true),
26 inside_begin_frame_deadline_interval_(false),
27 needs_draw_(false),
28 entire_display_damaged_(false),
29 all_active_surfaces_ready_to_draw_(false),
30 pending_swaps_(0),
31 max_pending_swaps_(max_pending_swaps),
32 weak_ptr_factory_(this) {
33 begin_frame_source_->AddObserver(this);
34 begin_frame_deadline_closure_ = base::Bind(
35 &DisplayScheduler::OnBeginFrameDeadline, weak_ptr_factory_.GetWeakPtr());
36 }
37
38 DisplayScheduler::~DisplayScheduler() {
39 begin_frame_source_->RemoveObserver(this);
40 }
41
42 // If we try to draw when the Browser has locked it's resources, the
43 // draw will fail.
44 void DisplayScheduler::SetResourcesLockedByBrowser(bool locked) {
45 resources_locked_by_browser_ = locked;
46 ScheduleBeginFrameDeadline();
47 }
48
49 // Notification that there was a resize or the root surface changed and
50 // that we should just draw immediately.
51 void DisplayScheduler::EntireDisplayDamaged() {
52 TRACE_EVENT0("cc", "DisplayScheduler::EntireDisplayDamaged");
53 needs_draw_ = true;
54 entire_display_damaged_ = true;
55 ScheduleBeginFrameDeadline();
56 }
57
58 // Indicates that there was damage to one of the surfaces.
59 // Has some logic to wait for multiple active surfaces before
60 // triggering the deadline.
61 void DisplayScheduler::SurfaceDamaged(SurfaceId surface_id) {
62 TRACE_EVENT1("cc", "DisplayScheduler::SurfaceDamaged", "surface_id",
63 surface_id.id);
64
65 needs_draw_ = true;
66
67 surface_ids_damaged_.insert(surface_id);
68
69 // TODO(mithro): Use hints from SetNeedsBeginFrames.
70 all_active_surfaces_ready_to_draw_ = base::STLIncludes(
71 surface_ids_damaged_, surface_ids_to_expect_damage_from_);
72
73 begin_frame_source_->SetNeedsBeginFrames(!output_surface_lost_);
74 ScheduleBeginFrameDeadline();
75 }
76
77 void DisplayScheduler::OutputSurfaceLost() {
78 TRACE_EVENT0("cc", "DisplayScheduler::OutputSurfaceLost");
79 output_surface_lost_ = true;
80 begin_frame_source_->SetNeedsBeginFrames(false);
81 ScheduleBeginFrameDeadline();
82 }
83
84 void DisplayScheduler::DrawAndSwap() {
85 TRACE_EVENT0("cc", "DisplayScheduler::DrawAndSwap");
86 DCHECK_LT(pending_swaps_, max_pending_swaps_);
87 DCHECK(!output_surface_lost_);
88
89 needs_draw_ = false;
90 entire_display_damaged_ = false;
91 all_active_surfaces_ready_to_draw_ = false;
92
93 client_->DrawAndSwap();
94
95 surface_ids_to_expect_damage_from_ =
96 base::STLSetIntersection<std::vector<SurfaceId>>(
97 surface_ids_damaged_, surface_ids_damaged_prev_);
98
99 surface_ids_damaged_prev_.swap(surface_ids_damaged_);
100 surface_ids_damaged_.clear();
101 }
102
103 bool DisplayScheduler::OnBeginFrameMixInDelegate(const BeginFrameArgs& args) {
104 TRACE_EVENT1("cc", "DisplayScheduler::BeginFrame", "args", args.AsValue());
105
106 // If we get another BeginFrame before the previous deadline,
107 // synchronously trigger the previous deadline before progressing.
108 if (inside_begin_frame_deadline_interval_) {
109 OnBeginFrameDeadline();
110 }
111
112 // Schedule the deadline.
113 current_begin_frame_args_ = args;
114 current_begin_frame_args_.deadline -=
115 BeginFrameArgs::DefaultEstimatedParentDrawTime();
116 inside_begin_frame_deadline_interval_ = true;
117 ScheduleBeginFrameDeadline();
118
119 return true;
120 }
121
122 base::TimeTicks DisplayScheduler::DesiredBeginFrameDeadlineTime() {
123 if (output_surface_lost_) {
124 TRACE_EVENT_INSTANT0("cc", "Lost output surface", TRACE_EVENT_SCOPE_THREAD);
125 return base::TimeTicks();
126 }
127
128 if (pending_swaps_ >= max_pending_swaps_) {
129 TRACE_EVENT_INSTANT0("cc", "Swap throttled", TRACE_EVENT_SCOPE_THREAD);
130 return current_begin_frame_args_.frame_time +
131 current_begin_frame_args_.interval;
132 }
133
134 if (resources_locked_by_browser_) {
135 TRACE_EVENT_INSTANT0("cc", "Resources locked by Browser",
136 TRACE_EVENT_SCOPE_THREAD);
137 return current_begin_frame_args_.frame_time +
138 current_begin_frame_args_.interval;
139 }
140
141 if (entire_display_damaged_) {
142 TRACE_EVENT_INSTANT0("cc", "Entire display damaged",
143 TRACE_EVENT_SCOPE_THREAD);
144 return base::TimeTicks();
145 }
146
147 if (all_active_surfaces_ready_to_draw_) {
148 TRACE_EVENT_INSTANT0("cc", "Active surfaces ready",
149 TRACE_EVENT_SCOPE_THREAD);
150 return base::TimeTicks();
151 }
152
153 if (needs_draw_) {
154 TRACE_EVENT_INSTANT0("cc", "More damage expected soon",
155 TRACE_EVENT_SCOPE_THREAD);
156 return current_begin_frame_args_.deadline;
157 }
158
159 TRACE_EVENT_INSTANT0("cc", "No damage yet", TRACE_EVENT_SCOPE_THREAD);
160 return current_begin_frame_args_.frame_time +
161 current_begin_frame_args_.interval;
162 }
163
164 void DisplayScheduler::ScheduleBeginFrameDeadline() {
165 TRACE_EVENT0("cc", "DisplayScheduler::ScheduleBeginFrameDeadline");
166
167 // We need to wait for the next BeginFrame before scheduling a deadline.
168 if (!inside_begin_frame_deadline_interval_) {
169 TRACE_EVENT_INSTANT0("cc", "Waiting for next BeginFrame",
170 TRACE_EVENT_SCOPE_THREAD);
171 DCHECK(begin_frame_deadline_task_.IsCancelled());
172 return;
173 }
174
175 // Determine the deadline we want to use.
176 base::TimeTicks desired_deadline = DesiredBeginFrameDeadlineTime();
177
178 // Avoid re-scheduling the deadline if it's already correctly scheduled.
179 if (!begin_frame_deadline_task_.IsCancelled() &&
180 desired_deadline == begin_frame_deadline_task_time_)
181 return;
182
183 // Schedule the deadline.
184 begin_frame_deadline_task_time_ = desired_deadline;
185 begin_frame_deadline_task_.Cancel();
186 begin_frame_deadline_task_.Reset(begin_frame_deadline_closure_);
187
188 base::TimeDelta delta =
189 std::max(base::TimeDelta(), desired_deadline - base::TimeTicks::Now());
190 task_runner_->PostDelayedTask(FROM_HERE,
191 begin_frame_deadline_task_.callback(), delta);
192 }
193
194 void DisplayScheduler::OnBeginFrameDeadline() {
195 TRACE_EVENT0("cc", "DisplayScheduler::OnBeginFrameDeadline");
196 begin_frame_deadline_task_.Cancel();
197 begin_frame_deadline_task_time_ = base::TimeTicks();
198
199 if (needs_draw_ && !output_surface_lost_) {
200 // TODO(brianderson): Figure out why supressing DrawAndSwap while
201 // resources_locked_by_browser_ is true causes hangs.
202 if (pending_swaps_ < max_pending_swaps_)
203 DrawAndSwap();
204 } else {
205 begin_frame_source_->SetNeedsBeginFrames(false);
206 }
207
208 inside_begin_frame_deadline_interval_ = false;
209 begin_frame_source_->DidFinishFrame(0);
210 }
211
212 void DisplayScheduler::DidSwapBuffers() {
213 pending_swaps_++;
214 TRACE_EVENT1("cc", "DisplayScheduler::DidSwapBuffers", "pending_frames",
215 pending_swaps_);
216 }
217
218 void DisplayScheduler::DidSwapBuffersComplete() {
219 pending_swaps_--;
220 TRACE_EVENT1("cc", "DisplayScheduler::DidSwapBuffersComplete",
221 "pending_frames", pending_swaps_);
222 ScheduleBeginFrameDeadline();
223 }
224
225 } // namespace cc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698