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

#include <memory>
#include <utility>
#include <variant>

#include "flutter/fml/logging.h"
#include "flutter/fml/macros.h"
#include "flutter/fml/trace_event.h"
#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/entity/contents/clip_contents.h"
#include "impeller/entity/contents/content_context.h"
#include "impeller/entity/contents/filters/color_filter_contents.h"
#include "impeller/entity/contents/filters/inputs/filter_input.h"
#include "impeller/entity/contents/framebuffer_blend_contents.h"
#include "impeller/entity/contents/texture_contents.h"
#include "impeller/entity/entity.h"
#include "impeller/entity/inline_pass_context.h"
#include "impeller/geometry/color.h"
#include "impeller/geometry/path_builder.h"
#include "impeller/renderer/command.h"
#include "impeller/renderer/command_buffer.h"
#include "impeller/renderer/render_pass.h"

#ifdef IMPELLER_DEBUG
#include "impeller/entity/contents/checkerboard_contents.h"
#endif  // IMPELLER_DEBUG

namespace impeller {

namespace {
std::tuple<std::optional<Color>, BlendMode> ElementAsBackgroundColor(
    const EntityPass::Element& element,
    ISize target_size) {
  if (const Entity* entity = std::get_if<Entity>(&element)) {
    std::optional<Color> entity_color = entity->AsBackgroundColor(target_size);
    if (entity_color.has_value()) {
      return {entity_color.value(), entity->GetBlendMode()};
    }
  }
  return {};
}
}  // namespace

EntityPass::EntityPass() = default;

EntityPass::~EntityPass() = default;

void EntityPass::SetDelegate(std::unique_ptr<EntityPassDelegate> delegate) {
  if (!delegate) {
    return;
  }
  delegate_ = std::move(delegate);
}

void EntityPass::AddEntity(Entity entity) {
  if (entity.GetBlendMode() == BlendMode::kSourceOver &&
      entity.GetContents()->IsOpaque()) {
    entity.SetBlendMode(BlendMode::kSource);
  }

  if (entity.GetBlendMode() > Entity::kLastPipelineBlendMode) {
    advanced_blend_reads_from_pass_texture_ += 1;
  }
  elements_.emplace_back(std::move(entity));
}

void EntityPass::SetElements(std::vector<Element> elements) {
  elements_ = std::move(elements);
}

size_t EntityPass::GetSubpassesDepth() const {
  size_t max_subpass_depth = 0u;
  for (const auto& element : elements_) {
    if (auto subpass = std::get_if<std::unique_ptr<EntityPass>>(&element)) {
      max_subpass_depth =
          std::max(max_subpass_depth, subpass->get()->GetSubpassesDepth());
    }
  }
  return max_subpass_depth + 1u;
}

std::optional<Rect> EntityPass::GetElementsCoverage(
    std::optional<Rect> coverage_limit) const {
  std::optional<Rect> result;
  for (const auto& element : elements_) {
    std::optional<Rect> coverage;

    if (auto entity = std::get_if<Entity>(&element)) {
      coverage = entity->GetCoverage();

      if (coverage.has_value() && coverage_limit.has_value()) {
        coverage = coverage->Intersection(coverage_limit.value());
      }
    } else if (auto subpass =
                   std::get_if<std::unique_ptr<EntityPass>>(&element)) {
      coverage = GetSubpassCoverage(*subpass->get(), coverage_limit);
    } else {
      FML_UNREACHABLE();
    }

    if (!result.has_value() && coverage.has_value()) {
      result = coverage;
      continue;
    }
    if (!coverage.has_value()) {
      continue;
    }
    result = result->Union(coverage.value());
  }
  return result;
}

std::optional<Rect> EntityPass::GetSubpassCoverage(
    const EntityPass& subpass,
    std::optional<Rect> coverage_limit) const {
  auto entities_coverage = subpass.GetElementsCoverage(coverage_limit);
  // The entities don't cover anything. There is nothing to do.
  if (!entities_coverage.has_value()) {
    return std::nullopt;
  }

  // The delegates don't have an opinion on what the entity coverage has to be.
  // Just use that as-is.
  auto delegate_coverage = subpass.delegate_->GetCoverageRect();
  if (!delegate_coverage.has_value()) {
    return entities_coverage;
  }
  // The delegate coverage hint is in given in local space, so apply the subpass
  // transformation.
  delegate_coverage = delegate_coverage->TransformBounds(subpass.xformation_);

  // If the delegate tells us the coverage is smaller than it needs to be, then
  // great. OTOH, if the delegate is being wasteful, limit coverage to what is
  // actually needed.
  return entities_coverage->Intersection(delegate_coverage.value());
}

EntityPass* EntityPass::GetSuperpass() const {
  return superpass_;
}

EntityPass* EntityPass::AddSubpass(std::unique_ptr<EntityPass> pass) {
  if (!pass) {
    return nullptr;
  }
  FML_DCHECK(pass->superpass_ == nullptr);
  pass->superpass_ = this;

  if (pass->backdrop_filter_proc_) {
    backdrop_filter_reads_from_pass_texture_ += 1;
  }
  if (pass->blend_mode_ > Entity::kLastPipelineBlendMode) {
    advanced_blend_reads_from_pass_texture_ += 1;
  }

  auto subpass_pointer = pass.get();
  elements_.emplace_back(std::move(pass));
  return subpass_pointer;
}

void EntityPass::AddSubpassInline(std::unique_ptr<EntityPass> pass) {
  if (!pass) {
    return;
  }
  FML_DCHECK(pass->superpass_ == nullptr);

  elements_.insert(elements_.end(),
                   std::make_move_iterator(pass->elements_.begin()),
                   std::make_move_iterator(pass->elements_.end()));

  backdrop_filter_reads_from_pass_texture_ +=
      pass->backdrop_filter_reads_from_pass_texture_;
  advanced_blend_reads_from_pass_texture_ +=
      pass->advanced_blend_reads_from_pass_texture_;
}

static RenderTarget::AttachmentConfig GetDefaultStencilConfig(bool readable) {
  return RenderTarget::AttachmentConfig{
      .storage_mode = readable ? StorageMode::kDevicePrivate
                               : StorageMode::kDeviceTransient,
      .load_action = LoadAction::kDontCare,
      .store_action = StoreAction::kDontCare,
  };
}

static EntityPassTarget CreateRenderTarget(ContentContext& renderer,
                                           ISize size,
                                           bool readable,
                                           const Color& clear_color) {
  auto context = renderer.GetContext();

  /// All of the load/store actions are managed by `InlinePassContext` when
  /// `RenderPasses` are created, so we just set them to `kDontCare` here.
  /// What's important is the `StorageMode` of the textures, which cannot be
  /// changed for the lifetime of the textures.

  RenderTarget target;
  if (context->GetCapabilities()->SupportsOffscreenMSAA()) {
    target = RenderTarget::CreateOffscreenMSAA(
        *context,      // context
        size,          // size
        "EntityPass",  // label
        RenderTarget::AttachmentConfigMSAA{
            .storage_mode = StorageMode::kDeviceTransient,
            .resolve_storage_mode = StorageMode::kDevicePrivate,
            .load_action = LoadAction::kDontCare,
            .store_action = StoreAction::kMultisampleResolve,
            .clear_color = clear_color},   // color_attachment_config
        GetDefaultStencilConfig(readable)  // stencil_attachment_config
    );
  } else {
    target = RenderTarget::CreateOffscreen(
        *context,      // context
        size,          // size
        "EntityPass",  // label
        RenderTarget::AttachmentConfig{
            .storage_mode = StorageMode::kDevicePrivate,
            .load_action = LoadAction::kDontCare,
            .store_action = StoreAction::kDontCare,
            .clear_color = clear_color,
        },                                 // color_attachment_config
        GetDefaultStencilConfig(readable)  // stencil_attachment_config
    );
  }

  return EntityPassTarget(
      target, renderer.GetDeviceCapabilities().SupportsReadFromResolve());
}

uint32_t EntityPass::GetTotalPassReads(ContentContext& renderer) const {
  return renderer.GetDeviceCapabilities().SupportsFramebufferFetch()
             ? backdrop_filter_reads_from_pass_texture_
             : backdrop_filter_reads_from_pass_texture_ +
                   advanced_blend_reads_from_pass_texture_;
}

bool EntityPass::Render(ContentContext& renderer,
                        const RenderTarget& render_target) const {
  auto root_render_target = render_target;

  if (root_render_target.GetColorAttachments().empty()) {
    VALIDATION_LOG << "The root RenderTarget must have a color attachment.";
    return false;
  }

  StencilCoverageStack stencil_coverage_stack = {StencilCoverageLayer{
      .coverage = Rect::MakeSize(root_render_target.GetRenderTargetSize()),
      .stencil_depth = 0}};

  bool supports_onscreen_backdrop_reads =
      renderer.GetDeviceCapabilities().SupportsReadFromOnscreenTexture() &&
      // If the backend doesn't have `SupportsReadFromResolve`, we need to flip
      // between two textures when restoring a previous MSAA pass.
      renderer.GetDeviceCapabilities().SupportsReadFromResolve();
  bool reads_from_onscreen_backdrop = GetTotalPassReads(renderer) > 0;
  // In this branch path, we need to render everything to an offscreen texture
  // and then blit the results onto the onscreen texture. If using this branch,
  // there's no need to set up a stencil attachment on the root render target.
  if (!supports_onscreen_backdrop_reads && reads_from_onscreen_backdrop) {
    auto offscreen_target = CreateRenderTarget(
        renderer, root_render_target.GetRenderTargetSize(), true,
        GetClearColor(render_target.GetRenderTargetSize()));

    if (!OnRender(renderer,  // renderer
                  offscreen_target.GetRenderTarget()
                      .GetRenderTargetSize(),  // root_pass_size
                  offscreen_target,            // pass_target
                  Point(),                     // global_pass_position
                  Point(),                     // local_pass_position
                  0,                           // pass_depth
                  stencil_coverage_stack       // stencil_coverage_stack
                  )) {
      // Validation error messages are triggered for all `OnRender()` failure
      // cases.
      return false;
    }

    auto command_buffer = renderer.GetContext()->CreateCommandBuffer();
    command_buffer->SetLabel("EntityPass Root Command Buffer");

    // If the context supports blitting, blit the offscreen texture to the
    // onscreen texture. Otherwise, draw it to the parent texture using a
    // pipeline (slower).
    if (renderer.GetContext()
            ->GetCapabilities()
            ->SupportsTextureToTextureBlits()) {
      auto blit_pass = command_buffer->CreateBlitPass();
      blit_pass->AddCopy(
          offscreen_target.GetRenderTarget().GetRenderTargetTexture(),
          root_render_target.GetRenderTargetTexture());

      if (!blit_pass->EncodeCommands(
              renderer.GetContext()->GetResourceAllocator())) {
        VALIDATION_LOG << "Failed to encode root pass blit command.";
        return false;
      }
    } else {
      auto render_pass = command_buffer->CreateRenderPass(root_render_target);
      render_pass->SetLabel("EntityPass Root Render Pass");

      {
        auto size_rect = Rect::MakeSize(
            offscreen_target.GetRenderTarget().GetRenderTargetSize());
        auto contents = TextureContents::MakeRect(size_rect);
        contents->SetTexture(
            offscreen_target.GetRenderTarget().GetRenderTargetTexture());
        contents->SetSourceRect(size_rect);
        contents->SetLabel("Root pass blit");

        Entity entity;
        entity.SetContents(contents);
        entity.SetBlendMode(BlendMode::kSource);

        entity.Render(renderer, *render_pass);
      }

      if (!render_pass->EncodeCommands()) {
        VALIDATION_LOG << "Failed to encode root pass command buffer.";
        return false;
      }
    }
    if (!command_buffer->SubmitCommands()) {
      VALIDATION_LOG << "Failed to submit root pass command buffer.";
      return false;
    }

    return true;
  }

  // If we make it this far, that means the context is capable of rendering
  // everything directly to the onscreen texture.

  // The safety check for fetching this color attachment is at the beginning of
  // this method.
  auto color0 = root_render_target.GetColorAttachments().find(0)->second;

  // If a root stencil was provided by the caller, then verify that it has a
  // configuration which can be used to render this pass.
  auto stencil_attachment = root_render_target.GetStencilAttachment();
  if (stencil_attachment.has_value()) {
    auto stencil_texture = stencil_attachment->texture;
    if (!stencil_texture) {
      VALIDATION_LOG << "The root RenderTarget must have a stencil texture.";
      return false;
    }

    auto stencil_storage_mode =
        stencil_texture->GetTextureDescriptor().storage_mode;
    if (reads_from_onscreen_backdrop &&
        stencil_storage_mode == StorageMode::kDeviceTransient) {
      VALIDATION_LOG << "The given root RenderTarget stencil needs to be read, "
                        "but it's marked as transient.";
      return false;
    }
  }
  // Setup a new root stencil with an optimal configuration if one wasn't
  // provided by the caller.
  else {
    root_render_target.SetupStencilAttachment(
        *renderer.GetContext(), color0.texture->GetSize(),
        renderer.GetContext()->GetCapabilities()->SupportsOffscreenMSAA(),
        "ImpellerOnscreen",
        GetDefaultStencilConfig(reads_from_onscreen_backdrop));
  }

  // Set up the clear color of the root pass.
  color0.clear_color = GetClearColor(render_target.GetRenderTargetSize());
  root_render_target.SetColorAttachment(color0, 0);

  EntityPassTarget pass_target(
      root_render_target,
      renderer.GetDeviceCapabilities().SupportsReadFromResolve());

  return OnRender(                               //
      renderer,                                  // renderer
      root_render_target.GetRenderTargetSize(),  // root_pass_size
      pass_target,                               // pass_target
      Point(),                                   // global_pass_position
      Point(),                                   // local_pass_position
      0,                                         // pass_depth
      stencil_coverage_stack);                   // stencil_coverage_stack
}

EntityPass::EntityResult EntityPass::GetEntityForElement(
    const EntityPass::Element& element,
    ContentContext& renderer,
    InlinePassContext& pass_context,
    ISize root_pass_size,
    Point global_pass_position,
    uint32_t pass_depth,
    StencilCoverageStack& stencil_coverage_stack,
    size_t stencil_depth_floor) const {
  Entity element_entity;

  //--------------------------------------------------------------------------
  /// Setup entity element.
  ///

  if (const auto& entity = std::get_if<Entity>(&element)) {
    element_entity = *entity;
    if (!global_pass_position.IsZero()) {
      // If the pass image is going to be rendered with a non-zero position,
      // apply the negative translation to entity copies before rendering them
      // so that they'll end up rendering to the correct on-screen position.
      element_entity.SetTransformation(
          Matrix::MakeTranslation(Vector3(-global_pass_position)) *
          element_entity.GetTransformation());
    }
  }

  //--------------------------------------------------------------------------
  /// Setup subpass element.
  ///

  else if (const auto& subpass_ptr =
               std::get_if<std::unique_ptr<EntityPass>>(&element)) {
    auto subpass = subpass_ptr->get();

    if (subpass->delegate_->CanElide()) {
      return EntityPass::EntityResult::Skip();
    }

    if (!subpass->backdrop_filter_proc_ &&
        subpass->delegate_->CanCollapseIntoParentPass(subpass)) {
      // Directly render into the parent target and move on.
      if (!subpass->OnRender(
              renderer,                      // renderer
              root_pass_size,                // root_pass_size
              pass_context.GetPassTarget(),  // pass_target
              global_pass_position,          // global_pass_position
              Point(),                       // local_pass_position
              pass_depth,                    // pass_depth
              stencil_coverage_stack,        // stencil_coverage_stack
              stencil_depth_,                // stencil_depth_floor
              nullptr,                       // backdrop_filter_contents
              pass_context.GetRenderPass(pass_depth)  // collapsed_parent_pass
              )) {
        // Validation error messages are triggered for all `OnRender()` failure
        // cases.
        return EntityPass::EntityResult::Failure();
      }
      return EntityPass::EntityResult::Skip();
    }

    std::shared_ptr<Contents> backdrop_filter_contents = nullptr;
    if (subpass->backdrop_filter_proc_) {
      auto texture = pass_context.GetTexture();
      // Render the backdrop texture before any of the pass elements.
      const auto& proc = subpass->backdrop_filter_proc_;
      backdrop_filter_contents =
          proc(FilterInput::Make(std::move(texture)), subpass->xformation_,
               /*is_subpass*/ true);

      // The subpass will need to read from the current pass texture when
      // rendering the backdrop, so if there's an active pass, end it prior to
      // rendering the subpass.
      pass_context.EndPass();
    }

    if (stencil_coverage_stack.empty()) {
      // The current clip is empty. This means the pass texture won't be
      // visible, so skip it.
      return EntityPass::EntityResult::Skip();
    }
    auto stencil_coverage_back = stencil_coverage_stack.back().coverage;
    if (!stencil_coverage_back.has_value()) {
      return EntityPass::EntityResult::Skip();
    }

    // The maximum coverage of the subpass. Subpasses textures should never
    // extend outside the parent pass texture or the current clip coverage.
    auto coverage_limit =
        Rect(global_pass_position, Size(pass_context.GetPassTarget()
                                            .GetRenderTarget()
                                            .GetRenderTargetSize()))
            .Intersection(stencil_coverage_back.value());
    if (!coverage_limit.has_value()) {
      return EntityPass::EntityResult::Skip();
    }

    coverage_limit =
        coverage_limit->Intersection(Rect::MakeSize(root_pass_size));
    if (!coverage_limit.has_value()) {
      return EntityPass::EntityResult::Skip();
    }

    auto subpass_coverage = (subpass->flood_clip_ || backdrop_filter_contents)
                                ? coverage_limit
                                : GetSubpassCoverage(*subpass, coverage_limit);
    if (!subpass_coverage.has_value()) {
      return EntityPass::EntityResult::Skip();
    }

    auto subpass_size = ISize(subpass_coverage->size);
    if (subpass_size.IsEmpty()) {
      return EntityPass::EntityResult::Skip();
    }

    auto subpass_target = CreateRenderTarget(
        renderer,                                  // renderer
        subpass_size,                              // size
        subpass->GetTotalPassReads(renderer) > 0,  // readable
        subpass->GetClearColor(subpass_size));     // clear_color

    if (!subpass_target.IsValid()) {
      VALIDATION_LOG << "Subpass render target is invalid.";
      return EntityPass::EntityResult::Failure();
    }

    // Stencil textures aren't shared between EntityPasses (as much of the
    // time they are transient).
    if (!subpass->OnRender(renderer,                  // renderer
                           root_pass_size,            // root_pass_size
                           subpass_target,            // pass_target
                           subpass_coverage->origin,  // global_pass_position
                           subpass_coverage->origin -
                               global_pass_position,  // local_pass_position
                           ++pass_depth,              // pass_depth
                           stencil_coverage_stack,    // stencil_coverage_stack
                           subpass->stencil_depth_,   // stencil_depth_floor
                           backdrop_filter_contents  // backdrop_filter_contents
                           )) {
      // Validation error messages are triggered for all `OnRender()` failure
      // cases.
      return EntityPass::EntityResult::Failure();
    }

    // The subpass target's texture may have changed during OnRender.
    auto subpass_texture =
        subpass_target.GetRenderTarget().GetRenderTargetTexture();

    auto offscreen_texture_contents =
        subpass->delegate_->CreateContentsForSubpassTarget(
            subpass_texture,
            Matrix::MakeTranslation(Vector3{-global_pass_position}) *
                subpass->xformation_);

    if (!offscreen_texture_contents) {
      // This is an error because the subpass delegate said the pass couldn't
      // be collapsed into its parent. Yet, when asked how it want's to
      // postprocess the offscreen texture, it couldn't give us an answer.
      //
      // Theoretically, we could collapse the pass now. But that would be
      // wasteful as we already have the offscreen texture and we don't want
      // to discard it without ever using it. Just make the delegate do the
      // right thing.
      return EntityPass::EntityResult::Failure();
    }

    element_entity.SetContents(std::move(offscreen_texture_contents));
    element_entity.SetStencilDepth(subpass->stencil_depth_);
    element_entity.SetBlendMode(subpass->blend_mode_);
    element_entity.SetTransformation(Matrix::MakeTranslation(
        Vector3(subpass_coverage->origin - global_pass_position)));
  } else {
    FML_UNREACHABLE();
  }

  return EntityPass::EntityResult::Success(element_entity);
}

bool EntityPass::OnRender(
    ContentContext& renderer,
    ISize root_pass_size,
    EntityPassTarget& pass_target,
    Point global_pass_position,
    Point local_pass_position,
    uint32_t pass_depth,
    StencilCoverageStack& stencil_coverage_stack,
    size_t stencil_depth_floor,
    std::shared_ptr<Contents> backdrop_filter_contents,
    const std::optional<InlinePassContext::RenderPassResult>&
        collapsed_parent_pass) const {
  TRACE_EVENT0("impeller", "EntityPass::OnRender");

  auto context = renderer.GetContext();
  InlinePassContext pass_context(
      context, pass_target, GetTotalPassReads(renderer), collapsed_parent_pass);
  if (!pass_context.IsValid()) {
    VALIDATION_LOG << SPrintF("Pass context invalid (Depth=%d)", pass_depth);
    return false;
  }

  if (!(GetClearColor(root_pass_size) == Color::BlackTransparent())) {
    // Force the pass context to create at least one new pass if the clear color
    // is present. The `EndPass` first ensures that the clear color will get
    // applied even if this EntityPass is getting collapsed into the parent
    // pass.
    pass_context.EndPass();
    pass_context.GetRenderPass(pass_depth);
  }

  auto render_element = [&stencil_depth_floor, &pass_context, &pass_depth,
                         &renderer, &stencil_coverage_stack,
                         &global_pass_position](Entity& element_entity) {
    auto result = pass_context.GetRenderPass(pass_depth);

    if (!result.pass) {
      // Failure to produce a render pass should be explained by specific errors
      // in `InlinePassContext::GetRenderPass()`, so avoid log spam and don't
      // append a validation log here.
      return false;
    }

    // If the pass context returns a texture, we need to draw it to the current
    // pass. We do this because it's faster and takes significantly less memory
    // than storing/loading large MSAA textures.
    // Also, it's not possible to blit the non-MSAA resolve texture of the
    // previous pass to MSAA textures (let alone a transient one).
    if (result.backdrop_texture) {
      auto size_rect = Rect::MakeSize(result.pass->GetRenderTargetSize());
      auto msaa_backdrop_contents = TextureContents::MakeRect(size_rect);
      msaa_backdrop_contents->SetStencilEnabled(false);
      msaa_backdrop_contents->SetLabel("MSAA backdrop");
      msaa_backdrop_contents->SetSourceRect(size_rect);
      msaa_backdrop_contents->SetTexture(result.backdrop_texture);

      Entity msaa_backdrop_entity;
      msaa_backdrop_entity.SetContents(std::move(msaa_backdrop_contents));
      msaa_backdrop_entity.SetBlendMode(BlendMode::kSource);
      if (!msaa_backdrop_entity.Render(renderer, *result.pass)) {
        VALIDATION_LOG << "Failed to render MSAA backdrop filter entity.";
        return false;
      }
    }

    auto current_stencil_coverage = stencil_coverage_stack.back().coverage;
    if (current_stencil_coverage.has_value()) {
      // Entity transforms are relative to the current pass position, so we need
      // to check stencil coverage in the same space.
      current_stencil_coverage->origin -= global_pass_position;
    }

    if (!element_entity.ShouldRender(current_stencil_coverage)) {
      return true;  // Nothing to render.
    }

    auto stencil_coverage =
        element_entity.GetStencilCoverage(current_stencil_coverage);
    if (stencil_coverage.coverage.has_value()) {
      stencil_coverage.coverage->origin += global_pass_position;
    }

    // The coverage hint tells the rendered Contents which portion of the
    // rendered output will actually be used, and so we set this to the current
    // stencil coverage (which is the max clip bounds). The contents may
    // optionally use this hint to avoid unnecessary rendering work.
    element_entity.GetContents()->SetCoverageHint(current_stencil_coverage);

    switch (stencil_coverage.type) {
      case Contents::StencilCoverage::Type::kNoChange:
        break;
      case Contents::StencilCoverage::Type::kAppend: {
        auto op = stencil_coverage_stack.back().coverage;
        stencil_coverage_stack.push_back(StencilCoverageLayer{
            .coverage = stencil_coverage.coverage,
            .stencil_depth = element_entity.GetStencilDepth() + 1});
        FML_DCHECK(stencil_coverage_stack.back().stencil_depth ==
                   stencil_coverage_stack.size() - 1);

        if (!op.has_value()) {
          // Running this append op won't impact the stencil because the whole
          // screen is already being clipped, so skip it.
          return true;
        }
      } break;
      case Contents::StencilCoverage::Type::kRestore: {
        if (stencil_coverage_stack.back().stencil_depth <=
            element_entity.GetStencilDepth()) {
          // Drop stencil restores that will do nothing.
          return true;
        }

        auto restoration_depth = element_entity.GetStencilDepth();
        FML_DCHECK(restoration_depth < stencil_coverage_stack.size());

        // We only need to restore the area that covers the coverage of the
        // stencil rect at target depth + 1.
        std::optional<Rect> restore_coverage =
            (restoration_depth + 1 < stencil_coverage_stack.size())
                ? stencil_coverage_stack[restoration_depth + 1].coverage
                : std::nullopt;
        if (restore_coverage.has_value()) {
          // Make the coverage rectangle relative to the current pass.
          restore_coverage->origin -= global_pass_position;
        }
        stencil_coverage_stack.resize(restoration_depth + 1);

        if (!stencil_coverage_stack.back().coverage.has_value()) {
          // Running this restore op won't make anything renderable, so skip it.
          return true;
        }

        auto restore_contents = static_cast<ClipRestoreContents*>(
            element_entity.GetContents().get());
        restore_contents->SetRestoreCoverage(restore_coverage);

      } break;
    }

    element_entity.SetStencilDepth(element_entity.GetStencilDepth() -
                                   stencil_depth_floor);
    if (!element_entity.Render(renderer, *result.pass)) {
      VALIDATION_LOG << "Failed to render entity.";
      return false;
    }
    return true;
  };

  if (backdrop_filter_proc_) {
    if (!backdrop_filter_contents) {
      VALIDATION_LOG
          << "EntityPass contains a backdrop filter, but no backdrop filter "
             "contents was supplied by the parent pass at render time. This is "
             "a bug in EntityPass. Parent passes are responsible for setting "
             "up backdrop filters for their children.";
      return false;
    }

    Entity backdrop_entity;
    backdrop_entity.SetContents(std::move(backdrop_filter_contents));
    backdrop_entity.SetTransformation(
        Matrix::MakeTranslation(Vector3(-local_pass_position)));
    backdrop_entity.SetStencilDepth(stencil_depth_floor);

    render_element(backdrop_entity);
  }

  bool is_collapsing_clear_colors = true;
  for (const auto& element : elements_) {
    // Skip elements that are incorporated into the clear color.
    if (is_collapsing_clear_colors) {
      auto [entity_color, _] =
          ElementAsBackgroundColor(element, root_pass_size);
      if (entity_color.has_value()) {
        continue;
      }
      is_collapsing_clear_colors = false;
    }

    EntityResult result =
        GetEntityForElement(element,                 // element
                            renderer,                // renderer
                            pass_context,            // pass_context
                            root_pass_size,          // root_pass_size
                            global_pass_position,    // global_pass_position
                            pass_depth,              // pass_depth
                            stencil_coverage_stack,  // stencil_coverage_stack
                            stencil_depth_floor);    // stencil_depth_floor

    switch (result.status) {
      case EntityResult::kSuccess:
        break;
      case EntityResult::kFailure:
        // All failure cases should be covered by specific validation messages
        // in `GetEntityForElement()`.
        return false;
      case EntityResult::kSkip:
        continue;
    };

    //--------------------------------------------------------------------------
    /// Setup advanced blends.
    ///

    if (result.entity.GetBlendMode() > Entity::kLastPipelineBlendMode) {
      if (renderer.GetDeviceCapabilities().SupportsFramebufferFetch()) {
        auto src_contents = result.entity.GetContents();
        auto contents = std::make_shared<FramebufferBlendContents>();
        contents->SetChildContents(src_contents);
        contents->SetBlendMode(result.entity.GetBlendMode());
        result.entity.SetContents(std::move(contents));
        result.entity.SetBlendMode(BlendMode::kSource);
      } else {
        // End the active pass and flush the buffer before rendering "advanced"
        // blends. Advanced blends work by binding the current render target
        // texture as an input ("destination"), blending with a second texture
        // input ("source"), writing the result to an intermediate texture, and
        // finally copying the data from the intermediate texture back to the
        // render target texture. And so all of the commands that have written
        // to the render target texture so far need to execute before it's bound
        // for blending (otherwise the blend pass will end up executing before
        // all the previous commands in the active pass).

        if (!pass_context.EndPass()) {
          VALIDATION_LOG
              << "Failed to end the current render pass in order to read from "
                 "the backdrop texture and apply an advanced blend.";
          return false;
        }

        // Amend an advanced blend filter to the contents, attaching the pass
        // texture.
        auto texture = pass_context.GetTexture();
        if (!texture) {
          VALIDATION_LOG << "Failed to fetch the color texture in order to "
                            "apply an advanced blend.";
          return false;
        }

        FilterInput::Vector inputs = {
            FilterInput::Make(texture,
                              result.entity.GetTransformation().Invert()),
            FilterInput::Make(result.entity.GetContents())};
        auto contents = ColorFilterContents::MakeBlend(
            result.entity.GetBlendMode(), inputs);
        contents->SetCoverageHint(result.entity.GetCoverage());
        result.entity.SetContents(std::move(contents));
        result.entity.SetBlendMode(BlendMode::kSource);
      }
    }

    //--------------------------------------------------------------------------
    /// Render the Element.
    ///

    if (!render_element(result.entity)) {
      // Specific validation logs are handled in `render_element()`.
      return false;
    }
  }

#ifdef IMPELLER_DEBUG
  //--------------------------------------------------------------------------
  /// Draw debug checkerboard over offscreen textures.
  ///

  // When the pass depth is > 0, this EntityPass is being rendered to an
  // offscreen texture.
  if (enable_offscreen_debug_checkerboard_ &&
      !collapsed_parent_pass.has_value() && pass_depth > 0) {
    auto result = pass_context.GetRenderPass(pass_depth);
    if (!result.pass) {
      // Failure to produce a render pass should be explained by specific errors
      // in `InlinePassContext::GetRenderPass()`.
      return false;
    }
    auto checkerboard = CheckerboardContents();
    auto color = ColorHSB(0,                                    // hue
                          1,                                    // saturation
                          std::max(0.0, 0.6 - pass_depth / 5),  // brightness
                          0.25);                                // alpha
    checkerboard.SetColor(Color(color));
    checkerboard.Render(renderer, {}, *result.pass);
  }
#endif

  return true;
}

void EntityPass::IterateAllEntities(
    const std::function<bool(Entity&)>& iterator) {
  if (!iterator) {
    return;
  }

  for (auto& element : elements_) {
    if (auto entity = std::get_if<Entity>(&element)) {
      if (!iterator(*entity)) {
        return;
      }
      continue;
    }
    if (auto subpass = std::get_if<std::unique_ptr<EntityPass>>(&element)) {
      subpass->get()->IterateAllEntities(iterator);
      continue;
    }
    FML_UNREACHABLE();
  }
}

bool EntityPass::IterateUntilSubpass(
    const std::function<bool(Entity&)>& iterator) {
  if (!iterator) {
    return true;
  }

  for (auto& element : elements_) {
    if (auto entity = std::get_if<Entity>(&element)) {
      if (!iterator(*entity)) {
        return false;
      }
      continue;
    }
    return true;
  }
  return false;
}

size_t EntityPass::GetElementCount() const {
  return elements_.size();
}

std::unique_ptr<EntityPass> EntityPass::Clone() const {
  std::vector<Element> new_elements;
  new_elements.reserve(elements_.size());

  for (const auto& element : elements_) {
    if (auto entity = std::get_if<Entity>(&element)) {
      new_elements.push_back(*entity);
      continue;
    }
    if (auto subpass = std::get_if<std::unique_ptr<EntityPass>>(&element)) {
      new_elements.push_back(subpass->get()->Clone());
      continue;
    }
    FML_UNREACHABLE();
  }

  auto pass = std::make_unique<EntityPass>();
  pass->SetElements(std::move(new_elements));
  return pass;
}

void EntityPass::SetTransformation(Matrix xformation) {
  xformation_ = xformation;
}

void EntityPass::SetStencilDepth(size_t stencil_depth) {
  stencil_depth_ = stencil_depth;
}

void EntityPass::SetBlendMode(BlendMode blend_mode) {
  blend_mode_ = blend_mode;
  flood_clip_ = Entity::IsBlendModeDestructive(blend_mode);
}

Color EntityPass::GetClearColor(ISize target_size) const {
  Color result = Color::BlackTransparent();
  for (const Element& element : elements_) {
    auto [entity_color, blend_mode] =
        ElementAsBackgroundColor(element, target_size);
    if (!entity_color.has_value()) {
      break;
    }
    result = result.Blend(entity_color.value(), blend_mode);
  }
  return result.Premultiply();
}

void EntityPass::SetBackdropFilter(BackdropFilterProc proc) {
  if (superpass_) {
    VALIDATION_LOG << "Backdrop filters cannot be set on EntityPasses that "
                      "have already been appended to another pass.";
  }

  backdrop_filter_proc_ = std::move(proc);
}

void EntityPass::SetEnableOffscreenCheckerboard(bool enabled) {
  enable_offscreen_debug_checkerboard_ = enabled;
}

}  // namespace impeller
