/*
 * Copyright 2021 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/Caps.h"

#include "include/core/SkCapabilities.h"
#include "include/gpu/ShaderErrorHandler.h"
#include "include/gpu/graphite/ContextOptions.h"
#include "include/gpu/graphite/TextureInfo.h"
#include "include/private/SkTArray.h"
#include "include/private/SkTo.h"
#include "src/gpu/graphite/ContextOptionsPriv.h"
#include "src/gpu/graphite/RenderPassDesc.h"
#include "src/gpu/graphite/ResourceTypes.h"
#include "src/gpu/graphite/TextureInfoPriv.h"
#include "src/sksl/SkSLUtil.h"

#include <algorithm>

namespace skgpu::graphite {

Caps::Caps()
        : fShaderCaps(std::make_unique<SkSL::ShaderCaps>())
        , fCapabilities(new SkCapabilities()) {
    this->setDefaultShaderCaps();
}

Caps::~Caps() {}

void Caps::setDefaultShaderCaps() {
    fShaderCaps->fFlatInterpolationSupport = true;
    fShaderCaps->fShaderDerivativeSupport = true;
    fShaderCaps->fExplicitTextureLodSupport = true;
    fShaderCaps->fSampleMaskSupport = true;
    fShaderCaps->fInfinitySupport = true;
    fShaderCaps->fIntegerSupport = true;
    fShaderCaps->fNonsquareMatrixSupport = true;
    fShaderCaps->fInverseHyperbolicSupport = true;
    fShaderCaps->fFloatIs32Bits = true;
}

void Caps::finishInitialization(const ContextOptions& options) {
    fCapabilities->initSkCaps(fShaderCaps.get());

    fMaxInternalSampleCount = options.fInternalMultisampleCount;

    if (options.fShaderErrorHandler) {
        fShaderErrorHandler = options.fShaderErrorHandler;
    } else {
        fShaderErrorHandler = DefaultShaderErrorHandler();
    }

#if defined(GPU_TEST_UTILS)
    if (options.fOptionsPriv) {
        fMaxTextureSize = std::min(fMaxTextureSize, options.fOptionsPriv->fMaxTextureSizeOverride);
        fRequestedPathRendererStrategy = options.fOptionsPriv->fPathRendererStrategy;
        fDrawListLayer = options.fOptionsPriv->fDrawListLayer;
    }
#endif
    fGlyphCacheTextureMaximumBytes = options.fGlyphCacheTextureMaximumBytes;
    fMinMSAAPathSize = options.fMinimumPathSizeForMSAA;
    fMinDistanceFieldFontSize = options.fMinDistanceFieldFontSize;
    fGlyphsAsPathsFontSize = options.fGlyphsAsPathsFontSize;
    fMaxPathAtlasTextureSize = options.fMaxPathAtlasTextureSize;
    fAllowMultipleAtlasTextures = options.fAllowMultipleAtlasTextures;
    fSupportBilerpFromGlyphAtlas = options.fSupportBilerpFromGlyphAtlas;
    fRequireOrderedRecordings = options.fRequireOrderedRecordings;
    fSetBackendLabels = options.fSetBackendLabels;
    fAvoidDepthMode = options.fAvoidDepthMode;

    // Enable setting this flag from either the private or public context options.
    fDrawListLayer |= options.fUseDrawListLayer;

    fResourceBindingReqs.fMaxFallbackTextureSize =
            std::max(std::min(ResourceBindingRequirements::kDefaultMaxFallbackTextureSize,
                              fMaxTextureSize),
                     1);

    constexpr int kBytesPerTexel = 16;  // 4 floats (RGBA32F) per fallback texel
    fResourceBindingReqs.fMaxFallbackTextureBytes =
            fResourceBindingReqs.fMaxFallbackTextureSize *
            fResourceBindingReqs.fMaxFallbackTextureSize *
            kBytesPerTexel;
}

sk_sp<SkCapabilities> Caps::capabilities() const { return fCapabilities; }

bool Caps::isSampleCountSupported(TextureFormat format, SampleCount sampleCount) const {
    // Assume optimal tiling
    auto [formatSupport, sampleCounts] = this->getTextureSupport(format, Tiling::kOptimal);
    return SkToBool(formatSupport & TextureUsage::kRender) && SkToBool(sampleCounts & sampleCount);
}

TextureFormat Caps::getDepthStencilFormat(SkEnumBitMask<DepthStencilFlags> dssFlags) const {
    auto canUse = [this](TextureFormat format) {
        auto [formatSupport, sampleCounts] = this->getTextureSupport(format, Tiling::kOptimal);
        // Check that the format can be rendered into and that it supports single-sampled rendering,
        // and if we aren't avoiding MSAA, that it also has some additional sample count.
        return SkToBool(formatSupport & TextureUsage::kRender) &&
               SkToBool(sampleCounts & SampleCount::k1) &&
               (this->avoidMSAA() || sampleCounts != SampleCount::k1);
    };

    if (dssFlags == DepthStencilFlags::kDepth) {
        // Prefer D16, but fallback to D32F or lastly a combined DS format if needed
        if (canUse(TextureFormat::kD16)) {
            return TextureFormat::kD16;
        } else if (canUse(TextureFormat::kD32F)) {
            return TextureFormat::kD32F;
        } else {
            return this->getDepthStencilFormat(DepthStencilFlags::kDepthStencil);
        }
    } else if (dssFlags == DepthStencilFlags::kStencil) {
        // Prefer S8, but fallback to a combined DS format if needed
        if (canUse(TextureFormat::kS8)) {
            return TextureFormat::kS8;
        } else {
            return this->getDepthStencilFormat(DepthStencilFlags::kDepthStencil);
        }
    } else if (dssFlags == DepthStencilFlags::kDepthStencil) {
        // Prefer D24_S8 over D32F_S8 for memory savings if it is available
        if (canUse(TextureFormat::kD24_S8)) {
            return TextureFormat::kD24_S8;
        } else {
            return TextureFormat::kD32F_S8;
        }
    }

    return TextureFormat::kUnsupported; // i.e. no attachment needed
}

bool Caps::isSupported(const TextureInfo& info,
                       SkEnumBitMask<TextureUsage> test,
                       bool allowMSAA,
                       bool allowExternal,
                       bool allowCompressed,
                       bool allowProtected) const {
    const TextureFormat format = TextureInfoPriv::ViewFormat(info);
    if (format == TextureFormat::kUnsupported) {
        return false;
    }
    SkASSERT(info.isValid());

    auto [textureUsage, tiling] = this->getTextureUsage(info);
    auto [formatSupport, supportedSampleCounts] = this->getTextureSupport(format, tiling);

    if (!allowMSAA) {
        // Remove everything but 1x if the operation requires non-MSAA
        supportedSampleCounts &= SampleCount::k1;
    }

    // Intersect what the format and the texture can do to see if `test` is available, and make
    // sure that the texture's sample count is supported.
    if ((formatSupport & textureUsage & test) == test &&
        SkToBool(supportedSampleCounts & info.sampleCount())) {
        // Basic rules that should be reflected in the supported operations bit masks
        SkASSERT((allowProtected  || info.isProtected() == Protected::kNo) &&
                 (allowMSAA       || info.sampleCount() == SampleCount::k1) &&
                 (allowCompressed || TextureFormatCompressionType(format) ==
                                            SkTextureCompressionType::kNone) &&
                 (allowExternal   || format != TextureFormat::kExternal));
        return true;
    } else {
        return false;
    }
}

bool Caps::isTexturable(const TextureInfo& info, bool allowMSAA) const {
    return this->isSupported(info, TextureUsage::kSample,
                             allowMSAA,
                             /*allowExternal=*/true,
                             /*allowCompressed=*/true,
                             /*allowProtected=*/true);
}

