diff options
Diffstat (limited to 'chromium/cc/scheduler/frame_rate_controller.cc')
-rw-r--r-- | chromium/cc/scheduler/frame_rate_controller.cc | 172 |
1 files changed, 172 insertions, 0 deletions
diff --git a/chromium/cc/scheduler/frame_rate_controller.cc b/chromium/cc/scheduler/frame_rate_controller.cc new file mode 100644 index 00000000000..54c1bdaf48f --- /dev/null +++ b/chromium/cc/scheduler/frame_rate_controller.cc @@ -0,0 +1,172 @@ +// Copyright 2011 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/scheduler/frame_rate_controller.h" + +#include "base/bind.h" +#include "base/debug/trace_event.h" +#include "base/location.h" +#include "base/logging.h" +#include "base/single_thread_task_runner.h" +#include "cc/scheduler/delay_based_time_source.h" +#include "cc/scheduler/time_source.h" + +namespace cc { + +class FrameRateControllerTimeSourceAdapter : public TimeSourceClient { + public: + static scoped_ptr<FrameRateControllerTimeSourceAdapter> Create( + FrameRateController* frame_rate_controller) { + return make_scoped_ptr( + new FrameRateControllerTimeSourceAdapter(frame_rate_controller)); + } + virtual ~FrameRateControllerTimeSourceAdapter() {} + + virtual void OnTimerTick() OVERRIDE { + frame_rate_controller_->OnTimerTick(); + } + + private: + explicit FrameRateControllerTimeSourceAdapter( + FrameRateController* frame_rate_controller) + : frame_rate_controller_(frame_rate_controller) {} + + FrameRateController* frame_rate_controller_; +}; + +FrameRateController::FrameRateController(scoped_refptr<TimeSource> timer) + : client_(NULL), + num_frames_pending_(0), + max_swaps_pending_(0), + interval_(BeginFrameArgs::DefaultInterval()), + time_source_(timer), + active_(false), + is_time_source_throttling_(true), + weak_factory_(this), + task_runner_(NULL) { + time_source_client_adapter_ = + FrameRateControllerTimeSourceAdapter::Create(this); + time_source_->SetClient(time_source_client_adapter_.get()); +} + +FrameRateController::FrameRateController( + base::SingleThreadTaskRunner* task_runner) + : client_(NULL), + num_frames_pending_(0), + max_swaps_pending_(0), + interval_(BeginFrameArgs::DefaultInterval()), + active_(false), + is_time_source_throttling_(false), + weak_factory_(this), + task_runner_(task_runner) {} + +FrameRateController::~FrameRateController() { + if (is_time_source_throttling_) + time_source_->SetActive(false); +} + +BeginFrameArgs FrameRateController::SetActive(bool active) { + if (active_ == active) + return BeginFrameArgs(); + TRACE_EVENT1("cc", "FrameRateController::SetActive", "active", active); + active_ = active; + + if (is_time_source_throttling_) { + base::TimeTicks missed_tick_time = time_source_->SetActive(active); + if (!missed_tick_time.is_null()) { + base::TimeTicks deadline = NextTickTime(); + return BeginFrameArgs::Create(missed_tick_time, + deadline, + interval_); + } + } else { + if (active) + PostManualTick(); + else + weak_factory_.InvalidateWeakPtrs(); + } + + return BeginFrameArgs(); +} + +void FrameRateController::SetMaxSwapsPending(int max_swaps_pending) { + DCHECK_GE(max_swaps_pending, 0); + max_swaps_pending_ = max_swaps_pending; +} + +void FrameRateController::SetTimebaseAndInterval(base::TimeTicks timebase, + base::TimeDelta interval) { + interval_ = interval; + if (is_time_source_throttling_) + time_source_->SetTimebaseAndInterval(timebase, interval); +} + +void FrameRateController::SetDeadlineAdjustment(base::TimeDelta delta) { + deadline_adjustment_ = delta; +} + +void FrameRateController::OnTimerTick() { + TRACE_EVENT0("cc", "FrameRateController::OnTimerTick"); + DCHECK(active_); + + // Check if we have too many frames in flight. + bool throttled = + max_swaps_pending_ && num_frames_pending_ >= max_swaps_pending_; + TRACE_COUNTER_ID1("cc", "ThrottledCompositor", task_runner_, throttled); + + if (client_) { + // TODO(brianderson): Use an adaptive parent compositor deadline. + base::TimeTicks frame_time = LastTickTime(); + base::TimeTicks deadline = NextTickTime() + deadline_adjustment_; + client_->FrameRateControllerTick( + throttled, + BeginFrameArgs::Create(frame_time, deadline, interval_)); + } + + if (!is_time_source_throttling_ && !throttled) + PostManualTick(); +} + +void FrameRateController::PostManualTick() { + if (active_) { + task_runner_->PostTask(FROM_HERE, + base::Bind(&FrameRateController::ManualTick, + weak_factory_.GetWeakPtr())); + } +} + +void FrameRateController::ManualTick() { + OnTimerTick(); +} + +void FrameRateController::DidSwapBuffers() { + num_frames_pending_++; +} + +void FrameRateController::DidSwapBuffersComplete() { + DCHECK_GT(num_frames_pending_, 0); + num_frames_pending_--; + if (!is_time_source_throttling_) + PostManualTick(); +} + +void FrameRateController::DidAbortAllPendingFrames() { + num_frames_pending_ = 0; +} + +base::TimeTicks FrameRateController::NextTickTime() { + if (is_time_source_throttling_) + return time_source_->NextTickTime(); + + return base::TimeTicks(); +} + +base::TimeTicks FrameRateController::LastTickTime() { + if (is_time_source_throttling_) + return time_source_->LastTickTime(); + + return base::TimeTicks::Now(); +} + +} // namespace cc |