Index: cc/surfaces/display_scheduler.cc |
diff --git a/cc/surfaces/display_scheduler.cc b/cc/surfaces/display_scheduler.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..ff74da2bc6594ae74e5ddc13edbdeadacb9f77f0 |
--- /dev/null |
+++ b/cc/surfaces/display_scheduler.cc |
@@ -0,0 +1,105 @@ |
+// Copyright 2014 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "cc/surfaces/display_scheduler.h" |
+ |
+#include "base/debug/trace_event.h" |
+#include "cc/output/output_surface.h" |
+#include "ui/gfx/frame_time.h" |
+ |
+namespace cc { |
+ |
+const size_t kDurationHistorySize = 60; |
+const double kDrawDurationEstimationPercentile = 95.0; |
+const int kDrawDurationEstimatePaddingInMicroseconds = 0; |
+ |
+DisplayScheduler::DisplayScheduler( |
+ OutputSurface* output_surface, |
+ Display* display, |
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner) |
+ : output_surface_(output_surface), |
+ display_(display), |
+ task_runner_(task_runner), |
+ draw_duration_history_(kDurationHistorySize), |
+ output_surface_lost_(false), |
+ need_draw_(false), |
+ pending_frames_(0), |
+ weak_ptr_factory_(this) { |
+ begin_frame_source_ = SyntheticBeginFrameSource::Create( |
+ task_runner_.get(), gfx::FrameTime::Now(), |
+ BeginFrameArgs::DefaultInterval()); |
+ begin_frame_source_->AddObserver(this); |
+} |
+ |
+DisplayScheduler::~DisplayScheduler() { |
+} |
+ |
+void DisplayScheduler::CommitVSyncParameters(base::TimeTicks timebase, |
+ base::TimeDelta interval) { |
+ if (begin_frame_source_ && interval != base::TimeDelta()) |
+ begin_frame_source_->OnUpdateVSyncParameters(timebase, interval); |
+} |
+ |
+void DisplayScheduler::DisplayDamaged() { |
+ TRACE_EVENT0("cc", "DisplayScheduler::DisplayDamaged"); |
+ begin_frame_source_->SetNeedsBeginFrames(!output_surface_lost_); |
+ need_draw_ = true; |
+} |
+ |
+void DisplayScheduler::OutputSurfaceLost() { |
+ output_surface_lost_ = true; |
+ begin_frame_source_->SetNeedsBeginFrames(false); |
+} |
+ |
+void DisplayScheduler::Draw() { |
+ TRACE_EVENT0("cc", "DisplayScheduler::Draw"); |
+ if (!need_draw_) { |
+ begin_frame_source_->SetNeedsBeginFrames(false); |
+ return; |
+ } |
+ if (pending_frames_ >= display_->GetMaxFramesPending()) |
+ return; |
+ if (output_surface_lost_) |
+ return; |
+ need_draw_ = false; |
+ base::TimeTicks start_time = gfx::FrameTime::Now(); |
+ display_->Draw(); |
+ draw_duration_history_.InsertSample(gfx::FrameTime::Now() - start_time); |
+} |
+ |
+void DisplayScheduler::OnBeginFrame(const BeginFrameArgs& args) { |
brianderson
2014/11/19 02:40:21
Until the DisplayScheduler has knowledge about all
|
+ TRACE_EVENT0("cc", "DisplayScheduler::OnBeginFrame"); |
+ current_begin_frame_args_ = args; |
+ |
+ current_begin_frame_args_.deadline -= |
+ draw_duration_history_.Percentile(kDrawDurationEstimationPercentile) + |
+ base::TimeDelta::FromMicroseconds( |
+ kDrawDurationEstimatePaddingInMicroseconds); |
+ |
+ base::TimeDelta draw_delay = |
+ current_begin_frame_args_.deadline - gfx::FrameTime::Now(); |
+ if (draw_delay < base::TimeDelta()) |
+ draw_delay = base::TimeDelta(); |
+ task_runner_->PostDelayedTask( |
+ FROM_HERE, |
+ base::Bind(&DisplayScheduler::Draw, weak_ptr_factory_.GetWeakPtr()), |
+ draw_delay); |
+} |
+ |
+const BeginFrameArgs DisplayScheduler::LastUsedBeginFrameArgs() const { |
+ return current_begin_frame_args_; |
+} |
+ |
+void DisplayScheduler::AsValueInto(base::debug::TracedValue* dict) const { |
+} |
+ |
+void DisplayScheduler::DidSwapBuffers() { |
+ pending_frames_++; |
+} |
+ |
+void DisplayScheduler::DidSwapBuffersComplete() { |
+ pending_frames_--; |
+} |
+ |
+} // namespace cc |