// Copyright 2017 The Fuchsia 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 "garnet/lib/ui/gfx/engine/session.h"

#include <lib/async/cpp/task.h>
#include <lib/async/default.h>
#include <lib/fostr/fidl/fuchsia/ui/gfx/formatting.h>
#include <trace/event.h>

#include <memory>
#include <utility>

#include "garnet/lib/ui/gfx/engine/gfx_command_applier.h"
#include "garnet/lib/ui/gfx/engine/hit_tester.h"
#include "garnet/lib/ui/gfx/engine/session_handler.h"
#include "garnet/lib/ui/gfx/resources/compositor/layer_stack.h"
#include "garnet/lib/ui/gfx/resources/image_pipe.h"
#include "garnet/lib/ui/gfx/swapchain/swapchain_factory.h"
#include "garnet/lib/ui/gfx/util/time.h"
#include "garnet/lib/ui/gfx/util/unwrap.h"
#include "garnet/lib/ui/gfx/util/wrap.h"
#include "src/ui/lib/escher/hmd/pose_buffer.h"
#include "src/ui/lib/escher/renderer/batch_gpu_uploader.h"
#include "src/ui/lib/escher/shape/mesh.h"
#include "src/ui/lib/escher/shape/rounded_rect_factory.h"
#include "src/ui/lib/escher/util/type_utils.h"

