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

#ifndef SkYUVAPixmaps_DEFINED
#define SkYUVAPixmaps_DEFINED

#include "include/core/SkData.h"
#include "include/core/SkImageInfo.h"
#include "include/core/SkPixmap.h"
#include "include/core/SkYUVAInfo.h"
#include "include/private/SkTo.h"

#include <array>
#include <bitset>

class GrImageContext;
struct SkYUVASizeInfo;
struct SkYUVAIndex;

/**
 * SkYUVAInfo combined with per-plane SkColorTypes and row bytes. Fully specifies the SkPixmaps
 * for a YUVA image without the actual pixel memory and data.
 */
class SK_API SkYUVAPixmapInfo {
public:
    static constexpr auto kMaxPlanes = SkYUVAInfo::kMaxPlanes;

    using PlaneConfig  = SkYUVAInfo::PlaneConfig;
    using Subsampling  = SkYUVAInfo::Subsampling;

    /**
     * Data type for Y, U, V, and possibly A channels independent of how values are packed into
     * planes.
     **/
    enum class DataType {
        kUnorm8,          ///< 8 bit unsigned normalized
        kUnorm16,         ///< 16 bit unsigned normalized
        kFloat16,         ///< 16 bit (half) floating point
        kUnorm10_Unorm2,  ///< 10 bit unorm for Y, U, and V. 2 bit unorm for alpha (if present).

        kLast = kUnorm10_Unorm2
    };
    static constexpr int kDataTypeCnt = static_cast<int>(DataType::kLast) + 1;

    class SK_API SupportedDataTypes {
    public:
        /** Defaults to nothing supported. */
        constexpr SupportedDataTypes() = default;

        /** Init based on texture formats supported by the context. */
        SupportedDataTypes(const GrImageContext&);

        /** All legal combinations of PlaneConfig and DataType are supported. */
        static constexpr SupportedDataTypes All();

        /**
         * Checks whether there is a supported combination of color types for planes structured
         * as indicated by PlaneConfig with channel data types as indicated by DataType.
         */
        constexpr bool supported(PlaneConfig, DataType) const;

        /**
         * Update to add support for pixmaps with numChannel channels where each channel is
         * represented as DataType.
         */
        void enableDataType(DataType, int numChannels);

    private:
        // The bit for DataType dt with n channels is at index kDataTypeCnt*(n-1) + dt.
        std::bitset<kDataTypeCnt*4> fDataTypeSupport = {};
    };

    /**
     * Gets the default SkColorType to use with numChannels channels, each represented as DataType.
     * Returns kUnknown_SkColorType if no such color type.
     */
    static constexpr SkColorType DefaultColorTypeForDataType(DataType dataType, int numChannels);

    /**
     * If the SkColorType is supported for YUVA pixmaps this will return the number of YUVA channels
     * that can be stored in a plane of this color type and what the DataType is of those channels.
     * If the SkColorType is not supported as a YUVA plane the number of channels is reported as 0
     * and the DataType returned should be ignored.
     */
    static std::tuple<int, DataType> NumChannelsAndDataType(SkColorType);

    /** Default SkYUVAPixmapInfo is invalid. */
    SkYUVAPixmapInfo() = default;

    /**
     * Initializes the SkYUVAPixmapInfo from a SkYUVAInfo with per-plane color types and row bytes.
     * This will be invalid if the colorTypes aren't compatible with the SkYUVAInfo or if a
     * rowBytes entry is not valid for the plane dimensions and color type. Color type and
     * row byte values beyond the number of planes in SkYUVAInfo are ignored. All SkColorTypes
     * must have the same DataType or this will be invalid.
     *
     * If rowBytes is nullptr then bpp*width is assumed for each plane.
     */
    SkYUVAPixmapInfo(const SkYUVAInfo&,
                     const SkColorType[kMaxPlanes],
                     const size_t rowBytes[kMaxPlanes]);
    /**
     * Like above but uses DefaultColorTypeForDataType to determine each plane's SkColorType. If
     * rowBytes is nullptr then bpp*width is assumed for each plane.
     */
    SkYUVAPixmapInfo(const SkYUVAInfo&, DataType, const size_t rowBytes[kMaxPlanes]);

    SkYUVAPixmapInfo(const SkYUVAPixmapInfo&) = default;

    SkYUVAPixmapInfo& operator=(const SkYUVAPixmapInfo&) = default;

    bool operator==(const SkYUVAPixmapInfo&) const;
    bool operator!=(const SkYUVAPixmapInfo& that) const { return !(*this == that); }

    const SkYUVAInfo& yuvaInfo() const { return fYUVAInfo; }

    SkYUVColorSpace yuvColorSpace() const { return fYUVAInfo.yuvColorSpace(); }

    /** The number of SkPixmap planes, 0 if this SkYUVAPixmapInfo is invalid. */
    int numPlanes() const { return fYUVAInfo.numPlanes(); }

    /** The per-YUV[A] channel data type. */
    DataType dataType() const { return fDataType; }

