| 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> |
| 11 | 11 |
| 12 #include "base/bind.h" | 12 #include "base/bind.h" |
| 13 #include "base/debug/trace_event.h" | 13 #include "base/debug/trace_event.h" |
| 14 #include "base/logging.h" | 14 #include "base/logging.h" |
| 15 #include "base/message_loop/message_loop.h" | 15 #include "base/message_loop/message_loop.h" |
| 16 #include "base/metrics/histogram.h" | 16 #include "base/metrics/histogram.h" |
| 17 #include "base/strings/string_split.h" | 17 #include "base/strings/string_split.h" |
| 18 #include "base/strings/string_util.h" | 18 #include "base/strings/string_util.h" |
| 19 #include "cc/output/compositor_frame.h" | 19 #include "cc/output/compositor_frame.h" |
| 20 #include "cc/output/compositor_frame_ack.h" | 20 #include "cc/output/compositor_frame_ack.h" |
| 21 #include "cc/output/managed_memory_policy.h" | 21 #include "cc/output/managed_memory_policy.h" |
| 22 #include "cc/output/output_surface_client.h" | 22 #include "cc/output/output_surface_client.h" |
| 23 #include "cc/scheduler/delay_based_time_source.h" | 23 #include "cc/scheduler/delay_based_time_source.h" |
| 24 #include "gpu/GLES2/gl2extchromium.h" | |
| 25 #include "gpu/command_buffer/client/context_support.h" | 24 #include "gpu/command_buffer/client/context_support.h" |
| 26 #include "gpu/command_buffer/client/gles2_interface.h" | 25 #include "gpu/command_buffer/client/gles2_interface.h" |
| 27 #include "third_party/khronos/GLES2/gl2.h" | 26 #include "third_party/khronos/GLES2/gl2.h" |
| 28 #include "third_party/khronos/GLES2/gl2ext.h" | 27 #include "third_party/khronos/GLES2/gl2ext.h" |
| 29 #include "ui/gfx/frame_time.h" | 28 #include "ui/gfx/frame_time.h" |
| 30 #include "ui/gfx/rect.h" | 29 #include "ui/gfx/rect.h" |
| 31 #include "ui/gfx/size.h" | 30 #include "ui/gfx/size.h" |
| 32 | 31 |
| 33 using std::set; | 32 using std::set; |
| 34 using std::string; | 33 using std::string; |
| 35 using std::vector; | 34 using std::vector; |
| 36 | 35 |
| 37 namespace { | |
| 38 | |
| 39 const size_t kGpuLatencyHistorySize = 60; | |
| 40 const double kGpuLatencyEstimationPercentile = 100.0; | |
| 41 | |
| 42 } | |
| 43 | |
| 44 namespace cc { | 36 namespace cc { |
| 45 | 37 |
| 46 OutputSurface::OutputSurface(scoped_refptr<ContextProvider> context_provider) | 38 OutputSurface::OutputSurface(scoped_refptr<ContextProvider> context_provider) |
| 47 : client_(NULL), | 39 : client_(NULL), |
| 48 context_provider_(context_provider), | 40 context_provider_(context_provider), |
| 49 device_scale_factor_(-1), | 41 device_scale_factor_(-1), |
| 50 external_stencil_test_enabled_(false), | 42 external_stencil_test_enabled_(false), |
| 51 weak_ptr_factory_(this), | 43 weak_ptr_factory_(this) { |
| 52 gpu_latency_history_(kGpuLatencyHistorySize) { | |
| 53 } | 44 } |
| 54 | 45 |
| 55 OutputSurface::OutputSurface(scoped_ptr<SoftwareOutputDevice> software_device) | 46 OutputSurface::OutputSurface(scoped_ptr<SoftwareOutputDevice> software_device) |
| 56 : client_(NULL), | 47 : client_(NULL), |
| 57 software_device_(software_device.Pass()), | 48 software_device_(software_device.Pass()), |
| 58 device_scale_factor_(-1), | 49 device_scale_factor_(-1), |
| 59 external_stencil_test_enabled_(false), | 50 external_stencil_test_enabled_(false), |
| 60 weak_ptr_factory_(this), | 51 weak_ptr_factory_(this) { |
| 61 gpu_latency_history_(kGpuLatencyHistorySize) { | |
| 62 } | 52 } |
| 63 | 53 |
| 64 OutputSurface::OutputSurface(scoped_refptr<ContextProvider> context_provider, | 54 OutputSurface::OutputSurface(scoped_refptr<ContextProvider> context_provider, |
| 65 scoped_ptr<SoftwareOutputDevice> software_device) | 55 scoped_ptr<SoftwareOutputDevice> software_device) |
| 66 : client_(NULL), | 56 : client_(NULL), |
| 67 context_provider_(context_provider), | 57 context_provider_(context_provider), |
| 68 software_device_(software_device.Pass()), | 58 software_device_(software_device.Pass()), |
| 69 device_scale_factor_(-1), | 59 device_scale_factor_(-1), |
| 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) { | |
| 73 } | 62 } |
| 74 | 63 |
| 75 void OutputSurface::CommitVSyncParameters(base::TimeTicks timebase, | 64 void OutputSurface::CommitVSyncParameters(base::TimeTicks timebase, |
| 76 base::TimeDelta interval) { | 65 base::TimeDelta interval) { |
| 77 TRACE_EVENT2("cc", | 66 TRACE_EVENT2("cc", |
| 78 "OutputSurface::CommitVSyncParameters", | 67 "OutputSurface::CommitVSyncParameters", |
| 79 "timebase", | 68 "timebase", |
| 80 (timebase - base::TimeTicks()).InSecondsF(), | 69 (timebase - base::TimeTicks()).InSecondsF(), |
| 81 "interval", | 70 "interval", |
| 82 interval.InSecondsF()); | 71 interval.InSecondsF()); |
| 83 client_->CommitVSyncParameters(timebase, interval); | 72 client_->CommitVSyncParameters(timebase, interval); |
| 84 } | 73 } |
| 85 | 74 |
| 86 // Forwarded to OutputSurfaceClient | 75 // Forwarded to OutputSurfaceClient |
| 87 void OutputSurface::SetNeedsRedrawRect(const gfx::Rect& damage_rect) { | 76 void OutputSurface::SetNeedsRedrawRect(const gfx::Rect& damage_rect) { |
| 88 TRACE_EVENT0("cc", "OutputSurface::SetNeedsRedrawRect"); | 77 TRACE_EVENT0("cc", "OutputSurface::SetNeedsRedrawRect"); |
| 89 client_->SetNeedsRedrawRect(damage_rect); | 78 client_->SetNeedsRedrawRect(damage_rect); |
| 90 } | 79 } |
| 91 | 80 |
| 92 void OutputSurface::ReclaimResources(const CompositorFrameAck* ack) { | 81 void OutputSurface::ReclaimResources(const CompositorFrameAck* ack) { |
| 93 client_->ReclaimResources(ack); | 82 client_->ReclaimResources(ack); |
| 94 } | 83 } |
| 95 | 84 |
| 96 void OutputSurface::DidLoseOutputSurface() { | 85 void OutputSurface::DidLoseOutputSurface() { |
| 97 TRACE_EVENT0("cc", "OutputSurface::DidLoseOutputSurface"); | 86 TRACE_EVENT0("cc", "OutputSurface::DidLoseOutputSurface"); |
| 98 pending_gpu_latency_query_ids_.clear(); | |
| 99 available_gpu_latency_query_ids_.clear(); | |
| 100 client_->DidLoseOutputSurface(); | 87 client_->DidLoseOutputSurface(); |
| 101 } | 88 } |
| 102 | 89 |
| 103 void OutputSurface::SetExternalStencilTest(bool enabled) { | 90 void OutputSurface::SetExternalStencilTest(bool enabled) { |
| 104 external_stencil_test_enabled_ = enabled; | 91 external_stencil_test_enabled_ = enabled; |
| 105 } | 92 } |
| 106 | 93 |
| 107 void OutputSurface::SetExternalDrawConstraints(const gfx::Transform& transform, | 94 void OutputSurface::SetExternalDrawConstraints(const gfx::Transform& transform, |
| 108 const gfx::Rect& viewport, | 95 const gfx::Rect& viewport, |
| 109 const gfx::Rect& clip, | 96 const gfx::Rect& clip, |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 182 } | 169 } |
| 183 | 170 |
| 184 void OutputSurface::ReleaseContextProvider() { | 171 void OutputSurface::ReleaseContextProvider() { |
| 185 DCHECK(client_); | 172 DCHECK(client_); |
| 186 DCHECK(context_provider_); | 173 DCHECK(context_provider_); |
| 187 ResetContext3d(); | 174 ResetContext3d(); |
| 188 } | 175 } |
| 189 | 176 |
| 190 void OutputSurface::ResetContext3d() { | 177 void OutputSurface::ResetContext3d() { |
| 191 if (context_provider_.get()) { | 178 if (context_provider_.get()) { |
| 192 while (!pending_gpu_latency_query_ids_.empty()) { | |
| 193 unsigned query_id = pending_gpu_latency_query_ids_.front(); | |
| 194 pending_gpu_latency_query_ids_.pop_front(); | |
| 195 context_provider_->ContextGL()->DeleteQueriesEXT(1, &query_id); | |
| 196 } | |
| 197 while (!available_gpu_latency_query_ids_.empty()) { | |
| 198 unsigned query_id = available_gpu_latency_query_ids_.front(); | |
| 199 available_gpu_latency_query_ids_.pop_front(); | |
| 200 context_provider_->ContextGL()->DeleteQueriesEXT(1, &query_id); | |
| 201 } | |
| 202 context_provider_->SetLostContextCallback( | 179 context_provider_->SetLostContextCallback( |
| 203 ContextProvider::LostContextCallback()); | 180 ContextProvider::LostContextCallback()); |
| 204 context_provider_->SetMemoryPolicyChangedCallback( | 181 context_provider_->SetMemoryPolicyChangedCallback( |
| 205 ContextProvider::MemoryPolicyChangedCallback()); | 182 ContextProvider::MemoryPolicyChangedCallback()); |
| 206 if (gpu::ContextSupport* support = context_provider_->ContextSupport()) | 183 if (gpu::ContextSupport* support = context_provider_->ContextSupport()) |
| 207 support->SetSwapBuffersCompleteCallback(base::Closure()); | 184 support->SetSwapBuffersCompleteCallback(base::Closure()); |
| 208 } | 185 } |
| 209 context_provider_ = NULL; | 186 context_provider_ = NULL; |
| 210 } | 187 } |
| 211 | 188 |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 247 void OutputSurface::SwapBuffers(CompositorFrame* frame) { | 224 void OutputSurface::SwapBuffers(CompositorFrame* frame) { |
| 248 if (frame->software_frame_data) { | 225 if (frame->software_frame_data) { |
| 249 PostSwapBuffersComplete(); | 226 PostSwapBuffersComplete(); |
| 250 client_->DidSwapBuffers(); | 227 client_->DidSwapBuffers(); |
| 251 return; | 228 return; |
| 252 } | 229 } |
| 253 | 230 |
| 254 DCHECK(context_provider_); | 231 DCHECK(context_provider_); |
| 255 DCHECK(frame->gl_frame_data); | 232 DCHECK(frame->gl_frame_data); |
| 256 | 233 |
| 257 UpdateAndMeasureGpuLatency(); | |
| 258 if (frame->gl_frame_data->sub_buffer_rect == | 234 if (frame->gl_frame_data->sub_buffer_rect == |
| 259 gfx::Rect(frame->gl_frame_data->size)) { | 235 gfx::Rect(frame->gl_frame_data->size)) { |
| 260 context_provider_->ContextSupport()->Swap(); | 236 context_provider_->ContextSupport()->Swap(); |
| 261 } else { | 237 } else { |
| 262 context_provider_->ContextSupport()->PartialSwapBuffers( | 238 context_provider_->ContextSupport()->PartialSwapBuffers( |
| 263 frame->gl_frame_data->sub_buffer_rect); | 239 frame->gl_frame_data->sub_buffer_rect); |
| 264 } | 240 } |
| 265 | 241 |
| 266 client_->DidSwapBuffers(); | 242 client_->DidSwapBuffers(); |
| 267 } | 243 } |
| 268 | 244 |
| 269 base::TimeDelta OutputSurface::GpuLatencyEstimate() { | |
| 270 if (context_provider_ && !capabilities_.adjust_deadline_for_parent) | |
| 271 return gpu_latency_history_.Percentile(kGpuLatencyEstimationPercentile); | |
| 272 else | |
| 273 return base::TimeDelta(); | |
| 274 } | |
| 275 | |
| 276 void OutputSurface::UpdateAndMeasureGpuLatency() { | |
| 277 // http://crbug.com/306690 tracks re-enabling latency queries. | |
| 278 #if 0 | |
| 279 // We only care about GPU latency for surfaces that do not have a parent | |
| 280 // compositor, since surfaces that do have a parent compositor can use | |
| 281 // mailboxes or delegated rendering to send frames to their parent without | |
| 282 // incurring GPU latency. | |
| 283 if (capabilities_.adjust_deadline_for_parent) | |
| 284 return; | |
| 285 | |
| 286 while (pending_gpu_latency_query_ids_.size()) { | |
| 287 unsigned query_id = pending_gpu_latency_query_ids_.front(); | |
| 288 unsigned query_complete = 1; | |
| 289 context_provider_->ContextGL()->GetQueryObjectuivEXT( | |
| 290 query_id, GL_QUERY_RESULT_AVAILABLE_EXT, &query_complete); | |
| 291 if (!query_complete) | |
| 292 break; | |
| 293 | |
| 294 unsigned value = 0; | |
| 295 context_provider_->ContextGL()->GetQueryObjectuivEXT( | |
| 296 query_id, GL_QUERY_RESULT_EXT, &value); | |
| 297 pending_gpu_latency_query_ids_.pop_front(); | |
| 298 available_gpu_latency_query_ids_.push_back(query_id); | |
| 299 | |
| 300 base::TimeDelta latency = base::TimeDelta::FromMicroseconds(value); | |
| 301 base::TimeDelta latency_estimate = GpuLatencyEstimate(); | |
| 302 gpu_latency_history_.InsertSample(latency); | |
| 303 | |
| 304 base::TimeDelta latency_overestimate; | |
| 305 base::TimeDelta latency_underestimate; | |
| 306 if (latency > latency_estimate) | |
| 307 latency_underestimate = latency - latency_estimate; | |
| 308 else | |
| 309 latency_overestimate = latency_estimate - latency; | |
| 310 UMA_HISTOGRAM_CUSTOM_TIMES("Renderer.GpuLatency", | |
| 311 latency, | |
| 312 base::TimeDelta::FromMilliseconds(1), | |
| 313 base::TimeDelta::FromMilliseconds(100), | |
| 314 50); | |
| 315 UMA_HISTOGRAM_CUSTOM_TIMES("Renderer.GpuLatencyUnderestimate", | |
| 316 latency_underestimate, | |
| 317 base::TimeDelta::FromMilliseconds(1), | |
| 318 base::TimeDelta::FromMilliseconds(100), | |
| 319 50); | |
| 320 UMA_HISTOGRAM_CUSTOM_TIMES("Renderer.GpuLatencyOverestimate", | |
| 321 latency_overestimate, | |
| 322 base::TimeDelta::FromMilliseconds(1), | |
| 323 base::TimeDelta::FromMilliseconds(100), | |
| 324 50); | |
| 325 } | |
| 326 | |
| 327 unsigned gpu_latency_query_id; | |
| 328 if (available_gpu_latency_query_ids_.size()) { | |
| 329 gpu_latency_query_id = available_gpu_latency_query_ids_.front(); | |
| 330 available_gpu_latency_query_ids_.pop_front(); | |
| 331 } else { | |
| 332 context_provider_->ContextGL()->GenQueriesEXT(1, &gpu_latency_query_id); | |
| 333 } | |
| 334 | |
| 335 context_provider_->ContextGL()->BeginQueryEXT(GL_LATENCY_QUERY_CHROMIUM, | |
| 336 gpu_latency_query_id); | |
| 337 context_provider_->ContextGL()->EndQueryEXT(GL_LATENCY_QUERY_CHROMIUM); | |
| 338 pending_gpu_latency_query_ids_.push_back(gpu_latency_query_id); | |
| 339 #endif | |
| 340 } | |
| 341 | |
| 342 void OutputSurface::PostSwapBuffersComplete() { | 245 void OutputSurface::PostSwapBuffersComplete() { |
| 343 base::MessageLoop::current()->PostTask( | 246 base::MessageLoop::current()->PostTask( |
| 344 FROM_HERE, | 247 FROM_HERE, |
| 345 base::Bind(&OutputSurface::OnSwapBuffersComplete, | 248 base::Bind(&OutputSurface::OnSwapBuffersComplete, |
| 346 weak_ptr_factory_.GetWeakPtr())); | 249 weak_ptr_factory_.GetWeakPtr())); |
| 347 } | 250 } |
| 348 | 251 |
| 349 // We don't post tasks bound to the client directly since they might run | 252 // We don't post tasks bound to the client directly since they might run |
| 350 // after the OutputSurface has been destroyed. | 253 // after the OutputSurface has been destroyed. |
| 351 void OutputSurface::OnSwapBuffersComplete() { | 254 void OutputSurface::OnSwapBuffersComplete() { |
| 352 client_->DidSwapBuffersComplete(); | 255 client_->DidSwapBuffersComplete(); |
| 353 } | 256 } |
| 354 | 257 |
| 355 void OutputSurface::SetMemoryPolicy(const ManagedMemoryPolicy& policy) { | 258 void OutputSurface::SetMemoryPolicy(const ManagedMemoryPolicy& policy) { |
| 356 TRACE_EVENT1("cc", "OutputSurface::SetMemoryPolicy", | 259 TRACE_EVENT1("cc", "OutputSurface::SetMemoryPolicy", |
| 357 "bytes_limit_when_visible", policy.bytes_limit_when_visible); | 260 "bytes_limit_when_visible", policy.bytes_limit_when_visible); |
| 358 // Just ignore the memory manager when it says to set the limit to zero | 261 // Just ignore the memory manager when it says to set the limit to zero |
| 359 // bytes. This will happen when the memory manager thinks that the renderer | 262 // bytes. This will happen when the memory manager thinks that the renderer |
| 360 // is not visible (which the renderer knows better). | 263 // is not visible (which the renderer knows better). |
| 361 if (policy.bytes_limit_when_visible) | 264 if (policy.bytes_limit_when_visible) |
| 362 client_->SetMemoryPolicy(policy); | 265 client_->SetMemoryPolicy(policy); |
| 363 } | 266 } |
| 364 | 267 |
| 365 } // namespace cc | 268 } // namespace cc |
| OLD | NEW |