/*
 * Copyright 2023 Google LLC
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "src/gpu/graphite/vk/VulkanSampler.h"

#include "include/core/SkSamplingOptions.h"
#include "src/gpu/graphite/vk/VulkanCaps.h"
#include "src/gpu/graphite/vk/VulkanGraphiteUtilsPriv.h"

namespace skgpu::graphite {

VulkanSampler::VulkanSampler(const VulkanSharedContext* sharedContext,
                             const SamplerDesc& desc,
                             VkSampler sampler,
                             sk_sp<VulkanYcbcrConversion> ycbcrConversion)
        : Sampler(sharedContext)
        , fDesc(desc)
        , fSampler(sampler)
        , fYcbcrConversion(ycbcrConversion) {}

static VkSamplerAddressMode tile_mode_to_vk_sampler_address(SkTileMode tileMode) {
    switch (tileMode) {
        case SkTileMode::kClamp:
            return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
        case SkTileMode::kRepeat:
            return VK_SAMPLER_ADDRESS_MODE_REPEAT;
        case SkTileMode::kMirror:
            return VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT;
        case SkTileMode::kDecal:
            return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER;
    }
    SkUNREACHABLE;
}

sk_sp<VulkanSampler> VulkanSampler::Make(
        const VulkanSharedContext* sharedContext,
        const SamplerDesc& desc,
        sk_sp<VulkanYcbcrConversion> ycbcrConversion) {
    VkSamplerCreateInfo samplerInfo;
    memset(&samplerInfo, 0, sizeof(VkSamplerCreateInfo));
    samplerInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;

    void* pNext = nullptr;
    VkSamplerYcbcrConversionInfo conversionInfo;
    if (ycbcrConversion) {
        conversionInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO;
        conversionInfo.pNext = nullptr;
        conversionInfo.conversion = ycbcrConversion->ycbcrConversion();
        pNext = &conversionInfo;
    }

    samplerInfo.pNext = pNext;
    samplerInfo.flags = 0;

    VkFilter minMagFilter = [&] {
        switch (desc.samplingOptions().filter) {
            case SkFilterMode::kNearest: return VK_FILTER_NEAREST;
            case SkFilterMode::kLinear:  return VK_FILTER_LINEAR;
        }
        SkUNREACHABLE;
    }();

    VkSamplerMipmapMode mipmapMode = [&] {
      switch (desc.samplingOptions().mipmap) {
          // There is no disable mode. We use max level to disable mip mapping.
          // It may make more sense to use NEAREST for kNone but Chrome pixel tests have
          // been dependent on subtle rendering differences introduced by switching this.
          case SkMipmapMode::kNone:    return VK_SAMPLER_MIPMAP_MODE_LINEAR;
          case SkMipmapMode::kNearest: return VK_SAMPLER_MIPMAP_MODE_NEAREST;
          case SkMipmapMode::kLinear:  return VK_SAMPLER_MIPMAP_MODE_LINEAR;
      }
      SkUNREACHABLE;
    }();

    samplerInfo.magFilter = minMagFilter;
    samplerInfo.minFilter = minMagFilter;
    samplerInfo.mipmapMode = mipmapMode;
    samplerInfo.addressModeU = tile_mode_to_vk_sampler_address(desc.tileModeX());
    samplerInfo.addressModeV = tile_mode_to_vk_sampler_address(desc.tileModeY());
    samplerInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
    samplerInfo.mipLodBias = 0;
    samplerInfo.anisotropyEnable = VK_FALSE;
    samplerInfo.maxAnisotropy = 1; // TODO: when we start using aniso, need to add to key
    samplerInfo.compareEnable = VK_FALSE;
    samplerInfo.compareOp = VK_COMPARE_OP_NEVER;
    // Vulkan doesn't have a direct mapping to use nearest or linear filters for minFilter since
    // there is always a mipmapMode. To get the same effect we can set minLod = maxLod = 0.0.
    // This works since our min and mag filters are the same (this forces us to use mag on the 0
    // level mip). If the filters weren't the same we could set min = 0 and max = 0.25 to force
    // the minFilter on mip level 0.
    samplerInfo.minLod = 0;
    samplerInfo.maxLod = (desc.samplingOptions().mipmap == SkMipmapMode::kNone) ? 0.0f
                                                                                : VK_LOD_CLAMP_NONE;
    samplerInfo.borderColor = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK;
    samplerInfo.unnormalizedCoordinates = VK_FALSE;

    VkSampler sampler;
    VkResult result;
    VULKAN_CALL_RESULT(sharedContext,
                       result,
                       CreateSampler(sharedContext->device(), &samplerInfo, nullptr, &sampler));
    if (result != VK_SUCCESS) {
        return nullptr;
    }

    return sk_sp<VulkanSampler>(new VulkanSampler(sharedContext,
                                                  desc,
                                                  sampler,
                                                  std::move(ycbcrConversion)));
}

void VulkanSampler::freeGpuData() {
    const VulkanSharedContext* sharedContext =
        static_cast<const VulkanSharedContext*>(this->sharedContext());
    SkASSERT(fSampler);
    VULKAN_CALL(sharedContext->interface(),
                DestroySampler(sharedContext->device(), fSampler, nullptr));
    fSampler = VK_NULL_HANDLE;
}

} // namespace skgpu::graphite

