/*
 * 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/base/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()) {}

Caps::~Caps() {}

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;
}

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::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,
                                        TextureFormat format,
                                        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
    }

    auto [supportedUsage, supportedSampleCounts] =
            this->getTextureSupport(format, Tiling::kOptimal);
    if ((supportedUsage & usage) != usage || !SkToBool(supportedSampleCounts & sampleCount)) {
        return {}; // unsupported
    }

    if (SkToBool(usage & TextureUsage::kRender) &&
        SkToBool(supportedUsage & TextureUsage::kMSRTSS) &&
        sampleCount == SampleCount::k1) {
        // Proactively 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);
}

TextureInfo Caps::getDefaultAttachmentTextureInfo(AttachmentDesc desc,
                                                  Protected isProtected,
                                                  Discardable discardable) const {
    return this->getDefaultTextureInfo(TextureUsage::kRender,
                                       desc.fFormat,
                                       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;
    if (renderable == Renderable::kYes) {
        usage |= TextureUsage::kRender;
    }

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

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

TextureInfo Caps::getDefaultCompressedTextureInfo(SkTextureCompressionType compressionType,
                                                  Mipmapped mipmapped,
                                                  Protected isProtected) const {
    // Remove CopySrc for compressed textures
    return this->getDefaultTextureInfo(kDefaultSampledUsage & ~TextureUsage::kCopySrc,
                                       CompressionTypeToTextureFormat(compressionType),
                                       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,
                                       this->getFormatForColorType(colorType, Renderable::kNo),
                                       SampleCount::k1,
                                       Mipmapped::kNo,
                                       Protected::kNo,
                                       Discardable::kNo);
}

bool Caps::areColorTypeAndTextureInfoCompatible(SkColorType ct, const TextureInfo& info) const {
    // TODO: add SkTextureCompressionType handling
    // (can be handled by setting up the colorTypeInfo instead?)

    return SkToBool(this->getColorTypeInfo(ct, info));
}

const Caps::ColorTypeInfo* Caps::getColorTypeInfo(SkColorType ct, const TextureInfo& info) const {
    if (!info.isValid()) {
        return nullptr;
    }

    for (const ColorTypeInfo& colorInfo : this->getColorTypeInfos(info)) {
        if (colorInfo.fColorType == ct) {
            return &colorInfo;
        }
    }
    return nullptr;
}

SkColorType Caps::getDefaultColorType(const TextureInfo& info) const {
    if (!info.isValid()) {
        return kUnknown_SkColorType;
    }

    const bool isRenderable = this->isRenderable(info);
    for (const ColorTypeInfo& colorInfo : this->getColorTypeInfos(info)) {
        if (!isRenderable || (colorInfo.fFlags & ColorTypeInfo::kRenderable_Flag)) {
            return colorInfo.fColorType;
        }
    }
    return kUnknown_SkColorType;
}

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;
}

skgpu::Swizzle Caps::getReadSwizzle(SkColorType ct, const TextureInfo& info) const {
    // TODO: add SkTextureCompressionType handling
    // (can be handled by setting up the colorTypeInfo instead?)

    auto colorTypeInfo = this->getColorTypeInfo(ct, info);
    if (!colorTypeInfo) {
        SkDEBUGFAILF("Illegal color type (%d) and format combination.", static_cast<int>(ct));
        return {};
    }

    return colorTypeInfo->fReadSwizzle;
}

skgpu::Swizzle Caps::getWriteSwizzle(SkColorType ct, const TextureInfo& info) const {
    auto colorTypeInfo = this->getColorTypeInfo(ct, info);
    if (!colorTypeInfo) {
        SkDEBUGFAILF("Illegal color type (%d) and format combination.", static_cast<int>(ct));
        return {};
    }

    return colorTypeInfo->fWriteSwizzle;
}

std::pair<SkColorType, bool /*isRGBFormat*/> Caps::supportedTransferColorType(
        SkColorType colorType,
        const TextureInfo& textureInfo) const {
    // NOTE: Compressed textures can't be read back, and external format textures can't be read or
    // written to. However, this is not checked here. Instead that is expected to be handled by
    // supports[Read|Write]Pixels().
    const ColorTypeInfo* colorInfo = this->getColorTypeInfo(colorType, textureInfo);
    if (colorInfo) {
        const TextureFormat format = TextureInfoPriv::ViewFormat(textureInfo);
        const bool rgbRequiresIntervention =
                TextureFormatChannelMask(format) == kRGB_SkColorChannelFlags &&
                colorInfo->fTransferColorType != kRGB_565_SkColorType;
        return {colorInfo->fTransferColorType, rgbRequiresIntervention};
    } else {
        return {kUnknown_SkColorType, false};
    }
}

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*/};
#else
    return sktext::gpu::SubRunControl{/*forcePathAA=*/true};
#endif
}

} // namespace skgpu::graphite
