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

#include <lib/async/default.h>
#include <lib/ui/scenic/cpp/commands.h>
#include <zircon/status.h>
#include <zircon/types.h>

#include <cmath>

#include "flutter/fml/logging.h"
#include "flutter/fml/trace_event.h"
#include "fuchsia/sysmem/cpp/fidl.h"
#include "include/core/SkImageInfo.h"
#include "third_party/skia/include/core/SkColorSpace.h"
#include "third_party/skia/include/core/SkImageInfo.h"

#include "../runtime/dart/utils/inlines.h"

namespace flutter_runner {

namespace {

constexpr SkColorType kSkiaColorType = kRGBA_8888_SkColorType;

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

uint32_t SoftwareSurface::sNextBufferId = 1;  // 0 is invalid; start at 1.

SoftwareSurface::SoftwareSurface(
    fuchsia::sysmem::AllocatorSyncPtr& sysmem_allocator,
    fuchsia::ui::composition::AllocatorPtr& flatland_allocator,
    scenic::Session* session,
    const SkISize& size)
    : session_(session), wait_for_surface_read_finished_(this) {
  FML_CHECK((session_ || flatland_allocator.is_bound()) &&
            !(session_ && flatland_allocator.is_bound()));

  if (!SetupSkiaSurface(sysmem_allocator, flatland_allocator, size)) {
    FML_LOG(ERROR) << "Could not create render surface.";
    return;
  }

  if (!CreateFences()) {
    FML_LOG(ERROR) << "Could not create signal fences.";
    return;
  }

  if (session) {
    if (image_id_ == 0) {
      image_id_ = session->AllocResourceId();
    }
    session->Enqueue(scenic::NewCreateImage2Cmd(
        image_id_, sk_surface_->width(), sk_surface_->height(), buffer_id_, 0));
  }

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

  valid_ = true;
}

SoftwareSurface::~SoftwareSurface() {
  if (session_) {
    if (image_id_) {
      session_->Enqueue(scenic::NewReleaseResourceCmd(image_id_));
    }
    if (buffer_id_) {
      session_->DeregisterBufferCollection(buffer_id_);
    }
  } else {
    release_image_callback_();
  }
  wait_for_surface_read_finished_.Cancel();
  wait_for_surface_read_finished_.set_object(ZX_HANDLE_INVALID);
}

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

SkISize SoftwareSurface::GetSize() const {
  if (!valid_) {
    return SkISize::Make(0, 0);
  }

  return SkISize::Make(sk_surface_->width(), sk_surface_->height());
}

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

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

