OLD | NEW |
---|---|
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 26 matching lines...) Expand all Loading... | |
37 namespace { | 37 namespace { |
38 | 38 |
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 : client_(NULL), |
48 is_lost_(false), | |
49 context_provider_(context_provider), | |
48 device_scale_factor_(-1), | 50 device_scale_factor_(-1), |
49 begin_frame_interval_(BeginFrameArgs::DefaultInterval()), | |
50 throttle_frame_production_(true), | |
51 needs_begin_frame_(false), | |
52 client_ready_for_begin_frame_(true), | |
53 client_(NULL), | |
54 is_lost_(false), | |
55 check_for_retroactive_begin_frame_pending_(false), | |
56 external_stencil_test_enabled_(false), | 51 external_stencil_test_enabled_(false), |
57 weak_ptr_factory_(this), | 52 weak_ptr_factory_(this), |
58 gpu_latency_history_(kGpuLatencyHistorySize) {} | 53 gpu_latency_history_(kGpuLatencyHistorySize) {} |
59 | 54 |
60 OutputSurface::OutputSurface(scoped_ptr<SoftwareOutputDevice> software_device) | 55 OutputSurface::OutputSurface(scoped_ptr<SoftwareOutputDevice> software_device) |
61 : software_device_(software_device.Pass()), | 56 : client_(NULL), |
57 is_lost_(false), | |
58 software_device_(software_device.Pass()), | |
62 device_scale_factor_(-1), | 59 device_scale_factor_(-1), |
63 begin_frame_interval_(BeginFrameArgs::DefaultInterval()), | |
64 throttle_frame_production_(true), | |
65 needs_begin_frame_(false), | |
66 client_ready_for_begin_frame_(true), | |
67 client_(NULL), | |
68 is_lost_(false), | |
69 check_for_retroactive_begin_frame_pending_(false), | |
70 external_stencil_test_enabled_(false), | 60 external_stencil_test_enabled_(false), |
71 weak_ptr_factory_(this), | 61 weak_ptr_factory_(this), |
72 gpu_latency_history_(kGpuLatencyHistorySize) {} | 62 gpu_latency_history_(kGpuLatencyHistorySize) {} |
73 | 63 |
74 OutputSurface::OutputSurface(scoped_refptr<ContextProvider> context_provider, | 64 OutputSurface::OutputSurface(scoped_refptr<ContextProvider> context_provider, |
75 scoped_ptr<SoftwareOutputDevice> software_device) | 65 scoped_ptr<SoftwareOutputDevice> software_device) |
76 : context_provider_(context_provider), | 66 : client_(NULL), |
67 is_lost_(false), | |
68 context_provider_(context_provider), | |
77 software_device_(software_device.Pass()), | 69 software_device_(software_device.Pass()), |
78 device_scale_factor_(-1), | 70 device_scale_factor_(-1), |
79 begin_frame_interval_(BeginFrameArgs::DefaultInterval()), | |
80 throttle_frame_production_(true), | |
81 needs_begin_frame_(false), | |
82 client_ready_for_begin_frame_(true), | |
83 client_(NULL), | |
84 is_lost_(false), | |
85 check_for_retroactive_begin_frame_pending_(false), | |
86 external_stencil_test_enabled_(false), | 71 external_stencil_test_enabled_(false), |
87 weak_ptr_factory_(this), | 72 weak_ptr_factory_(this), |
88 gpu_latency_history_(kGpuLatencyHistorySize) {} | 73 gpu_latency_history_(kGpuLatencyHistorySize) {} |
89 | 74 |
90 void OutputSurface::SetThrottleFrameProduction(bool enable) { | |
91 DCHECK(!frame_rate_controller_); | |
92 throttle_frame_production_ = enable; | |
93 } | |
94 | |
95 void OutputSurface::InitializeBeginFrameEmulation( | |
96 base::SingleThreadTaskRunner* task_runner, | |
97 base::TimeDelta interval) { | |
98 DCHECK(throttle_frame_production_); | |
99 scoped_refptr<DelayBasedTimeSource> time_source; | |
100 if (gfx::FrameTime::TimestampsAreHighRes()) | |
101 time_source = DelayBasedTimeSourceHighRes::Create(interval, task_runner); | |
102 else | |
103 time_source = DelayBasedTimeSource::Create(interval, task_runner); | |
104 frame_rate_controller_.reset(new FrameRateController(time_source)); | |
105 | |
106 frame_rate_controller_->SetClient(this); | |
107 frame_rate_controller_->SetDeadlineAdjustment( | |
108 capabilities_.adjust_deadline_for_parent ? | |
109 BeginFrameArgs::DefaultDeadlineAdjustment() : base::TimeDelta()); | |
110 } | |
111 | |
112 void OutputSurface::CommitVSyncParameters(base::TimeTicks timebase, | 75 void OutputSurface::CommitVSyncParameters(base::TimeTicks timebase, |
113 base::TimeDelta interval) { | 76 base::TimeDelta interval) { |
114 TRACE_EVENT2("cc", | 77 TRACE_EVENT2("cc", |
115 "OutputSurface::CommitVSyncParameters", | 78 "OutputSurface::CommitVSyncParameters", |
116 "timebase", | 79 "timebase", |
117 (timebase - base::TimeTicks()).InSecondsF(), | 80 (timebase - base::TimeTicks()).InSecondsF(), |
118 "interval", | 81 "interval", |
119 interval.InSecondsF()); | 82 interval.InSecondsF()); |
120 begin_frame_interval_ = interval; | 83 client_->CommitVSyncParameters(timebase, interval); |
121 if (frame_rate_controller_) | |
122 frame_rate_controller_->SetTimebaseAndInterval(timebase, interval); | |
123 } | |
124 | |
125 void OutputSurface::FrameRateControllerTick(const BeginFrameArgs& args) { | |
126 DCHECK(frame_rate_controller_); | |
127 BeginFrame(args); | |
128 } | |
129 | |
130 // Forwarded to OutputSurfaceClient | |
131 void OutputSurface::SetNeedsRedrawRect(const gfx::Rect& damage_rect) { | |
132 TRACE_EVENT0("cc", "OutputSurface::SetNeedsRedrawRect"); | |
133 client_->SetNeedsRedrawRect(damage_rect); | |
134 } | |
135 | |
136 void OutputSurface::SetNeedsBeginFrame(bool enable) { | |
137 TRACE_EVENT1("cc", "OutputSurface::SetNeedsBeginFrame", "enable", enable); | |
138 needs_begin_frame_ = enable; | |
139 client_ready_for_begin_frame_ = true; | |
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_) { | |
148 BeginFrameArgs skipped = frame_rate_controller_->SetActive(enable); | |
149 if (skipped.IsValid()) | |
150 skipped_begin_frame_args_ = skipped; | |
151 } | |
152 | |
153 if (needs_begin_frame_) | |
154 PostCheckForRetroactiveBeginFrame(); | |
155 } | |
156 | |
157 void OutputSurface::BeginFrame(const BeginFrameArgs& args) { | |
158 TRACE_EVENT1("cc", | |
159 "OutputSurface::BeginFrame", | |
160 "client_ready_for_begin_frame_", | |
161 client_ready_for_begin_frame_); | |
162 if (!needs_begin_frame_ || !client_ready_for_begin_frame_) { | |
163 skipped_begin_frame_args_ = args; | |
164 } else { | |
165 client_ready_for_begin_frame_ = false; | |
166 client_->BeginFrame(args); | |
167 // args might be an alias for skipped_begin_frame_args_. | |
168 // Do not reset it before calling BeginFrame! | |
169 skipped_begin_frame_args_ = BeginFrameArgs(); | |
170 } | |
171 } | |
172 | |
173 base::TimeTicks OutputSurface::RetroactiveBeginFrameDeadline() { | |
174 // TODO(brianderson): Remove the alternative deadline once we have better | |
175 // deadline estimations. | |
176 base::TimeTicks alternative_deadline = | |
177 skipped_begin_frame_args_.frame_time + | |
178 BeginFrameArgs::DefaultRetroactiveBeginFramePeriod(); | |
179 return std::max(skipped_begin_frame_args_.deadline, alternative_deadline); | |
180 } | |
181 | |
182 void OutputSurface::PostCheckForRetroactiveBeginFrame() { | |
183 if (!skipped_begin_frame_args_.IsValid() || | |
184 check_for_retroactive_begin_frame_pending_) | |
185 return; | |
186 | |
187 base::MessageLoop::current()->PostTask( | |
188 FROM_HERE, | |
189 base::Bind(&OutputSurface::CheckForRetroactiveBeginFrame, | |
190 weak_ptr_factory_.GetWeakPtr())); | |
191 check_for_retroactive_begin_frame_pending_ = true; | |
192 } | |
193 | |
194 void OutputSurface::CheckForRetroactiveBeginFrame() { | |
195 TRACE_EVENT0("cc", "OutputSurface::CheckForRetroactiveBeginFrame"); | |
196 check_for_retroactive_begin_frame_pending_ = false; | |
197 if (!throttle_frame_production_ || | |
198 gfx::FrameTime::Now() < RetroactiveBeginFrameDeadline()) | |
199 BeginFrame(skipped_begin_frame_args_); | |
200 } | |
201 | |
202 void OutputSurface::DidSwapBuffers() { | |
203 if (is_lost_) | |
204 return; | |
205 TRACE_EVENT0("cc", "OutputSurface::DidSwapBuffers"); | |
206 client_->DidSwapBuffers(); | |
207 } | |
208 | |
209 void OutputSurface::OnSwapBuffersComplete() { | |
210 if (is_lost_) | |
211 return; | |
212 TRACE_EVENT0("cc", "OutputSurface::OnSwapBuffersComplete"); | |
213 client_->OnSwapBuffersComplete(); | |
214 } | 84 } |
215 | 85 |
216 void OutputSurface::ReclaimResources(const CompositorFrameAck* ack) { | 86 void OutputSurface::ReclaimResources(const CompositorFrameAck* ack) { |
217 client_->ReclaimResources(ack); | 87 client_->ReclaimResources(ack); |
218 } | 88 } |
219 | 89 |
220 void OutputSurface::DidLoseOutputSurface() { | 90 void OutputSurface::DidLoseOutputSurface() { |
221 TRACE_EVENT0("cc", "OutputSurface::DidLoseOutputSurface"); | 91 TRACE_EVENT0("cc", "OutputSurface::DidLoseOutputSurface"); |
222 client_ready_for_begin_frame_ = true; | 92 is_lost_ = true; |
223 skipped_begin_frame_args_ = BeginFrameArgs(); | |
224 if (frame_rate_controller_) | |
225 frame_rate_controller_->SetActive(false); | |
226 pending_gpu_latency_query_ids_.clear(); | 93 pending_gpu_latency_query_ids_.clear(); |
227 available_gpu_latency_query_ids_.clear(); | 94 available_gpu_latency_query_ids_.clear(); |
228 client_->DidLoseOutputSurface(); | 95 client_->DidLoseOutputSurface(); |
229 is_lost_ = true; | |
230 } | 96 } |
231 | 97 |
232 void OutputSurface::SetExternalStencilTest(bool enabled) { | 98 void OutputSurface::SetExternalStencilTest(bool enabled) { |
233 external_stencil_test_enabled_ = enabled; | 99 external_stencil_test_enabled_ = enabled; |
234 } | 100 } |
235 | 101 |
236 void OutputSurface::SetExternalDrawConstraints(const gfx::Transform& transform, | 102 void OutputSurface::SetExternalDrawConstraints(const gfx::Transform& transform, |
237 const gfx::Rect& viewport, | 103 const gfx::Rect& viewport, |
238 const gfx::Rect& clip, | 104 const gfx::Rect& clip, |
239 bool valid_for_tile_management) { | 105 bool valid_for_tile_management) { |
240 client_->SetExternalDrawConstraints( | 106 client_->SetExternalDrawConstraints( |
241 transform, viewport, clip, valid_for_tile_management); | 107 transform, viewport, clip, valid_for_tile_management); |
242 } | 108 } |
243 | 109 |
244 OutputSurface::~OutputSurface() { | 110 OutputSurface::~OutputSurface() { |
245 if (frame_rate_controller_) | |
246 frame_rate_controller_->SetActive(false); | |
247 ResetContext3d(); | 111 ResetContext3d(); |
248 } | 112 } |
249 | 113 |
250 bool OutputSurface::HasExternalStencilTest() const { | 114 bool OutputSurface::HasExternalStencilTest() const { |
251 return external_stencil_test_enabled_; | 115 return external_stencil_test_enabled_; |
252 } | 116 } |
253 | 117 |
254 bool OutputSurface::ForcedDrawToSoftwareDevice() const { return false; } | 118 bool OutputSurface::ForcedDrawToSoftwareDevice() const { return false; } |
255 | 119 |
256 bool OutputSurface::BindToClient(OutputSurfaceClient* client) { | 120 bool OutputSurface::BindToClient(OutputSurfaceClient* client) { |
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
366 } | 230 } |
367 | 231 |
368 void OutputSurface::BindFramebuffer() { | 232 void OutputSurface::BindFramebuffer() { |
369 DCHECK(context_provider_); | 233 DCHECK(context_provider_); |
370 context_provider_->ContextGL()->BindFramebuffer(GL_FRAMEBUFFER, 0); | 234 context_provider_->ContextGL()->BindFramebuffer(GL_FRAMEBUFFER, 0); |
371 } | 235 } |
372 | 236 |
373 void OutputSurface::SwapBuffers(CompositorFrame* frame) { | 237 void OutputSurface::SwapBuffers(CompositorFrame* frame) { |
374 if (frame->software_frame_data) { | 238 if (frame->software_frame_data) { |
375 PostSwapBuffersComplete(); | 239 PostSwapBuffersComplete(); |
376 DidSwapBuffers(); | 240 client_->DidSwapBuffers(); |
377 return; | 241 return; |
378 } | 242 } |
379 | 243 |
380 DCHECK(context_provider_); | 244 DCHECK(context_provider_); |
381 DCHECK(frame->gl_frame_data); | 245 DCHECK(frame->gl_frame_data); |
382 | 246 |
383 UpdateAndMeasureGpuLatency(); | 247 UpdateAndMeasureGpuLatency(); |
384 if (frame->gl_frame_data->sub_buffer_rect == | 248 if (frame->gl_frame_data->sub_buffer_rect == |
385 gfx::Rect(frame->gl_frame_data->size)) { | 249 gfx::Rect(frame->gl_frame_data->size)) { |
386 context_provider_->ContextSupport()->Swap(); | 250 context_provider_->ContextSupport()->Swap(); |
387 } else { | 251 } else { |
388 context_provider_->ContextSupport()->PartialSwapBuffers( | 252 context_provider_->ContextSupport()->PartialSwapBuffers( |
389 frame->gl_frame_data->sub_buffer_rect); | 253 frame->gl_frame_data->sub_buffer_rect); |
390 } | 254 } |
391 | 255 |
392 DidSwapBuffers(); | 256 client_->DidSwapBuffers(); |
Sami
2014/04/08 13:46:01
Should we guard against is_lost_?
brianderson
2014/04/09 02:52:05
Good idea. I will return early if is_lost_ here an
brianderson
2014/04/10 23:45:58
Done.
| |
393 } | 257 } |
394 | 258 |
395 base::TimeDelta OutputSurface::GpuLatencyEstimate() { | 259 base::TimeDelta OutputSurface::GpuLatencyEstimate() { |
396 if (context_provider_ && !capabilities_.adjust_deadline_for_parent) | 260 if (context_provider_ && !capabilities_.adjust_deadline_for_parent) |
397 return gpu_latency_history_.Percentile(kGpuLatencyEstimationPercentile); | 261 return gpu_latency_history_.Percentile(kGpuLatencyEstimationPercentile); |
398 else | 262 else |
399 return base::TimeDelta(); | 263 return base::TimeDelta(); |
400 } | 264 } |
401 | 265 |
402 void OutputSurface::UpdateAndMeasureGpuLatency() { | 266 void OutputSurface::UpdateAndMeasureGpuLatency() { |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
465 #endif | 329 #endif |
466 } | 330 } |
467 | 331 |
468 void OutputSurface::PostSwapBuffersComplete() { | 332 void OutputSurface::PostSwapBuffersComplete() { |
469 base::MessageLoop::current()->PostTask( | 333 base::MessageLoop::current()->PostTask( |
470 FROM_HERE, | 334 FROM_HERE, |
471 base::Bind(&OutputSurface::OnSwapBuffersComplete, | 335 base::Bind(&OutputSurface::OnSwapBuffersComplete, |
472 weak_ptr_factory_.GetWeakPtr())); | 336 weak_ptr_factory_.GetWeakPtr())); |
473 } | 337 } |
474 | 338 |
339 void OutputSurface::OnSwapBuffersComplete() { | |
340 if (!is_lost_) | |
341 client_->OnSwapBuffersComplete(); | |
342 } | |
343 | |
475 void OutputSurface::SetMemoryPolicy(const ManagedMemoryPolicy& policy) { | 344 void OutputSurface::SetMemoryPolicy(const ManagedMemoryPolicy& policy) { |
476 TRACE_EVENT1("cc", "OutputSurface::SetMemoryPolicy", | 345 TRACE_EVENT1("cc", "OutputSurface::SetMemoryPolicy", |
477 "bytes_limit_when_visible", policy.bytes_limit_when_visible); | 346 "bytes_limit_when_visible", policy.bytes_limit_when_visible); |
478 // Just ignore the memory manager when it says to set the limit to zero | 347 // Just ignore the memory manager when it says to set the limit to zero |
479 // bytes. This will happen when the memory manager thinks that the renderer | 348 // bytes. This will happen when the memory manager thinks that the renderer |
480 // is not visible (which the renderer knows better). | 349 // is not visible (which the renderer knows better). |
481 if (policy.bytes_limit_when_visible) | 350 if (policy.bytes_limit_when_visible) |
482 client_->SetMemoryPolicy(policy); | 351 client_->SetMemoryPolicy(policy); |
483 } | 352 } |
484 | 353 |
485 } // namespace cc | 354 } // namespace cc |
OLD | NEW |