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