bool Caps::isReadable(const TextureInfo& info, bool allowMSAA) const {
    return this->isSupported(info, TextureUsage::kRead,
                             allowMSAA,
                             /*allowExternal=*/true,
                             /*allowCompressed=*/true,
                             /*allowProtected=*/true);
}

bool Caps::isRenderable(const TextureInfo& info) const {
    return this->isSupported(info, TextureUsage::kRender,
                             /*allowMSAA=*/true,
                             /*allowExternal=*/true,
                             /*allowCompressed=*/false,
                             /*allowProtected=*/true);
}

bool Caps::isCopyableSrc(const TextureInfo& info) const {
    return this->isSupported(info, TextureUsage::kCopySrc,
                             /*allowMSAA=*/false,
                             /*allowExternal=*/false,
                             /*allowCompressed=*/false,
                             /*allowProtected=*/false);
}

bool Caps::isCopyableDst(const TextureInfo& info) const {
    return this->isSupported(info, TextureUsage::kCopyDst,
                             /*allowMSAA=*/false,
                             /*allowExternal=*/false,
                             /*allowCompressed=*/true,
                             /*allowProtected=*/true);
}

bool Caps::isStorage(const TextureInfo& info) const {
    return this->isSupported(info, TextureUsage::kStorage,
                             /*allowMSAA=*/false,
                             /*allowExternal=*/false,
                             /*allowCompressed=*/false,
                             /*allowProtected=*/false);
}

