// 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/skwasm/images.h"

#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
#include <emscripten/html5_webgl.h>

#include "flutter/display_list/geometry/dl_geometry_conversions.h"
#include "flutter/display_list/image/dl_image_skia.h"
#include "flutter/display_list/skia/dl_sk_conversions.h"
#include "flutter/display_list/skia/dl_sk_dispatcher.h"
#include "third_party/skia/include/core/SkColorSpace.h"
#include "third_party/skia/include/core/SkData.h"
#include "third_party/skia/include/core/SkImage.h"
#include "third_party/skia/include/core/SkImageInfo.h"
#include "third_party/skia/include/core/SkPicture.h"
#include "third_party/skia/include/core/SkPictureRecorder.h"
#include "third_party/skia/include/gpu/GpuTypes.h"
#include "third_party/skia/include/gpu/ganesh/GrBackendSurface.h"
#include "third_party/skia/include/gpu/ganesh/GrDirectContext.h"
#include "third_party/skia/include/gpu/ganesh/GrExternalTextureGenerator.h"
#include "third_party/skia/include/gpu/ganesh/SkImageGanesh.h"
#include "third_party/skia/include/gpu/ganesh/SkSurfaceGanesh.h"
#include "third_party/skia/include/gpu/ganesh/gl/GrGLBackendSurface.h"
#include "third_party/skia/include/gpu/ganesh/gl/GrGLInterface.h"
#include "third_party/skia/include/gpu/ganesh/gl/GrGLTypes.h"

namespace {

SkColorType ColorTypeForPixelFormat(Skwasm::PixelFormat format) {
  switch (format) {
    case Skwasm::PixelFormat::rgba8888:
      return SkColorType::kRGBA_8888_SkColorType;
    case Skwasm::PixelFormat::bgra8888:
      return SkColorType::kBGRA_8888_SkColorType;
    case Skwasm::PixelFormat::rgbaFloat32:
      return SkColorType::kRGBA_F32_SkColorType;
  }
}

SkAlphaType AlphaTypeForPixelFormat(Skwasm::PixelFormat format) {
  switch (format) {
    case Skwasm::PixelFormat::rgba8888:
    case Skwasm::PixelFormat::bgra8888:
      return SkAlphaType::kPremul_SkAlphaType;
    case Skwasm::PixelFormat::rgbaFloat32:
      return SkAlphaType::kUnpremul_SkAlphaType;
  }
}

class ExternalWebGLTexture : public GrExternalTexture {
 public:
  ExternalWebGLTexture(GrBackendTexture backend_texture,
                       GLuint texture_id,
                       EMSCRIPTEN_WEBGL_CONTEXT_HANDLE context)
      : backend_texture_(backend_texture),
        texture_id_(texture_id),
        web_gl_context_(context) {}

  GrBackendTexture getBackendTexture() override { return backend_texture_; }

  void dispose() override {
    Skwasm::makeCurrent(web_gl_context_);
    glDeleteTextures(1, &texture_id_);
  }

 private:
  GrBackendTexture backend_texture_;
  GLuint texture_id_;
  EMSCRIPTEN_WEBGL_CONTEXT_HANDLE web_gl_context_;
};

class TextureSourceImageGenerator : public GrExternalTextureGenerator {
 public:
  TextureSourceImageGenerator(SkImageInfo ii,
                              Skwasm::SkwasmObject texture_source,
                              Skwasm::Surface* surface)
      : GrExternalTextureGenerator(ii),
        texture_source_wrapper_(
            surface->CreateTextureSourceWrapper(texture_source)) {}

  std::unique_ptr<GrExternalTexture> generateExternalTexture(
      GrRecordingContext* context,
      skgpu::Mipmapped mipmapped) override {
    GrGLTextureInfo gl_info;
    gl_info.fID = skwasm_createGlTextureFromTextureSource(
        texture_source_wrapper_->GetTextureSource(), fInfo.width(),
        fInfo.height());
    gl_info.fFormat = GL_RGBA8_OES;
    gl_info.fTarget = GL_TEXTURE_2D;

    auto backend_texture = GrBackendTextures::MakeGL(
        fInfo.width(), fInfo.height(), skgpu::Mipmapped::kNo, gl_info);

    // In order to bind the image source to the texture, makeTexture has changed
    // which texture is "in focus" for the WebGL context.
    GrAsDirectContext(context)->resetContext(kTextureBinding_GrGLBackendState);
    return std::make_unique<ExternalWebGLTexture>(
        backend_texture, gl_info.fID, emscripten_webgl_get_current_context());
  }

 private:
  std::unique_ptr<Skwasm::TextureSourceWrapper> texture_source_wrapper_;
};

}  // namespace

namespace Skwasm {

sk_sp<flutter::DlImage> MakeImageFromPicture(flutter::DisplayList* display_list,
                                             int32_t width,
                                             int32_t height) {
  SkPictureRecorder recorder;
  SkCanvas* canvas =
      recorder.beginRecording(flutter::ToSkRect(display_list->GetBounds()));
  flutter::DlSkCanvasDispatcher dispatcher(canvas);
  dispatcher.drawDisplayList(sk_ref_sp(display_list), 1.0f);

  return flutter::DlImageSkia::Make(SkImages::DeferredFromPicture(
      recorder.finishRecordingAsPicture(), {width, height}, nullptr, nullptr,
      SkImages::BitDepth::kU8, SkColorSpace::MakeSRGB()));
}

sk_sp<flutter::DlImage> MakeImageFromTexture(SkwasmObject texture_source,
                                             int width,
                                             int height,
                                             Skwasm::Surface* surface) {
  return flutter::DlImageSkia::Make(SkImages::DeferredFromTextureGenerator(
      std::unique_ptr<TextureSourceImageGenerator>(
          new TextureSourceImageGenerator(
              SkImageInfo::Make(width, height,
                                SkColorType::kRGBA_8888_SkColorType,
                                SkAlphaType::kPremul_SkAlphaType),
              texture_source, surface))));
}

sk_sp<flutter::DlImage> MakeImageFromPixels(SkData* data,
                                            int width,
                                            int height,
                                            Skwasm::PixelFormat pixel_format,
                                            size_t row_byte_count) {
  return flutter::DlImageSkia::Make(SkImages::RasterFromData(
      SkImageInfo::Make(width, height, ColorTypeForPixelFormat(pixel_format),
                        AlphaTypeForPixelFormat(pixel_format),
                        SkColorSpace::MakeSRGB()),
      sk_ref_sp(data), row_byte_count));
}
}  // namespace Skwasm