    /**
     * Row bytes for the ith plane. Returns zero if i >= numPlanes() or this SkYUVAPixmapInfo is
     * invalid.
     */
    size_t rowBytes(int i) const { return fRowBytes[static_cast<size_t>(i)]; }

    /** Image info for the ith plane, or default SkImageInfo if i >= numPlanes() */
    const SkImageInfo& planeInfo(int i) const { return fPlaneInfos[static_cast<size_t>(i)]; }

    /**
     * Determine size to allocate for all planes. Optionally retrieves the per-plane sizes in
     * planeSizes if not null. If total size overflows will return SIZE_MAX and set all planeSizes
     * to SIZE_MAX. Returns 0 and fills planesSizes with 0 if this SkYUVAPixmapInfo is not valid.
     */
    size_t computeTotalBytes(size_t planeSizes[kMaxPlanes] = nullptr) const;

    /**
     * Takes an allocation that is assumed to be at least computeTotalBytes() in size and configures
     * the first numPlanes() entries in pixmaps array to point into that memory. The remaining
     * entries of pixmaps are default initialized. Fails if this SkYUVAPixmapInfo not valid.
     */
    bool initPixmapsFromSingleAllocation(void* memory, SkPixmap pixmaps[kMaxPlanes]) const;

    /**
     * Returns true if this has been configured with a non-empty dimensioned SkYUVAInfo with
     * compatible color types and row bytes.
     */
    bool isValid() const { return fYUVAInfo.isValid(); }

    /** Is this valid and does it use color types allowed by the passed SupportedDataTypes? */
    bool isSupported(const SupportedDataTypes&) const;

private:
    SkYUVAInfo fYUVAInfo;
    std::array<SkImageInfo, kMaxPlanes> fPlaneInfos = {};
    std::array<size_t, kMaxPlanes> fRowBytes = {};
    DataType fDataType = DataType::kUnorm8;
    static_assert(kUnknown_SkColorType == 0, "default init isn't kUnknown");
};

/**
 * Helper to store SkPixmap planes as described by a SkYUVAPixmapInfo. Can be responsible for
 * allocating/freeing memory for pixmaps or use external memory.
 */
class SK_API SkYUVAPixmaps {
public:
    using DataType = SkYUVAPixmapInfo::DataType;
    static constexpr auto kMaxPlanes = SkYUVAPixmapInfo::kMaxPlanes;

    static SkColorType RecommendedRGBAColorType(DataType);

    /** Allocate space for pixmaps' pixels in the SkYUVAPixmaps. */
    static SkYUVAPixmaps Allocate(const SkYUVAPixmapInfo& yuvaPixmapInfo);

    /**
     * Use storage in SkData as backing store for pixmaps' pixels. SkData is retained by the
     * SkYUVAPixmaps.
     */
    static SkYUVAPixmaps FromData(const SkYUVAPixmapInfo&, sk_sp<SkData>);

    /**
     * Makes a deep copy of the src SkYUVAPixmaps. The returned SkYUVAPixmaps owns its planes'
     * backing stores.
     */
    static SkYUVAPixmaps MakeCopy(const SkYUVAPixmaps& src);

    /**
     * Use passed in memory as backing store for pixmaps' pixels. Caller must ensure memory remains
     * allocated while pixmaps are in use. There must be at least
     * SkYUVAPixmapInfo::computeTotalBytes() allocated starting at memory.
     */
    static SkYUVAPixmaps FromExternalMemory(const SkYUVAPixmapInfo&, void* memory);

    /**
     * Wraps existing SkPixmaps. The SkYUVAPixmaps will have no ownership of the SkPixmaps' pixel
     * memory so the caller must ensure it remains valid. Will return an invalid SkYUVAPixmaps if
     * the SkYUVAInfo isn't compatible with the SkPixmap array (number of planes, plane dimensions,
     * sufficient color channels in planes, ...).
     */
    static SkYUVAPixmaps FromExternalPixmaps(const SkYUVAInfo&, const SkPixmap[kMaxPlanes]);

    /** Default SkYUVAPixmaps is invalid. */
    SkYUVAPixmaps() = default;
    ~SkYUVAPixmaps() = default;

    SkYUVAPixmaps(SkYUVAPixmaps&& that) = default;
    SkYUVAPixmaps& operator=(SkYUVAPixmaps&& that) = default;
    SkYUVAPixmaps(const SkYUVAPixmaps&) = default;
    SkYUVAPixmaps& operator=(const SkYUVAPixmaps& that) = default;

    /** Does have initialized pixmaps compatible with its SkYUVAInfo. */
    bool isValid() const { return !fYUVAInfo.dimensions().isEmpty(); }

    const SkYUVAInfo& yuvaInfo() const { return fYUVAInfo; }

    DataType dataType() const { return fDataType; }

    SkYUVAPixmapInfo pixmapsInfo() const;

    /** Number of pixmap planes or 0 if this SkYUVAPixmaps is invalid. */
    int numPlanes() const { return this->isValid() ? fYUVAInfo.numPlanes() : 0; }

