Chromium Code Reviews| 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 |