// Copyright 2022 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 "src/embedder/software_surface.h"

#include <fuchsia/sysmem/cpp/fidl.h>
#include <lib/async/default.h>
#include <lib/syslog/global.h>
#include <lib/ui/scenic/cpp/commands.h>
#include <zircon/rights.h>
#include <zircon/status.h>
#include <zircon/types.h>

#include <cmath>

#include "src/embedder/logging.h"

namespace embedder {

namespace {

uint32_t BytesPerRow(const fuchsia::sysmem::SingleBufferSettings& settings,
                     uint32_t bytes_per_pixel, uint32_t image_width) {
  const uint32_t bytes_per_row_divisor = settings.image_format_constraints.bytes_per_row_divisor;
  const uint32_t min_bytes_per_row = settings.image_format_constraints.min_bytes_per_row;
  const uint32_t unrounded_bytes_per_row =
      std::max(image_width * bytes_per_pixel, min_bytes_per_row);
  const uint32_t roundup_bytes = unrounded_bytes_per_row % bytes_per_row_divisor;

  return unrounded_bytes_per_row + roundup_bytes;
}

}  // namespace

SoftwareSurface::SoftwareSurface(fuchsia::sysmem::AllocatorSyncPtr& sysmem_allocator,
                                 fuchsia::ui::composition::AllocatorPtr& flatland_allocator,
                                 const Size size)
    : wait_for_read_finished_(this) {
  if (!flatland_allocator.is_bound()) {
    FX_LOG(FATAL, kLogTag,
           "fuchsia.ui.composition.Allocator must be bound before creating "
           "SoftwareSurface");
    return;
  }

  if (!AcquireSurface(sysmem_allocator, flatland_allocator, size)) {
    FX_LOG(ERROR, kLogTag, "Could not create render surface.");
    return;
  }

  if (!CreateFences()) {
    FX_LOG(ERROR, kLogTag, "Could not create signal fences.");
    return;
  }

  wait_for_read_finished_.set_object(release_event_.get());
  wait_for_read_finished_.set_trigger(ZX_EVENT_SIGNALED);
  Reset();

  valid_ = true;
}

SoftwareSurface::~SoftwareSurface() {
  release_image_callback_();
  wait_for_read_finished_.Cancel();
  wait_for_read_finished_.set_object(ZX_HANDLE_INVALID);
}

bool SoftwareSurface::CreateFences() {
  if (zx::event::create(0, &acquire_event_) != ZX_OK) {
    FX_LOG(ERROR, kLogTag, "Failed to create acquire event.");
    return false;
  }

  if (zx::event::create(0, &release_event_) != ZX_OK) {
    FX_LOG(ERROR, kLogTag, "Failed to create release event.");
    return false;
  }

  return true;
}

bool SoftwareSurface::AcquireSurface(fuchsia::sysmem::AllocatorSyncPtr& sysmem_allocator,
                                     fuchsia::ui::composition::AllocatorPtr& flatland_allocator,
                                     const Size size) {
  // Verify args.
  // TODO(akbiggs): Fix race that's making this fail randomly.
  const uint32_t width = size.width;
  const uint32_t height = size.height;
  if (width <= 0 || height <= 0) {
    FX_LOG(ERROR, kLogTag, "Failed to allocate surface, size is empty.");
    return false;
  }

  // Allocate a "local" sysmem token to represent Flutter's handle to the
  // sysmem buffer.
  fuchsia::sysmem::BufferCollectionTokenSyncPtr local_token;
  zx_status_t status = sysmem_allocator->AllocateSharedCollection(local_token.NewRequest());
  if (status != ZX_OK) {
    FX_LOGF(ERROR, kLogTag, "Failed to allocate collection: %s", zx_status_get_string(status));
    return false;
  }

  // Create a single duplicate of the token and sync it; the single
  // duplicate token represents Flatland's handle to the sysmem buffer
  // collection.
  std::vector<fuchsia::sysmem::BufferCollectionTokenHandle> duplicate_tokens;
  status =
      local_token->DuplicateSync(std::vector<zx_rights_t>{ZX_RIGHT_SAME_RIGHTS}, &duplicate_tokens);
  if (status != ZX_OK) {
    FX_LOGF(ERROR, kLogTag, "Failed to duplicate collection token: %s",
            zx_status_get_string(status));
    return false;
  }
  if (duplicate_tokens.size() != 1u) {
    FX_LOG(ERROR, kLogTag,
           "Failed to duplicate collection token: Incorrect number of "
           "tokens returned");
    return false;
  }
  auto buffer_collection_token = std::move(duplicate_tokens[0]);

  // Create a token pair (export and import token) for Flatland.
  // The export token is Flatland's token for the surface,
  // representing the surface in Flatland.
  // The import token is our token for the surface, letting
  // us tell Flatland to present that surface.
  fuchsia::ui::composition::BufferCollectionExportToken export_token;
  fuchsia::ui::composition::BufferCollectionImportToken import_token;
  status = zx::eventpair::create(0, &export_token.value, &import_token.value);
  if (status != ZX_OK) {
    FX_LOGF(ERROR, kLogTag, "Failed to create Flatland token pair: %s",
            zx_status_get_string(status));
    return false;
  }
  import_token_ = std::move(import_token);

  fuchsia::ui::composition::RegisterBufferCollectionArgs args;
  args.set_export_token(std::move(export_token));
  args.set_buffer_collection_token(std::move(buffer_collection_token));
  args.set_usage(fuchsia::ui::composition::RegisterBufferCollectionUsage::DEFAULT);
  flatland_allocator->RegisterBufferCollection(
      std::move(args),
      [](fuchsia::ui::composition::Allocator_RegisterBufferCollection_Result result) {
        if (result.is_err()) {
          FX_LOGF(ERROR, kLogTag,
                  "RegisterBufferCollection call to Flatland Allocator failed. "
                  "RegisterBufferCollectionError value: %d",
                  static_cast<int>(result.err()));
        }
      });

  width_ = width;
  height_ = height;

  // Acquire Flutter's local handle to the sysmem buffer.
  fuchsia::sysmem::BufferCollectionSyncPtr buffer_collection;
  status = sysmem_allocator->BindSharedCollection(std::move(local_token),
                                                  buffer_collection.NewRequest());
  if (status != ZX_OK) {
    FX_LOGF(ERROR, kLogTag, "Failed to bind collection token: %s", zx_status_get_string(status));
    return false;
  }

  // Set Flutter's constraints on the sysmem buffer.  Software rendering
  // only requires CPU access to the surface and a basic R8G8B8A8 pixel
  // format.
  fuchsia::sysmem::BufferCollectionConstraints constraints;
  constraints.min_buffer_count = 1;
  constraints.usage.cpu = fuchsia::sysmem::cpuUsageWrite | fuchsia::sysmem::cpuUsageWriteOften;
  constraints.has_buffer_memory_constraints = true;
  constraints.buffer_memory_constraints.physically_contiguous_required = false;
  constraints.buffer_memory_constraints.secure_required = false;
  constraints.buffer_memory_constraints.ram_domain_supported = true;
  constraints.buffer_memory_constraints.cpu_domain_supported = true;
  constraints.buffer_memory_constraints.inaccessible_domain_supported = false;
  constraints.image_format_constraints_count = 1;
  fuchsia::sysmem::ImageFormatConstraints& image_constraints =
      constraints.image_format_constraints[0];
  image_constraints = fuchsia::sysmem::ImageFormatConstraints();
  image_constraints.min_coded_width = static_cast<uint32_t>(width);
  image_constraints.min_coded_height = static_cast<uint32_t>(height);
  image_constraints.min_bytes_per_row = static_cast<uint32_t>(width) * 4;
  image_constraints.pixel_format.type = fuchsia::sysmem::PixelFormatType::R8G8B8A8;
  image_constraints.color_spaces_count = 1;
  image_constraints.color_space[0].type = fuchsia::sysmem::ColorSpaceType::SRGB;
  image_constraints.pixel_format.has_format_modifier = true;
  image_constraints.pixel_format.format_modifier.value = fuchsia::sysmem::FORMAT_MODIFIER_LINEAR;
  status = buffer_collection->SetConstraints(true, constraints);
  if (status != ZX_OK) {
    FX_LOGF(ERROR, kLogTag, "Failed to set constraints: %s", zx_status_get_string(status));
    return false;
  }

  // Wait for sysmem to allocate, now that constraints are set.
  fuchsia::sysmem::BufferCollectionInfo_2 buffer_collection_info;
  zx_status_t allocation_status = ZX_OK;
  zx_status_t wait_for_allocated_status =
      buffer_collection->WaitForBuffersAllocated(&allocation_status, &buffer_collection_info);
  if (allocation_status != ZX_OK) {
    FX_LOGF(ERROR, kLogTag, "Failed to allocate: %s", zx_status_get_string(allocation_status));
    return false;
  }
  if (wait_for_allocated_status != ZX_OK) {
    FX_LOGF(ERROR, kLogTag, "Failed to wait for allocate: %s",
            zx_status_get_string(wait_for_allocated_status));
    return false;
  }

  if (buffer_collection_info.settings.buffer_settings.size_bytes == 0) {
    FX_LOG(ERROR, kLogTag,
           "Allocating the software surface succeeded but created an empty "
           "buffer. This could indicate an internal bug.");
    return false;
  }
  if (buffer_collection_info.buffers[0].vmo == ZX_HANDLE_INVALID) {
    FX_LOG(ERROR, kLogTag,
           "Allocating the software surface succeeded but returned an invalid "
           "VMO. This could indicate an internal bug.");
    return false;
  }

  // Cache the allocated surface VMO and metadata.
  //
  // TODO(akbiggs): Signal cache clean using this data.
  // See
  // https://github.com/flutter/engine/blob/main/shell/platform/fuchsia/flutter/software_surface.cc#L383.
  vmo_ = std::move(buffer_collection_info.buffers[0].vmo);
  size_bytes_ = buffer_collection_info.settings.buffer_settings.size_bytes;
  if (buffer_collection_info.settings.buffer_settings.coherency_domain ==
      fuchsia::sysmem::CoherencyDomain::RAM) {
    // RAM coherency domain requires a cache clean when writes are
    // finished.
    needs_cache_clean_ = true;
  }

  // Map the allocated buffer to the CPU.
  uint8_t* vmo_base = nullptr;
  status = zx::vmar::root_self()->map(ZX_VM_PERM_WRITE | ZX_VM_PERM_READ /* options */,
                                      0 /* vmar_offset */, vmo_, 0 /* vmo_offset */, size_bytes_,
                                      reinterpret_cast<uintptr_t*>(&vmo_base) /* mapped_addr */);
  if (status != ZX_OK) {
    FX_LOGF(ERROR, kLogTag, "Failed to map buffer memory: %s", zx_status_get_string(status));
    return false;
  }

  // Now that the buffer is CPU-readable, it's safe to discard Flutter's
  // connection to sysmem.
  status = buffer_collection->Close();
  if (status != ZX_OK) {
    FX_LOGF(ERROR, kLogTag, "Failed to close buffer: %s", zx_status_get_string(status));
    return false;
  }

  const uint64_t vmo_offset = buffer_collection_info.buffers[0].vmo_usable_start;
  bytes_per_row_ = BytesPerRow(buffer_collection_info.settings, 4u /* bytes_per_pixel */, width);
  allocation_ = vmo_base + vmo_offset;

  return true;
}

void SoftwareSurface::SetImageId(uint32_t image_id) {
  if (image_id_ != 0) {
    FX_LOGF(FATAL, kLogTag,
            "Trying to set SoftwareSurface image ID to %d but it has already "
            "been set to %d",
            image_id, image_id_);
    return;
  }
  image_id_ = image_id;
}

uint32_t SoftwareSurface::GetImageId() const { return image_id_; }

Size SoftwareSurface::GetSize() const {
  if (!IsValid()) {
    FX_LOG(ERROR, kLogTag, "Tried to get size of invalid surface. Returning (0, 0).");
    return {.width = 0, .height = 0};
  }
  return {.width = width_, .height = height_};
}

fuchsia::ui::composition::BufferCollectionImportToken
SoftwareSurface::GetBufferCollectionImportToken() {
  fuchsia::ui::composition::BufferCollectionImportToken import_dup;
  import_token_.value.duplicate(ZX_RIGHT_SAME_RIGHTS, &import_dup.value);
  return import_dup;
}

zx::event SoftwareSurface::GetAcquireFence() {
  zx::event fence;
  acquire_event_.duplicate(ZX_RIGHT_SAME_RIGHTS, &fence);
  return fence;
}

zx::event SoftwareSurface::GetReleaseFence() {
  zx::event fence;
  release_event_.duplicate(ZX_RIGHT_SAME_RIGHTS, &fence);
  return fence;
}

void SoftwareSurface::SetReleaseImageCallback(ReleaseImageCallback release_image_callback) {
  release_image_callback_ = release_image_callback;
}

void SoftwareSurface::SignalWritesFinished(const std::function<void(void)>& on_read_finished) {
  if (!IsValid()) {
    on_read_finished();
    return;
  }

  if (read_finished_callback_ != nullptr) {
    // Commented out until we figure out why this is being triggered. It's spamming the logs.
    // FX_LOG(ERROR, kLogTag,
    //        "Attempted to signal a write on the surface when the "
    //        "previous write has not yet been acknowledged by the "
    //        "compositor.");
    return;
  }
  read_finished_callback_ = on_read_finished;

  // Sysmem *may* require the cache to be cleared after writes to the surface
  // are complete.
  if (needs_cache_clean_) {
    vmo_.op_range(ZX_VMO_OP_CACHE_CLEAN, 0, size_bytes_, nullptr /* buffer */, 0 /* buffer_size */);
  }

  // Inform Scenic that Flutter is finished writing to the surface.
  zx_status_t status = acquire_event_.signal(0u, ZX_EVENT_SIGNALED);
  if (status != ZX_OK) {
    FX_LOGF(ERROR, kLogTag, "Failed to signal acquire event: %s", zx_status_get_string(status));
  }
}

void SoftwareSurface::Reset() {
  if (acquire_event_.signal(ZX_EVENT_SIGNALED, 0u) != ZX_OK ||
      release_event_.signal(ZX_EVENT_SIGNALED, 0u) != ZX_OK) {
    valid_ = false;
    FX_LOG(ERROR, kLogTag, "Could not reset fences. The surface is no longer valid.");
  }

  wait_for_read_finished_.Begin(async_get_default_dispatcher());

  // It is safe for the caller to collect the surface in the callback.
  auto callback = read_finished_callback_;
  read_finished_callback_ = nullptr;
  if (callback) {
    callback();
  }
}

void SoftwareSurface::OnReadFinished(async_dispatcher_t* dispatcher, async::WaitBase* wait,
                                     zx_status_t status, const zx_packet_signal_t* signal) {
  if (status != ZX_OK) {
    return;
  }
  // Validate that we were actually signalled before calling this.
  if (!(signal->observed & ZX_EVENT_SIGNALED)) {
    FX_LOG(ERROR, kLogTag, "SoftwareSurface::OnReadFinished called without a signal.");
  }

  Reset();
}

bool SoftwareSurface::IsValid() const { return valid_; }

uint8_t* SoftwareSurface::GetAllocation() const { return allocation_; }

uint32_t SoftwareSurface::GetBytesPerRow() const { return bytes_per_row_; }

}  // namespace embedder