    /**
     * Access the SkPixmap planes. They are default initialized if this is not a valid
     * SkYUVAPixmaps.
     */
    const std::array<SkPixmap, kMaxPlanes>& planes() const { return fPlanes; }

    /**
     * Get the ith SkPixmap plane. SkPixmap will be default initialized if i >= numPlanes or this
     * SkYUVAPixmaps is invalid.
     */
    const SkPixmap& plane(int i) const { return fPlanes[SkToSizeT(i)]; }

    /**
     * Computes a SkYUVAIndex representation of the planar layout. Returns true on success and
     * false on failure. Will succeed whenever this->isValid() is true.
     */
    bool toYUVAIndices(SkYUVAIndex[SkYUVAIndex::kIndexCount]) const;

    /** Does this SkPixmaps own the backing store of the planes? */
    bool ownsStorage() const { return SkToBool(fData); }

    /**
     * Conversion to legacy SkYUVA data structures.
     */
    bool toLegacy(SkYUVASizeInfo*, SkYUVAIndex[SkYUVAIndex::kIndexCount]) const;

private:
    SkYUVAPixmaps(const SkYUVAPixmapInfo&, sk_sp<SkData>);
    SkYUVAPixmaps(const SkYUVAInfo&, DataType, const SkPixmap[kMaxPlanes]);

    std::array<SkPixmap, kMaxPlanes> fPlanes = {};
    sk_sp<SkData> fData;
    SkYUVAInfo fYUVAInfo;
    DataType fDataType;
};

//////////////////////////////////////////////////////////////////////////////

constexpr SkYUVAPixmapInfo::SupportedDataTypes SkYUVAPixmapInfo::SupportedDataTypes::All() {
    using ULL = unsigned long long; // bitset cons. takes this.
    ULL bits = 0;
    for (ULL c = 1; c <= 4; ++c) {
        for (ULL dt = 0; dt <= ULL(kDataTypeCnt); ++dt) {
            if (DefaultColorTypeForDataType(static_cast<DataType>(dt),
                                            static_cast<int>(c)) != kUnknown_SkColorType) {
                bits |= ULL(1) << (dt + static_cast<ULL>(kDataTypeCnt)*(c - 1));
            }
        }
    }
    SupportedDataTypes combinations;
    combinations.fDataTypeSupport = bits;
    return combinations;
}

constexpr bool SkYUVAPixmapInfo::SupportedDataTypes::supported(PlaneConfig config,
                                                               DataType type) const {
    int n = SkYUVAInfo::NumPlanes(config);
    for (int i = 0; i < n; ++i) {
        auto c = static_cast<size_t>(SkYUVAInfo::NumChannelsInPlane(config, i));
        SkASSERT(c >= 1 && c <= 4);
        if (!fDataTypeSupport[static_cast<size_t>(type) +
                              (c - 1)*static_cast<size_t>(kDataTypeCnt)]) {
            return false;
        }
    }
    return true;
}

constexpr SkColorType SkYUVAPixmapInfo::DefaultColorTypeForDataType(DataType dataType,
                                                                    int numChannels) {
    switch (numChannels) {
        case 1:
            switch (dataType) {
                case DataType::kUnorm8:         return kGray_8_SkColorType;
                case DataType::kUnorm16:        return kA16_unorm_SkColorType;
                case DataType::kFloat16:        return kA16_float_SkColorType;
                case DataType::kUnorm10_Unorm2: return kUnknown_SkColorType;
            }
            break;
        case 2:
            switch (dataType) {
                case DataType::kUnorm8:         return kR8G8_unorm_SkColorType;
                case DataType::kUnorm16:        return kR16G16_unorm_SkColorType;
                case DataType::kFloat16:        return kR16G16_float_SkColorType;
                case DataType::kUnorm10_Unorm2: return kUnknown_SkColorType;
            }
            break;
        case 3:
            // None of these are tightly packed. The intended use case is for interleaved YUVA
            // planes where we're forcing opaqueness by ignoring the alpha values.
            // There are "x" rather than "A" variants for Unorm8 and Unorm10_Unorm2 but we don't
            // choose them because 1) there is no inherent advantage and 2) there is better support
            // in the GPU backend for the "A" versions.
            switch (dataType) {
                case DataType::kUnorm8:         return kRGBA_8888_SkColorType;
                case DataType::kUnorm16:        return kR16G16B16A16_unorm_SkColorType;
                case DataType::kFloat16:        return kRGBA_F16_SkColorType;
                case DataType::kUnorm10_Unorm2: return kRGBA_1010102_SkColorType;
            }
            break;
        case 4:
            switch (dataType) {
                case DataType::kUnorm8:         return kRGBA_8888_SkColorType;
                case DataType::kUnorm16:        return kR16G16B16A16_unorm_SkColorType;
                case DataType::kFloat16:        return kRGBA_F16_SkColorType;
                case DataType::kUnorm10_Unorm2: return kRGBA_1010102_SkColorType;
            }
            break;
    }
    return kUnknown_SkColorType;
}

#endif
