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

#ifndef GrMtlCaps_DEFINED
#define GrMtlCaps_DEFINED

#include "include/private/SkTDArray.h"
#include "src/gpu/GrCaps.h"
#include "src/gpu/mtl/GrMtlAttachment.h"

#import <Metal/Metal.h>

class GrShaderCaps;
class GrMtlRenderTarget;

/**
 * Stores some capabilities of a Mtl backend.
 */
class GrMtlCaps : public GrCaps {
public:
    GrMtlCaps(const GrContextOptions& contextOptions, id<MTLDevice> device);

    bool isFormatSRGB(const GrBackendFormat&) const override;

    bool isFormatTexturable(const GrBackendFormat&, GrTextureType) const override;
    bool isFormatTexturable(MTLPixelFormat) const;

    bool isFormatCopyable(const GrBackendFormat&) const override { return true; }

    bool isFormatAsColorTypeRenderable(GrColorType ct, const GrBackendFormat& format,
                                       int sampleCount = 1) const override;
    bool isFormatRenderable(const GrBackendFormat& format, int sampleCount) const override;
    bool isFormatRenderable(MTLPixelFormat, int sampleCount) const;

    int getRenderTargetSampleCount(int requestedCount, const GrBackendFormat&) const override;
    int getRenderTargetSampleCount(int requestedCount, MTLPixelFormat) const;

    int maxRenderTargetSampleCount(const GrBackendFormat&) const override;
    int maxRenderTargetSampleCount(MTLPixelFormat) const;

    SupportedWrite supportedWritePixelsColorType(GrColorType surfaceColorType,
                                                 const GrBackendFormat& surfaceFormat,
                                                 GrColorType srcColorType) const override;

    SurfaceReadPixelsSupport surfaceSupportsReadPixels(const GrSurface*) const override;

    DstCopyRestrictions getDstCopyRestrictions(const GrRenderTargetProxy* src,
                                               GrColorType ct) const override;

    /**
     * Returns both a supported and most prefered stencil format to use in draws.
     */
    MTLPixelFormat preferredStencilFormat() const {
        return fPreferredStencilFormat;
    }

    bool canCopyAsBlit(MTLPixelFormat dstFormat, int dstSampleCount,
                       MTLPixelFormat srcFormat, int srcSampleCount,
                       const SkIRect& srcRect, const SkIPoint& dstPoint,
                       bool areDstSrcSameObj) const;

    bool canCopyAsResolve(MTLPixelFormat dstFormat, int dstSampleCount,
                          MTLPixelFormat srcFormat, int srcSampleCount,
                          bool srcIsRenderTarget, const SkISize srcDimensions,
                          const SkIRect& srcRect,
                          const SkIPoint& dstPoint,
                          bool areDstSrcSameObj) const;

    GrBackendFormat getBackendFormatFromCompressionType(SkImage::CompressionType) const override;

    MTLPixelFormat getFormatFromColorType(GrColorType colorType) const {
        int idx = static_cast<int>(colorType);
        return fColorTypeToFormatTable[idx];
    }

    GrSwizzle getWriteSwizzle(const GrBackendFormat&, GrColorType) const override;

    uint64_t computeFormatKey(const GrBackendFormat&) const override;

    GrProgramDesc makeDesc(GrRenderTarget*,
                           const GrProgramInfo&,
                           ProgramDescOverrideFlags) const override;
    MTLPixelFormat getStencilPixelFormat(const GrProgramDesc& desc);

    // if true, MTLStoreActionStoreAndMultiplesampleResolve is available
    bool storeAndMultisampleResolveSupport() const { return fStoreAndMultisampleResolveSupport; }

    // If true when doing MSAA draws, we will prefer to discard the MSAA attachment on load
    // and stores. The use of this feature for specific draws depends on the render target having a
    // resolve attachment, and if we need to load previous data the resolve attachment must
    // be readable in a shader. Otherwise we will just write out and store the MSAA attachment
    // like normal.
    bool preferDiscardableMSAAAttachment() const { return fPreferDiscardableMSAAAttachment; }
    bool renderTargetSupportsDiscardableMSAA(const GrMtlRenderTarget*) const;

#if GR_TEST_UTILS
    std::vector<TestFormatColorTypeCombination> getTestingCombinations() const override;
#endif
    void onDumpJSON(SkJSONWriter*) const override;

private:
    void initGPUFamily(id<MTLDevice> device);

