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

#include <utility>

#include "impeller/base/validation.h"
#include "impeller/core/formats.h"
#include "impeller/core/texture_descriptor.h"
#include "impeller/entity/entity_pass_target.h"
#include "impeller/renderer/command_buffer.h"

namespace impeller {

InlinePassContext::InlinePassContext(
    std::shared_ptr<Context> context,
    EntityPassTarget& pass_target,
    uint32_t pass_texture_reads,
    uint32_t entity_count,
    std::optional<RenderPassResult> collapsed_parent_pass)
    : context_(std::move(context)),
      pass_target_(pass_target),
      entity_count_(entity_count),
      is_collapsed_(collapsed_parent_pass.has_value()) {
  if (collapsed_parent_pass.has_value()) {
    pass_ = collapsed_parent_pass.value().pass;
  }
}

InlinePassContext::~InlinePassContext() {
  if (!is_collapsed_) {
    EndPass();
  }
}

bool InlinePassContext::IsValid() const {
  return pass_target_.IsValid();
}

bool InlinePassContext::IsActive() const {
  return pass_ != nullptr;
}

std::shared_ptr<Texture> InlinePassContext::GetTexture() {
  if (!IsValid()) {
    return nullptr;
  }
  return pass_target_.GetRenderTarget().GetRenderTargetTexture();
}

bool InlinePassContext::EndPass() {
  if (!IsActive()) {
    return true;
  }

  if (command_buffer_) {
    if (!command_buffer_->EncodeAndSubmit(pass_)) {
      VALIDATION_LOG
          << "Failed to encode and submit command buffer while ending "
             "render pass.";
      return false;
    }
  }

  pass_ = nullptr;
  command_buffer_ = nullptr;

  return true;
}

EntityPassTarget& InlinePassContext::GetPassTarget() const {
  return pass_target_;
}

InlinePassContext::RenderPassResult InlinePassContext::GetRenderPass(
    uint32_t pass_depth) {
  if (IsActive()) {
    return {.pass = pass_};
  }

  /// Create a new render pass if one isn't active. This path will run the first
  /// time this method is called, but it'll also run if the pass has been
  /// previously ended via `EndPass`.

  command_buffer_ = context_->CreateCommandBuffer();
  if (!command_buffer_) {
    VALIDATION_LOG << "Could not create command buffer.";
    return {};
  }

  if (pass_target_.GetRenderTarget().GetColorAttachments().empty()) {
    VALIDATION_LOG << "Color attachment unexpectedly missing from the "
                      "EntityPass render target.";
    return {};
  }

  command_buffer_->SetLabel(
      "EntityPass Command Buffer: Depth=" + std::to_string(pass_depth) +
      " Count=" + std::to_string(pass_count_));

  RenderPassResult result;
  {
    // If the pass target has a resolve texture, then we're using MSAA.
    bool is_msaa = pass_target_.GetRenderTarget()
                       .GetColorAttachments()
                       .find(0)
                       ->second.resolve_texture != nullptr;
    if (pass_count_ > 0 && is_msaa) {
      result.backdrop_texture =
          pass_target_.Flip(*context_->GetResourceAllocator());
      if (!result.backdrop_texture) {
        VALIDATION_LOG << "Could not flip the EntityPass render target.";
      }
    }
  }

  // Find the color attachment a second time, since the target may have just
  // flipped.
  auto color0 =
      pass_target_.GetRenderTarget().GetColorAttachments().find(0)->second;
  bool is_msaa = color0.resolve_texture != nullptr;

  if (pass_count_ > 0) {
    // When MSAA is being used, we end up overriding the entire backdrop by
    // drawing the previous pass texture, and so we don't have to clear it and
    // can use kDontCare.
    color0.load_action = is_msaa ? LoadAction::kDontCare : LoadAction::kLoad;
  } else {
    color0.load_action = LoadAction::kClear;
  }

  color0.store_action =
      is_msaa ? StoreAction::kMultisampleResolve : StoreAction::kStore;

  auto stencil = pass_target_.GetRenderTarget().GetStencilAttachment();
  if (!stencil.has_value()) {
    VALIDATION_LOG << "Stencil attachment unexpectedly missing from the "
                      "EntityPass render target.";
    return {};
  }

  stencil->load_action = LoadAction::kClear;
  stencil->store_action = StoreAction::kDontCare;
  pass_target_.target_.SetStencilAttachment(stencil.value());
  pass_target_.target_.SetColorAttachment(color0, 0);

  pass_ = command_buffer_->CreateRenderPass(pass_target_.GetRenderTarget());
  if (!pass_) {
    VALIDATION_LOG << "Could not create render pass.";
    return {};
  }
  // Commands are fairly large (500B) objects, so re-allocation of the command
  // buffer while encoding can add a surprising amount of overhead. We make a
  // conservative npot estimate to avoid this case.
  pass_->ReserveCommands(Allocation::NextPowerOfTwoSize(entity_count_));
  pass_->SetLabel(
      "EntityPass Render Pass: Depth=" + std::to_string(pass_depth) +
      " Count=" + std::to_string(pass_count_));

  result.pass = pass_;

  if (!context_->GetCapabilities()->SupportsReadFromResolve() &&
      result.backdrop_texture ==
          result.pass->GetRenderTarget().GetRenderTargetTexture()) {
    VALIDATION_LOG << "EntityPass backdrop restore configuration is not valid "
                      "for the current graphics backend.";
  }

  ++pass_count_;
  return result;
}

uint32_t InlinePassContext::GetPassCount() const {
  return pass_count_;
}

}  // namespace impeller
