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

Side by Side Diff: cc/output/output_surface.cc

Issue 199523002: cc: Throttle swaps in Scheduler instead of OutputSurface (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: rebase; DidSwapBuffersComplete Created 6 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
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2013 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/output/output_surface.h" 5 #include "cc/output/output_surface.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <set> 8 #include <set>
9 #include <string> 9 #include <string>
10 #include <vector> 10 #include <vector>
(...skipping 28 matching lines...) Expand all
39 const size_t kGpuLatencyHistorySize = 60; 39 const size_t kGpuLatencyHistorySize = 60;
40 const double kGpuLatencyEstimationPercentile = 100.0; 40 const double kGpuLatencyEstimationPercentile = 100.0;
41 41
42 } 42 }
43 43
44 namespace cc { 44 namespace cc {
45 45
46 OutputSurface::OutputSurface(scoped_refptr<ContextProvider> context_provider) 46 OutputSurface::OutputSurface(scoped_refptr<ContextProvider> context_provider)
47 : context_provider_(context_provider), 47 : context_provider_(context_provider),
48 device_scale_factor_(-1), 48 device_scale_factor_(-1),
49 max_frames_pending_(0), 49 begin_frame_interval_(BeginFrameArgs::DefaultInterval()),
50 pending_swap_buffers_(0), 50 throttle_frame_production_(true),
51 needs_begin_frame_(false), 51 needs_begin_frame_(false),
52 client_ready_for_begin_frame_(true), 52 client_ready_for_begin_frame_(true),
53 client_(NULL), 53 client_(NULL),
54 is_lost_(false),
54 check_for_retroactive_begin_frame_pending_(false), 55 check_for_retroactive_begin_frame_pending_(false),
55 external_stencil_test_enabled_(false), 56 external_stencil_test_enabled_(false),
56 weak_ptr_factory_(this), 57 weak_ptr_factory_(this),
57 gpu_latency_history_(kGpuLatencyHistorySize) {} 58 gpu_latency_history_(kGpuLatencyHistorySize) {}
58 59
59 OutputSurface::OutputSurface(scoped_ptr<SoftwareOutputDevice> software_device) 60 OutputSurface::OutputSurface(scoped_ptr<SoftwareOutputDevice> software_device)
60 : software_device_(software_device.Pass()), 61 : software_device_(software_device.Pass()),
61 device_scale_factor_(-1), 62 device_scale_factor_(-1),
62 max_frames_pending_(0), 63 begin_frame_interval_(BeginFrameArgs::DefaultInterval()),
63 pending_swap_buffers_(0), 64 throttle_frame_production_(true),
64 needs_begin_frame_(false), 65 needs_begin_frame_(false),
65 client_ready_for_begin_frame_(true), 66 client_ready_for_begin_frame_(true),
66 client_(NULL), 67 client_(NULL),
68 is_lost_(false),
67 check_for_retroactive_begin_frame_pending_(false), 69 check_for_retroactive_begin_frame_pending_(false),
68 external_stencil_test_enabled_(false), 70 external_stencil_test_enabled_(false),
69 weak_ptr_factory_(this), 71 weak_ptr_factory_(this),
70 gpu_latency_history_(kGpuLatencyHistorySize) {} 72 gpu_latency_history_(kGpuLatencyHistorySize) {}
71 73
72 OutputSurface::OutputSurface(scoped_refptr<ContextProvider> context_provider, 74 OutputSurface::OutputSurface(scoped_refptr<ContextProvider> context_provider,
73 scoped_ptr<SoftwareOutputDevice> software_device) 75 scoped_ptr<SoftwareOutputDevice> software_device)
74 : context_provider_(context_provider), 76 : context_provider_(context_provider),
75 software_device_(software_device.Pass()), 77 software_device_(software_device.Pass()),
76 device_scale_factor_(-1), 78 device_scale_factor_(-1),
77 max_frames_pending_(0), 79 begin_frame_interval_(BeginFrameArgs::DefaultInterval()),
78 pending_swap_buffers_(0), 80 throttle_frame_production_(true),
79 needs_begin_frame_(false), 81 needs_begin_frame_(false),
80 client_ready_for_begin_frame_(true), 82 client_ready_for_begin_frame_(true),
81 client_(NULL), 83 client_(NULL),
84 is_lost_(false),
82 check_for_retroactive_begin_frame_pending_(false), 85 check_for_retroactive_begin_frame_pending_(false),
83 external_stencil_test_enabled_(false), 86 external_stencil_test_enabled_(false),
84 weak_ptr_factory_(this), 87 weak_ptr_factory_(this),
85 gpu_latency_history_(kGpuLatencyHistorySize) {} 88 gpu_latency_history_(kGpuLatencyHistorySize) {}
86 89
90 void OutputSurface::SetThrottleFrameProduction(bool enable) {
91 DCHECK(!frame_rate_controller_);
92 throttle_frame_production_ = enable;
93 }
94
87 void OutputSurface::InitializeBeginFrameEmulation( 95 void OutputSurface::InitializeBeginFrameEmulation(
88 base::SingleThreadTaskRunner* task_runner, 96 base::SingleThreadTaskRunner* task_runner,
89 bool throttle_frame_production,
90 base::TimeDelta interval) { 97 base::TimeDelta interval) {
91 if (throttle_frame_production) { 98 DCHECK(throttle_frame_production_);
92 scoped_refptr<DelayBasedTimeSource> time_source; 99 scoped_refptr<DelayBasedTimeSource> time_source;
93 if (gfx::FrameTime::TimestampsAreHighRes()) 100 if (gfx::FrameTime::TimestampsAreHighRes())
94 time_source = DelayBasedTimeSourceHighRes::Create(interval, task_runner); 101 time_source = DelayBasedTimeSourceHighRes::Create(interval, task_runner);
95 else 102 else
96 time_source = DelayBasedTimeSource::Create(interval, task_runner); 103 time_source = DelayBasedTimeSource::Create(interval, task_runner);
97 frame_rate_controller_.reset(new FrameRateController(time_source)); 104 frame_rate_controller_.reset(new FrameRateController(time_source));
98 } else {
99 frame_rate_controller_.reset(new FrameRateController(task_runner));
100 }
101 105
102 frame_rate_controller_->SetClient(this); 106 frame_rate_controller_->SetClient(this);
103 frame_rate_controller_->SetMaxSwapsPending(max_frames_pending_);
104 frame_rate_controller_->SetDeadlineAdjustment( 107 frame_rate_controller_->SetDeadlineAdjustment(
105 capabilities_.adjust_deadline_for_parent ? 108 capabilities_.adjust_deadline_for_parent ?
106 BeginFrameArgs::DefaultDeadlineAdjustment() : base::TimeDelta()); 109 BeginFrameArgs::DefaultDeadlineAdjustment() : base::TimeDelta());
107
108 // The new frame rate controller will consume the swap acks of the old
109 // frame rate controller, so we set that expectation up here.
110 for (int i = 0; i < pending_swap_buffers_; i++)
111 frame_rate_controller_->DidSwapBuffers();
112 }
113
114 void OutputSurface::SetMaxFramesPending(int max_frames_pending) {
115 if (frame_rate_controller_)
116 frame_rate_controller_->SetMaxSwapsPending(max_frames_pending);
117 max_frames_pending_ = max_frames_pending;
118 } 110 }
119 111
120 void OutputSurface::CommitVSyncParameters(base::TimeTicks timebase, 112 void OutputSurface::CommitVSyncParameters(base::TimeTicks timebase,
121 base::TimeDelta interval) { 113 base::TimeDelta interval) {
122 TRACE_EVENT2("cc", 114 TRACE_EVENT2("cc",
123 "OutputSurface::CommitVSyncParameters", 115 "OutputSurface::CommitVSyncParameters",
124 "timebase", 116 "timebase",
125 (timebase - base::TimeTicks()).InSecondsF(), 117 (timebase - base::TimeTicks()).InSecondsF(),
126 "interval", 118 "interval",
127 interval.InSecondsF()); 119 interval.InSecondsF());
120 begin_frame_interval_ = interval;
128 if (frame_rate_controller_) 121 if (frame_rate_controller_)
129 frame_rate_controller_->SetTimebaseAndInterval(timebase, interval); 122 frame_rate_controller_->SetTimebaseAndInterval(timebase, interval);
130 } 123 }
131 124
132 void OutputSurface::FrameRateControllerTick(bool throttled, 125 void OutputSurface::FrameRateControllerTick(const BeginFrameArgs& args) {
133 const BeginFrameArgs& args) {
134 DCHECK(frame_rate_controller_); 126 DCHECK(frame_rate_controller_);
135 if (throttled) 127 BeginFrame(args);
136 skipped_begin_frame_args_ = args;
137 else
138 BeginFrame(args);
139 } 128 }
140 129
141 // Forwarded to OutputSurfaceClient 130 // Forwarded to OutputSurfaceClient
142 void OutputSurface::SetNeedsRedrawRect(const gfx::Rect& damage_rect) { 131 void OutputSurface::SetNeedsRedrawRect(const gfx::Rect& damage_rect) {
143 TRACE_EVENT0("cc", "OutputSurface::SetNeedsRedrawRect"); 132 TRACE_EVENT0("cc", "OutputSurface::SetNeedsRedrawRect");
144 client_->SetNeedsRedrawRect(damage_rect); 133 client_->SetNeedsRedrawRect(damage_rect);
145 } 134 }
146 135
147 void OutputSurface::SetNeedsBeginFrame(bool enable) { 136 void OutputSurface::SetNeedsBeginFrame(bool enable) {
148 TRACE_EVENT1("cc", "OutputSurface::SetNeedsBeginFrame", "enable", enable); 137 TRACE_EVENT1("cc", "OutputSurface::SetNeedsBeginFrame", "enable", enable);
149 needs_begin_frame_ = enable; 138 needs_begin_frame_ = enable;
150 client_ready_for_begin_frame_ = true; 139 client_ready_for_begin_frame_ = true;
151 if (frame_rate_controller_) { 140 if (!throttle_frame_production_) {
141 if (enable) {
142 base::TimeTicks frame_time = gfx::FrameTime::Now();
143 base::TimeTicks deadline = frame_time + begin_frame_interval_;
144 skipped_begin_frame_args_ =
145 BeginFrameArgs::Create(frame_time, deadline, begin_frame_interval_);
146 }
147 } else if (frame_rate_controller_) {
152 BeginFrameArgs skipped = frame_rate_controller_->SetActive(enable); 148 BeginFrameArgs skipped = frame_rate_controller_->SetActive(enable);
153 if (skipped.IsValid()) 149 if (skipped.IsValid())
154 skipped_begin_frame_args_ = skipped; 150 skipped_begin_frame_args_ = skipped;
155 } 151 }
152
156 if (needs_begin_frame_) 153 if (needs_begin_frame_)
157 PostCheckForRetroactiveBeginFrame(); 154 PostCheckForRetroactiveBeginFrame();
158 } 155 }
159 156
160 void OutputSurface::BeginFrame(const BeginFrameArgs& args) { 157 void OutputSurface::BeginFrame(const BeginFrameArgs& args) {
161 TRACE_EVENT2("cc", 158 TRACE_EVENT1("cc",
162 "OutputSurface::BeginFrame", 159 "OutputSurface::BeginFrame",
163 "client_ready_for_begin_frame_", 160 "client_ready_for_begin_frame_",
164 client_ready_for_begin_frame_, 161 client_ready_for_begin_frame_);
165 "pending_swap_buffers_", 162 if (!needs_begin_frame_ || !client_ready_for_begin_frame_) {
166 pending_swap_buffers_);
167 if (!needs_begin_frame_ || !client_ready_for_begin_frame_ ||
168 (pending_swap_buffers_ >= max_frames_pending_ &&
169 max_frames_pending_ > 0)) {
170 skipped_begin_frame_args_ = args; 163 skipped_begin_frame_args_ = args;
171 } else { 164 } else {
172 client_ready_for_begin_frame_ = false; 165 client_ready_for_begin_frame_ = false;
173 client_->BeginFrame(args); 166 client_->BeginFrame(args);
174 // args might be an alias for skipped_begin_frame_args_. 167 // args might be an alias for skipped_begin_frame_args_.
175 // Do not reset it before calling BeginFrame! 168 // Do not reset it before calling BeginFrame!
176 skipped_begin_frame_args_ = BeginFrameArgs(); 169 skipped_begin_frame_args_ = BeginFrameArgs();
177 } 170 }
178 } 171 }
179 172
(...skipping 14 matching lines...) Expand all
194 base::MessageLoop::current()->PostTask( 187 base::MessageLoop::current()->PostTask(
195 FROM_HERE, 188 FROM_HERE,
196 base::Bind(&OutputSurface::CheckForRetroactiveBeginFrame, 189 base::Bind(&OutputSurface::CheckForRetroactiveBeginFrame,
197 weak_ptr_factory_.GetWeakPtr())); 190 weak_ptr_factory_.GetWeakPtr()));
198 check_for_retroactive_begin_frame_pending_ = true; 191 check_for_retroactive_begin_frame_pending_ = true;
199 } 192 }
200 193
201 void OutputSurface::CheckForRetroactiveBeginFrame() { 194 void OutputSurface::CheckForRetroactiveBeginFrame() {
202 TRACE_EVENT0("cc", "OutputSurface::CheckForRetroactiveBeginFrame"); 195 TRACE_EVENT0("cc", "OutputSurface::CheckForRetroactiveBeginFrame");
203 check_for_retroactive_begin_frame_pending_ = false; 196 check_for_retroactive_begin_frame_pending_ = false;
204 if (gfx::FrameTime::Now() < RetroactiveBeginFrameDeadline()) 197 if (!throttle_frame_production_ ||
198 gfx::FrameTime::Now() < RetroactiveBeginFrameDeadline())
205 BeginFrame(skipped_begin_frame_args_); 199 BeginFrame(skipped_begin_frame_args_);
206 } 200 }
207 201
208 void OutputSurface::DidSwapBuffers() { 202 void OutputSurface::DidSwapBuffers() {
209 pending_swap_buffers_++; 203 if (is_lost_)
danakj 2014/04/11 15:12:28 Why do you need these is_lost_ checks here? If ne
brianderson 2014/04/11 20:49:40 The is_lost_ check should probably go into each Sw
danakj 2014/04/14 18:14:50 The single thread implementation checks for this b
210 TRACE_EVENT1("cc", "OutputSurface::DidSwapBuffers", 204 return;
211 "pending_swap_buffers_", pending_swap_buffers_); 205 TRACE_EVENT0("cc", "OutputSurface::DidSwapBuffers");
212 client_->DidSwapBuffers(); 206 client_->DidSwapBuffers();
213 if (frame_rate_controller_)
214 frame_rate_controller_->DidSwapBuffers();
215 PostCheckForRetroactiveBeginFrame();
216 } 207 }
217 208
218 void OutputSurface::OnSwapBuffersComplete() { 209 void OutputSurface::OnSwapBuffersComplete() {
219 pending_swap_buffers_--; 210 if (is_lost_)
danakj 2014/04/14 18:14:50 Since this is an ACK from the browser IPC it makes
220 TRACE_EVENT1("cc", "OutputSurface::OnSwapBuffersComplete", 211 return;
221 "pending_swap_buffers_", pending_swap_buffers_); 212 TRACE_EVENT0("cc", "OutputSurface::OnSwapBuffersComplete");
222 client_->OnSwapBuffersComplete(); 213 client_->DidSwapBuffersComplete();
223 if (frame_rate_controller_)
224 frame_rate_controller_->DidSwapBuffersComplete();
225 PostCheckForRetroactiveBeginFrame();
226 } 214 }
227 215
228 void OutputSurface::ReclaimResources(const CompositorFrameAck* ack) { 216 void OutputSurface::ReclaimResources(const CompositorFrameAck* ack) {
229 client_->ReclaimResources(ack); 217 client_->ReclaimResources(ack);
230 } 218 }
231 219
232 void OutputSurface::DidLoseOutputSurface() { 220 void OutputSurface::DidLoseOutputSurface() {
233 TRACE_EVENT0("cc", "OutputSurface::DidLoseOutputSurface"); 221 TRACE_EVENT0("cc", "OutputSurface::DidLoseOutputSurface");
234 client_ready_for_begin_frame_ = true; 222 client_ready_for_begin_frame_ = true;
235 pending_swap_buffers_ = 0;
236 skipped_begin_frame_args_ = BeginFrameArgs(); 223 skipped_begin_frame_args_ = BeginFrameArgs();
237 if (frame_rate_controller_) 224 if (frame_rate_controller_)
238 frame_rate_controller_->SetActive(false); 225 frame_rate_controller_->SetActive(false);
239 pending_gpu_latency_query_ids_.clear(); 226 pending_gpu_latency_query_ids_.clear();
240 available_gpu_latency_query_ids_.clear(); 227 available_gpu_latency_query_ids_.clear();
241 client_->DidLoseOutputSurface(); 228 client_->DidLoseOutputSurface();
229 is_lost_ = true;
242 } 230 }
243 231
244 void OutputSurface::SetExternalStencilTest(bool enabled) { 232 void OutputSurface::SetExternalStencilTest(bool enabled) {
245 external_stencil_test_enabled_ = enabled; 233 external_stencil_test_enabled_ = enabled;
246 } 234 }
247 235
248 void OutputSurface::SetExternalDrawConstraints(const gfx::Transform& transform, 236 void OutputSurface::SetExternalDrawConstraints(const gfx::Transform& transform,
249 const gfx::Rect& viewport, 237 const gfx::Rect& viewport,
250 const gfx::Rect& clip, 238 const gfx::Rect& clip,
251 bool valid_for_tile_management) { 239 bool valid_for_tile_management) {
(...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after
488 TRACE_EVENT1("cc", "OutputSurface::SetMemoryPolicy", 476 TRACE_EVENT1("cc", "OutputSurface::SetMemoryPolicy",
489 "bytes_limit_when_visible", policy.bytes_limit_when_visible); 477 "bytes_limit_when_visible", policy.bytes_limit_when_visible);
490 // Just ignore the memory manager when it says to set the limit to zero 478 // Just ignore the memory manager when it says to set the limit to zero
491 // bytes. This will happen when the memory manager thinks that the renderer 479 // bytes. This will happen when the memory manager thinks that the renderer
492 // is not visible (which the renderer knows better). 480 // is not visible (which the renderer knows better).
493 if (policy.bytes_limit_when_visible) 481 if (policy.bytes_limit_when_visible)
494 client_->SetMemoryPolicy(policy); 482 client_->SetMemoryPolicy(policy);
495 } 483 }
496 484
497 } // namespace cc 485 } // namespace cc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698