// 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,
    std::optional<RenderPassResult> collapsed_parent_pass)
    : context_(std::move(context)),
      pass_target_(pass_target),
      total_pass_reads_(pass_texture_reads),
      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 (!pass_->EncodeCommands()) {
    VALIDATION_LOG
        << "Failed to encode commands while ending the current render pass.";
    return false;
  }

  if (!command_buffer_->SubmitCommands()) {
    VALIDATION_LOG
        << "Failed to 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 {};
  }

  // Only clear the stencil if this is the very first pass of the
  // layer.
  stencil->load_action =
      pass_count_ > 0 ? LoadAction::kLoad : LoadAction::kClear;
  // If we're on the last pass of the layer, there's no need to store the
  // stencil because nothing needs to read it.
  stencil->store_action = pass_count_ == total_pass_reads_
                              ? StoreAction::kDontCare
                              : StoreAction::kStore;
  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 {};
  }

  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
