// 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/renderer/backend/gles/blit_command_gles.h"

#include "flutter/fml/closure.h"
#include "impeller/base/validation.h"
#include "impeller/renderer/backend/gles/device_buffer_gles.h"
#include "impeller/renderer/backend/gles/texture_gles.h"

namespace impeller {

BlitEncodeGLES::~BlitEncodeGLES() = default;

static void DeleteFBO(const ProcTableGLES& gl, GLuint fbo, GLenum type) {
  if (fbo != GL_NONE) {
    gl.BindFramebuffer(type, GL_NONE);
    gl.DeleteFramebuffers(1u, &fbo);
  }
};

static std::optional<GLuint> ConfigureFBO(
    const ProcTableGLES& gl,
    const std::shared_ptr<Texture>& texture,
    GLenum fbo_type) {
  auto handle = TextureGLES::Cast(texture.get())->GetGLHandle();
  if (!handle.has_value()) {
    return std::nullopt;
  }

  if (TextureGLES::Cast(*texture).IsWrapped()) {
    // The texture is attached to the default FBO, so there's no need to
    // create/configure one.
    gl.BindFramebuffer(fbo_type, 0);
    return 0;
  }

  GLuint fbo;
  gl.GenFramebuffers(1u, &fbo);
  gl.BindFramebuffer(fbo_type, fbo);

  if (!TextureGLES::Cast(*texture).SetAsFramebufferAttachment(
          fbo_type, TextureGLES::AttachmentType::kColor0)) {
    VALIDATION_LOG << "Could not attach texture to framebuffer.";
    DeleteFBO(gl, fbo, fbo_type);
    return std::nullopt;
  }

  if (gl.CheckFramebufferStatus(fbo_type) != GL_FRAMEBUFFER_COMPLETE) {
    VALIDATION_LOG << "Could not create a complete framebuffer.";
    DeleteFBO(gl, fbo, fbo_type);
    return std::nullopt;
  }

  return fbo;
};

BlitCopyTextureToTextureCommandGLES::~BlitCopyTextureToTextureCommandGLES() =
    default;

std::string BlitCopyTextureToTextureCommandGLES::GetLabel() const {
  return label;
}

bool BlitCopyTextureToTextureCommandGLES::Encode(
    const ReactorGLES& reactor) const {
  const auto& gl = reactor.GetProcTable();

  // glBlitFramebuffer is a GLES3 proc. Since we target GLES2, we need to
  // emulate the blit when it's not available in the driver.
  if (!gl.BlitFramebuffer.IsAvailable()) {
    // TODO(bdero): Emulate the blit using a raster draw call here.
    FML_LOG(ERROR) << "Texture blit fallback not implemented yet for GLES2.";
    return false;
  }

  GLuint read_fbo = GL_NONE;
  GLuint draw_fbo = GL_NONE;
  fml::ScopedCleanupClosure delete_fbos([&gl, &read_fbo, &draw_fbo]() {
    DeleteFBO(gl, read_fbo, GL_READ_FRAMEBUFFER);
    DeleteFBO(gl, draw_fbo, GL_DRAW_FRAMEBUFFER);
  });

  {
    auto read = ConfigureFBO(gl, source, GL_READ_FRAMEBUFFER);
    if (!read.has_value()) {
      return false;
    }
    read_fbo = read.value();
  }

  {
    auto draw = ConfigureFBO(gl, destination, GL_DRAW_FRAMEBUFFER);
    if (!draw.has_value()) {
      return false;
    }
    draw_fbo = draw.value();
  }

  gl.Disable(GL_SCISSOR_TEST);
  gl.Disable(GL_DEPTH_TEST);
  gl.Disable(GL_STENCIL_TEST);

  gl.BlitFramebuffer(source_region.GetX(),       // srcX0
                     source_region.GetY(),       // srcY0
                     source_region.GetWidth(),   // srcX1
                     source_region.GetHeight(),  // srcY1
                     destination_origin.x,       // dstX0
                     destination_origin.y,       // dstY0
                     source_region.GetWidth(),   // dstX1
                     source_region.GetHeight(),  // dstY1
                     GL_COLOR_BUFFER_BIT,        // mask
                     GL_NEAREST                  // filter
  );

  return true;
};

BlitCopyTextureToBufferCommandGLES::~BlitCopyTextureToBufferCommandGLES() =
    default;

std::string BlitCopyTextureToBufferCommandGLES::GetLabel() const {
  return label;
}

bool BlitCopyTextureToBufferCommandGLES::Encode(
    const ReactorGLES& reactor) const {
  if (source->GetTextureDescriptor().format != PixelFormat::kR8G8B8A8UNormInt) {
    VALIDATION_LOG << "Only textures with pixel format RGBA are supported yet.";
    return false;
  }

  const auto& gl = reactor.GetProcTable();

  GLuint read_fbo = GL_NONE;
  fml::ScopedCleanupClosure delete_fbos(
      [&gl, &read_fbo]() { DeleteFBO(gl, read_fbo, GL_READ_FRAMEBUFFER); });

  {
    auto read = ConfigureFBO(gl, source, GL_READ_FRAMEBUFFER);
    if (!read.has_value()) {
      return false;
    }
    read_fbo = read.value();
  }

  DeviceBufferGLES::Cast(*destination)
      .UpdateBufferData([&gl, this](uint8_t* data, size_t length) {
        gl.ReadPixels(source_region.GetX(), source_region.GetY(),
                      source_region.GetWidth(), source_region.GetHeight(),
                      GL_RGBA, GL_UNSIGNED_BYTE, data + destination_offset);
      });

  return true;
};

BlitGenerateMipmapCommandGLES::~BlitGenerateMipmapCommandGLES() = default;

std::string BlitGenerateMipmapCommandGLES::GetLabel() const {
  return label;
}

bool BlitGenerateMipmapCommandGLES::Encode(const ReactorGLES& reactor) const {
  auto texture_gles = TextureGLES::Cast(texture.get());
  if (!texture_gles->GenerateMipmap()) {
    return false;
  }

  return true;
};

}  // namespace impeller
