// 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 "flutter/lib/gpu/render_pass.h"
#include <future>
#include <memory>

#include "flutter/lib/gpu/formats.h"
#include "flutter/lib/gpu/render_pipeline.h"
#include "flutter/lib/gpu/shader.h"
#include "fml/make_copyable.h"
#include "fml/memory/ref_ptr.h"
#include "impeller/core/buffer_view.h"
#include "impeller/core/formats.h"
#include "impeller/core/sampler_descriptor.h"
#include "impeller/core/shader_types.h"
#include "impeller/core/vertex_buffer.h"
#include "impeller/geometry/color.h"
#include "impeller/renderer/pipeline.h"
#include "impeller/renderer/pipeline_descriptor.h"
#include "impeller/renderer/pipeline_library.h"
#include "lib/ui/ui_dart_state.h"
#include "tonic/converter/dart_converter.h"

namespace flutter {
namespace gpu {

IMPLEMENT_WRAPPERTYPEINFO(flutter_gpu, RenderPass);

RenderPass::RenderPass()
    : vertex_buffer_(
          impeller::VertexBuffer{.index_type = impeller::IndexType::kNone}){};

RenderPass::~RenderPass() = default;

const std::shared_ptr<const impeller::Context>& RenderPass::GetContext() const {
  return render_pass_->GetContext();
}

impeller::Command& RenderPass::GetCommand() {
  return command_;
}

const impeller::Command& RenderPass::GetCommand() const {
  return command_;
}

impeller::RenderTarget& RenderPass::GetRenderTarget() {
  return render_target_;
}

const impeller::RenderTarget& RenderPass::GetRenderTarget() const {
  return render_target_;
}

impeller::ColorAttachmentDescriptor& RenderPass::GetColorAttachmentDescriptor(
    size_t color_attachment_index) {
  auto color = color_descriptors_.find(color_attachment_index);
  if (color == color_descriptors_.end()) {
    return color_descriptors_[color_attachment_index] = {};
  }
  return color->second;
}

impeller::DepthAttachmentDescriptor&
RenderPass::GetDepthAttachmentDescriptor() {
  return depth_desc_;
}

impeller::StencilAttachmentDescriptor&
RenderPass::GetStencilFrontAttachmentDescriptor() {
  return stencil_front_desc_;
}

impeller::StencilAttachmentDescriptor&
RenderPass::GetStencilBackAttachmentDescriptor() {
  return stencil_back_desc_;
}

impeller::VertexBuffer& RenderPass::GetVertexBuffer() {
  return vertex_buffer_;
}

impeller::PipelineDescriptor& RenderPass::GetPipelineDescriptor() {
  return pipeline_descriptor_;
}

bool RenderPass::Begin(flutter::gpu::CommandBuffer& command_buffer) {
  render_pass_ =
      command_buffer.GetCommandBuffer()->CreateRenderPass(render_target_);
  if (!render_pass_) {
    return false;
  }
  command_buffer.AddRenderPass(render_pass_);
  return true;
}

void RenderPass::SetPipeline(fml::RefPtr<RenderPipeline> pipeline) {
  render_pipeline_ = std::move(pipeline);
}

std::shared_ptr<impeller::Pipeline<impeller::PipelineDescriptor>>
RenderPass::GetOrCreatePipeline() {
  // Infer the pipeline layout based on the shape of the RenderTarget.
  auto pipeline_desc = pipeline_descriptor_;
  for (const auto& it : render_target_.GetColorAttachments()) {
    auto& color = GetColorAttachmentDescriptor(it.first);
    color.format = render_target_.GetRenderTargetPixelFormat();
  }
  pipeline_desc.SetColorAttachmentDescriptors(color_descriptors_);

  {
    auto stencil = render_target_.GetStencilAttachment();
    if (stencil && impeller::IsStencilWritable(
                       stencil->texture->GetTextureDescriptor().format)) {
      pipeline_desc.SetStencilPixelFormat(
          stencil->texture->GetTextureDescriptor().format);
      pipeline_desc.SetStencilAttachmentDescriptors(stencil_front_desc_,
                                                    stencil_back_desc_);
    } else {
      pipeline_desc.ClearStencilAttachments();
    }
  }

  {
    auto depth = render_target_.GetDepthAttachment();
    if (depth && impeller::IsDepthWritable(
                     depth->texture->GetTextureDescriptor().format)) {
      pipeline_desc.SetDepthPixelFormat(
          depth->texture->GetTextureDescriptor().format);
      pipeline_desc.SetDepthStencilAttachmentDescriptor(depth_desc_);
    } else {
      pipeline_desc.ClearDepthAttachment();
    }
  }

  auto& context = *GetContext();

  render_pipeline_->BindToPipelineDescriptor(*context.GetShaderLibrary(),
                                             pipeline_desc);

  std::shared_ptr<impeller::Pipeline<impeller::PipelineDescriptor>> pipeline;

  if (context.GetBackendType() == impeller::Context::BackendType::kOpenGLES &&
      !context.GetPipelineLibrary()->HasPipeline(pipeline_desc)) {
    // For GLES, new pipeline creation must be done on the reactor (raster)
    // thread. We're about the draw, so we need to synchronize with a raster
    // task in order to get the new pipeline. Depending on how busy the raster
    // thread is, this could hang the UI thread long enough to miss a frame.

    // Note that this branch is only called if a new pipeline actually needs to
    // be built.
    auto dart_state = flutter::UIDartState::Current();
    std::promise<
        std::shared_ptr<impeller::Pipeline<impeller::PipelineDescriptor>>>
        pipeline_promise;
    auto pipeline_future = pipeline_promise.get_future();
    fml::TaskRunner::RunNowOrPostTask(
        dart_state->GetTaskRunners().GetRasterTaskRunner(),
        fml::MakeCopyable([promise = std::move(pipeline_promise),
                           context = GetContext(), pipeline_desc]() mutable {
          promise.set_value(
              context->GetPipelineLibrary()->GetPipeline(pipeline_desc).Get());
        }));
    pipeline = pipeline_future.get();
  } else {
    pipeline = context.GetPipelineLibrary()->GetPipeline(pipeline_desc).Get();
  }

  FML_DCHECK(pipeline) << "Couldn't resolve render pipeline";
  return pipeline;
}

impeller::Command RenderPass::ProvisionRasterCommand() {
  impeller::Command result = command_;

  result.pipeline = GetOrCreatePipeline();
  result.BindVertices(vertex_buffer_);

  return result;
}

bool RenderPass::Draw() {
  impeller::Command result = ProvisionRasterCommand();
#ifdef IMPELLER_DEBUG
  render_pass_->SetCommandLabel(result.label);
#endif  // IMPELLER_DEBUG
  render_pass_->SetPipeline(result.pipeline);
  render_pass_->SetStencilReference(result.stencil_reference);
  render_pass_->SetBaseVertex(result.base_vertex);
  if (result.viewport.has_value()) {
    render_pass_->SetViewport(result.viewport.value());
  }
  if (result.scissor.has_value()) {
    render_pass_->SetScissor(result.scissor.value());
  }
  render_pass_->SetVertexBuffer(result.vertex_buffer);
  for (const auto& buffer : result.vertex_bindings.buffers) {
    render_pass_->BindResource(impeller::ShaderStage::kVertex,
                               impeller::DescriptorType::kUniformBuffer,
                               buffer.slot, *buffer.view.GetMetadata(),
                               buffer.view.resource);
  }
  for (const auto& texture : result.vertex_bindings.sampled_images) {
    render_pass_->BindResource(impeller::ShaderStage::kVertex,
                               impeller::DescriptorType::kSampledImage,
                               texture.slot, *texture.texture.GetMetadata(),
                               texture.texture.resource, texture.sampler);
  }
  for (const auto& buffer : result.fragment_bindings.buffers) {
    render_pass_->BindResource(impeller::ShaderStage::kFragment,
                               impeller::DescriptorType::kUniformBuffer,
                               buffer.slot, *buffer.view.GetMetadata(),
                               buffer.view.resource);
  }
  for (const auto& texture : result.fragment_bindings.sampled_images) {
    render_pass_->BindResource(impeller::ShaderStage::kFragment,
                               impeller::DescriptorType::kSampledImage,
                               texture.slot, *texture.texture.GetMetadata(),
                               texture.texture.resource, texture.sampler);
  }
  return render_pass_->Draw().ok();
}

}  // namespace gpu
}  // namespace flutter