    void initStencilFormat(id<MTLDevice> device);

    void initGrCaps(id<MTLDevice> device);
    void initShaderCaps();

    void applyDriverCorrectnessWorkarounds(const GrContextOptions&, const id<MTLDevice>);

    void initFormatTable();

    bool onSurfaceSupportsWritePixels(const GrSurface*) const override;
    bool onCanCopySurface(const GrSurfaceProxy* dst, const GrSurfaceProxy* src,
                          const SkIRect& srcRect, const SkIPoint& dstPoint) const override;
    GrBackendFormat onGetDefaultBackendFormat(GrColorType) const override;
    bool onAreColorTypeAndFormatCompatible(GrColorType, const GrBackendFormat&) const override;

    SupportedRead onSupportedReadPixelsColorType(GrColorType, const GrBackendFormat&,
                                                 GrColorType) const override;

    GrSwizzle onGetReadSwizzle(const GrBackendFormat&, GrColorType) const override;

    // ColorTypeInfo for a specific format
    struct ColorTypeInfo {
        GrColorType fColorType = GrColorType::kUnknown;
        enum {
            kUploadData_Flag = 0x1,
            // Does Ganesh itself support rendering to this colorType & format pair. Renderability
            // still additionally depends on if the format itself is renderable.
            kRenderable_Flag = 0x2,
        };
        uint32_t fFlags = 0;

        GrSwizzle fReadSwizzle;
        GrSwizzle fWriteSwizzle;
    };

    struct FormatInfo {
        uint32_t colorTypeFlags(GrColorType colorType) const {
            for (int i = 0; i < fColorTypeInfoCount; ++i) {
                if (fColorTypeInfos[i].fColorType == colorType) {
                    return fColorTypeInfos[i].fFlags;
                }
            }
            return 0;
        }

        enum {
            kTexturable_Flag  = 0x1,
            kRenderable_Flag  = 0x2, // Color attachment and blendable
            kMSAA_Flag        = 0x4,
            kResolve_Flag     = 0x8,
        };
        static const uint16_t kAllFlags = kTexturable_Flag | kRenderable_Flag |
                                          kMSAA_Flag | kResolve_Flag;

        uint16_t fFlags = 0;

        std::unique_ptr<ColorTypeInfo[]> fColorTypeInfos;
        int fColorTypeInfoCount = 0;
    };
#ifdef SK_BUILD_FOR_IOS
    inline static constexpr size_t kNumMtlFormats = 17;
#else
    inline static constexpr size_t kNumMtlFormats = 16;
#endif
    static size_t GetFormatIndex(MTLPixelFormat);
    FormatInfo fFormatTable[kNumMtlFormats];

    const FormatInfo& getFormatInfo(const MTLPixelFormat pixelFormat) const {
        size_t index = GetFormatIndex(pixelFormat);
        return fFormatTable[index];
    }

    MTLPixelFormat fColorTypeToFormatTable[kGrColorTypeCnt];
    void setColorType(GrColorType, std::initializer_list<MTLPixelFormat> formats);

    enum class GPUFamily {
        kMac,
        kApple,
    };
    bool isMac() { return fGPUFamily == GPUFamily::kMac; }
    bool isApple() { return fGPUFamily == GPUFamily::kApple; }
    bool getGPUFamily(id<MTLDevice> device, GPUFamily* gpuFamily, int* group);
    bool getGPUFamilyFromFeatureSet(id<MTLDevice> device, GrMtlCaps::GPUFamily* gpuFamily,
                                    int* group);

    GPUFamily fGPUFamily;
    int fFamilyGroup;

    SkTDArray<int> fSampleCounts;

    MTLPixelFormat fPreferredStencilFormat;

    bool fStoreAndMultisampleResolveSupport : 1;
    bool fPreferDiscardableMSAAAttachment : 1;

    using INHERITED = GrCaps;
};

#endif
