// 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/ui/painting/display_list_deferred_image_gpu_impeller.h"

#include <utility>

#include "flutter/fml/make_copyable.h"

namespace flutter {

sk_sp<DlDeferredImageGPUImpeller> DlDeferredImageGPUImpeller::Make(
    std::unique_ptr<LayerTree> layer_tree,
    fml::TaskRunnerAffineWeakPtr<SnapshotDelegate> snapshot_delegate,
    fml::RefPtr<fml::TaskRunner> raster_task_runner) {
  return sk_sp<DlDeferredImageGPUImpeller>(new DlDeferredImageGPUImpeller(
      DlDeferredImageGPUImpeller::ImageWrapper::Make(
          std::move(layer_tree), std::move(snapshot_delegate),
          std::move(raster_task_runner))));
}

sk_sp<DlDeferredImageGPUImpeller> DlDeferredImageGPUImpeller::Make(
    sk_sp<DisplayList> display_list,
    const SkISize& size,
    fml::TaskRunnerAffineWeakPtr<SnapshotDelegate> snapshot_delegate,
    fml::RefPtr<fml::TaskRunner> raster_task_runner) {
  return sk_sp<DlDeferredImageGPUImpeller>(new DlDeferredImageGPUImpeller(
      DlDeferredImageGPUImpeller::ImageWrapper::Make(
          std::move(display_list), size, std::move(snapshot_delegate),
          std::move(raster_task_runner))));
}

DlDeferredImageGPUImpeller::DlDeferredImageGPUImpeller(
    std::shared_ptr<ImageWrapper> wrapper)
    : wrapper_(std::move(wrapper)) {}

// |DlImage|
DlDeferredImageGPUImpeller::~DlDeferredImageGPUImpeller() = default;

// |DlImage|
sk_sp<SkImage> DlDeferredImageGPUImpeller::skia_image() const {
  return nullptr;
};

// |DlImage|
std::shared_ptr<impeller::Texture>
DlDeferredImageGPUImpeller::impeller_texture() const {
  if (!wrapper_) {
    return nullptr;
  }
  return wrapper_->texture();
}

// |DlImage|
bool DlDeferredImageGPUImpeller::isOpaque() const {
  // Impeller doesn't currently implement opaque alpha types.
  return false;
}

// |DlImage|
bool DlDeferredImageGPUImpeller::isTextureBacked() const {
  return wrapper_ && wrapper_->isTextureBacked();
}

// |DlImage|
bool DlDeferredImageGPUImpeller::isUIThreadSafe() const {
  return true;
}

// |DlImage|
SkISize DlDeferredImageGPUImpeller::dimensions() const {
  if (!wrapper_) {
    return SkISize::MakeEmpty();
  }
  return wrapper_->size();
}

// |DlImage|
size_t DlDeferredImageGPUImpeller::GetApproximateByteSize() const {
  auto size = sizeof(DlDeferredImageGPUImpeller);
  if (wrapper_) {
    if (wrapper_->texture()) {
      size += wrapper_->texture()
                  ->GetTextureDescriptor()
                  .GetByteSizeOfBaseMipLevel();
    } else {
      size += wrapper_->size().width() * wrapper_->size().height() * 4;
    }
  }
  return size;
}

std::shared_ptr<DlDeferredImageGPUImpeller::ImageWrapper>
DlDeferredImageGPUImpeller::ImageWrapper::Make(
    sk_sp<DisplayList> display_list,
    const SkISize& size,
    fml::TaskRunnerAffineWeakPtr<SnapshotDelegate> snapshot_delegate,
    fml::RefPtr<fml::TaskRunner> raster_task_runner) {
  auto wrapper = std::shared_ptr<ImageWrapper>(new ImageWrapper(
      std::move(display_list), size, std::move(snapshot_delegate),
      std::move(raster_task_runner)));
  wrapper->SnapshotDisplayList();
  return wrapper;
}

std::shared_ptr<DlDeferredImageGPUImpeller::ImageWrapper>
DlDeferredImageGPUImpeller::ImageWrapper::Make(
    std::unique_ptr<LayerTree> layer_tree,
    fml::TaskRunnerAffineWeakPtr<SnapshotDelegate> snapshot_delegate,
    fml::RefPtr<fml::TaskRunner> raster_task_runner) {
  auto wrapper = std::shared_ptr<ImageWrapper>(new ImageWrapper(
      nullptr, layer_tree->frame_size(), std::move(snapshot_delegate),
      std::move(raster_task_runner)));
  wrapper->SnapshotDisplayList(std::move(layer_tree));
  return wrapper;
}

DlDeferredImageGPUImpeller::ImageWrapper::ImageWrapper(
    sk_sp<DisplayList> display_list,
    const SkISize& size,
    fml::TaskRunnerAffineWeakPtr<SnapshotDelegate> snapshot_delegate,
    fml::RefPtr<fml::TaskRunner> raster_task_runner)
    : size_(size),
      display_list_(std::move(display_list)),
      snapshot_delegate_(std::move(snapshot_delegate)),
      raster_task_runner_(std::move(raster_task_runner)) {}

DlDeferredImageGPUImpeller::ImageWrapper::~ImageWrapper() {
  fml::TaskRunner::RunNowOrPostTask(
      raster_task_runner_, [id = reinterpret_cast<uintptr_t>(this),
                            texture_registry = std::move(texture_registry_)]() {
        if (texture_registry) {
          texture_registry->UnregisterContextListener(id);
        }
      });
}

void DlDeferredImageGPUImpeller::ImageWrapper::OnGrContextCreated() {
  FML_DCHECK(raster_task_runner_->RunsTasksOnCurrentThread());
  SnapshotDisplayList();
}

void DlDeferredImageGPUImpeller::ImageWrapper::OnGrContextDestroyed() {
  // Impeller textures do not have threading requirements for deletion, and
  texture_.reset();
}

bool DlDeferredImageGPUImpeller::ImageWrapper::isTextureBacked() const {
  return texture_ && texture_->IsValid();
}

void DlDeferredImageGPUImpeller::ImageWrapper::SnapshotDisplayList(
    std::unique_ptr<LayerTree> layer_tree) {
  fml::TaskRunner::RunNowOrPostTask(
      raster_task_runner_,
      fml::MakeCopyable([weak_this = weak_from_this(),
                         layer_tree = std::move(layer_tree)]() {
        TRACE_EVENT0("flutter", "SnapshotDisplayList (impeller)");
        auto wrapper = weak_this.lock();
        if (!wrapper) {
          return;
        }
        auto snapshot_delegate = wrapper->snapshot_delegate_;
        if (!snapshot_delegate) {
          return;
        }

        wrapper->texture_registry_ = snapshot_delegate->GetTextureRegistry();
        wrapper->texture_registry_->RegisterContextListener(
            reinterpret_cast<uintptr_t>(wrapper.get()), weak_this);

        if (layer_tree) {
          wrapper->display_list_ = layer_tree->Flatten(
              SkRect::MakeWH(wrapper->size_.width(), wrapper->size_.height()),
              wrapper->texture_registry_);
        }
        auto snapshot = snapshot_delegate->MakeRasterSnapshot(
            wrapper->display_list_, wrapper->size_);
        if (!snapshot) {
          std::scoped_lock lock(wrapper->error_mutex_);
          wrapper->error_ = "Failed to create snapshot.";
          return;
        }
        wrapper->texture_ = snapshot->impeller_texture();
      }));
}

std::optional<std::string>
DlDeferredImageGPUImpeller::ImageWrapper::get_error() {
  std::scoped_lock lock(error_mutex_);
  return error_;
}

}  // namespace flutter