//----------------------------------------------------------------------------
/// Exports
///

void InternalFlutterGpu_RenderPass_Initialize(Dart_Handle wrapper) {
  auto res = fml::MakeRefCounted<flutter::gpu::RenderPass>();
  res->AssociateWithDartWrapper(wrapper);
}

Dart_Handle InternalFlutterGpu_RenderPass_SetColorAttachment(
    flutter::gpu::RenderPass* wrapper,
    int color_attachment_index,
    int load_action,
    int store_action,
    float clear_color_r,
    float clear_color_g,
    float clear_color_b,
    float clear_color_a,
    flutter::gpu::Texture* texture,
    Dart_Handle resolve_texture_wrapper) {
  impeller::ColorAttachment desc;
  desc.load_action = flutter::gpu::ToImpellerLoadAction(load_action);
  desc.store_action = flutter::gpu::ToImpellerStoreAction(store_action);
  desc.clear_color = impeller::Color(clear_color_r, clear_color_g,
                                     clear_color_b, clear_color_a);
  desc.texture = texture->GetTexture();
  if (!Dart_IsNull(resolve_texture_wrapper)) {
    flutter::gpu::Texture* resolve_texture =
        tonic::DartConverter<flutter::gpu::Texture*>::FromDart(
            resolve_texture_wrapper);
    desc.resolve_texture = resolve_texture->GetTexture();
  }
  wrapper->GetRenderTarget().SetColorAttachment(desc, color_attachment_index);
  return Dart_Null();
}

