// 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/shell/platform/embedder/embedder_surface_gl_impeller.h"

#include <utility>

#include "impeller/entity/gles/entity_shaders_gles.h"
#include "impeller/entity/gles/framebuffer_blend_shaders_gles.h"
#include "impeller/entity/gles/modern_shaders_gles.h"
#include "impeller/renderer/backend/gles/context_gles.h"
#include "impeller/renderer/backend/gles/proc_table_gles.h"

#if IMPELLER_ENABLE_3D
#include "impeller/scene/shaders/gles/scene_shaders_gles.h"  // nogncheck
#endif  // IMPELLER_ENABLE_3D

namespace flutter {

class ReactorWorker final : public impeller::ReactorGLES::Worker {
 public:
  ReactorWorker() = default;

  // |ReactorGLES::Worker|
  bool CanReactorReactOnCurrentThreadNow(
      const impeller::ReactorGLES& reactor) const override {
    impeller::ReaderLock lock(mutex_);
    auto found = reactions_allowed_.find(std::this_thread::get_id());
    if (found == reactions_allowed_.end()) {
      return false;
    }
    return found->second;
  }

  void SetReactionsAllowedOnCurrentThread(bool allowed) {
    impeller::WriterLock lock(mutex_);
    reactions_allowed_[std::this_thread::get_id()] = allowed;
  }

 private:
  mutable impeller::RWMutex mutex_;
  std::map<std::thread::id, bool> reactions_allowed_ IPLR_GUARDED_BY(mutex_);