bool Caps::isRenderableWithMSRTSS(const TextureInfo& info) const {
    return this->isSupported(info, TextureUsage::kMSRTSS | TextureUsage::kRender,
                             /*allowMSAA=*/true,
                             /*allowExternal=*/true,
                             /*allowCompressed=*/false,
                             /*allowProtected=*/true);
}

TextureInfo Caps::getDefaultTextureInfo(SkEnumBitMask<TextureUsage> usage,
                                        SkSpan<const TextureFormat> formats,
                                        SampleCount sampleCount,
                                        Mipmapped mipmapped,
                                        Protected isProtected,
                                        Discardable discardable) const {
    // Assert we're only requesting Discardable::kYes when the requested usages make sense for it.
    [[maybe_unused]] static constexpr SkEnumBitMask<TextureUsage> kDiscardableAllowed =
            TextureUsage::kRender | TextureUsage::kMSRTSS;
    SkASSERT(discardable == Discardable::kNo || (usage & kDiscardableAllowed) == usage);

    if (isProtected == Protected::kYes && !this->protectedSupport()) {
        return {}; // Cannot handle protected content on this Context
    }

    for (TextureFormat format : formats) {
        auto [supportedUsage, supportedSampleCounts] =
                this->getTextureSupport(format, Tiling::kOptimal);
        if ((supportedUsage & usage) != usage || !SkToBool(supportedSampleCounts & sampleCount)) {
            continue; // unsupported, move on to the next possible format
        }

        if (SkToBool(usage & TextureUsage::kRender) &&
            SkToBool(supportedUsage & TextureUsage::kMSRTSS) &&
            sampleCount == SampleCount::k1) {
            // Proactivately prepare a single-sampled image for use with MSRTSS if it's supported by
            // the format and kRender is requested. This flag is expected to be harmless (if not,
            // it's a driver bug).
            usage |= TextureUsage::kMSRTSS;
        }

        if (SkToBool(usage & TextureUsage::kCopyDst) &&
            SkToBool(supportedUsage & TextureUsage::kHostCopy) &&
            !SkToBool(usage & TextureUsage::kRender) &&
            isProtected == Protected::kNo) {
            // Proactively enable kHostCopy when supported by the format and kCopyDst is requested,
            // so long as it's not going to be protected or rendered into. On every known driver
            // where VK_EXT_host_image_copy is used by Skia, it's known that using the
            // host-image-copy flag reduces the performance of renderable images.
            usage |= TextureUsage::kHostCopy;
        }
        return this->onGetDefaultTextureInfo(usage, format, sampleCount, mipmapped,
                                            isProtected, discardable);
    }

    // None of the possible formats were supported
    return {};
}

TextureInfo Caps::getDefaultAttachmentTextureInfo(AttachmentDesc desc,
                                                  Protected isProtected,
                                                  Discardable discardable) const {
    return this->getDefaultTextureInfo(TextureUsage::kRender,
                                       SkSpan(&desc.fFormat, 1),
                                       desc.fSampleCount,
                                       Mipmapped::kNo,
                                       isProtected,
                                       discardable);
}

// Graphite by default requires copy-src and copy-dst for sampled textures.
static constexpr SkEnumBitMask<TextureUsage> kDefaultSampledUsage =
        TextureUsage::kSample | TextureUsage::kCopySrc | TextureUsage::kCopyDst;

TextureInfo Caps::getDefaultSampledTextureInfo(SkColorType colorType,
                                               Mipmapped mipmapped,
                                               Protected isProtected,
                                               Renderable renderable) const {
    SkEnumBitMask<TextureUsage> usage = kDefaultSampledUsage;
    SkSpan<const TextureFormat> formats = PreferredTextureFormats(colorType);
    skia_private::STArray<3, TextureFormat> validFormats;
    if (renderable == Renderable::kYes) {
        usage |= TextureUsage::kRender;
        // Any possible preferred format must also have a valid write swizzle for the requested
        // color type.
        for (TextureFormat f : formats) {
            if (WriteSwizzleForColorType(colorType, f).has_value()) {
                validFormats.push_back(f);
            }
        }
        formats = validFormats;
    }

    return this->getDefaultTextureInfo(usage,
                                       formats,
                                       SampleCount::k1,
                                       mipmapped,
                                       isProtected,
                                       Discardable::kNo);
}