Dart_Handle InternalFlutterGpu_RenderPass_SetDepthStencilAttachment(
    flutter::gpu::RenderPass* wrapper,
    int depth_load_action,
    int depth_store_action,
    float depth_clear_value,
    int stencil_load_action,
    int stencil_store_action,
    int stencil_clear_value,
    flutter::gpu::Texture* texture) {
  {
    impeller::DepthAttachment desc;
    desc.load_action = flutter::gpu::ToImpellerLoadAction(depth_load_action);
    desc.store_action = flutter::gpu::ToImpellerStoreAction(depth_store_action);
    desc.clear_depth = depth_clear_value;
    desc.texture = texture->GetTexture();
    wrapper->GetRenderTarget().SetDepthAttachment(desc);
  }
  {
    impeller::StencilAttachment desc;
    desc.load_action = flutter::gpu::ToImpellerLoadAction(stencil_load_action);
    desc.store_action =
        flutter::gpu::ToImpellerStoreAction(stencil_store_action);
    desc.clear_stencil = stencil_clear_value;
    desc.texture = texture->GetTexture();
    wrapper->GetRenderTarget().SetStencilAttachment(desc);
  }

  return Dart_Null();
}

Dart_Handle InternalFlutterGpu_RenderPass_Begin(
    flutter::gpu::RenderPass* wrapper,
    flutter::gpu::CommandBuffer* command_buffer) {
  if (!wrapper->Begin(*command_buffer)) {
    return tonic::ToDart("Failed to begin RenderPass");
  }
  return Dart_Null();
}

void InternalFlutterGpu_RenderPass_BindPipeline(
    flutter::gpu::RenderPass* wrapper,
    flutter::gpu::RenderPipeline* pipeline) {
  auto ref = fml::RefPtr<flutter::gpu::RenderPipeline>(pipeline);
  wrapper->SetPipeline(std::move(ref));
}

template <typename TBuffer>
static void BindVertexBuffer(flutter::gpu::RenderPass* wrapper,
                             TBuffer buffer,
                             int offset_in_bytes,
                             int length_in_bytes,
                             int vertex_count) {
  auto& vertex_buffer = wrapper->GetVertexBuffer();
  vertex_buffer.vertex_buffer = impeller::BufferView{
      .buffer = buffer,
      .range = impeller::Range(offset_in_bytes, length_in_bytes),
  };
  // If the index type is set, then the `vertex_count` becomes the index
  // count... So don't overwrite the count if it's already been set when binding
  // the index buffer.
  // TODO(bdero): Consider just doing a more traditional API with
  //              draw(vertexCount) and drawIndexed(indexCount). This is fine,
  //              but overall it would be a bit more explicit and we wouldn't
  //              have to document this behavior where the presence of the index
  //              buffer always takes precedent.
  if (vertex_buffer.index_type == impeller::IndexType::kNone) {
    vertex_buffer.vertex_count = vertex_count;
  }
}

