// 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 "impeller/renderer/render_target.h"

#include <sstream>

#include "impeller/base/strings.h"
#include "impeller/base/validation.h"
#include "impeller/core/allocator.h"
#include "impeller/core/formats.h"
#include "impeller/core/texture.h"
#include "impeller/core/texture_descriptor.h"
#include "impeller/renderer/context.h"

namespace impeller {

RenderTarget::RenderTarget() = default;

RenderTarget::~RenderTarget() = default;

bool RenderTarget::IsValid() const {
  // Validate that there is a color attachment at zero index.
  if (!HasColorAttachment(0u)) {
    VALIDATION_LOG
        << "Render target does not have color attachment at index 0.";
    return false;
  }

  // Validate that all attachments are of the same size.
  {
    std::optional<ISize> size;
    bool sizes_are_same = true;
    auto iterator = [&](const Attachment& attachment) -> bool {
      if (!size.has_value()) {
        size = attachment.texture->GetSize();
      }
      if (size != attachment.texture->GetSize()) {
        sizes_are_same = false;
        return false;
      }
      return true;
    };
    IterateAllAttachments(iterator);
    if (!sizes_are_same) {
      VALIDATION_LOG
          << "Sizes of all render target attachments are not the same.";
      return false;
    }
  }

  // Validate that all attachments are of the same type and sample counts.
  {
    std::optional<TextureType> texture_type;
    std::optional<SampleCount> sample_count;
    bool passes_type_validation = true;
    auto iterator = [&](const Attachment& attachment) -> bool {
      if (!texture_type.has_value() || !sample_count.has_value()) {
        texture_type = attachment.texture->GetTextureDescriptor().type;
        sample_count = attachment.texture->GetTextureDescriptor().sample_count;
      }

      if (texture_type != attachment.texture->GetTextureDescriptor().type) {
        passes_type_validation = false;
        VALIDATION_LOG << "Render target has incompatible texture types: "
                       << TextureTypeToString(texture_type.value()) << " != "
                       << TextureTypeToString(
                              attachment.texture->GetTextureDescriptor().type)
                       << " on target " << ToString();
        return false;
      }

      if (sample_count !=
          attachment.texture->GetTextureDescriptor().sample_count) {
        passes_type_validation = false;
        VALIDATION_LOG << "Render target (" << ToString()
                       << ") has incompatible sample counts.";

        return false;
      }

      return true;
    };
    IterateAllAttachments(iterator);
    if (!passes_type_validation) {
      return false;
    }
  }

  return true;
}

void RenderTarget::IterateAllAttachments(
    const std::function<bool(const Attachment& attachment)>& iterator) const {
  for (const auto& color : colors_) {
    if (!iterator(color.second)) {
      return;
    }
  }

  if (depth_.has_value()) {
    if (!iterator(depth_.value())) {
      return;
    }
  }

  if (stencil_.has_value()) {
    if (!iterator(stencil_.value())) {
      return;
    }
  }
}

SampleCount RenderTarget::GetSampleCount() const {
  if (auto found = colors_.find(0u); found != colors_.end()) {
    return found->second.texture->GetTextureDescriptor().sample_count;
  }
  return SampleCount::kCount1;
}

bool RenderTarget::HasColorAttachment(size_t index) const {
  if (auto found = colors_.find(index); found != colors_.end()) {
    return true;
  }
  return false;
}

std::optional<ISize> RenderTarget::GetColorAttachmentSize(size_t index) const {
  auto found = colors_.find(index);

  if (found == colors_.end()) {
    return std::nullopt;
  }

  return found->second.texture->GetSize();
}

ISize RenderTarget::GetRenderTargetSize() const {
  auto size = GetColorAttachmentSize(0u);
  return size.has_value() ? size.value() : ISize{};
}

std::shared_ptr<Texture> RenderTarget::GetRenderTargetTexture() const {
  auto found = colors_.find(0u);
  if (found == colors_.end()) {
    return nullptr;
  }
  return found->second.resolve_texture ? found->second.resolve_texture
                                       : found->second.texture;
}

PixelFormat RenderTarget::GetRenderTargetPixelFormat() const {
  if (auto texture = GetRenderTargetTexture(); texture != nullptr) {
    return texture->GetTextureDescriptor().format;
  }

  return PixelFormat::kUnknown;
}

size_t RenderTarget::GetMaxColorAttacmentBindIndex() const {
  size_t max = 0;
  for (const auto& color : colors_) {
    max = std::max(color.first, max);
  }
  return max;
}

RenderTarget& RenderTarget::SetColorAttachment(
    const ColorAttachment& attachment,
    size_t index) {
  if (attachment.IsValid()) {
    colors_[index] = attachment;
  }
  return *this;
}

RenderTarget& RenderTarget::SetDepthAttachment(
    std::optional<DepthAttachment> attachment) {
  if (!attachment.has_value()) {
    depth_ = std::nullopt;
  } else if (attachment->IsValid()) {
    depth_ = std::move(attachment);
  }
  return *this;
}

RenderTarget& RenderTarget::SetStencilAttachment(
    std::optional<StencilAttachment> attachment) {
  if (!attachment.has_value()) {
    stencil_ = std::nullopt;
  } else if (attachment->IsValid()) {
    stencil_ = std::move(attachment);
  }
  return *this;
}

const std::map<size_t, ColorAttachment>& RenderTarget::GetColorAttachments()
    const {
  return colors_;
}

const std::optional<DepthAttachment>& RenderTarget::GetDepthAttachment() const {
  return depth_;
}

const std::optional<StencilAttachment>& RenderTarget::GetStencilAttachment()
    const {
  return stencil_;
}

size_t RenderTarget::GetTotalAttachmentCount() const {
  size_t count = 0u;
  for (const auto& [_, color] : colors_) {
    if (color.texture) {
      count++;
    }
    if (color.resolve_texture) {
      count++;
    }
  }
  if (depth_.has_value()) {
    count++;
  }
  if (stencil_.has_value()) {
    count++;
  }
  return count;
}

std::string RenderTarget::ToString() const {
  std::stringstream stream;

  for (const auto& [index, color] : colors_) {
    stream << SPrintF("Color[%zu]=(%s)", index,
                      ColorAttachmentToString(color).c_str());
  }
  if (depth_) {
    stream << ",";
    stream << SPrintF("Depth=(%s)",
                      DepthAttachmentToString(depth_.value()).c_str());
  }
  if (stencil_) {
    stream << ",";
    stream << SPrintF("Stencil=(%s)",
                      StencilAttachmentToString(stencil_.value()).c_str());
  }
  return stream.str();
}

RenderTargetAllocator::RenderTargetAllocator(
    std::shared_ptr<Allocator> allocator)
    : allocator_(std::move(allocator)) {}

void RenderTargetAllocator::Start() {}

void RenderTargetAllocator::End() {}

RenderTarget RenderTargetAllocator::CreateOffscreen(
    const Context& context,
    ISize size,
    int mip_count,
    const std::string& label,
    RenderTarget::AttachmentConfig color_attachment_config,
    std::optional<RenderTarget::AttachmentConfig> stencil_attachment_config,
    const std::shared_ptr<Texture>& existing_color_texture,
    const std::shared_ptr<Texture>& existing_depth_stencil_texture) {
  if (size.IsEmpty()) {
    return {};
  }

  RenderTarget target;

  std::shared_ptr<Texture> color0_tex;
  if (existing_color_texture) {
    color0_tex = existing_color_texture;
  } else {
    PixelFormat pixel_format =
        context.GetCapabilities()->GetDefaultColorFormat();
    TextureDescriptor color0_tex_desc;
    color0_tex_desc.storage_mode = color_attachment_config.storage_mode;
    color0_tex_desc.format = pixel_format;
    color0_tex_desc.size = size;
    color0_tex_desc.mip_count = mip_count;
    color0_tex_desc.usage = static_cast<uint64_t>(TextureUsage::kRenderTarget) |
                            static_cast<uint64_t>(TextureUsage::kShaderRead);
    color0_tex = allocator_->CreateTexture(color0_tex_desc);
    if (!color0_tex) {
      return {};
    }
  }
  color0_tex->SetLabel(SPrintF("%s Color Texture", label.c_str()));

  ColorAttachment color0;
  color0.clear_color = color_attachment_config.clear_color;
  color0.load_action = color_attachment_config.load_action;
  color0.store_action = color_attachment_config.store_action;
  color0.texture = color0_tex;
  target.SetColorAttachment(color0, 0u);

  if (stencil_attachment_config.has_value()) {
    target.SetupDepthStencilAttachments(
        context, *allocator_, size, false, label,
        stencil_attachment_config.value(), existing_depth_stencil_texture);
  } else {
    target.SetStencilAttachment(std::nullopt);
    target.SetDepthAttachment(std::nullopt);
  }

  return target;
}

RenderTarget RenderTargetAllocator::CreateOffscreenMSAA(
    const Context& context,
    ISize size,
    int mip_count,
    const std::string& label,
    RenderTarget::AttachmentConfigMSAA color_attachment_config,
    std::optional<RenderTarget::AttachmentConfig> stencil_attachment_config,
    const std::shared_ptr<Texture>& existing_color_msaa_texture,
    const std::shared_ptr<Texture>& existing_color_resolve_texture,
    const std::shared_ptr<Texture>& existing_depth_stencil_texture) {
  if (size.IsEmpty()) {
    return {};
  }

  RenderTarget target;
  PixelFormat pixel_format = context.GetCapabilities()->GetDefaultColorFormat();

  // Create MSAA color texture.
  std::shared_ptr<Texture> color0_msaa_tex;
  if (existing_color_msaa_texture) {
    color0_msaa_tex = existing_color_msaa_texture;
  } else {
    TextureDescriptor color0_tex_desc;
    color0_tex_desc.storage_mode = color_attachment_config.storage_mode;
    color0_tex_desc.type = TextureType::kTexture2DMultisample;
    color0_tex_desc.sample_count = SampleCount::kCount4;
    color0_tex_desc.format = pixel_format;
    color0_tex_desc.size = size;
    color0_tex_desc.usage = static_cast<uint64_t>(TextureUsage::kRenderTarget);
    if (context.GetCapabilities()->SupportsImplicitResolvingMSAA()) {
      // See below ("SupportsImplicitResolvingMSAA") for more details.
      color0_tex_desc.storage_mode = StorageMode::kDevicePrivate;
    }
    color0_msaa_tex = allocator_->CreateTexture(color0_tex_desc);
    if (!color0_msaa_tex) {
      VALIDATION_LOG << "Could not create multisample color texture.";
      return {};
    }
  }
  color0_msaa_tex->SetLabel(
      SPrintF("%s Color Texture (Multisample)", label.c_str()));

  // Create color resolve texture.
  std::shared_ptr<Texture> color0_resolve_tex;
  if (existing_color_resolve_texture) {
    color0_resolve_tex = existing_color_resolve_texture;
  } else {
    TextureDescriptor color0_resolve_tex_desc;
    color0_resolve_tex_desc.storage_mode =
        color_attachment_config.resolve_storage_mode;
    color0_resolve_tex_desc.format = pixel_format;
    color0_resolve_tex_desc.size = size;
    color0_resolve_tex_desc.compression_type = CompressionType::kLossy;
    color0_resolve_tex_desc.usage =
        static_cast<uint64_t>(TextureUsage::kRenderTarget) |
        static_cast<uint64_t>(TextureUsage::kShaderRead);
    color0_resolve_tex_desc.mip_count = mip_count;
    color0_resolve_tex = allocator_->CreateTexture(color0_resolve_tex_desc);
    if (!color0_resolve_tex) {
      VALIDATION_LOG << "Could not create color texture.";
      return {};
    }
  }
  color0_resolve_tex->SetLabel(SPrintF("%s Color Texture", label.c_str()));

  // Color attachment.

  ColorAttachment color0;
  color0.clear_color = color_attachment_config.clear_color;
  color0.load_action = color_attachment_config.load_action;
  color0.store_action = color_attachment_config.store_action;
  color0.texture = color0_msaa_tex;
  color0.resolve_texture = color0_resolve_tex;

  if (context.GetCapabilities()->SupportsImplicitResolvingMSAA()) {
    // If implicit MSAA is supported, then the resolve texture is not needed
    // because the multisample texture is automatically resolved. We instead
    // provide a view of the multisample texture as the resolve texture (because
    // the HAL does expect a resolve texture).
    //
    // In practice, this is used for GLES 2.0 EXT_multisampled_render_to_texture
    // https://registry.khronos.org/OpenGL/extensions/EXT/EXT_multisampled_render_to_texture.txt
    color0.resolve_texture = color0_msaa_tex;
  }

  target.SetColorAttachment(color0, 0u);

  // Create MSAA stencil texture.

  if (stencil_attachment_config.has_value()) {
    target.SetupDepthStencilAttachments(context, *allocator_, size, true, label,
                                        stencil_attachment_config.value(),
                                        existing_depth_stencil_texture);
  } else {
    target.SetDepthAttachment(std::nullopt);
    target.SetStencilAttachment(std::nullopt);
  }

  return target;
}

void RenderTarget::SetupDepthStencilAttachments(
    const Context& context,
    Allocator& allocator,
    ISize size,
    bool msaa,
    const std::string& label,
    RenderTarget::AttachmentConfig stencil_attachment_config,
    const std::shared_ptr<Texture>& existing_depth_stencil_texture) {
  std::shared_ptr<Texture> depth_stencil_texture;
  if (existing_depth_stencil_texture) {
    depth_stencil_texture = existing_depth_stencil_texture;
  } else {
    TextureDescriptor depth_stencil_texture_desc;
    depth_stencil_texture_desc.storage_mode =
        stencil_attachment_config.storage_mode;
    if (msaa) {
      depth_stencil_texture_desc.type = TextureType::kTexture2DMultisample;
      depth_stencil_texture_desc.sample_count = SampleCount::kCount4;
    }
    depth_stencil_texture_desc.format =
        context.GetCapabilities()->GetDefaultDepthStencilFormat();
    depth_stencil_texture_desc.size = size;
    depth_stencil_texture_desc.usage =
        static_cast<TextureUsageMask>(TextureUsage::kRenderTarget);
    depth_stencil_texture = allocator.CreateTexture(depth_stencil_texture_desc);
    if (!depth_stencil_texture) {
      return;  // Error messages are handled by `Allocator::CreateTexture`.
    }
  }

  DepthAttachment depth0;
  depth0.load_action = stencil_attachment_config.load_action;
  depth0.store_action = stencil_attachment_config.store_action;
  depth0.clear_depth = 0u;
  depth0.texture = depth_stencil_texture;

  StencilAttachment stencil0;
  stencil0.load_action = stencil_attachment_config.load_action;
  stencil0.store_action = stencil_attachment_config.store_action;
  stencil0.clear_stencil = 0u;
  stencil0.texture = std::move(depth_stencil_texture);

  stencil0.texture->SetLabel(
      SPrintF("%s Depth+Stencil Texture", label.c_str()));
  SetDepthAttachment(std::move(depth0));
  SetStencilAttachment(std::move(stencil0));
}

}  // namespace impeller
