// 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/metal/allocator_mtl.h"

#include "flutter/fml/build_config.h"
#include "flutter/fml/logging.h"
#include "impeller/base/validation.h"
#include "impeller/core/buffer.h"
#include "impeller/renderer/backend/metal/device_buffer_mtl.h"
#include "impeller/renderer/backend/metal/formats_mtl.h"
#include "impeller/renderer/backend/metal/texture_mtl.h"

namespace impeller {

static bool DeviceSupportsMemorylessTargets(id<MTLDevice> device) {
  // Refer to the "Memoryless render targets" feature in the table below:
  // https://developer.apple.com/metal/Metal-Feature-Set-Tables.pdf
  if (@available(ios 13.0, tvos 13.0, macos 10.15, *)) {
    return [device supportsFamily:MTLGPUFamilyApple2];
  } else {
#if FML_OS_IOS
    // This is perhaps redundant. But, just in case we somehow get into a case
    // where Impeller runs on iOS versions less than 8.0 and/or without A8
    // GPUs, we explicitly check feature set support.
    return [device supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily2_v1];
#else
    // MacOS devices with Apple GPUs are only available with macos 10.15 and
    // above. So, if we are here, it is safe to assume that memory-less targets
    // are not supported.
    return false;
#endif
  }
  FML_UNREACHABLE();
}

static bool DeviceHasUnifiedMemoryArchitecture(id<MTLDevice> device) {
  if (@available(ios 13.0, tvos 13.0, macOS 10.15, *)) {
    return [device hasUnifiedMemory];
  } else {
#if FML_OS_IOS
    // iOS devices where the availability check can fail always have had UMA.
    return true;
#else
    // Mac devices where the availability check can fail have never had UMA.
    return false;
#endif
  }
  FML_UNREACHABLE();
}

static ISize DeviceMaxTextureSizeSupported(id<MTLDevice> device) {
  // Since Apple didn't expose API for us to get the max texture size, we have
  // to use hardcoded data from
  // https://developer.apple.com/metal/Metal-Feature-Set-Tables.pdf
  // According to the feature set table, there are two supported max sizes :
  // 16384 and 8192 for devices flutter support. The former is used on macs and
  // latest ios devices. The latter is used on old ios devices.
  if (@available(macOS 10.15, iOS 13, tvOS 13, *)) {
    if ([device supportsFamily:MTLGPUFamilyApple3] ||
        [device supportsFamily:MTLGPUFamilyMacCatalyst1] ||
        [device supportsFamily:MTLGPUFamilyMac1]) {
      return {16384, 16384};
    }
    return {8192, 8192};
  } else {
#if FML_OS_IOS
    if ([device supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily4_v1] ||
        [device supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily3_v1]) {
      return {16384, 16384};
    }
#endif
#if FML_OS_MACOSX
    return {16384, 16384};
#endif
    return {8192, 8192};
  }
}

static bool SupportsLossyTextureCompression(id<MTLDevice> device) {
#ifdef FML_OS_IOS_SIMULATOR
  return false;
#else
  if (@available(macOS 10.15, iOS 13, tvOS 13, *)) {
    return [device supportsFamily:MTLGPUFamilyApple8];
  }
  return false;
#endif
}

AllocatorMTL::AllocatorMTL(id<MTLDevice> device, std::string label)
    : device_(device), allocator_label_(std::move(label)) {
  if (!device_) {
    return;
  }

  supports_memoryless_targets_ = DeviceSupportsMemorylessTargets(device_);
  supports_uma_ = DeviceHasUnifiedMemoryArchitecture(device_);
  max_texture_supported_ = DeviceMaxTextureSizeSupported(device_);

  is_valid_ = true;
}

AllocatorMTL::~AllocatorMTL() = default;

bool AllocatorMTL::IsValid() const {
  return is_valid_;
}

static MTLResourceOptions ToMTLResourceOptions(StorageMode type,
                                               bool supports_memoryless_targets,
                                               bool supports_uma) {
  switch (type) {
    case StorageMode::kHostVisible:
#if FML_OS_IOS
      return MTLResourceStorageModeShared;
#else
      if (supports_uma) {
        return MTLResourceStorageModeShared;
      } else {
        return MTLResourceStorageModeManaged;
      }
#endif
    case StorageMode::kDevicePrivate:
      return MTLResourceStorageModePrivate;
    case StorageMode::kDeviceTransient:
      if (supports_memoryless_targets) {
        // Device may support but the OS has not been updated.
        if (@available(macOS 11.0, *)) {
          return MTLResourceStorageModeMemoryless;
        } else {
          return MTLResourceStorageModePrivate;
        }
      } else {
        return MTLResourceStorageModePrivate;
      }
      FML_UNREACHABLE();
  }
  FML_UNREACHABLE();
}

static MTLStorageMode ToMTLStorageMode(StorageMode mode,
                                       bool supports_memoryless_targets,
                                       bool supports_uma) {
  switch (mode) {
    case StorageMode::kHostVisible:
#if FML_OS_IOS
      return MTLStorageModeShared;
#else
      if (supports_uma) {
        return MTLStorageModeShared;
      } else {
        return MTLStorageModeManaged;
      }
#endif
    case StorageMode::kDevicePrivate:
      return MTLStorageModePrivate;
    case StorageMode::kDeviceTransient:
      if (supports_memoryless_targets) {
        // Device may support but the OS has not been updated.
        if (@available(macOS 11.0, *)) {
          return MTLStorageModeMemoryless;
        } else {
          return MTLStorageModePrivate;
        }
      } else {
        return MTLStorageModePrivate;
      }
      FML_UNREACHABLE();
  }
  FML_UNREACHABLE();
}

std::shared_ptr<DeviceBuffer> AllocatorMTL::OnCreateBuffer(
    const DeviceBufferDescriptor& desc) {
  const auto resource_options = ToMTLResourceOptions(
      desc.storage_mode, supports_memoryless_targets_, supports_uma_);
  const auto storage_mode = ToMTLStorageMode(
      desc.storage_mode, supports_memoryless_targets_, supports_uma_);

  auto buffer = [device_ newBufferWithLength:desc.size
                                     options:resource_options];
  if (!buffer) {
    return nullptr;
  }
  return std::shared_ptr<DeviceBufferMTL>(new DeviceBufferMTL(desc,         //
                                                              buffer,       //
                                                              storage_mode  //
                                                              ));
}

std::shared_ptr<Texture> AllocatorMTL::OnCreateTexture(
    const TextureDescriptor& desc) {
  if (!IsValid()) {
    return nullptr;
  }

  auto mtl_texture_desc = ToMTLTextureDescriptor(desc);

  if (!mtl_texture_desc) {
    VALIDATION_LOG << "Texture descriptor was invalid.";
    return nullptr;
  }

  mtl_texture_desc.storageMode = ToMTLStorageMode(
      desc.storage_mode, supports_memoryless_targets_, supports_uma_);

  if (@available(macOS 12.5, ios 15.0, *)) {
    if (desc.compression_type == CompressionType::kLossy &&
        SupportsLossyTextureCompression(device_)) {
      mtl_texture_desc.compressionType = MTLTextureCompressionTypeLossy;
    }
  }

  auto texture = [device_ newTextureWithDescriptor:mtl_texture_desc];
  if (!texture) {
    return nullptr;
  }
  return std::make_shared<TextureMTL>(desc, texture);
}

uint16_t AllocatorMTL::MinimumBytesPerRow(PixelFormat format) const {
  return static_cast<uint16_t>([device_
      minimumLinearTextureAlignmentForPixelFormat:ToMTLPixelFormat(format)]);
}

ISize AllocatorMTL::GetMaxTextureSizeSupported() const {
  return max_texture_supported_;
}

}  // namespace impeller
