// 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.

#ifndef FLUTTER_FLOW_SKIA_GPU_OBJECT_H_
#define FLUTTER_FLOW_SKIA_GPU_OBJECT_H_

#include <mutex>
#include <queue>

#include "flutter/fml/memory/ref_counted.h"
#include "flutter/fml/memory/weak_ptr.h"
#include "flutter/fml/task_runner.h"
#include "flutter/fml/trace_event.h"
#include "third_party/skia/include/core/SkRefCnt.h"
#include "third_party/skia/include/gpu/GrBackendSurface.h"
#include "third_party/skia/include/gpu/GrDirectContext.h"
#include "third_party/skia/include/gpu/GrTypes.h"

namespace flutter {

// A queue that holds Skia objects that must be destructed on the given task
// runner.
template <class T>
class UnrefQueue : public fml::RefCountedThreadSafe<UnrefQueue<T>> {
 public:
  using ResourceContext = T;

  void Unref(SkRefCnt* object) {
    if (drain_immediate_) {
      object->unref();
      return;
    }
    std::scoped_lock lock(mutex_);
    objects_.push_back(object);
    if (!drain_pending_) {
      drain_pending_ = true;
      task_runner_->PostDelayedTask(
          [strong = fml::Ref(this)]() { strong->Drain(); }, drain_delay_);
    }
  }

  void DeleteTexture(GrBackendTexture texture) {
    // drain_immediate_ should only be used on Impeller.
    FML_DCHECK(!drain_immediate_);
    std::scoped_lock lock(mutex_);
    textures_.push_back(texture);
    if (!drain_pending_) {
      drain_pending_ = true;
      task_runner_->PostDelayedTask(
          [strong = fml::Ref(this)]() { strong->Drain(); }, drain_delay_);
    }
  }

  // Usually, the drain is called automatically. However, during IO manager
  // shutdown (when the platform side reference to the OpenGL context is about
  // to go away), we may need to pre-emptively drain the unref queue. It is the
  // responsibility of the caller to ensure that no further unrefs are queued
  // after this call.
  void Drain() {
    TRACE_EVENT0("flutter", "SkiaUnrefQueue::Drain");
    std::deque<SkRefCnt*> skia_objects;
    std::deque<GrBackendTexture> textures;
    {
      std::scoped_lock lock(mutex_);
      objects_.swap(skia_objects);
      textures_.swap(textures);
      drain_pending_ = false;
    }
    DoDrain(skia_objects, textures, context_);
  }

  void UpdateResourceContext(sk_sp<ResourceContext> context) {
    context_ = context;
  }

 private:
  const fml::RefPtr<fml::TaskRunner> task_runner_;
  const fml::TimeDelta drain_delay_;
  std::mutex mutex_;
  std::deque<SkRefCnt*> objects_;
  std::deque<GrBackendTexture> textures_;
  bool drain_pending_;
  sk_sp<ResourceContext> context_;
  // Enabled when there is an impeller context, which removes the usage of
  // the queue altogether.
  bool drain_immediate_;

  // The `GrDirectContext* context` is only used for signaling Skia to
  // performDeferredCleanup. It can be nullptr when such signaling is not needed
  // (e.g., in unit tests).
  UnrefQueue(fml::RefPtr<fml::TaskRunner> task_runner,
             fml::TimeDelta delay,
             sk_sp<ResourceContext> context = nullptr,
             bool drain_immediate = false)
      : task_runner_(std::move(task_runner)),
        drain_delay_(delay),
        drain_pending_(false),
        context_(context),
        drain_immediate_(drain_immediate) {}

  ~UnrefQueue() {
    // The ResourceContext must be deleted on the task runner thread.
    // Transfer ownership of the UnrefQueue's ResourceContext reference
    // into a task queued to that thread.
    ResourceContext* raw_context = context_.release();
    fml::TaskRunner::RunNowOrPostTask(
        task_runner_, [objects = std::move(objects_),
                       textures = std::move(textures_), raw_context]() mutable {
          sk_sp<ResourceContext> context(raw_context);
          DoDrain(objects, textures, context);
          context.reset();
        });
  }

  // static
  static void DoDrain(const std::deque<SkRefCnt*>& skia_objects,
                      const std::deque<GrBackendTexture>& textures,
                      sk_sp<ResourceContext> context) {
    for (SkRefCnt* skia_object : skia_objects) {
      skia_object->unref();
    }

    if (context) {
      for (GrBackendTexture texture : textures) {
        context->deleteBackendTexture(texture);
      }

      if (!skia_objects.empty()) {
        context->performDeferredCleanup(std::chrono::milliseconds(0));
      }

      context->flushAndSubmit(GrSyncCpu::kYes);
    }
  }

  FML_FRIEND_REF_COUNTED_THREAD_SAFE(UnrefQueue);
  FML_FRIEND_MAKE_REF_COUNTED(UnrefQueue);
  FML_DISALLOW_COPY_AND_ASSIGN(UnrefQueue);
};

using SkiaUnrefQueue = UnrefQueue<GrDirectContext>;

/// An object whose deallocation needs to be performed on an specific unref
/// queue. The template argument U need to have a call operator that returns
/// that unref queue.
template <class T>
class SkiaGPUObject {
 public:
  using SkiaObjectType = T;

  SkiaGPUObject() = default;
  SkiaGPUObject(sk_sp<SkiaObjectType> object, fml::RefPtr<SkiaUnrefQueue> queue)
      : object_(std::move(object)), queue_(std::move(queue)) {
    FML_DCHECK(object_);
  }
  SkiaGPUObject(SkiaGPUObject&&) = default;
  ~SkiaGPUObject() { reset(); }

  SkiaGPUObject& operator=(SkiaGPUObject&&) = default;

  sk_sp<SkiaObjectType> skia_object() const { return object_; }

  void reset() {
    if (object_ && queue_) {
      queue_->Unref(object_.release());
    }
    queue_ = nullptr;
    FML_DCHECK(object_ == nullptr);
  }

 private:
  sk_sp<SkiaObjectType> object_;
  fml::RefPtr<SkiaUnrefQueue> queue_;

  FML_DISALLOW_COPY_AND_ASSIGN(SkiaGPUObject);
};

}  // namespace flutter

#endif  // FLUTTER_FLOW_SKIA_GPU_OBJECT_H_
