// 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/scenic/resources/host_image.h"

#include "garnet/lib/ui/scenic/engine/session.h"
#include "garnet/lib/ui/scenic/resources/gpu_memory.h"
#include "garnet/lib/ui/scenic/resources/host_memory.h"
#include "lib/escher/util/image_utils.h"
#include "lib/escher/util/image_formats.h"

namespace scene_manager {

const ResourceTypeInfo HostImage::kTypeInfo = {
    ResourceType::kHostImage | ResourceType::kImage | ResourceType::kImageBase,
    "HostImage"};

HostImage::HostImage(Session* session,
                     scenic::ResourceId id,
                     HostMemoryPtr memory,
                     escher::ImagePtr gpu_image,
                     uint64_t host_memory_offset,
                     scenic::ImageInfo host_image_format)
    : Image(session, id, HostImage::kTypeInfo),
      memory_(std::move(memory)),
      memory_offset_(host_memory_offset),
      host_image_format_(host_image_format) {
  image_ = std::move(gpu_image);
  image_conversion_function_ =
      escher::image_formats::GetConversionFunction(host_image_format);
}

ImagePtr HostImage::New(Session* session,
                        scenic::ResourceId id,
                        HostMemoryPtr host_memory,
                        const scenic::ImageInfoPtr& host_image_info,
                        uint64_t memory_offset,
                        mz::ErrorReporter* error_reporter) {
  // No matter what the incoming format, the gpu format will be BGRA:
  vk::Format gpu_image_pixel_format = vk::Format::eB8G8R8A8Unorm;
  size_t bytes_per_pixel =
      escher::image_formats::BytesPerPixel(host_image_info->pixel_format);
  size_t pixel_alignment =
      escher::image_formats::PixelAlignment(host_image_info->pixel_format);

  if (host_image_info->width <= 0) {
    error_reporter->ERROR()
        << "Image::CreateFromMemory(): width must be greater than 0.";
    return nullptr;
  }
  if (host_image_info->height <= 0) {
    error_reporter->ERROR()
        << "Image::CreateFromMemory(): height must be greater than 0.";
    return nullptr;
  }

  auto& caps = session->engine()->escher()->device()->caps();
  if (host_image_info->width > caps.max_image_width) {
    error_reporter->ERROR()
        << "Image::CreateFromMemory(): image width exceeds maximum ("
        << host_image_info->width << " vs. " << caps.max_image_width << ").";
    return nullptr;
  }
  if (host_image_info->height > caps.max_image_height) {
    error_reporter->ERROR()
        << "Image::CreateFromMemory(): image height exceeds maximum ("
        << host_image_info->height << " vs. " << caps.max_image_height << ").";
    return nullptr;
  }

  if (host_image_info->stride < host_image_info->width * bytes_per_pixel) {
    error_reporter->ERROR()
        << "Image::CreateFromMemory(): stride too small for width.";
    return nullptr;
  }
  if (host_image_info->stride % pixel_alignment != 0) {
    error_reporter->ERROR()
        << "Image::CreateFromMemory(): stride must preserve pixel alignment.";
    return nullptr;
  }
  if (host_image_info->tiling != scenic::ImageInfo::Tiling::LINEAR) {
    error_reporter->ERROR()
        << "Image::CreateFromMemory(): tiling must be LINEAR for images "
        << "created using host memory.";
    return nullptr;
  }

  size_t image_size = host_image_info->height * host_image_info->stride;
  if (memory_offset >= host_memory->size()) {
    error_reporter->ERROR()
        << "Image::CreateFromMemory(): the offset of the Image must be "
        << "within the range of the Memory";
    return nullptr;
  }

  if (memory_offset + image_size > host_memory->size()) {
    error_reporter->ERROR()
        << "Image::CreateFromMemory(): the Image must fit within the size "
        << "of the Memory";
    return nullptr;
  }

  // TODO(MZ-141): Support non-minimal strides.
  if (host_image_info->stride != host_image_info->width * bytes_per_pixel) {
    error_reporter->ERROR()
        << "Image::CreateFromMemory(): the stride must be minimal (MZ-141)";
    return nullptr;
  }

  auto escher_image = escher::image_utils::NewGpuImageFromPixels(
      session->engine()->escher_image_factory(), gpu_image_pixel_format,
      host_image_info->width, host_image_info->height);

  return fxl::AdoptRef(new HostImage(session, id, std::move(host_memory),
                                     std::move(escher_image), memory_offset,
                                     *host_image_info));
}

bool HostImage::UpdatePixels() {
  if (session()->engine()->escher_gpu_uploader()) {
    escher::image_utils::WritePixelsToImage(
        session()->engine()->escher_gpu_uploader(),
        static_cast<uint8_t*>(memory_->memory_base()) + memory_offset_, image_,
        image_conversion_function_);
    return true;
  }
  return false;
}

ImagePtr HostImage::NewForTesting(Session* session,
                                  scenic::ResourceId id,
                                  escher::ResourceManager* image_owner,
                                  HostMemoryPtr host_memory) {
  escher::ImagePtr escher_image = escher::Image::New(
      image_owner, escher::ImageInfo(), vk::Image(), nullptr);
  FXL_CHECK(escher_image);
  scenic::ImageInfo host_image_format;
  host_image_format.pixel_format = scenic::ImageInfo::PixelFormat::BGRA_8;
  return fxl::AdoptRef(new HostImage(session, id, host_memory, escher_image, 0,
                                     host_image_format));
}

}  // namespace scene_manager
