// 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"
#include "impeller/renderer/sampler_library.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 = pass.GetTransientsBuffer();

  auto src_snapshot = child_contents_->RenderToSnapshot(
      renderer,                                    // renderer
      entity,                                      // entity
      Rect::MakeSize(pass.GetRenderTargetSize()),  // coverage_limit
      std::nullopt,                                // sampler_descriptor
      true,                                        // msaa_enabled
      "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.size;
  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 vtx_buffer = vtx_builder.CreateVertexBuffer(host_buffer);

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

  Command cmd;
  DEBUG_COMMAND_INFO(cmd, "Framebuffer Advanced Blend Filter");
  cmd.BindVertices(vtx_buffer);
  cmd.stencil_reference = entity.GetClipDepth();

  switch (blend_mode_) {
    case BlendMode::kScreen:
      cmd.pipeline = renderer.GetFramebufferBlendScreenPipeline(options);
      break;
    case BlendMode::kOverlay:
      cmd.pipeline = renderer.GetFramebufferBlendOverlayPipeline(options);
      break;
    case BlendMode::kDarken:
      cmd.pipeline = renderer.GetFramebufferBlendDarkenPipeline(options);
      break;
    case BlendMode::kLighten:
      cmd.pipeline = renderer.GetFramebufferBlendLightenPipeline(options);
      break;
    case BlendMode::kColorDodge:
      cmd.pipeline = renderer.GetFramebufferBlendColorDodgePipeline(options);
      break;
    case BlendMode::kColorBurn:
      cmd.pipeline = renderer.GetFramebufferBlendColorBurnPipeline(options);
      break;
    case BlendMode::kHardLight:
      cmd.pipeline = renderer.GetFramebufferBlendHardLightPipeline(options);
      break;
    case BlendMode::kSoftLight:
      cmd.pipeline = renderer.GetFramebufferBlendSoftLightPipeline(options);
      break;
    case BlendMode::kDifference:
      cmd.pipeline = renderer.GetFramebufferBlendDifferencePipeline(options);
      break;
    case BlendMode::kExclusion:
      cmd.pipeline = renderer.GetFramebufferBlendExclusionPipeline(options);
      break;
    case BlendMode::kMultiply:
      cmd.pipeline = renderer.GetFramebufferBlendMultiplyPipeline(options);
      break;
    case BlendMode::kHue:
      cmd.pipeline = renderer.GetFramebufferBlendHuePipeline(options);
      break;
    case BlendMode::kSaturation:
      cmd.pipeline = renderer.GetFramebufferBlendSaturationPipeline(options);
      break;
    case BlendMode::kColor:
      cmd.pipeline = renderer.GetFramebufferBlendColorPipeline(options);
      break;
    case BlendMode::kLuminosity:
      cmd.pipeline = 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;
  }
  auto src_sampler = renderer.GetContext()->GetSamplerLibrary()->GetSampler(
      src_sampler_descriptor);
  FS::BindTextureSamplerSrc(cmd, src_snapshot->texture, src_sampler);

  frame_info.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) *
                   src_snapshot->transform;
  frame_info.src_y_coord_scale = src_snapshot->texture->GetYCoordScale();
  VS::BindFrameInfo(cmd, host_buffer.EmplaceUniform(frame_info));

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

  return pass.AddCommand(std::move(cmd));
}

}  // namespace impeller
