// 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/scheduler/begin_frame_source.h"

#include "base/auto_reset.h"
#include "base/debug/trace_event.h"
#include "base/debug/trace_event_argument.h"
#include "base/logging.h"
#include "base/strings/string_number_conversions.h"
#include "cc/scheduler/delay_based_time_source.h"
#include "cc/scheduler/scheduler.h"
#include "ui/gfx/frame_time.h"

#ifdef NDEBUG
#define DEBUG_FRAMES(...)
#else
#define DEBUG_FRAMES(name, arg1_name, arg1_val, arg2_name, arg2_val)   \
  TRACE_EVENT2(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler.frames"), \
               name,                                                   \
               arg1_name,                                              \
               arg1_val,                                               \
               arg2_name,                                              \
               arg2_val);
#endif

namespace cc {

// BeginFrameObserverMixIn -----------------------------------------------
BeginFrameObserverMixIn::BeginFrameObserverMixIn()
    : last_begin_frame_args_(), dropped_begin_frame_args_(0) {
}

const BeginFrameArgs BeginFrameObserverMixIn::LastUsedBeginFrameArgs() const {
  return last_begin_frame_args_;
}
void BeginFrameObserverMixIn::OnBeginFrame(const BeginFrameArgs& args) {
  DEBUG_FRAMES("BeginFrameObserverMixIn::OnBeginFrame",
               "last args",
               last_begin_frame_args_.AsValue(),
               "new args",
               args.AsValue());
  DCHECK(args.IsValid());
  DCHECK(args.frame_time >= last_begin_frame_args_.frame_time);
  bool used = OnBeginFrameMixInDelegate(args);
  if (used) {
    last_begin_frame_args_ = args;
  } else {
    ++dropped_begin_frame_args_;
  }
}

void BeginFrameObserverMixIn::AsValueInto(
    base::debug::TracedValue* dict) const {
  dict->BeginDictionary("last_begin_frame_args_");
  last_begin_frame_args_.AsValueInto(dict);
  dict->EndDictionary();
  dict->SetInteger("dropped_begin_frame_args_", dropped_begin_frame_args_);
}

// BeginFrameSourceMixIn ------------------------------------------------------
BeginFrameSourceMixIn::BeginFrameSourceMixIn()
    : observer_(NULL),
      needs_begin_frames_(false),
      inside_as_value_into_(false) {
  DCHECK(!observer_);
  DCHECK_EQ(inside_as_value_into_, false);
}

bool BeginFrameSourceMixIn::NeedsBeginFrames() const {
  return needs_begin_frames_;
}

void BeginFrameSourceMixIn::SetNeedsBeginFrames(bool needs_begin_frames) {
  DEBUG_FRAMES("BeginFrameSourceMixIn::SetNeedsBeginFrames",
               "current state",
               needs_begin_frames_,
               "new state",
               needs_begin_frames);
  if (needs_begin_frames_ != needs_begin_frames) {
    needs_begin_frames_ = needs_begin_frames;
    OnNeedsBeginFramesChange(needs_begin_frames);
  }
}

void BeginFrameSourceMixIn::AddObserver(BeginFrameObserver* obs) {
  DEBUG_FRAMES("BeginFrameSourceMixIn::AddObserver",
               "current observer",
               observer_,
               "to add observer",
               obs);
  DCHECK(!observer_);
  observer_ = obs;
}

void BeginFrameSourceMixIn::RemoveObserver(BeginFrameObserver* obs) {
  DEBUG_FRAMES("BeginFrameSourceMixIn::RemoveObserver",
               "current observer",
               observer_,
               "to remove observer",
               obs);
  DCHECK_EQ(observer_, obs);
  observer_ = NULL;
}

void BeginFrameSourceMixIn::CallOnBeginFrame(const BeginFrameArgs& args) {
  DEBUG_FRAMES("BeginFrameSourceMixIn::CallOnBeginFrame",
               "current observer",
               observer_,
               "args",
               args.AsValue());
  if (observer_) {
    return observer_->OnBeginFrame(args);
  }
}

// Tracing support
void BeginFrameSourceMixIn::AsValueInto(base::debug::TracedValue* dict) const {
  // As the observer might try to trace the source, prevent an infinte loop
  // from occuring.
  if (inside_as_value_into_) {
    dict->SetString("observer", "<loop detected>");
    return;
  }

  if (observer_) {
    base::AutoReset<bool> prevent_loops(
        const_cast<bool*>(&inside_as_value_into_), true);
    dict->BeginDictionary("observer");
    observer_->AsValueInto(dict);
    dict->EndDictionary();
  } else {
    dict->SetString("observer", "NULL");
  }
  dict->SetBoolean("needs_begin_frames", NeedsBeginFrames());
}

// BackToBackBeginFrameSourceMixIn --------------------------------------------
scoped_ptr<BackToBackBeginFrameSource> BackToBackBeginFrameSource::Create(
    base::SingleThreadTaskRunner* task_runner) {
  return make_scoped_ptr(new BackToBackBeginFrameSource(task_runner));
}

BackToBackBeginFrameSource::BackToBackBeginFrameSource(
    base::SingleThreadTaskRunner* task_runner)
    : BeginFrameSourceMixIn(),
      weak_factory_(this),
      task_runner_(task_runner),
      send_begin_frame_posted_(false) {
  DCHECK(task_runner);
  DCHECK_EQ(needs_begin_frames_, false);
  DCHECK_EQ(send_begin_frame_posted_, false);
}

BackToBackBeginFrameSource::~BackToBackBeginFrameSource() {
}

base::TimeTicks BackToBackBeginFrameSource::Now() {
  return gfx::FrameTime::Now();
}

void BackToBackBeginFrameSource::OnNeedsBeginFramesChange(
    bool needs_begin_frames) {
  if (!needs_begin_frames)
    return;

  if (send_begin_frame_posted_)
    return;

  send_begin_frame_posted_ = true;
  task_runner_->PostTask(FROM_HERE,
                         base::Bind(&BackToBackBeginFrameSource::BeginFrame,
                                    weak_factory_.GetWeakPtr()));
}

void BackToBackBeginFrameSource::BeginFrame() {
  send_begin_frame_posted_ = false;

  if (!needs_begin_frames_)
    return;

  base::TimeTicks now = Now();
  BeginFrameArgs args =
      BeginFrameArgs::Create(now,
                             now + BeginFrameArgs::DefaultInterval(),
                             BeginFrameArgs::DefaultInterval());
  CallOnBeginFrame(args);
}

// BeginFrameSource support

void BackToBackBeginFrameSource::DidFinishFrame(size_t remaining_frames) {
  if (remaining_frames == 0) {
    OnNeedsBeginFramesChange(NeedsBeginFrames());
  }
}

// Tracing support
void BackToBackBeginFrameSource::AsValueInto(
    base::debug::TracedValue* dict) const {
  dict->SetString("type", "BackToBackBeginFrameSource");
  BeginFrameSourceMixIn::AsValueInto(dict);
  dict->SetBoolean("send_begin_frame_posted_", send_begin_frame_posted_);
}

// SyntheticBeginFrameSource ---------------------------------------------
scoped_ptr<SyntheticBeginFrameSource> SyntheticBeginFrameSource::Create(
    base::SingleThreadTaskRunner* task_runner,
    base::TimeTicks initial_vsync_timebase,
    base::TimeDelta initial_vsync_interval) {
  scoped_refptr<DelayBasedTimeSource> time_source;
  if (gfx::FrameTime::TimestampsAreHighRes()) {
    time_source = DelayBasedTimeSourceHighRes::Create(initial_vsync_interval,
                                                      task_runner);
  } else {
    time_source =
        DelayBasedTimeSource::Create(initial_vsync_interval, task_runner);
  }

  return make_scoped_ptr(new SyntheticBeginFrameSource(time_source));
}

SyntheticBeginFrameSource::SyntheticBeginFrameSource(
    scoped_refptr<DelayBasedTimeSource> time_source)
    : BeginFrameSourceMixIn(), time_source_(time_source) {
  time_source_->SetActive(false);
  time_source_->SetClient(this);
}

SyntheticBeginFrameSource::~SyntheticBeginFrameSource() {
  if (NeedsBeginFrames())
    time_source_->SetActive(false);
}

void SyntheticBeginFrameSource::OnUpdateVSyncParameters(
    base::TimeTicks new_vsync_timebase,
    base::TimeDelta new_vsync_interval) {
  time_source_->SetTimebaseAndInterval(new_vsync_timebase, new_vsync_interval);
}

BeginFrameArgs SyntheticBeginFrameSource::CreateBeginFrameArgs(
    base::TimeTicks frame_time,
    BeginFrameArgs::BeginFrameArgsType type) {
  base::TimeTicks deadline = time_source_->NextTickTime();
  return BeginFrameArgs::CreateTyped(
      frame_time, deadline, time_source_->Interval(), type);
}

// TimeSourceClient support
void SyntheticBeginFrameSource::OnTimerTick() {
  CallOnBeginFrame(CreateBeginFrameArgs(time_source_->LastTickTime(),
                                        BeginFrameArgs::NORMAL));
}

// BeginFrameSourceMixIn support
void SyntheticBeginFrameSource::OnNeedsBeginFramesChange(
    bool needs_begin_frames) {
  base::TimeTicks missed_tick_time =
      time_source_->SetActive(needs_begin_frames);
  if (!missed_tick_time.is_null()) {
    CallOnBeginFrame(
        CreateBeginFrameArgs(missed_tick_time, BeginFrameArgs::MISSED));
  }
}

bool SyntheticBeginFrameSource::NeedsBeginFrames() const {
  return time_source_->Active();
}

// Tracing support
void SyntheticBeginFrameSource::AsValueInto(
    base::debug::TracedValue* dict) const {
  dict->SetString("type", "SyntheticBeginFrameSource");
  BeginFrameSourceMixIn::AsValueInto(dict);

  dict->BeginDictionary("time_source");
  time_source_->AsValueInto(dict);
  dict->EndDictionary();
}

// BeginFrameSourceMultiplexer -------------------------------------------
scoped_ptr<BeginFrameSourceMultiplexer> BeginFrameSourceMultiplexer::Create() {
  return make_scoped_ptr(new BeginFrameSourceMultiplexer());
}

BeginFrameSourceMultiplexer::BeginFrameSourceMultiplexer()
    : BeginFrameSourceMixIn(),
      minimum_interval_(base::TimeDelta()),
      active_source_(NULL),
      source_list_() {
}

BeginFrameSourceMultiplexer::BeginFrameSourceMultiplexer(
    base::TimeDelta minimum_interval)
    : BeginFrameSourceMixIn(),
      minimum_interval_(minimum_interval),
      active_source_(NULL),
      source_list_() {
}

BeginFrameSourceMultiplexer::~BeginFrameSourceMultiplexer() {
}

void BeginFrameSourceMultiplexer::SetMinimumInterval(
    base::TimeDelta new_minimum_interval) {
  DEBUG_FRAMES("BeginFrameSourceMultiplexer::SetMinimumInterval",
               "current minimum (us)",
               minimum_interval_.InMicroseconds(),
               "new minimum (us)",
               new_minimum_interval.InMicroseconds());
  DCHECK_GE(new_minimum_interval.ToInternalValue(), 0);
  minimum_interval_ = new_minimum_interval;
}

void BeginFrameSourceMultiplexer::AddSource(BeginFrameSource* new_source) {
  DEBUG_FRAMES("BeginFrameSourceMultiplexer::AddSource",
               "current active",
               active_source_,
               "source to remove",
               new_source);
  DCHECK(new_source);
  DCHECK(!HasSource(new_source));

  source_list_.insert(new_source);

  // If there is no active source, set the new one as the active one.
  if (!active_source_)
    SetActiveSource(new_source);
}

void BeginFrameSourceMultiplexer::RemoveSource(
    BeginFrameSource* existing_source) {
  DEBUG_FRAMES("BeginFrameSourceMultiplexer::RemoveSource",
               "current active",
               active_source_,
               "source to remove",
               existing_source);
  DCHECK(existing_source);
  DCHECK(HasSource(existing_source));
  DCHECK_NE(existing_source, active_source_);
  source_list_.erase(existing_source);
}

void BeginFrameSourceMultiplexer::SetActiveSource(
    BeginFrameSource* new_source) {
  DEBUG_FRAMES("BeginFrameSourceMultiplexer::SetActiveSource",
               "current active",
               active_source_,
               "to become active",
               new_source);

  DCHECK(HasSource(new_source) || new_source == NULL);

  bool needs_begin_frames = NeedsBeginFrames();
  if (active_source_) {
    if (needs_begin_frames)
      SetNeedsBeginFrames(false);

    // Technically we shouldn't need to remove observation, but this prevents
    // the case where SetNeedsBeginFrames message gets to the source after a
    // message has already been sent.
    active_source_->RemoveObserver(this);
    active_source_ = NULL;
  }
  DCHECK(!active_source_);
  active_source_ = new_source;

  if (active_source_) {
    active_source_->AddObserver(this);

    if (needs_begin_frames) {
      SetNeedsBeginFrames(true);
    }
  }
}

const BeginFrameSource* BeginFrameSourceMultiplexer::ActiveSource() {
  return active_source_;
}

// BeginFrameObserver support
void BeginFrameSourceMultiplexer::OnBeginFrame(const BeginFrameArgs& args) {
  if (!IsIncreasing(args)) {
    DEBUG_FRAMES("BeginFrameSourceMultiplexer::OnBeginFrame",
                 "action",
                 "discarding",
                 "new args",
                 args.AsValue());
    return;
  }
  DEBUG_FRAMES("BeginFrameSourceMultiplexer::OnBeginFrame",
               "action",
               "using",
               "new args",
               args.AsValue());
  CallOnBeginFrame(args);
}

const BeginFrameArgs BeginFrameSourceMultiplexer::LastUsedBeginFrameArgs()
    const {
  if (observer_)
    return observer_->LastUsedBeginFrameArgs();
  else
    return BeginFrameArgs();
}

// BeginFrameSource support
bool BeginFrameSourceMultiplexer::NeedsBeginFrames() const {
  if (active_source_) {
    return active_source_->NeedsBeginFrames();
  } else {
    return false;
  }
}

void BeginFrameSourceMultiplexer::SetNeedsBeginFrames(bool needs_begin_frames) {
  DEBUG_FRAMES("BeginFrameSourceMultiplexer::SetNeedsBeginFrames",
               "active_source",
               active_source_,
               "needs_begin_frames",
               needs_begin_frames);
  if (active_source_) {
    active_source_->SetNeedsBeginFrames(needs_begin_frames);
  } else {
    DCHECK(!needs_begin_frames);
  }
}

void BeginFrameSourceMultiplexer::DidFinishFrame(size_t remaining_frames) {
  DEBUG_FRAMES("BeginFrameSourceMultiplexer::DidFinishFrame",
               "active_source",
               active_source_,
               "remaining_frames",
               remaining_frames);
  if (active_source_) {
    active_source_->DidFinishFrame(remaining_frames);
  }
}

// Tracing support
void BeginFrameSourceMultiplexer::AsValueInto(
    base::debug::TracedValue* dict) const {
  dict->SetString("type", "BeginFrameSourceMultiplexer");

  dict->SetInteger("minimum_interval_us", minimum_interval_.InMicroseconds());
  if (observer_) {
    dict->BeginDictionary("last_begin_frame_args");
    observer_->LastUsedBeginFrameArgs().AsValueInto(dict);
    dict->EndDictionary();
  }

  if (active_source_) {
    dict->BeginDictionary("active_source");
    active_source_->AsValueInto(dict);
    dict->EndDictionary();
  } else {
    dict->SetString("active_source", "NULL");
  }

  dict->BeginArray("sources");
  for (std::set<BeginFrameSource*>::const_iterator it = source_list_.begin();
       it != source_list_.end();
       ++it) {
    dict->BeginDictionary();
    (*it)->AsValueInto(dict);
    dict->EndDictionary();
  }
  dict->EndArray();
}

// protected methods
bool BeginFrameSourceMultiplexer::HasSource(BeginFrameSource* source) {
  return (source_list_.find(source) != source_list_.end());
}

bool BeginFrameSourceMultiplexer::IsIncreasing(const BeginFrameArgs& args) {
  DCHECK(args.IsValid());
  if (!observer_)
    return false;

  // If the last begin frame is invalid, then any new begin frame is valid.
  if (!observer_->LastUsedBeginFrameArgs().IsValid())
    return true;

  // Only allow new args have a *strictly bigger* frame_time value and statisfy
  // minimum interval requirement.
  return (args.frame_time >=
          observer_->LastUsedBeginFrameArgs().frame_time + minimum_interval_);
}

}  // namespace cc