  FML_DISALLOW_COPY_AND_ASSIGN(ReactorWorker);
};

EmbedderSurfaceGLImpeller::EmbedderSurfaceGLImpeller(
    EmbedderSurfaceGL::GLDispatchTable gl_dispatch_table,
    bool fbo_reset_after_present,
    std::shared_ptr<EmbedderExternalViewEmbedder> external_view_embedder)
    : gl_dispatch_table_(std::move(gl_dispatch_table)),
      fbo_reset_after_present_(fbo_reset_after_present),
      external_view_embedder_(std::move(external_view_embedder)),
      worker_(std::make_shared<ReactorWorker>()) {
  // Make sure all required members of the dispatch table are checked.
  if (!gl_dispatch_table_.gl_make_current_callback ||
      !gl_dispatch_table_.gl_clear_current_callback ||
      !gl_dispatch_table_.gl_present_callback ||
      !gl_dispatch_table_.gl_fbo_callback ||
      !gl_dispatch_table_.gl_populate_existing_damage ||
      !gl_dispatch_table_.gl_proc_resolver) {
    return;
  }
  // Certain GL backends need to made current before any GL
  // state can be accessed.
  gl_dispatch_table_.gl_make_current_callback();

  std::vector<std::shared_ptr<fml::Mapping>> shader_mappings = {
      std::make_shared<fml::NonOwnedMapping>(
          impeller_entity_shaders_gles_data,
          impeller_entity_shaders_gles_length),
      std::make_shared<fml::NonOwnedMapping>(
          impeller_modern_shaders_gles_data,
          impeller_modern_shaders_gles_length),
      std::make_shared<fml::NonOwnedMapping>(
          impeller_framebuffer_blend_shaders_gles_data,
          impeller_framebuffer_blend_shaders_gles_length),
#if IMPELLER_ENABLE_3D
      std::make_shared<fml::NonOwnedMapping>(
          impeller_scene_shaders_gles_data, impeller_scene_shaders_gles_length),
#endif  // IMPELLER_ENABLE_3D
  };
  auto gl = std::make_unique<impeller::ProcTableGLES>(
      gl_dispatch_table_.gl_proc_resolver);
  if (!gl->IsValid()) {
    return;
  }

  impeller_context_ = impeller::ContextGLES::Create(
      std::move(gl), shader_mappings, /*enable_gpu_tracing=*/false);

  if (!impeller_context_) {
    FML_LOG(ERROR) << "Could not create Impeller context.";
    return;
  }

  auto worker_id = impeller_context_->AddReactorWorker(worker_);
  if (!worker_id.has_value()) {
    FML_LOG(ERROR) << "Could not add reactor worker.";
    return;
  }

  gl_dispatch_table_.gl_clear_current_callback();
  FML_LOG(IMPORTANT) << "Using the Impeller rendering backend (OpenGL).";
  valid_ = true;
}

EmbedderSurfaceGLImpeller::~EmbedderSurfaceGLImpeller() = default;

// |EmbedderSurface|
bool EmbedderSurfaceGLImpeller::IsValid() const {
  return valid_;
}

// |GPUSurfaceGLDelegate|
std::unique_ptr<GLContextResult>
EmbedderSurfaceGLImpeller::GLContextMakeCurrent() {
  worker_->SetReactionsAllowedOnCurrentThread(true);
  return std::make_unique<GLContextDefaultResult>(
      gl_dispatch_table_.gl_make_current_callback());
}

// |GPUSurfaceGLDelegate|
bool EmbedderSurfaceGLImpeller::GLContextClearCurrent() {
  worker_->SetReactionsAllowedOnCurrentThread(false);
  return gl_dispatch_table_.gl_clear_current_callback();
}

// |GPUSurfaceGLDelegate|
bool EmbedderSurfaceGLImpeller::GLContextPresent(
    const GLPresentInfo& present_info) {
  // Pass the present information to the embedder present callback.
  return gl_dispatch_table_.gl_present_callback(present_info);
}

// |GPUSurfaceGLDelegate|
GLFBOInfo EmbedderSurfaceGLImpeller::GLContextFBO(
    GLFrameInfo frame_info) const {
  // Get the FBO ID using the gl_fbo_callback and then get exiting damage by
  // passing that ID to the gl_populate_existing_damage.
  return gl_dispatch_table_.gl_populate_existing_damage(
      gl_dispatch_table_.gl_fbo_callback(frame_info));
}

// |GPUSurfaceGLDelegate|
bool EmbedderSurfaceGLImpeller::GLContextFBOResetAfterPresent() const {
  return fbo_reset_after_present_;
}

// |GPUSurfaceGLDelegate|
SkMatrix EmbedderSurfaceGLImpeller::GLContextSurfaceTransformation() const {
  auto callback = gl_dispatch_table_.gl_surface_transformation_callback;
  if (!callback) {
    SkMatrix matrix;
    matrix.setIdentity();
    return matrix;
  }
  return callback();
}

// |GPUSurfaceGLDelegate|
EmbedderSurfaceGL::GLProcResolver EmbedderSurfaceGLImpeller::GetGLProcResolver()
    const {
  return gl_dispatch_table_.gl_proc_resolver;
}

// |GPUSurfaceGLDelegate|
SurfaceFrame::FramebufferInfo
EmbedderSurfaceGLImpeller::GLContextFramebufferInfo() const {
  // Enable partial repaint by default on the embedders.
  auto info = SurfaceFrame::FramebufferInfo{};
  info.supports_readback = true;
  info.supports_partial_repaint =
      gl_dispatch_table_.gl_populate_existing_damage != nullptr;
  return info;
}

// |EmbedderSurface|
std::unique_ptr<Surface> EmbedderSurfaceGLImpeller::CreateGPUSurface() {
  // Ensure that the GL context is current before creating the GPU surface.
  // GPUSurfaceGLImpeller initialization will set up shader pipelines, and the
  // current thread needs to be able to execute reactor operations.
  GLContextMakeCurrent();

  return std::make_unique<GPUSurfaceGLImpeller>(
      this,                     // GPU surface GL delegate
      impeller_context_,        // Impeller context
      !external_view_embedder_  // render to surface
  );
}

// |EmbedderSurface|
std::shared_ptr<impeller::Context>
EmbedderSurfaceGLImpeller::CreateImpellerContext() const {
  return impeller_context_;
}

// |EmbedderSurface|
sk_sp<GrDirectContext> EmbedderSurfaceGLImpeller::CreateResourceContext()
    const {
  if (gl_dispatch_table_.gl_make_resource_current_callback()) {
    worker_->SetReactionsAllowedOnCurrentThread(true);
  } else {
    FML_DLOG(ERROR) << "Could not make the resource context current.";
    worker_->SetReactionsAllowedOnCurrentThread(false);
  }
  return nullptr;
}

}  // namespace flutter