namespace scenic_impl {
namespace gfx {

namespace {

#define SESSION_TRACE_ID(session_id, count) \
  (((uint64_t)(session_id) << 32) | (count))

}  // anonymous namespace

Session::Session(SessionId id, SessionContext session_context,
                 EventReporter* event_reporter, ErrorReporter* error_reporter,
                 inspect::Node inspect_node)
    : id_(id),
      error_reporter_(error_reporter),
      event_reporter_(event_reporter),
      session_context_(std::move(session_context)),
      resource_context_(
          /* Sessions can be used in integration tests, with and without Vulkan.
             When Vulkan is unavailable, the Escher pointer is null. These
             ternaries protect against null-pointer dispatching for these
             non-Vulkan tests. */
          {session_context_.vk_device,
           session_context_.escher != nullptr
               ? session_context_.escher->vk_physical_device()
               : vk::PhysicalDevice(),
           session_context_.escher != nullptr
               ? session_context_.escher->device()->dispatch_loader()
               : vk::DispatchLoaderDynamic(),
           session_context_.escher != nullptr
               ? session_context_.escher->device()->caps()
               : escher::VulkanDeviceQueues::Caps(),
           session_context_.escher_resource_recycler,
           session_context_.escher_image_factory}),
      resources_(error_reporter),
      inspect_node_(std::move(inspect_node)),
      weak_factory_(this) {
  FXL_DCHECK(error_reporter);

  inspect_resource_count_ = inspect_node_.CreateUIntMetric("resource_count", 0);
  inspect_last_applied_target_presentation_time_ =
      inspect_node_.CreateUIntMetric("last_applied_target_presentation_time",
                                     0);
  inspect_last_applied_requested_presentation_time_ =
      inspect_node_.CreateUIntMetric("last_applied_request_presentation_time",
                                     0);
  inspect_last_requested_presentation_time_ =
      inspect_node_.CreateUIntMetric("last_requested_presentation_time", 0);
}

Session::~Session() {
  resources_.Clear();
  scheduled_image_pipe_updates_ = {};

  // We assume the channel for the associated gfx::Session is closed by
  // SessionHandler before this point, since |scheduled_updates_| contains
  // pending callbacks to gfx::Session::Present(). If the channel was not closed
  // we would have to invoke those callbacks before destroying them.
  scheduled_updates_ = {};
  fences_to_release_on_next_update_.clear();

  if (resource_count_ != 0) {
    auto exported_count =
        session_context_.resource_linker->NumExportsForSession(this);
    FXL_CHECK(resource_count_ == 0)
        << "Session::~Session(): Not all resources have been collected. "
           "Exported resources: "
        << exported_count
        << ", total outstanding resources: " << resource_count_;
  }
  error_reporter_ = nullptr;
}

ErrorReporter* Session::error_reporter() const {
  return error_reporter_ ? error_reporter_ : ErrorReporter::Default();
}

EventReporter* Session::event_reporter() const { return event_reporter_; }

bool Session::ScheduleUpdate(
    uint64_t requested_presentation_time,
    std::vector<::fuchsia::ui::gfx::Command> commands,
    std::vector<zx::event> acquire_fences,
    std::vector<zx::event> release_events,
    fuchsia::ui::scenic::Session::PresentCallback callback) {
  TRACE_DURATION("gfx", "Session::ScheduleUpdate", "session_id", id_,
                 "session_debug_name", debug_name_, "requested time",
                 requested_presentation_time);

  // Logic verifying client requests presents in-order.
  uint64_t last_scheduled_presentation_time =
      last_applied_update_presentation_time_;
  if (!scheduled_updates_.empty()) {
    last_scheduled_presentation_time =
        std::max(last_scheduled_presentation_time,
                 scheduled_updates_.back().presentation_time);
  }

  if (requested_presentation_time < last_scheduled_presentation_time) {
    error_reporter_->ERROR()
        << "scenic_impl::gfx::Session: Present called with out-of-order "
           "presentation time. "
        << "requested presentation time=" << requested_presentation_time
        << ", last scheduled presentation time="
        << last_scheduled_presentation_time << ".";
    return false;
  }

  auto acquire_fence_set =
      std::make_unique<escher::FenceSetListener>(std::move(acquire_fences));
  acquire_fence_set->WaitReadyAsync(
      [weak = GetWeakPtr(), requested_presentation_time] {
        if (weak) {
          weak->session_context_.frame_scheduler->ScheduleUpdateForSession(
              requested_presentation_time, weak->id());
        }
      });

  ++scheduled_update_count_;
  TRACE_FLOW_BEGIN("gfx", "scheduled_update",
                   SESSION_TRACE_ID(id_, scheduled_update_count_));

  scheduled_updates_.push(
      Update{requested_presentation_time, std::move(commands),
             std::move(acquire_fence_set), std::move(release_events),
             std::move(callback)});

  inspect_last_requested_presentation_time_.Set(requested_presentation_time);

  return true;
}

void Session::ScheduleImagePipeUpdate(uint64_t presentation_time,
                                      ImagePipePtr image_pipe) {
  FXL_DCHECK(image_pipe);
  scheduled_image_pipe_updates_.push(
      {presentation_time, std::move(image_pipe)});

  session_context_.frame_scheduler->ScheduleUpdateForSession(presentation_time,
                                                             id_);
}

Session::ApplyUpdateResult Session::ApplyScheduledUpdates(
    CommandContext* command_context, uint64_t target_presentation_time,
    uint64_t needs_render_id) {
  FXL_DCHECK(target_presentation_time >= last_presentation_time_);
  TRACE_DURATION("gfx", "Session::ApplyScheduledUpdates", "session_id", id_,
                 "session_debug_name", debug_name_, "target_presentation_time",
                 target_presentation_time);

  ApplyUpdateResult update_results{
      .success = false, .needs_render = false, .all_fences_ready = true};

  while (!scheduled_updates_.empty() &&
         scheduled_updates_.front().presentation_time <
             target_presentation_time) {
    auto& update = scheduled_updates_.front();
    FXL_DCHECK(last_applied_update_presentation_time_ <=
               update.presentation_time);

    if (!update.acquire_fences->ready()) {
      TRACE_INSTANT("gfx", "Session missed frame", TRACE_SCOPE_PROCESS,
                    "session_id", id(), "session_debug_name", debug_name_,
                    "target presentation time", target_presentation_time,
                    "session target presentation time",
                    scheduled_updates_.front().presentation_time);
      update_results.all_fences_ready = false;
      break;
    }

    ++applied_update_count_;
    TRACE_FLOW_END("gfx", "scheduled_update",
                   SESSION_TRACE_ID(id_, applied_update_count_));

    if (!ApplyUpdate(command_context, std::move(update.commands))) {
      // An error was encountered while applying the update.
      FXL_LOG(WARNING) << "scenic_impl::gfx::Session::ApplyScheduledUpdates(): "
                          "An error was encountered while applying the update. "
                          "Initiating teardown.";
      update_results.success = false;
      scheduled_updates_ = {};
      return update_results;
    }

    for (size_t i = 0; i < fences_to_release_on_next_update_.size(); ++i) {
      session_context_.release_fence_signaller->AddCPUReleaseFence(
          std::move(fences_to_release_on_next_update_.at(i)));
    }
    fences_to_release_on_next_update_ = std::move(update.release_fences);

    last_applied_update_presentation_time_ = update.presentation_time;
    // Collect callbacks to be signalled in
    // |Engine::SignalSuccessfulPresentCallbacks|
    update_results.callbacks.push(std::move(update.present_callback));
    update_results.needs_render = true;
    scheduled_updates_.pop();

    // TODO(SCN-1202): gather statistics about how close the actual
    // presentation_time was to the requested time.
    inspect_last_applied_requested_presentation_time_.Set(
        last_applied_update_presentation_time_);
    inspect_last_applied_target_presentation_time_.Set(
        target_presentation_time);
    inspect_resource_count_.Set(resource_count_);
  }

  // TODO(SCN-1219): Unify with other session updates.
  std::unordered_map<ResourceId, ImagePipePtr> image_pipe_updates_to_upload;
  while (!scheduled_image_pipe_updates_.empty() &&
         scheduled_image_pipe_updates_.top().presentation_time <=
             target_presentation_time) {
    auto& update = scheduled_image_pipe_updates_.top();
    if (update.image_pipe) {
      auto image_pipe_update_results = update.image_pipe->Update(
          session_context_.release_fence_signaller, target_presentation_time);

      // Collect callbacks to be signalled in
      // |Engine::SignalSuccessfulPresentCallbacks|
      while (!image_pipe_update_results.callbacks.empty()) {
        update_results.image_pipe_callbacks.push(
            std::move(image_pipe_update_results.callbacks.front()));
        image_pipe_update_results.callbacks.pop();
      }

      // Only upload images that were updated and are currently dirty, and only
      // do one upload per ImagePipe.
      if (image_pipe_update_results.image_updated) {
        image_pipe_updates_to_upload.try_emplace(update.image_pipe->id(),
                                                 std::move(update.image_pipe));
      }
    }
    scheduled_image_pipe_updates_.pop();
  }

  // Stage GPU uploads for the latest dirty image on each updated ImagePipe.
  for (const auto& entry : image_pipe_updates_to_upload) {
    ImagePipePtr image_pipe = entry.second;
    image_pipe->UpdateEscherImage(command_context->batch_gpu_uploader());
    // Image was updated so the image in the scene is dirty.
    update_results.needs_render = true;
  }
  image_pipe_updates_to_upload.clear();

  if (update_results.needs_render) {
    TRACE_FLOW_BEGIN("gfx", "needs_render", needs_render_id);
  }

  update_results.success = true;
  return update_results;
}

void Session::EnqueueEvent(::fuchsia::ui::gfx::Event event) {
  event_reporter_->EnqueueEvent(std::move(event));
}

void Session::EnqueueEvent(::fuchsia::ui::input::InputEvent event) {
  event_reporter_->EnqueueEvent(std::move(event));
}

bool Session::SetRootView(fxl::WeakPtr<View> view) {
  // Check that the root view ID is being set or being cleared. If there is
  // already a root view, another cannot be set.
  if (root_view_) {
    return false;
  }

  root_view_ = view;
  return true;
}

bool Session::ApplyUpdate(CommandContext* command_context,
                          std::vector<::fuchsia::ui::gfx::Command> commands) {
  TRACE_DURATION("gfx", "Session::ApplyUpdate");
  for (auto& command : commands) {
    if (!ApplyCommand(command_context, std::move(command))) {
      error_reporter_->ERROR() << "scenic_impl::gfx::Session::ApplyCommand() "
                                  "failed to apply Command: "
                               << command;
      return false;
    }
  }
  return true;
  // TODO: acquire_fences and release_fences should be added to a list that is
  // consumed by the FrameScheduler.
}

}  // namespace gfx
}  // namespace scenic_impl
