// 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(size.width, size.height), Point(1, 1)},
      {Point(0, 0), Point(0, 0)},
      {Point(size.width, size.height), Point(1, 1)},
      {Point(0, size.height), Point(0, 1)},
  });
  auto vtx_buffer = vtx_builder.CreateVertexBuffer(host_buffer);

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

  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()) {
    // No known devices that support framebuffer fetch but not decal tile mode.
    return false;
  }
  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
