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