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

#include "impeller/entity/contents/content_context.h"
#include "impeller/renderer/render_pass.h"

namespace impeller {

FramebufferBlendContents::FramebufferBlendContents() = default;

FramebufferBlendContents::~FramebufferBlendContents() = default;

void FramebufferBlendContents::SetBlendMode(BlendMode blend_mode) {
  blend_mode_ = blend_mode;
}

void FramebufferBlendContents::SetChildContents(
    std::shared_ptr<Contents> child_contents) {
  child_contents_ = std::move(child_contents);
}

// |Contents|
std::optional<Rect> FramebufferBlendContents::GetCoverage(
    const Entity& entity) const {
  return child_contents_->GetCoverage(entity);
}

bool FramebufferBlendContents::Render(const ContentContext& renderer,
                                      const Entity& entity,
                                      RenderPass& pass) const {
  if (!renderer.GetDeviceCapabilities().SupportsFramebufferFetch()) {
    return false;
  }

  using VS = FramebufferBlendScreenPipeline::VertexShader;
  using FS = FramebufferBlendScreenPipeline::FragmentShader;

  auto& host_buffer = renderer.GetTransientsBuffer();

  auto src_snapshot = child_contents_->RenderToSnapshot(
      renderer,                                    // renderer
      entity,                                      // entity
      Rect::MakeSize(pass.GetRenderTargetSize()),  // coverage_limit
      std::nullopt,                                // sampler_descriptor
      true,                                        // msaa_enabled
      /*mip_count=*/1,
      "FramebufferBlendContents Snapshot");  // label

  if (!src_snapshot.has_value()) {
    return true;
  }
  auto coverage = src_snapshot->GetCoverage();
  if (!coverage.has_value()) {
    return true;
  }
  Rect src_coverage = coverage.value();

  auto size = src_coverage.GetSize();
  VertexBufferBuilder<VS::PerVertexData> vtx_builder;
  vtx_builder.AddVertices({
      {Point(0, 0), Point(0, 0)},
      {Point(size.width, 0), Point(1, 0)},
      {Point(0, size.height), Point(0, 1)},
      {Point(size.width, size.height), Point(1, 1)},
  });

  auto options = OptionsFromPass(pass);
  options.blend_mode = BlendMode::kSource;
  options.primitive_type = PrimitiveType::kTriangleStrip;

  pass.SetCommandLabel("Framebuffer Advanced Blend Filter");
  pass.SetVertexBuffer(vtx_builder.CreateVertexBuffer(host_buffer));
  pass.SetStencilReference(entity.GetClipDepth());

  switch (blend_mode_) {
    case BlendMode::kScreen:
      pass.SetPipeline(renderer.GetFramebufferBlendScreenPipeline(options));
      break;
    case BlendMode::kOverlay:
      pass.SetPipeline(renderer.GetFramebufferBlendOverlayPipeline(options));
      break;
    case BlendMode::kDarken:
      pass.SetPipeline(renderer.GetFramebufferBlendDarkenPipeline(options));
      break;
    case BlendMode::kLighten:
      pass.SetPipeline(renderer.GetFramebufferBlendLightenPipeline(options));
      break;
    case BlendMode::kColorDodge:
      pass.SetPipeline(renderer.GetFramebufferBlendColorDodgePipeline(options));
      break;
    case BlendMode::kColorBurn:
      pass.SetPipeline(renderer.GetFramebufferBlendColorBurnPipeline(options));
      break;
    case BlendMode::kHardLight:
      pass.SetPipeline(renderer.GetFramebufferBlendHardLightPipeline(options));
      break;
    case BlendMode::kSoftLight:
      pass.SetPipeline(renderer.GetFramebufferBlendSoftLightPipeline(options));
      break;
    case BlendMode::kDifference:
      pass.SetPipeline(renderer.GetFramebufferBlendDifferencePipeline(options));
      break;
    case BlendMode::kExclusion:
      pass.SetPipeline(renderer.GetFramebufferBlendExclusionPipeline(options));
      break;
    case BlendMode::kMultiply:
      pass.SetPipeline(renderer.GetFramebufferBlendMultiplyPipeline(options));
      break;
    case BlendMode::kHue:
      pass.SetPipeline(renderer.GetFramebufferBlendHuePipeline(options));
      break;
    case BlendMode::kSaturation:
      pass.SetPipeline(renderer.GetFramebufferBlendSaturationPipeline(options));
      break;
    case BlendMode::kColor:
      pass.SetPipeline(renderer.GetFramebufferBlendColorPipeline(options));
      break;
    case BlendMode::kPlusAdvanced:
      pass.SetPipeline(
          renderer.GetFramebufferBlendPlusAdvancedPipeline(options));
      break;
    case BlendMode::kLuminosity:
      pass.SetPipeline(renderer.GetFramebufferBlendLuminosityPipeline(options));
      break;
    default:
      return false;
  }

  VS::FrameInfo frame_info;
  FS::FragInfo frag_info;

  auto src_sampler_descriptor = src_snapshot->sampler_descriptor;
  if (renderer.GetDeviceCapabilities().SupportsDecalSamplerAddressMode()) {
    src_sampler_descriptor.width_address_mode = SamplerAddressMode::kDecal;
    src_sampler_descriptor.height_address_mode = SamplerAddressMode::kDecal;
  }
  const std::unique_ptr<const Sampler>& src_sampler =
      renderer.GetContext()->GetSamplerLibrary()->GetSampler(
          src_sampler_descriptor);
  FS::BindTextureSamplerSrc(pass, src_snapshot->texture, src_sampler);

  frame_info.mvp = Entity::GetShaderTransform(entity.GetShaderClipDepth(), pass,
                                              src_snapshot->transform);
  frame_info.src_y_coord_scale = src_snapshot->texture->GetYCoordScale();
  VS::BindFrameInfo(pass, host_buffer.EmplaceUniform(frame_info));

  frag_info.src_input_alpha = src_snapshot->opacity;
  FS::BindFragInfo(pass, host_buffer.EmplaceUniform(frag_info));

  return pass.Draw().ok();
}

}  // namespace impeller