TextureInfo Caps::getDefaultReadableTextureInfo(TextureFormat format, Protected isProtected) const {
    return this->getDefaultTextureInfo(TextureUsage::kRead |
                                       TextureUsage::kCopySrc |
                                       TextureUsage::kCopyDst,
                                       SkSpan(&format, 1),
                                       SampleCount::k1,
                                       Mipmapped::kNo,
                                       isProtected,
                                       Discardable::kNo);
}

TextureInfo Caps::getTextureInfoForSampledCopy(const TextureInfo& info, Mipmapped mipmapped) const {
    const TextureFormat format = TextureInfoPriv::ViewFormat(info);
    return this->getDefaultTextureInfo(kDefaultSampledUsage,
                                       SkSpan(&format, 1),
                                       SampleCount::k1,
                                       mipmapped,
                                       info.isProtected(),
                                       Discardable::kNo);
}

TextureInfo Caps::getTextureInfoForReadableCopy(const TextureInfo& info) const {
    return this->getDefaultReadableTextureInfo(TextureInfoPriv::ViewFormat(info),
                                               info.isProtected());
}

TextureInfo Caps::getDefaultCompressedTextureInfo(SkTextureCompressionType compressionType,
                                                  Mipmapped mipmapped,
                                                  Protected isProtected) const {
    // Remove CopySrc for compressed textures
    const TextureFormat format = CompressionTypeToTextureFormat(compressionType);
    return this->getDefaultTextureInfo(kDefaultSampledUsage & ~TextureUsage::kCopySrc,
                                       SkSpan(&format, 1),
                                       SampleCount::k1,
                                       mipmapped,
                                       isProtected,
                                       Discardable::kNo);
}

TextureInfo Caps::getDefaultStorageTextureInfo(SkColorType colorType) const {
    // Storage textures are currently always assumed to be sampleable from a shader and can be
    // copied out of (for unit tests).
    return this->getDefaultTextureInfo(TextureUsage::kStorage |
                                       TextureUsage::kSample |
                                       TextureUsage::kCopySrc,
                                       PreferredTextureFormats(colorType),
                                       SampleCount::k1,
                                       Mipmapped::kNo,
                                       Protected::kNo,
                                       Discardable::kNo);
}

TextureInfo Caps::getDefaultReadableStorageTextureInfo(TextureFormat format,
                                                       Protected isProtected) const {
    return this->getDefaultTextureInfo(TextureUsage::kStorage |
                                       TextureUsage::kRead |
                                       TextureUsage::kCopySrc |
                                       TextureUsage::kCopyDst,
                                       SkSpan(&format, 1),
                                       SampleCount::k1,
                                       Mipmapped::kNo,
                                       isProtected,
                                       Discardable::kNo);
}

SampleCount Caps::getCompatibleMSAASampleCount(const TextureInfo& info) const {
    if (info.sampleCount() > SampleCount::k1) {
        // Use the inherent sample count since it's already MSAA
        return info.sampleCount();
    } else if (!this->avoidMSAA()) {
        // The max internal sample count may be higher than what is universally supported for
        // every renderable TextureFormat, but unless avoidMSAA() was true, this should bottom out
        // at SampleCount::k4.
        TextureFormat format = TextureInfoPriv::ViewFormat(info);
        for (SampleCount s = fMaxInternalSampleCount;
             s > SampleCount::k1;
             s = static_cast<SampleCount>((uint8_t)s >> 1)) {
            if (this->isSampleCountSupported(format, s)) {
                return s;
            }
        }
    }

    // If we got here, MSAA has been disabled somehow (by ContextOption, driver workaround, or
    // no support for a particular TextureFormat).
    return SampleCount::k1;
}

DstReadStrategy Caps::getDstReadStrategy() const {
    // TODO(b/238757201; b/383769988): Dst reads are currently only supported by FB fetch and
    // texture copy.
    if (this->shaderCaps()->fFBFetchSupport) {
        return DstReadStrategy::kFramebufferFetch;
    } else {
        return DstReadStrategy::kTextureCopy;
    }
}

sktext::gpu::SubRunControl Caps::getSubRunControl(bool useSDFTForSmallText) const {
#if !defined(SK_DISABLE_SDF_TEXT)
    return sktext::gpu::SubRunControl{
            this->shaderCaps()->supportsDistanceFieldText(),
            useSDFTForSmallText,
            true, /*ableToUsePerspectiveSDFT*/
            this->minDistanceFieldFontSize(),
            this->glyphsAsPathsFontSize(),
            true, /*forcePathAA*/
            this->supportBilerpFromGlyphAtlas()};
#else
    return sktext::gpu::SubRunControl{/*forcePathAA=*/true, this->supportBilerpFromGlyphAtlas()};
#endif
}

} // namespace skgpu::graphite