void InternalFlutterGpu_RenderPass_BindVertexBufferDevice(
    flutter::gpu::RenderPass* wrapper,
    flutter::gpu::DeviceBuffer* device_buffer,
    int offset_in_bytes,
    int length_in_bytes,
    int vertex_count) {
  BindVertexBuffer(wrapper, device_buffer->GetBuffer(), offset_in_bytes,
                   length_in_bytes, vertex_count);
}

void InternalFlutterGpu_RenderPass_BindVertexBufferHost(
    flutter::gpu::RenderPass* wrapper,
    flutter::gpu::HostBuffer* host_buffer,
    int offset_in_bytes,
    int length_in_bytes,
    int vertex_count) {
  std::optional<impeller::BufferView> view =
      host_buffer->GetBufferViewForOffset(offset_in_bytes);
  if (!view.has_value()) {
    FML_LOG(ERROR)
        << "Failed to bind vertex buffer due to invalid HostBuffer offset: "
        << offset_in_bytes;
    return;
  }
  BindVertexBuffer(wrapper, view->buffer, view->range.offset,
                   view->range.length, vertex_count);
}

template <typename TBuffer>
static void BindIndexBuffer(flutter::gpu::RenderPass* wrapper,
                            TBuffer buffer,
                            int offset_in_bytes,
                            int length_in_bytes,
                            int index_type,
                            int index_count) {
  auto& vertex_buffer = wrapper->GetVertexBuffer();
  vertex_buffer.index_buffer = impeller::BufferView{
      .buffer = buffer,
      .range = impeller::Range(offset_in_bytes, length_in_bytes),
  };
  vertex_buffer.index_type = flutter::gpu::ToImpellerIndexType(index_type);
  vertex_buffer.vertex_count = index_count;
}

void InternalFlutterGpu_RenderPass_BindIndexBufferDevice(
    flutter::gpu::RenderPass* wrapper,
    flutter::gpu::DeviceBuffer* device_buffer,
    int offset_in_bytes,
    int length_in_bytes,
    int index_type,
    int index_count) {
  BindIndexBuffer(wrapper, device_buffer->GetBuffer(), offset_in_bytes,
                  length_in_bytes, index_type, index_count);
}

void InternalFlutterGpu_RenderPass_BindIndexBufferHost(
    flutter::gpu::RenderPass* wrapper,
    flutter::gpu::HostBuffer* host_buffer,
    int offset_in_bytes,
    int length_in_bytes,
    int index_type,
    int index_count) {
  auto view = host_buffer->GetBufferViewForOffset(offset_in_bytes);
  if (!view.has_value()) {
    FML_LOG(ERROR)
        << "Failed to bind index buffer due to invalid HostBuffer offset: "
        << offset_in_bytes;
    return;
  }
  BindIndexBuffer(wrapper, view->buffer, view->range.offset, view->range.length,
                  index_type, index_count);
}

template <typename TBuffer>
static bool BindUniform(flutter::gpu::RenderPass* wrapper,
                        flutter::gpu::Shader* shader,
                        Dart_Handle uniform_name_handle,
                        TBuffer buffer,
                        int offset_in_bytes,
                        int length_in_bytes) {
  auto& command = wrapper->GetCommand();

  auto uniform_name = tonic::StdStringFromDart(uniform_name_handle);
  const flutter::gpu::Shader::UniformBinding* uniform_struct =
      shader->GetUniformStruct(uniform_name);
  // TODO(bdero): Return an error string stating that no uniform struct with
  //              this name exists and throw an exception.
  if (!uniform_struct) {
    return false;
  }

  return command.BindResource(
      shader->GetShaderStage(), impeller::DescriptorType::kUniformBuffer,
      uniform_struct->slot, uniform_struct->metadata,
      impeller::BufferView{
          .buffer = buffer,
          .range = impeller::Range(offset_in_bytes, length_in_bytes),
      });
}

