// Copyright 2013 The Flutter 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 "flatland_connection.h"

#include <lib/async/cpp/task.h>
#include <lib/async/default.h>

#include <zircon/rights.h>
#include <zircon/status.h>
#include <zircon/types.h>

#include <utility>

#include "flutter/fml/logging.h"

namespace flutter_runner {

namespace {

// Helper function for traces.
double DeltaFromNowInNanoseconds(const fml::TimePoint& now,
                                 const fml::TimePoint& time) {
  return (time - now).ToNanoseconds();
}

}  // namespace

FlatlandConnection::FlatlandConnection(
    const std::string& debug_label,
    fuchsia::ui::composition::FlatlandHandle flatland,
    fml::closure error_callback,
    on_frame_presented_event on_frame_presented_callback,
    async_dispatcher_t* dispatcher)
    : dispatcher_(dispatcher),
      flatland_(flatland.Bind()),
      error_callback_(std::move(error_callback)),
      on_frame_presented_callback_(std::move(on_frame_presented_callback)) {
  flatland_.set_error_handler([callback = error_callback_](zx_status_t status) {
    FML_LOG(ERROR) << "Flatland disconnected: " << zx_status_get_string(status);
    callback();
  });
  debug_label_ = debug_label;
  flatland_->SetDebugName(debug_label);
  flatland_.events().OnError =
      fit::bind_member(this, &FlatlandConnection::OnError);
  flatland_.events().OnFramePresented =
      fit::bind_member(this, &FlatlandConnection::OnFramePresented);
  flatland_.events().OnNextFrameBegin =
      fit::bind_member(this, &FlatlandConnection::OnNextFrameBegin);
}

FlatlandConnection::~FlatlandConnection() = default;

// This method is called from the raster thread.
void FlatlandConnection::Present() {
  TRACE_DURATION("flutter", "FlatlandConnection::Present");
  std::scoped_lock<std::mutex> lock(threadsafe_state_.mutex_);
  if (threadsafe_state_.present_credits_ > 0) {
    DoPresent();
  } else {
    present_waiting_for_credit_ = true;
  }
}

// This method is called from the raster thread.
void FlatlandConnection::DoPresent() {
  TRACE_DURATION("flutter", "FlatlandConnection::DoPresent");

  std::string per_app_tracing_name =
      "Flatland::PerAppPresent[" + debug_label_ + "]";
  TRACE_FLOW_BEGIN("gfx", per_app_tracing_name.c_str(), next_present_trace_id_);
  ++next_present_trace_id_;

  FML_CHECK(threadsafe_state_.present_credits_ > 0);
  --threadsafe_state_.present_credits_;

  fuchsia::ui::composition::PresentArgs present_args;
  present_args.set_requested_presentation_time(0);
  present_args.set_acquire_fences(std::move(acquire_fences_));

  // Schedule acquire fence overflow signaling if there is one.
  if (acquire_overflow_ != nullptr) {
    FML_CHECK(acquire_overflow_->event_.is_valid());
    async::PostTask(dispatcher_, [dispatcher = dispatcher_,
                                  overflow = acquire_overflow_]() {
      const size_t fences_size = overflow->fences_.size();
      std::shared_ptr<size_t> fences_completed = std::make_shared<size_t>(0);
      std::shared_ptr<std::vector<async::WaitOnce>> closures;

      for (auto i = 0u; i < fences_size; i++) {
        auto wait = std::make_unique<async::WaitOnce>(
            overflow->fences_[i].get(), ZX_EVENT_SIGNALED, 0u);
        auto wait_ptr = wait.get();
        wait_ptr->Begin(
            dispatcher,
            [wait = std::move(wait), overflow, fences_size, fences_completed,
             closures](async_dispatcher_t*, async::WaitOnce*,
                       zx_status_t status, const zx_packet_signal_t*) {
              (*fences_completed)++;
              FML_CHECK(status == ZX_OK)
                  << "status: " << zx_status_get_string(status);
              if (*fences_completed == fences_size) {
                // Signal the acquire fence passed on to Flatland.
                const zx_status_t status =
                    overflow->event_.signal(0, ZX_EVENT_SIGNALED);
                FML_CHECK(status == ZX_OK)
                    << "status: " << zx_status_get_string(status);
              }
            });
      }
    });
    acquire_overflow_.reset();
  }
  FML_CHECK(acquire_overflow_ == nullptr);

  present_args.set_release_fences(std::move(previous_present_release_fences_));
  // Frame rate over latency.
  present_args.set_unsquashable(true);
  flatland_->Present(std::move(present_args));

  // In Flatland, release fences apply to the content of the previous present.
  // Keeping track of the old frame's release fences and swapping ensure we set
  // the correct ones for VulkanSurface's interpretation.
  previous_present_release_fences_.clear();
  previous_present_release_fences_.swap(current_present_release_fences_);
  previous_release_overflow_ = current_release_overflow_;
  current_release_overflow_ = nullptr;

  // Similar to the treatment of acquire_fences_overflow_ above. Except in
  // the other direction.
  if (previous_release_overflow_ != nullptr) {
    FML_CHECK(previous_release_overflow_->event_.is_valid());

    std::shared_ptr<Overflow> fences = previous_release_overflow_;

    async::PostTask(dispatcher_, [dispatcher = dispatcher_,
                                  fences = previous_release_overflow_]() {
      FML_CHECK(fences != nullptr);
      FML_CHECK(fences->event_.is_valid());

      auto wait = std::make_unique<async::WaitOnce>(fences->event_.get(),
                                                    ZX_EVENT_SIGNALED, 0u);
      auto wait_ptr = wait.get();

      wait_ptr->Begin(
          dispatcher, [_wait = std::move(wait), fences](
                          async_dispatcher_t*, async::WaitOnce*,
                          zx_status_t status, const zx_packet_signal_t*) {
            FML_CHECK(status == ZX_OK)
                << "status: " << zx_status_get_string(status);

            // Multiplex signaling all events.
            for (auto& event : fences->fences_) {
              const zx_status_t status = event.signal(0, ZX_EVENT_SIGNALED);
              FML_CHECK(status == ZX_OK)
                  << "status: " << zx_status_get_string(status);
            }
          });
    });
    previous_release_overflow_ = nullptr;
  }
  FML_CHECK(previous_release_overflow_ == nullptr);  // Moved.

  acquire_fences_.clear();
}

// This method is called from the UI thread.
void FlatlandConnection::AwaitVsync(FireCallbackCallback callback) {
  TRACE_DURATION("flutter", "FlatlandConnection::AwaitVsync");

  std::scoped_lock<std::mutex> lock(threadsafe_state_.mutex_);
  threadsafe_state_.pending_fire_callback_ = nullptr;
  const auto now = fml::TimePoint::Now();

  // Initial case.
  if (MaybeRunInitialVsyncCallback(now, callback)) {
    return;
  }

  // Throttle case.
  if (threadsafe_state_.present_credits_ == 0) {
    threadsafe_state_.pending_fire_callback_ = std::move(callback);
    return;
  }

  // Regular case.
  RunVsyncCallback(now, callback);
}

// This method is called from the UI thread.
void FlatlandConnection::AwaitVsyncForSecondaryCallback(
    FireCallbackCallback callback) {
  TRACE_DURATION("flutter",
                 "FlatlandConnection::AwaitVsyncForSecondaryCallback");

  std::scoped_lock<std::mutex> lock(threadsafe_state_.mutex_);
  const auto now = fml::TimePoint::Now();

  // Initial case.
  if (MaybeRunInitialVsyncCallback(now, callback)) {
    return;
  }

  // Regular case.
  RunVsyncCallback(now, callback);
}

// This method is called from the raster thread.
void FlatlandConnection::OnError(
    fuchsia::ui::composition::FlatlandError error) {
  FML_LOG(ERROR) << "Flatland error: " << static_cast<int>(error);
  error_callback_();
}

// This method is called from the raster thread.
void FlatlandConnection::OnNextFrameBegin(
    fuchsia::ui::composition::OnNextFrameBeginValues values) {
  // Collect now before locking because this is an important timing information
  // from Scenic.
  const auto now = fml::TimePoint::Now();

  std::scoped_lock<std::mutex> lock(threadsafe_state_.mutex_);
  threadsafe_state_.first_feedback_received_ = true;
  threadsafe_state_.present_credits_ += values.additional_present_credits();
  TRACE_DURATION("flutter", "FlatlandConnection::OnNextFrameBegin",
                 "present_credits", threadsafe_state_.present_credits_);

  if (present_waiting_for_credit_ && threadsafe_state_.present_credits_ > 0) {
    DoPresent();
    present_waiting_for_credit_ = false;
  }

  // Update vsync_interval_ by calculating the difference between the first two
  // presentation times. Flatland always returns >1 presentation_infos, so this
  // check is to guard against any changes to this assumption.
  if (values.has_future_presentation_infos() &&
      values.future_presentation_infos().size() > 1) {
    threadsafe_state_.vsync_interval_ = fml::TimeDelta::FromNanoseconds(
        values.future_presentation_infos().at(1).presentation_time() -
        values.future_presentation_infos().at(0).presentation_time());
  } else {
    FML_LOG(WARNING)
        << "Flatland didn't send enough future_presentation_infos to update "
           "vsync interval.";
  }

  // Update next_presentation_times_.
  std::queue<fml::TimePoint> new_times;
  for (const auto& info : values.future_presentation_infos()) {
    new_times.emplace(fml::TimePoint::FromEpochDelta(
        fml::TimeDelta::FromNanoseconds(info.presentation_time())));
  }
  threadsafe_state_.next_presentation_times_.swap(new_times);

  // Update vsync_offset_.
  // We use modulo here because Flatland may point to the following vsync if
  // OnNextFrameBegin() is called after the current frame's latch point.
  auto vsync_offset =
      (fml::TimePoint::FromEpochDelta(fml::TimeDelta::FromNanoseconds(
           values.future_presentation_infos().front().presentation_time())) -
       now) %
      threadsafe_state_.vsync_interval_;
  // Thread contention may result in OnNextFrameBegin() being called after the
  // presentation time. Ignore these outliers.
  if (vsync_offset > fml::TimeDelta::Zero()) {
    threadsafe_state_.vsync_offset_ = vsync_offset;
  }

  // Throttle case.
  if (threadsafe_state_.pending_fire_callback_ &&
      threadsafe_state_.present_credits_ > 0) {
    RunVsyncCallback(now, threadsafe_state_.pending_fire_callback_);
    threadsafe_state_.pending_fire_callback_ = nullptr;
  }
}

// This method is called from the raster thread.
void FlatlandConnection::OnFramePresented(
    fuchsia::scenic::scheduling::FramePresentedInfo info) {
  on_frame_presented_callback_(std::move(info));
}

// Parses and updates next_presentation_times_.
fml::TimePoint FlatlandConnection::GetNextPresentationTime(
    const fml::TimePoint& now) {
  const fml::TimePoint& cutoff =
      now > threadsafe_state_.last_presentation_time_
          ? now
          : threadsafe_state_.last_presentation_time_;

  // Remove presentation times that may have been passed. This may happen after
  // a long draw call.
  while (!threadsafe_state_.next_presentation_times_.empty() &&
         threadsafe_state_.next_presentation_times_.front() <= cutoff) {
    threadsafe_state_.next_presentation_times_.pop();
  }

  // Calculate a presentation time based on
  // |threadsafe_state_.last_presentation_time_| that is later than cutoff using
  // |vsync_interval| increments if we don't have any future presentation times
  // left.
  if (threadsafe_state_.next_presentation_times_.empty()) {
    auto result = threadsafe_state_.last_presentation_time_;
    while (result <= cutoff) {
      result = result + threadsafe_state_.vsync_interval_;
    }
    return result;
  }

  // Return the next presentation time in the queue for the regular case.
  const auto result = threadsafe_state_.next_presentation_times_.front();
  threadsafe_state_.next_presentation_times_.pop();
  return result;
}

// This method is called from the UI thread.
bool FlatlandConnection::MaybeRunInitialVsyncCallback(
    const fml::TimePoint& now,
    FireCallbackCallback& callback) {
  if (!threadsafe_state_.first_feedback_received_) {
    TRACE_DURATION("flutter",
                   "FlatlandConnection::MaybeRunInitialVsyncCallback");
    const auto frame_end = now + kInitialFlatlandVsyncOffset;
    threadsafe_state_.last_presentation_time_ = frame_end;
    callback(now, frame_end);
    return true;
  }
  return false;
}

// This method may be called from the raster or UI thread, but it is safe
// because VsyncWaiter posts the vsync callback on UI thread.
void FlatlandConnection::RunVsyncCallback(const fml::TimePoint& now,
                                          FireCallbackCallback& callback) {
  const auto& frame_end = GetNextPresentationTime(now);
  const auto& frame_start = frame_end - threadsafe_state_.vsync_offset_;
  threadsafe_state_.last_presentation_time_ = frame_end;
  TRACE_DURATION("flutter", "FlatlandConnection::RunVsyncCallback",
                 "frame_start_delta",
                 DeltaFromNowInNanoseconds(now, frame_start), "frame_end_delta",
                 DeltaFromNowInNanoseconds(now, frame_end));
  callback(frame_start, frame_end);
}

// Enqueue a single fence into either the "base" vector of fences, or a
// "special" overflow multiplexer.
//
// Args:
//   - fence: the fence to add
//   - fences: the "regular" fences vector to add to.
//   - overflow: the overflow fences vector. Fences added here if there are
//     more than can fit in `fences`.
static void Enqueue(zx::event fence,
                    std::vector<zx::event>* fences,
                    std::shared_ptr<Overflow>* overflow) {
  constexpr size_t kMaxFences =
      fuchsia::ui::composition::MAX_ACQUIRE_RELEASE_FENCE_COUNT;

  // Number of all previously added fences, plus this one.
  const auto num_all_fences =
      fences->size() + 1 +
      ((*overflow == nullptr) ? 0 : (*overflow)->fences_.size());

  // If more than max number of fences come in, schedule any further fences into
  // an overflow. The overflow fences are scheduled for processing here, but are
  // processed in DoPresent().
  if (num_all_fences <= kMaxFences) {
    fences->push_back(std::move(fence));
  } else if (num_all_fences == kMaxFences + 1) {
    // The ownership of the overflow will be handed over to the signaling
    // closure on DoPresent call. So we always expect that we enter here with
    // overflow not set.
    FML_CHECK((*overflow) == nullptr) << "overflow is still active";
    *overflow = std::make_shared<Overflow>();

    // Set up the overflow fences. Creates an overflow handle, places it
    // into `fences` instead of the previous fence, and puts the prior fence
    // and this one into overflow.
    zx::event overflow_handle = std::move(fences->back());
    fences->pop_back();

    zx::event overflow_fence;
    zx_status_t status = zx::event::create(0, &overflow_fence);
    FML_CHECK(status == ZX_OK) << "status: " << zx_status_get_string(status);

    // Every DoPresent should invalidate this handle.  Holler if not.
    FML_CHECK(!(*overflow)->event_.is_valid()) << "overflow valid";
    status =
        overflow_fence.duplicate(ZX_RIGHT_SAME_RIGHTS, &(*overflow)->event_);
    FML_CHECK(status == ZX_OK) << "status: " << zx_status_get_string(status);
    fences->push_back(std::move(overflow_fence));

    // Prepare for wait_many call.
    (*overflow)->fences_.push_back(std::move(overflow_handle));
    (*overflow)->fences_.push_back(std::move(fence));

    FML_LOG(INFO) << "Enqueue using fence overflow, expect a performance hit.";
  } else {
    FML_CHECK((*overflow) != nullptr);
    // Just add to the overflow fences.
    (*overflow)->fences_.push_back(std::move(fence));
  }
}

// This method is called from the raster thread.
void FlatlandConnection::EnqueueAcquireFence(zx::event fence) {
  Enqueue(std::move(fence), &acquire_fences_, &acquire_overflow_);
}

// This method is called from the raster thread.
void FlatlandConnection::EnqueueReleaseFence(zx::event fence) {
  Enqueue(std::move(fence), &current_present_release_fences_,
          &current_release_overflow_);
}

}  // namespace flutter_runner