  return true;
}

bool SoftwareSurface::SetupSkiaSurface(
    fuchsia::sysmem::AllocatorSyncPtr& sysmem_allocator,
    fuchsia::ui::composition::AllocatorPtr& flatland_allocator,
    const SkISize& size) {
  if (size.isEmpty()) {
    FML_LOG(ERROR) << "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 allocate_status =
      sysmem_allocator->AllocateSharedCollection(local_token.NewRequest());
  if (allocate_status != ZX_OK) {
    FML_LOG(ERROR) << "Failed to allocate collection: "
                   << zx_status_get_string(allocate_status);
    return false;
  }

  // Create a single Duplicate of the token and Sync it; the single duplicate
  // token represents scenic's handle to the sysmem buffer.
  std::vector<fuchsia::sysmem::BufferCollectionTokenHandle> duplicate_tokens;
  zx_status_t duplicate_status = local_token->DuplicateSync(
      std::vector<zx::rights>{zx::rights::SAME_RIGHTS}, &duplicate_tokens);
  if (duplicate_status != ZX_OK) {
    FML_LOG(ERROR) << "Failed to duplicate collection token: "
                   << zx_status_get_string(duplicate_status);
    return false;
  }
  if (duplicate_tokens.size() != 1u) {
    FML_LOG(ERROR) << "Failed to duplicate collection token: Incorrect number "
                      "of tokens returned.";
    return false;
  }
  auto scenic_token = std::move(duplicate_tokens[0]);

  // Register the sysmem token with flatland (or scenic's legacy gfx interface).
  //
  // This binds the sysmem token to a composition token, which is used later
  // to associate the rendering surface with a specific flatland Image.
  //
  // Under gfx, scenic uses an integral `buffer_id` instead of the composition
  // token.
  if (session_) {
    buffer_id_ = sNextBufferId++;
    session_->RegisterBufferCollection(buffer_id_, std::move(scenic_token));
  } else {
    fuchsia::ui::composition::BufferCollectionExportToken export_token;
    zx_status_t token_create_status =
        zx::eventpair::create(0, &export_token.value, &import_token_.value);
    if (token_create_status != ZX_OK) {
      FML_LOG(ERROR) << "Failed to create flatland export token: "
                     << zx_status_get_string(token_create_status);
      return false;
    }

    fuchsia::ui::composition::RegisterBufferCollectionArgs args;
    args.set_export_token(std::move(export_token));
    args.set_buffer_collection_token(std::move(scenic_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()) {
            FML_LOG(ERROR)
                << "RegisterBufferCollection call to Scenic Allocator failed.";
          }
        });
  }

  // Acquire flutter's local handle to the sysmem buffer.
  fuchsia::sysmem::BufferCollectionSyncPtr buffer_collection;
  zx_status_t bind_status = sysmem_allocator->BindSharedCollection(
      std::move(local_token), buffer_collection.NewRequest());
  if (bind_status != ZX_OK) {
    FML_LOG(ERROR) << "Failed to bind collection token: "
                   << zx_status_get_string(bind_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>(size.fWidth);
  image_constraints.min_coded_height = static_cast<uint32_t>(size.fHeight);
  image_constraints.min_bytes_per_row = static_cast<uint32_t>(size.fWidth) * 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;
  zx_status_t set_constraints_status =
      buffer_collection->SetConstraints(true, constraints);
  if (set_constraints_status != ZX_OK) {
    FML_LOG(ERROR) << "Failed to set constraints: "
                   << zx_status_get_string(set_constraints_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) {
    FML_LOG(ERROR) << "Failed to allocate: "
                   << zx_status_get_string(allocation_status);
    return false;
  }
  if (wait_for_allocated_status != ZX_OK) {
    FML_LOG(ERROR) << "Failed to wait for allocate: "
                   << zx_status_get_string(wait_for_allocated_status);
    return false;
  }

  // Cache the allocated surface VMO and metadata.
  FML_CHECK(buffer_collection_info.settings.buffer_settings.size_bytes != 0);
  FML_CHECK(buffer_collection_info.buffers[0].vmo != ZX_HANDLE_INVALID);
  surface_vmo_ = std::move(buffer_collection_info.buffers[0].vmo);
  surface_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;
  zx_status_t buffer_map_status = zx::vmar::root_self()->map(
      ZX_VM_PERM_WRITE | ZX_VM_PERM_READ, 0, surface_vmo_, 0,
      surface_size_bytes_, reinterpret_cast<uintptr_t*>(&vmo_base));
  if (buffer_map_status != ZX_OK) {
    FML_LOG(ERROR) << "Failed to map buffer memory: "
                   << zx_status_get_string(buffer_map_status);
    return false;
  }

  // Now that the buffer is CPU-readable, it's safe to discard flutter's
  // connection to sysmem.
  zx_status_t close_status = buffer_collection->Close();
  if (close_status != ZX_OK) {
    FML_LOG(ERROR) << "Failed to close buffer: "
                   << zx_status_get_string(close_status);
    return false;
  }

  // Wrap the buffer in a software-rendered Skia surface.
  const uint64_t vmo_offset =
      buffer_collection_info.buffers[0].vmo_usable_start;
  const size_t vmo_stride =
      BytesPerRow(buffer_collection_info.settings, 4u, size.width());
  SkSurfaceProps sk_surface_props(0, kUnknown_SkPixelGeometry);
  sk_surface_ = SkSurface::MakeRasterDirect(
      SkImageInfo::Make(size, kSkiaColorType, kPremul_SkAlphaType,
                        SkColorSpace::MakeSRGB()),
      vmo_base + vmo_offset, vmo_stride, &sk_surface_props);
  if (!sk_surface_ || sk_surface_->getCanvas() == nullptr) {
    FML_LOG(ERROR) << "SkSurface::MakeRasterDirect failed.";
    return false;
  }

  return true;
}

void SoftwareSurface::SetImageId(uint32_t image_id) {
  FML_CHECK(image_id_ == 0);
  FML_CHECK(!session_);
  image_id_ = image_id;
}

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

sk_sp<SkSurface> SoftwareSurface::GetSkiaSurface() const {
  return valid_ ? sk_surface_ : nullptr;
}

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

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

zx::event SoftwareSurface::GetReleaseFence() {
  FML_CHECK(!session_);
  zx::event fence;
  release_event_.duplicate(ZX_RIGHT_SAME_RIGHTS, &fence);
  return fence;
}
void SoftwareSurface::SetReleaseImageCallback(
    ReleaseImageCallback release_image_callback) {
  FML_CHECK(!session_);
  release_image_callback_ = release_image_callback;
}

size_t SoftwareSurface::AdvanceAndGetAge() {
  return ++age_;
}

bool SoftwareSurface::FlushSessionAcquireAndReleaseEvents() {
  if (session_) {
    zx::event acquire, release;
    if (acquire_event_.duplicate(ZX_RIGHT_SAME_RIGHTS, &acquire) != ZX_OK ||
        release_event_.duplicate(ZX_RIGHT_SAME_RIGHTS, &release) != ZX_OK) {
      return false;
    }
    session_->EnqueueAcquireFence(std::move(acquire));
    session_->EnqueueReleaseFence(std::move(release));
  }

  age_ = 0;
  return true;
}

void SoftwareSurface::SignalWritesFinished(
    const std::function<void(void)>& on_surface_read_finished) {
  FML_CHECK(on_surface_read_finished);

  if (!valid_) {
    on_surface_read_finished();
    return;
  }

  dart_utils::Check(surface_read_finished_callback_ == nullptr,
                    "Attempted to signal a write on the surface when the "
                    "previous write has not yet been acknowledged by the "
                    "compositor.");
  surface_read_finished_callback_ = on_surface_read_finished;

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

  // Inform scenic that flutter is finished writing to the surface.
  zx_status_t signal_status = acquire_event_.signal(0u, ZX_EVENT_SIGNALED);
  if (signal_status != ZX_OK) {
    FML_LOG(ERROR) << "Failed to signal acquire event; "
                   << zx_status_get_string(signal_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;
    FML_LOG(ERROR) << "Could not reset fences. The surface is no longer valid.";
  }

  wait_for_surface_read_finished_.Begin(async_get_default_dispatcher());

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

void SoftwareSurface::OnSurfaceReadFinished(async_dispatcher_t* dispatcher,
                                            async::WaitBase* wait,
                                            zx_status_t status,
                                            const zx_packet_signal_t* signal) {
  if (status != ZX_OK) {
    return;
  }
  FML_DCHECK(signal->observed & ZX_EVENT_SIGNALED);

  Reset();
}

}  // namespace flutter_runner