bool InternalFlutterGpu_RenderPass_BindUniformDevice(
    flutter::gpu::RenderPass* wrapper,
    flutter::gpu::Shader* shader,
    Dart_Handle uniform_name_handle,
    flutter::gpu::DeviceBuffer* device_buffer,
    int offset_in_bytes,
    int length_in_bytes) {
  return BindUniform(wrapper, shader, uniform_name_handle,
                     device_buffer->GetBuffer(), offset_in_bytes,
                     length_in_bytes);
}

bool InternalFlutterGpu_RenderPass_BindUniformHost(
    flutter::gpu::RenderPass* wrapper,
    flutter::gpu::Shader* shader,
    Dart_Handle uniform_name_handle,
    flutter::gpu::HostBuffer* host_buffer,
    int offset_in_bytes,
    int length_in_bytes) {
  auto view = host_buffer->GetBufferViewForOffset(offset_in_bytes);
  if (!view.has_value()) {
    FML_LOG(ERROR)
        << "Failed to bind index buffer due to invalid HostBuffer offset: "
        << offset_in_bytes;
    return false;
  }
  return BindUniform(wrapper, shader, uniform_name_handle, view->buffer,
                     view->range.offset, view->range.length);
}

bool InternalFlutterGpu_RenderPass_BindTexture(
    flutter::gpu::RenderPass* wrapper,
    flutter::gpu::Shader* shader,
    Dart_Handle uniform_name_handle,
    flutter::gpu::Texture* texture,
    int min_filter,
    int mag_filter,
    int mip_filter,
    int width_address_mode,
    int height_address_mode) {
  auto& command = wrapper->GetCommand();

  auto uniform_name = tonic::StdStringFromDart(uniform_name_handle);
  const flutter::gpu::Shader::TextureBinding* texture_binding =
      shader->GetUniformTexture(uniform_name);
  // TODO(bdero): Return an error string stating that no uniform texture with
  //              this name exists and throw an exception.
  if (!texture_binding) {
    return false;
  }

  impeller::SamplerDescriptor sampler_desc;
  sampler_desc.min_filter = flutter::gpu::ToImpellerMinMagFilter(min_filter);
  sampler_desc.mag_filter = flutter::gpu::ToImpellerMinMagFilter(mag_filter);
  sampler_desc.mip_filter = flutter::gpu::ToImpellerMipFilter(mip_filter);
  sampler_desc.width_address_mode =
      flutter::gpu::ToImpellerSamplerAddressMode(width_address_mode);
  sampler_desc.height_address_mode =
      flutter::gpu::ToImpellerSamplerAddressMode(height_address_mode);
  const std::unique_ptr<const impeller::Sampler>& sampler =
      wrapper->GetContext()->GetSamplerLibrary()->GetSampler(sampler_desc);
  return command.BindResource(shader->GetShaderStage(),
                              impeller::DescriptorType::kSampledImage,
                              texture_binding->slot, texture_binding->metadata,
                              texture->GetTexture(), sampler);
}

void InternalFlutterGpu_RenderPass_ClearBindings(
    flutter::gpu::RenderPass* wrapper) {
  auto& command = wrapper->GetCommand();
  command.vertex_buffer = {};
  command.vertex_bindings = {};
  command.fragment_bindings = {};
}

void InternalFlutterGpu_RenderPass_SetColorBlendEnable(
    flutter::gpu::RenderPass* wrapper,
    int color_attachment_index,
    bool enable) {
  auto& color = wrapper->GetColorAttachmentDescriptor(color_attachment_index);
  color.blending_enabled = enable;
}

