// 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(), BeginFrameArgs::NORMAL);
  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::Create(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
