// 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/backend/metal/surface_mtl.h"

#include "flutter/fml/trace_event.h"
#include "flutter/impeller/renderer/command_buffer.h"
#include "impeller/base/validation.h"
#include "impeller/renderer/backend/metal/context_mtl.h"
#include "impeller/renderer/backend/metal/formats_mtl.h"
#include "impeller/renderer/backend/metal/texture_mtl.h"
#include "impeller/renderer/render_target.h"

namespace impeller {

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunguarded-availability-new"

id<CAMetalDrawable> SurfaceMTL::GetMetalDrawableAndValidate(
    const std::shared_ptr<Context>& context,
    CAMetalLayer* layer) {
  TRACE_EVENT0("impeller", "SurfaceMTL::WrapCurrentMetalLayerDrawable");

  if (context == nullptr || !context->IsValid() || layer == nil) {
    return nullptr;
  }

  id<CAMetalDrawable> current_drawable = nil;
  {
    TRACE_EVENT0("impeller", "WaitForNextDrawable");
    current_drawable = [layer nextDrawable];
  }

  if (!current_drawable) {
    VALIDATION_LOG << "Could not acquire current drawable.";
    return nullptr;
  }
  return current_drawable;
}

std::unique_ptr<SurfaceMTL> SurfaceMTL::WrapCurrentMetalLayerDrawable(
    const std::shared_ptr<Context>& context,
    id<CAMetalDrawable> drawable,
    std::optional<IRect> clip_rect) {
  bool requires_blit = ShouldPerformPartialRepaint(clip_rect);
  const auto color_format = FromMTLPixelFormat(drawable.texture.pixelFormat);

  if (color_format == PixelFormat::kUnknown) {
    VALIDATION_LOG << "Unknown drawable color format.";
    return nullptr;
  }
  // compositor_context.cc will offset the rendering by the clip origin. Here we
  // shrink to the size of the clip. This has the same effect as clipping the
  // rendering but also creates smaller intermediate passes.
  ISize root_size;
  if (requires_blit) {
    if (!clip_rect.has_value()) {
      VALIDATION_LOG << "Missing clip rectangle.";
      return nullptr;
    }
    root_size = ISize(clip_rect->size.width, clip_rect->size.height);
  } else {
    root_size = {static_cast<ISize::Type>(drawable.texture.width),
                 static_cast<ISize::Type>(drawable.texture.height)};
  }

  TextureDescriptor msaa_tex_desc;
  msaa_tex_desc.storage_mode = StorageMode::kDeviceTransient;
  msaa_tex_desc.type = TextureType::kTexture2DMultisample;
  msaa_tex_desc.sample_count = SampleCount::kCount4;
  msaa_tex_desc.format = color_format;
  msaa_tex_desc.size = root_size;
  msaa_tex_desc.usage = static_cast<uint64_t>(TextureUsage::kRenderTarget);

  auto msaa_tex = context->GetResourceAllocator()->CreateTexture(msaa_tex_desc);
  if (!msaa_tex) {
    VALIDATION_LOG << "Could not allocate MSAA color texture.";
    return nullptr;
  }
  msaa_tex->SetLabel("ImpellerOnscreenColorMSAA");

  TextureDescriptor resolve_tex_desc;
  resolve_tex_desc.format = color_format;
  resolve_tex_desc.size = msaa_tex_desc.size;
  resolve_tex_desc.usage = static_cast<uint64_t>(TextureUsage::kRenderTarget) |
                           static_cast<uint64_t>(TextureUsage::kShaderRead);
  resolve_tex_desc.sample_count = SampleCount::kCount1;
  resolve_tex_desc.storage_mode = StorageMode::kDevicePrivate;

  // Create color resolve texture.
  std::shared_ptr<Texture> resolve_tex;
  if (requires_blit) {
    resolve_tex_desc.compression_type = CompressionType::kLossy;
    resolve_tex =
        context->GetResourceAllocator()->CreateTexture(resolve_tex_desc);
  } else {
    resolve_tex =
        std::make_shared<TextureMTL>(resolve_tex_desc, drawable.texture);
  }

  if (!resolve_tex) {
    VALIDATION_LOG << "Could not wrap resolve texture.";
    return nullptr;
  }
  resolve_tex->SetLabel("ImpellerOnscreenResolve");

  ColorAttachment color0;
  color0.texture = msaa_tex;
  color0.clear_color = Color::DarkSlateGray();
  color0.load_action = LoadAction::kClear;
  color0.store_action = StoreAction::kMultisampleResolve;
  color0.resolve_texture = resolve_tex;

  RenderTarget render_target_desc;
  render_target_desc.SetColorAttachment(color0, 0u);

  // The constructor is private. So make_unique may not be used.
  return std::unique_ptr<SurfaceMTL>(new SurfaceMTL(context, render_target_desc,
                                                    resolve_tex, drawable,
                                                    requires_blit, clip_rect));
}

SurfaceMTL::SurfaceMTL(const std::weak_ptr<Context>& context,
                       const RenderTarget& target,
                       std::shared_ptr<Texture> resolve_texture,
                       id<CAMetalDrawable> drawable,
                       bool requires_blit,
                       std::optional<IRect> clip_rect)
    : Surface(target),
      context_(context),
      resolve_texture_(std::move(resolve_texture)),
      drawable_(drawable),
      requires_blit_(requires_blit),
      clip_rect_(clip_rect) {}

// |Surface|
SurfaceMTL::~SurfaceMTL() = default;

bool SurfaceMTL::ShouldPerformPartialRepaint(std::optional<IRect> damage_rect) {
  // compositor_context.cc will conditionally disable partial repaint if the
  // damage region is large. If that happened, then a nullopt damage rect
  // will be provided here.
  if (!damage_rect.has_value()) {
    return false;
  }
  // If the damage rect is 0 in at least one dimension, partial repaint isn't
  // performed as we skip right to present.
  if (damage_rect->size.width <= 0 || damage_rect->size.height <= 0) {
    return false;
  }
  return true;
}

// |Surface|
IRect SurfaceMTL::coverage() const {
  return IRect::MakeSize(resolve_texture_->GetSize());
}

static bool ShouldWaitForCommandBuffer() {
#if ((FML_OS_MACOSX && !FML_OS_IOS) || FML_OS_IOS_SIMULATOR)
  // If a transaction is present, `presentDrawable` will present too early. And
  // so we wait on an empty command buffer to get scheduled instead, which
  // forces us to also wait for all of the previous command buffers in the queue
  // to get scheduled.
  return true;
#else
  // On Physical iOS devices we still need to wait if we're taking a frame
  // capture.
  return [[MTLCaptureManager sharedCaptureManager] isCapturing];
#endif  // ((FML_OS_MACOSX && !FML_OS_IOS) || FML_OS_IOS_SIMULATOR)
}

// |Surface|
bool SurfaceMTL::Present() const {
  if (drawable_ == nil) {
    return false;
  }

  auto context = context_.lock();
  if (!context) {
    return false;
  }

  if (requires_blit_) {
    auto blit_command_buffer = context->CreateCommandBuffer();
    if (!blit_command_buffer) {
      return false;
    }
    auto blit_pass = blit_command_buffer->CreateBlitPass();
    if (!clip_rect_.has_value()) {
      VALIDATION_LOG << "Missing clip rectangle.";
      return false;
    }
    auto current = TextureMTL::Wrapper({}, drawable_.texture);
    blit_pass->AddCopy(resolve_texture_, current, std::nullopt,
                       clip_rect_->origin);
    blit_pass->EncodeCommands(context->GetResourceAllocator());
    if (!blit_command_buffer->SubmitCommands()) {
      return false;
    }
  }

  if (ShouldWaitForCommandBuffer()) {
    id<MTLCommandBuffer> command_buffer =
        ContextMTL::Cast(context.get())->CreateMTLCommandBuffer();
    [command_buffer commit];
    [command_buffer waitUntilScheduled];
  }
  [drawable_ present];

  return true;
}
#pragma GCC diagnostic pop

}  // namespace impeller
