root/cc/scheduler/frame_rate_controller.cc

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. Create
  2. OnTimerTick
  3. weak_factory_
  4. weak_factory_
  5. SetActive
  6. SetMaxSwapsPending
  7. SetTimebaseAndInterval
  8. SetDeadlineAdjustment
  9. OnTimerTick
  10. PostManualTick
  11. ManualTick
  12. DidSwapBuffers
  13. DidSwapBuffersComplete
  14. DidAbortAllPendingFrames
  15. NextTickTime
  16. LastTickTime

// 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"
#include "ui/gfx/frame_time.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),
      manual_tick_pending_(false),
      task_runner_(NULL),
      weak_factory_(this) {
  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),
      manual_tick_pending_(false),
      task_runner_(task_runner),
      weak_factory_(this) {}

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 + deadline_adjustment_, interval_);
    }
  } else {
    if (active) {
      PostManualTick();
    } else {
      weak_factory_.InvalidateWeakPtrs();
      manual_tick_pending_ = false;
    }
  }

  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();
    BeginFrameArgs args = BeginFrameArgs::Create(
        frame_time, deadline + deadline_adjustment_, interval_);
    client_->FrameRateControllerTick(throttled, args);
  }

  if (!is_time_source_throttling_ && !throttled)
    PostManualTick();
}

void FrameRateController::PostManualTick() {
  if (active_ && !manual_tick_pending_) {
    manual_tick_pending_ = true;
    task_runner_->PostTask(FROM_HERE,
                           base::Bind(&FrameRateController::ManualTick,
                                      weak_factory_.GetWeakPtr()));
  }
}

void FrameRateController::ManualTick() {
  manual_tick_pending_ = false;
  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 gfx::FrameTime::Now();
}

}  // namespace cc

/* [<][>][^][v][top][bottom][index][help] */