void InternalFlutterGpu_RenderPass_SetColorBlendEquation(
    flutter::gpu::RenderPass* wrapper,
    int color_attachment_index,
    int color_blend_operation,
    int source_color_blend_factor,
    int destination_color_blend_factor,
    int alpha_blend_operation,
    int source_alpha_blend_factor,
    int destination_alpha_blend_factor) {
  auto& color = wrapper->GetColorAttachmentDescriptor(color_attachment_index);
  color.color_blend_op =
      flutter::gpu::ToImpellerBlendOperation(color_blend_operation);
  color.src_color_blend_factor =
      flutter::gpu::ToImpellerBlendFactor(source_color_blend_factor);
  color.dst_color_blend_factor =
      flutter::gpu::ToImpellerBlendFactor(destination_color_blend_factor);
  color.alpha_blend_op =
      flutter::gpu::ToImpellerBlendOperation(alpha_blend_operation);
  color.src_alpha_blend_factor =
      flutter::gpu::ToImpellerBlendFactor(source_alpha_blend_factor);
  color.dst_alpha_blend_factor =
      flutter::gpu::ToImpellerBlendFactor(destination_alpha_blend_factor);
}

void InternalFlutterGpu_RenderPass_SetDepthWriteEnable(
    flutter::gpu::RenderPass* wrapper,
    bool enable) {
  auto& depth = wrapper->GetDepthAttachmentDescriptor();
  depth.depth_write_enabled = true;
}

void InternalFlutterGpu_RenderPass_SetDepthCompareOperation(
    flutter::gpu::RenderPass* wrapper,
    int compare_operation) {
  auto& depth = wrapper->GetDepthAttachmentDescriptor();
  depth.depth_compare =
      flutter::gpu::ToImpellerCompareFunction(compare_operation);
}

void InternalFlutterGpu_RenderPass_SetStencilReference(
    flutter::gpu::RenderPass* wrapper,
    int stencil_reference) {
  auto& command = wrapper->GetCommand();
  command.stencil_reference = static_cast<uint32_t>(stencil_reference);
}

void InternalFlutterGpu_RenderPass_SetStencilConfig(
    flutter::gpu::RenderPass* wrapper,
    int stencil_compare_operation,
    int stencil_fail_operation,
    int depth_fail_operation,
    int depth_stencil_pass_operation,
    int read_mask,
    int write_mask,
    int target_face) {
  impeller::StencilAttachmentDescriptor desc;
  desc.stencil_compare =
      flutter::gpu::ToImpellerCompareFunction(stencil_compare_operation);
  desc.stencil_failure =
      flutter::gpu::ToImpellerStencilOperation(stencil_fail_operation);
  desc.depth_failure =
      flutter::gpu::ToImpellerStencilOperation(depth_fail_operation);
  desc.depth_stencil_pass =
      flutter::gpu::ToImpellerStencilOperation(depth_stencil_pass_operation);
  desc.read_mask = static_cast<uint32_t>(read_mask);
  desc.write_mask = static_cast<uint32_t>(write_mask);

  // Corresponds to the `StencilFace` enum in `gpu/lib/src/render_pass.dart`.
  if (target_face != 2 /* both or front */) {
    wrapper->GetStencilFrontAttachmentDescriptor() = desc;
  }
  if (target_face != 1 /* both or back */) {
    wrapper->GetStencilBackAttachmentDescriptor() = desc;
  }
}

void InternalFlutterGpu_RenderPass_SetCullMode(
    flutter::gpu::RenderPass* wrapper,
    int cull_mode) {
  impeller::PipelineDescriptor& pipeline_descriptor =
      wrapper->GetPipelineDescriptor();
  pipeline_descriptor.SetCullMode(flutter::gpu::ToImpellerCullMode(cull_mode));
}

void InternalFlutterGpu_RenderPass_SetPrimitiveType(
    flutter::gpu::RenderPass* wrapper,
    int primitive_type) {
  impeller::PipelineDescriptor& pipeline_descriptor =
      wrapper->GetPipelineDescriptor();
  pipeline_descriptor.SetPrimitiveType(
      flutter::gpu::ToImpellerPrimitiveType(primitive_type));
}

void InternalFlutterGpu_RenderPass_SetWindingOrder(
    flutter::gpu::RenderPass* wrapper,
    int winding_order) {
  impeller::PipelineDescriptor& pipeline_descriptor =
      wrapper->GetPipelineDescriptor();
  pipeline_descriptor.SetWindingOrder(
      flutter::gpu::ToImpellerWindingOrder(winding_order));
}

bool InternalFlutterGpu_RenderPass_Draw(flutter::gpu::RenderPass* wrapper) {
  return wrapper->Draw();
}
