// 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/swapchain/display_swapchain.h"

#include <trace/event.h>

#include "garnet/lib/ui/gfx/displays/display.h"
#include "garnet/lib/ui/gfx/displays/display_manager.h"
#include "garnet/lib/ui/gfx/engine/frame_timings.h"

#include "lib/escher/escher.h"
#include "lib/escher/flib/fence.h"
#include "lib/escher/impl/naive_image.h"
#include "lib/escher/util/fuchsia_utils.h"
#include "lib/escher/util/image_utils.h"
#include "lib/escher/vk/gpu_mem.h"

namespace scenic_impl {
namespace gfx {

namespace {

#define VK_CHECK_RESULT(XXX) FXL_CHECK(XXX.result == vk::Result::eSuccess)

// TODO(MZ-400): Don't triple buffer.  This is done to avoid "tearing", but it
// wastes memory, and can result in the "permanent" addition of an extra Vsync
// period of latency.  An alternative would be to use an acquire fence; this
// saves memory, but can still result in the permanent extra latency.  Here's
// how:
//
// First, let's see how tearing occurs in the 2-framebuffer case.
//
// Let's say we have framebuffers A and B in a world that conveniently starts at
// some negative time, such that the first frame rendered into A has a target
// presentation time of 0ms, and the next frame is rendered into B with a target
// presentation time of 16ms.
//
// However, assume that frame being rendered into A takes a bit too long, so
// that instead of being presented at 0ms, it is instead presented at 16ms.  The
// frame to render into B has already been scheduled, and starts rendering at
// 8ms to hit the target presentation time of 16ms.  Even if it's fast, it
// cannot present at 16ms, because that frame has already been "claimed" by A,
// and so it is instead presented at 32ms.
//
// The tearing occurs when it is time to render A again.  We don't know that B
// has been deferred to present at 32ms.  So, we wake up at 24ms to render into
// A to hit the 32ms target.  Oops!
//
// The problem is that A is still being displayed from 16-32ms, until it is
// replaced by B at 32ms.  Thus, tearing.
//
// If you followed that, it should be clear both why triple-buffering fixes the
// tearing, and why it adds the frame of latency.
const uint32_t kSwapchainImageCount = 3;

// Helper functions

// Enumerate the formats supported for the specified surface/device, and pick a
// suitable one.
vk::Format GetDisplayImageFormat(escher::VulkanDeviceQueues* device_queues);

// Determines if the VK_GOOGLE_IMAGE_USAGE_SCANOUT_EXTENSION is supported.
vk::ImageUsageFlags GetFramebufferImageUsage();

}  // namespace

DisplaySwapchain::DisplaySwapchain(DisplayManager* display_manager,
                                   Display* display,
                                   EventTimestamper* timestamper,
                                   escher::Escher* escher)
    : escher_(escher),
      display_manager_(display_manager),
      display_(display),
      timestamper_(timestamper) {
  FXL_DCHECK(display);
  FXL_DCHECK(timestamper);

  if (escher_) {
    device_ = escher_->vk_device();
    queue_ = escher_->device()->vk_main_queue();
    format_ = GetDisplayImageFormat(escher->device());

    display_->Claim();

    frames_.resize(kSwapchainImageCount);

    if (!InitializeFramebuffers(escher_->resource_recycler())) {
      FXL_LOG(ERROR) << "Initializing buffers for display swapchain failed.";
    }
  } else {
    device_ = vk::Device();
    queue_ = vk::Queue();
    format_ = vk::Format::eUndefined;

    display_->Claim();

    FXL_VLOG(2) << "Using a NULL escher in DisplaySwapchain; likely in a test.";
  }
}

bool DisplaySwapchain::InitializeFramebuffers(
    escher::ResourceRecycler* resource_recycler) {
  FXL_CHECK(escher_);
  vk::ImageUsageFlags image_usage = GetFramebufferImageUsage();

#if !defined(__aarch64__) && !defined(__x86_64__)
  FXL_DLOG(ERROR) << "Display swapchain only supported on intel and arm";
  return false;
#endif

  const uint32_t width_in_px = display_->width_in_px();
  const uint32_t height_in_px = display_->height_in_px();
  zx_pixel_format_t pixel_format;
#if defined(__aarch64__)
  pixel_format = ZX_PIXEL_FORMAT_RGB_x888;
#else
  pixel_format = ZX_PIXEL_FORMAT_ARGB_8888;
#endif

  display_manager_->SetImageConfig(width_in_px, height_in_px, pixel_format);
  for (uint32_t i = 0; i < kSwapchainImageCount; i++) {
    // Allocate a framebuffer.

    // Start by creating a VkImage.
    // TODO(ES-42): Create this using Escher APIs.
    vk::ImageCreateInfo create_info;
    create_info.imageType = vk::ImageType::e2D, create_info.format = format_;
    create_info.extent = vk::Extent3D{width_in_px, height_in_px, 1};
    create_info.mipLevels = 1;
    create_info.arrayLayers = 1;
    create_info.samples = vk::SampleCountFlagBits::e1;
#if defined(__x86_64__)
    create_info.tiling = vk::ImageTiling::eOptimal;
#else
    create_info.tiling = vk::ImageTiling::eLinear;
    // TODO(SCN-79): Use vulkan extension to allocate with correct stride.
    create_info.extent.width =
        display_manager_->FetchLinearStride(width_in_px, pixel_format);
#endif
    create_info.usage = image_usage;
    create_info.sharingMode = vk::SharingMode::eExclusive;
    create_info.initialLayout = vk::ImageLayout::eUndefined;

    auto image_result = device_.createImage(create_info);
    if (image_result.result != vk::Result::eSuccess) {
      FXL_LOG(ERROR) << "VkCreateImage failed: "
                     << vk::to_string(image_result.result);
      return false;
    }

    // Allocate memory to get a VkDeviceMemory.
    auto memory_requirements =
        device_.getImageMemoryRequirements(image_result.value);

    uint32_t memory_type_index = 0;

    zx::vmo memory =
        display_manager_->AllocateDisplayMemory(memory_requirements.size);
    if (!memory) {
      FXL_LOG(ERROR) << "allocating vmo failed";
      return false;
    }
    vk::ImportMemoryFuchsiaHandleInfoKHR import_info;
    import_info.setHandle(memory.release());
    import_info.setHandleType(
        vk::ExternalMemoryHandleTypeFlagBits::eFuchsiaVmoKHR);
    vk::MemoryAllocateInfo alloc_info;
    alloc_info.setPNext(&import_info);
    alloc_info.allocationSize = memory_requirements.size;
    alloc_info.memoryTypeIndex = memory_type_index;

    auto mem_result = device_.allocateMemory(alloc_info);

    if (mem_result.result != vk::Result::eSuccess) {
      FXL_LOG(ERROR) << "vkAllocMemory failed: "
                     << vk::to_string(mem_result.result);
      return false;
    }

    Framebuffer buffer;
    buffer.device_memory = escher::GpuMem::AdoptVkMemory(
        device_, mem_result.value, memory_requirements.size,
        false /* needs_mapped_ptr */);
    FXL_CHECK(buffer.device_memory);

    // Wrap the image and device memory in a escher::Image.
    escher::ImageInfo image_info;
    image_info.format = format_;
    image_info.width = width_in_px;
    image_info.height = height_in_px;
    image_info.usage = image_usage;

    // escher::NaiveImage::AdoptVkImage() binds the memory to the image.
    buffer.escher_image = escher::impl::NaiveImage::AdoptVkImage(
        resource_recycler, image_info, image_result.value,
        buffer.device_memory);

    if (!buffer.escher_image) {
      FXL_LOG(ERROR) << "Creating escher::EscherImage failed.";
      device_.destroyImage(image_result.value);
      return false;
    }

    // TODO(ES-39): Add stride to escher::ImageInfo so we can use
    // getImageSubresourceLayout to look up rowPitch and use it appropriately.
    /*vk::ImageSubresource subres;
    subres.aspectMask = vk::ImageAspectFlagBits::eColor;
    subres.mipLevel = 0;
    subres.arrayLayer = 0;
    auto layout = device_.getImageSubresourceLayout(image_result.value, subres);
    FXL_DCHECK(layout.rowPitch ==
               display_->width() *
    escher::image_utils::BytesPerPixel(format_));
    */

    // Export the vkDeviceMemory to a VMO.
    vk::MemoryGetFuchsiaHandleInfoKHR export_memory_info(
        buffer.device_memory->base(),
        vk::ExternalMemoryHandleTypeFlagBits::eFuchsiaVmoKHR);

    auto export_result =
        escher_->device()->proc_addrs().getMemoryFuchsiaHandleKHR(
            device_, export_memory_info);

    if (export_result.result != vk::Result::eSuccess) {
      FXL_LOG(ERROR) << "VkGetMemoryFuchsiaHandleKHR failed: "
                     << vk::to_string(export_result.result);
      return false;
    }

    buffer.vmo = zx::vmo(export_result.value);
    buffer.fb_id = display_manager_->ImportImage(buffer.vmo);
    if (buffer.fb_id == fuchsia::hardware::display::invalidId) {
      FXL_LOG(ERROR) << "Importing image failed.";
      return false;
    }

    swapchain_buffers_.push_back(std::move(buffer));
  }

  if (!display_manager_->EnableVsync(
          fit::bind_member(this, &DisplaySwapchain::OnVsync))) {
    FXL_LOG(ERROR) << "Failed to enable vsync";
    return false;
  }

  return true;
}

DisplaySwapchain::~DisplaySwapchain() {
  if (!escher_) {
    display_->Unclaim();
    return;
  }

  // Turn off operations.
  display_manager_->EnableVsync(nullptr);

  // A FrameRecord is now stale and will no longer receive the OnFramePresented
  // callback; OnFrameDropped will clean up and make the state consistent.
  for (size_t i = 0; i < frames_.size(); ++i) {
    const size_t idx = (i + next_frame_index_) % frames_.size();
    FrameRecord* record = frames_[idx].get();
    if (record && !record->frame_timings->finalized()) {
      record->frame_timings->OnFrameDropped(record->swapchain_index);
    }
  }

  display_->Unclaim();
  for (auto& buffer : swapchain_buffers_) {
    display_manager_->ReleaseImage(buffer.fb_id);
  }
}

std::unique_ptr<DisplaySwapchain::FrameRecord> DisplaySwapchain::NewFrameRecord(
    const FrameTimingsPtr& frame_timings) {
  FXL_DCHECK(frame_timings);
  FXL_CHECK(escher_);
  auto render_finished_escher_semaphore =
      escher::Semaphore::NewExportableSem(device_);

  zx::event render_finished_event =
      GetEventForSemaphore(escher_->device()->proc_addrs(), device_,
                           render_finished_escher_semaphore);
  uint64_t render_finished_event_id =
      display_manager_->ImportEvent(render_finished_event);

  if (!render_finished_escher_semaphore ||
      render_finished_event_id == fuchsia::hardware::display::invalidId) {
    FXL_LOG(ERROR)
        << "DisplaySwapchain::NewFrameRecord() failed to create semaphores";
    return std::unique_ptr<FrameRecord>();
  }

  zx::event retired_event;
  zx_status_t status = zx::event::create(0, &retired_event);
  if (status != ZX_OK) {
    FXL_LOG(ERROR)
        << "DisplaySwapchain::NewFrameRecord() failed to create retired event";
    return std::unique_ptr<FrameRecord>();
  }

  uint64_t retired_event_id = display_manager_->ImportEvent(retired_event);
  if (retired_event_id == fuchsia::hardware::display::invalidId) {
    FXL_LOG(ERROR)
        << "DisplaySwapchain::NewFrameRecord() failed to import retired event";
    return std::unique_ptr<FrameRecord>();
  }

  auto record = std::make_unique<FrameRecord>();
  record->frame_timings = frame_timings;
  record->swapchain_index = frame_timings->AddSwapchain(this);
  record->render_finished_escher_semaphore =
      std::move(render_finished_escher_semaphore);
  record->render_finished_event_id = render_finished_event_id;
  record->retired_event = std::move(retired_event);
  record->retired_event_id = retired_event_id;

  record->render_finished_watch = EventTimestamper::Watch(
      timestamper_, std::move(render_finished_event), escher::kFenceSignalled,
      [this, index = next_frame_index_](zx_time_t timestamp) {
        OnFrameRendered(index, timestamp);
      });

  return record;
}

bool DisplaySwapchain::DrawAndPresentFrame(const FrameTimingsPtr& frame_timings,
                                           const HardwareLayerAssignment& hla,
                                           DrawCallback draw_callback) {
  FXL_DCHECK(hla.swapchain == this);

  // Find the next framebuffer to render into, and other corresponding data.
  auto& buffer = swapchain_buffers_[next_frame_index_];

  // Create a record that can be used to notify |frame_timings| (and hence
  // ultimately the FrameScheduler) that the frame has been presented.
  //
  // There must not already exist a pending record.  If there is, it indicates
  // an error in the FrameScheduler logic (or somewhere similar), which should
  // not have scheduled another frame when there are no framebuffers available.
  if (frames_[next_frame_index_]) {
    FXL_CHECK(frames_[next_frame_index_]->frame_timings->finalized());
    if (frames_[next_frame_index_]->retired_event.wait_one(
            ZX_EVENT_SIGNALED, zx::time(), nullptr) != ZX_OK) {
      FXL_LOG(WARNING) << "DisplaySwapchain::DrawAndPresentFrame rendering "
                          "into in-use backbuffer";
    }
  }

  auto& frame_record = frames_[next_frame_index_] =
      NewFrameRecord(frame_timings);

  // TODO(MZ-244): See below.  What to do if rendering fails?
  frame_record->render_finished_watch.Start();

  next_frame_index_ = (next_frame_index_ + 1) % kSwapchainImageCount;
  outstanding_frame_count_++;

  // Render the scene.
  size_t num_hardware_layers = hla.items.size();
  // TODO(SCN-1088): handle more hardware layers.
  FXL_DCHECK(num_hardware_layers == 1);

  // TODO(SCN-1098): we'd like to validate that the layer ID is supported
  // by the display/display-controller, but the DisplayManager API doesn't
  // currently expose it, and rather than hack in an accessor for |layer_id_|
  // we should fix this "properly", whatever that means.
  // FXL_DCHECK(hla.items[0].hardware_layer_id is supported by display);
  for (size_t i = 0; i < num_hardware_layers; ++i) {
    TRACE_DURATION("gfx", "DisplaySwapchain::DrawAndPresent() draw");

    // A single semaphore is sufficient to guarantee that all images have been
    // rendered, so only provide the semaphore when rendering the image for
    // the final layer.
    escher::SemaphorePtr render_finished_escher_semaphore =
        (i + 1 == num_hardware_layers)
            ? frame_record->render_finished_escher_semaphore
            : escher::SemaphorePtr();
    // TODO(SCN-1088): handle more hardware layers: the single image from
    // buffer.escher_image is not enough; we need one for each layer.
    draw_callback(frame_timings->target_presentation_time(),
                  buffer.escher_image, hla.items[i], escher::SemaphorePtr(),
                  render_finished_escher_semaphore);
  }

  // When the image is completely rendered, present it.
  TRACE_DURATION("gfx", "DisplaySwapchain::DrawAndPresent() present");

  display_manager_->Flip(display_, buffer.fb_id,
                         frame_record->render_finished_event_id,
                         frame_record->retired_event_id);

  display_manager_->ReleaseEvent(frame_record->render_finished_event_id);
  display_manager_->ReleaseEvent(frame_record->retired_event_id);

  return true;
}

void DisplaySwapchain::OnFrameRendered(size_t frame_index,
                                       zx_time_t render_finished_time) {
  FXL_DCHECK(frame_index < kSwapchainImageCount);
  auto& record = frames_[frame_index];
  FXL_DCHECK(record);
  record->frame_timings->OnFrameRendered(record->swapchain_index,
                                         render_finished_time);
  // See ::OnVsync for comment about finalization.
}

void DisplaySwapchain::OnVsync(zx_time_t timestamp,
                               const std::vector<uint64_t>& image_ids) {
  if (image_ids.empty()) {
    return;
  }

  // Currently, only a single layer is ever used
  FXL_CHECK(image_ids.size() == 1);
  uint64_t image_id = image_ids[0];

  bool match = false;
  while (outstanding_frame_count_ && !match) {
    auto& buf = swapchain_buffers_[presented_frame_idx_];
    auto& record = frames_[presented_frame_idx_];
    match = buf.fb_id == image_id;

    // Don't double-report a frame as presented if a frame is shown twice
    // due to the next frame missing its deadline.
    if (!record->presented) {
      record->presented = true;

      if (match) {
        record->frame_timings->OnFramePresented(record->swapchain_index,
                                                timestamp);
      } else {
        record->frame_timings->OnFrameDropped(record->swapchain_index);
      }
    }

    // Retaining the currently displayed frame allows us to differentiate
    // between a frame being dropped and a frame being displayed twice
    // without having to look ahead in the queue, so only update the queue
    // when we know that the display controller has progressed to the next
    // frame.
    //
    // Since there is no guaranteed order between a frame being retired here
    // and OnFrameRendered() for a given frame, and since both must be called
    // in order for the FrameTimings to be finalzied, we don't immediately
    // destroy the FrameRecord. It will eventually be replaced by
    // DrawAndPresentFrame(), when a new frame is rendered into this index.
    if (!match) {
      presented_frame_idx_ = (presented_frame_idx_ + 1) % kSwapchainImageCount;
      outstanding_frame_count_--;
    }
  }
  FXL_DCHECK(match) << "Unhandled vsync";
}

namespace {

vk::ImageUsageFlags GetFramebufferImageUsage() {
  const std::string kGoogleImageUsageScanoutExtensionName(
      VK_GOOGLE_IMAGE_USAGE_SCANOUT_EXTENSION_NAME);
  auto instance_extensions = vk::enumerateInstanceExtensionProperties();
  if (instance_extensions.result != vk::Result::eSuccess) {
    FXL_DLOG(ERROR) << "vkEnumerateInstanceExtensionProperties failed: "
                    << vk::to_string(instance_extensions.result);
    return vk::ImageUsageFlagBits::eColorAttachment;
  }

  for (auto& extension : instance_extensions.value) {
    if (extension.extensionName == kGoogleImageUsageScanoutExtensionName) {
      return vk::ImageUsageFlagBits::eScanoutGOOGLE |
             vk::ImageUsageFlagBits::eColorAttachment;
    }
  }

  FXL_DLOG(ERROR)
      << "Unable to find optimal framebuffer image usage extension ("
      << kGoogleImageUsageScanoutExtensionName << ").";
  return vk::ImageUsageFlagBits::eColorAttachment;
}

vk::Format GetDisplayImageFormat(escher::VulkanDeviceQueues* device_queues) {
  return vk::Format::eB8G8R8A8Unorm;
}

}  // namespace

}  // namespace gfx
}  // namespace scenic_impl
