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 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
357 } | 234 } |
358 | 235 |
359 void OutputSurface::BindFramebuffer() { | 236 void OutputSurface::BindFramebuffer() { |
360 DCHECK(context_provider_); | 237 DCHECK(context_provider_); |
361 context_provider_->ContextGL()->BindFramebuffer(GL_FRAMEBUFFER, 0); | 238 context_provider_->ContextGL()->BindFramebuffer(GL_FRAMEBUFFER, 0); |
362 } | 239 } |
363 | 240 |
364 void OutputSurface::SwapBuffers(CompositorFrame* frame) { | 241 void OutputSurface::SwapBuffers(CompositorFrame* frame) { |
365 if (frame->software_frame_data) { | 242 if (frame->software_frame_data) { |
366 PostSwapBuffersComplete(); | 243 PostSwapBuffersComplete(); |
367 DidSwapBuffers(); | 244 client_->DidSwapBuffers(); |
368 return; | 245 return; |
369 } | 246 } |
370 | 247 |
371 DCHECK(context_provider_); | 248 DCHECK(context_provider_); |
372 DCHECK(frame->gl_frame_data); | 249 DCHECK(frame->gl_frame_data); |
373 | 250 |
374 UpdateAndMeasureGpuLatency(); | 251 UpdateAndMeasureGpuLatency(); |
375 if (frame->gl_frame_data->sub_buffer_rect == | 252 if (frame->gl_frame_data->sub_buffer_rect == |
376 gfx::Rect(frame->gl_frame_data->size)) { | 253 gfx::Rect(frame->gl_frame_data->size)) { |
377 context_provider_->ContextSupport()->Swap(); | 254 context_provider_->ContextSupport()->Swap(); |
378 } else { | 255 } else { |
379 context_provider_->ContextSupport()->PartialSwapBuffers( | 256 context_provider_->ContextSupport()->PartialSwapBuffers( |
380 frame->gl_frame_data->sub_buffer_rect); | 257 frame->gl_frame_data->sub_buffer_rect); |
381 } | 258 } |
382 | 259 |
383 DidSwapBuffers(); | 260 client_->DidSwapBuffers(); |
384 } | 261 } |
385 | 262 |
386 base::TimeDelta OutputSurface::GpuLatencyEstimate() { | 263 base::TimeDelta OutputSurface::GpuLatencyEstimate() { |
387 if (context_provider_ && !capabilities_.adjust_deadline_for_parent) | 264 if (context_provider_ && !capabilities_.adjust_deadline_for_parent) |
388 return gpu_latency_history_.Percentile(kGpuLatencyEstimationPercentile); | 265 return gpu_latency_history_.Percentile(kGpuLatencyEstimationPercentile); |
389 else | 266 else |
390 return base::TimeDelta(); | 267 return base::TimeDelta(); |
391 } | 268 } |
392 | 269 |
393 void OutputSurface::UpdateAndMeasureGpuLatency() { | 270 void OutputSurface::UpdateAndMeasureGpuLatency() { |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
456 #endif | 333 #endif |
457 } | 334 } |
458 | 335 |
459 void OutputSurface::PostSwapBuffersComplete() { | 336 void OutputSurface::PostSwapBuffersComplete() { |
460 base::MessageLoop::current()->PostTask( | 337 base::MessageLoop::current()->PostTask( |
461 FROM_HERE, | 338 FROM_HERE, |
462 base::Bind(&OutputSurface::OnSwapBuffersComplete, | 339 base::Bind(&OutputSurface::OnSwapBuffersComplete, |
463 weak_ptr_factory_.GetWeakPtr())); | 340 weak_ptr_factory_.GetWeakPtr())); |
464 } | 341 } |
465 | 342 |
| 343 // We don't post tasks bound to the client directly since they might run |
| 344 // after the OutputSurface has been destroyed. |
| 345 void OutputSurface::OnSwapBuffersComplete() { |
| 346 client_->DidSwapBuffersComplete(); |
| 347 } |
| 348 |
466 void OutputSurface::SetMemoryPolicy(const ManagedMemoryPolicy& policy) { | 349 void OutputSurface::SetMemoryPolicy(const ManagedMemoryPolicy& policy) { |
467 TRACE_EVENT1("cc", "OutputSurface::SetMemoryPolicy", | 350 TRACE_EVENT1("cc", "OutputSurface::SetMemoryPolicy", |
468 "bytes_limit_when_visible", policy.bytes_limit_when_visible); | 351 "bytes_limit_when_visible", policy.bytes_limit_when_visible); |
469 // Just ignore the memory manager when it says to set the limit to zero | 352 // Just ignore the memory manager when it says to set the limit to zero |
470 // bytes. This will happen when the memory manager thinks that the renderer | 353 // bytes. This will happen when the memory manager thinks that the renderer |
471 // is not visible (which the renderer knows better). | 354 // is not visible (which the renderer knows better). |
472 if (policy.bytes_limit_when_visible) | 355 if (policy.bytes_limit_when_visible) |
473 client_->SetMemoryPolicy(policy); | 356 client_->SetMemoryPolicy(policy); |
474 } | 357 } |
475 | 358 |
476 } // namespace cc | 359 } // namespace cc |
OLD | NEW |