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

#ifndef skgpu_BlendFormula_DEFINED
#define skgpu_BlendFormula_DEFINED

#include "include/private/base/SkAssert.h"
#include "include/private/base/SkMacros.h"
#include "include/private/base/SkTo.h"
#include "src/gpu/Blend.h"

namespace skgpu {

/**
 * Wraps the shader outputs and HW blend state that comprise a Porter Duff blend mode with coverage.
 */
class BlendFormula {
public:
    /**
     * Values the shader can write to primary and secondary outputs. These are all modulated by
     * coverage. We will ignore the multiplies when not using coverage.
     */
    enum OutputType {
        kNone_OutputType,        //<! 0
        kCoverage_OutputType,    //<! inputCoverage
        kModulate_OutputType,    //<! inputColor * inputCoverage
        kSAModulate_OutputType,  //<! inputColor.a * inputCoverage
        kISAModulate_OutputType, //<! (1 - inputColor.a) * inputCoverage
        kISCModulate_OutputType, //<! (1 - inputColor) * inputCoverage

        kLast_OutputType = kISCModulate_OutputType
    };

    constexpr BlendFormula(OutputType primaryOut,
                           OutputType secondaryOut,
                           skgpu::BlendEquation equation,
                           skgpu::BlendCoeff srcCoeff,
                           skgpu::BlendCoeff dstCoeff)
            : fPrimaryOutputType(primaryOut)
            , fSecondaryOutputType(secondaryOut)
            , fBlendEquation(SkTo<uint8_t>(equation))
            , fSrcCoeff(SkTo<uint8_t>(srcCoeff))
            , fDstCoeff(SkTo<uint8_t>(dstCoeff))
            , fProps(GetProperties(primaryOut, secondaryOut, equation, srcCoeff, dstCoeff)) {}

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

    bool operator==(const BlendFormula& that) const {
        return fPrimaryOutputType == that.fPrimaryOutputType &&
               fSecondaryOutputType == that. fSecondaryOutputType &&
               fBlendEquation == that.fBlendEquation &&
               fSrcCoeff == that.fSrcCoeff &&
               fDstCoeff == that.fDstCoeff &&
               fProps == that.fProps;
    }

    bool hasSecondaryOutput() const {
        return kNone_OutputType != fSecondaryOutputType;
    }
    bool modifiesDst() const {
        return SkToBool(fProps & kModifiesDst_Property);
    }
    bool unaffectedByDst() const {
        return SkToBool(fProps & kUnaffectedByDst_Property);
    }
    // We don't always fully optimize the blend formula (e.g., for opaque src-over), so we include
    // an "IfOpaque" variant to help set AnalysisProperties::kUnaffectedByDstValue in those cases.
    bool unaffectedByDstIfOpaque() const {
        return SkToBool(fProps & kUnaffectedByDstIfOpaque_Property);
    }
    bool usesInputColor() const {
        return SkToBool(fProps & kUsesInputColor_Property);
    }
    bool canTweakAlphaForCoverage() const {
        return SkToBool(fProps & kCanTweakAlphaForCoverage_Property);
    }

    skgpu::BlendEquation equation() const {
        return static_cast<skgpu::BlendEquation>(fBlendEquation);
    }

    skgpu::BlendCoeff srcCoeff() const {
        return static_cast<skgpu::BlendCoeff>(fSrcCoeff);
    }

    skgpu::BlendCoeff dstCoeff() const {
        return static_cast<skgpu::BlendCoeff>(fDstCoeff);
    }

    OutputType primaryOutput() const {
        return fPrimaryOutputType;
    }

    OutputType secondaryOutput() const {
        return fSecondaryOutputType;
    }

private:
    enum Properties {
        kModifiesDst_Property              = 1 << 0,
        kUnaffectedByDst_Property          = 1 << 1,
        kUnaffectedByDstIfOpaque_Property  = 1 << 2,
        kUsesInputColor_Property           = 1 << 3,
        kCanTweakAlphaForCoverage_Property = 1 << 4,

        kLast_Property = kCanTweakAlphaForCoverage_Property
    };
    SK_DECL_BITFIELD_OPS_FRIENDS(Properties)

    /**
     * Deduce the properties of a BlendFormula.
     */
    constexpr BlendFormula::Properties GetProperties(OutputType PrimaryOut,
                                                     OutputType SecondaryOut,
                                                     skgpu::BlendEquation BlendEquation,
                                                     skgpu::BlendCoeff SrcCoeff,
                                                     skgpu::BlendCoeff DstCoeff) {
        return
        // The provided formula should already be optimized before a BlendFormula is constructed.
        // Assert that here while setting up the properties in the constexpr constructor.
        SkASSERT((kNone_OutputType == PrimaryOut) ==
                 !skgpu::BlendCoeffsUseSrcColor(SrcCoeff, DstCoeff)),
        SkASSERT(!skgpu::BlendCoeffRefsSrc2(SrcCoeff)),
        SkASSERT((kNone_OutputType == SecondaryOut) == !skgpu::BlendCoeffRefsSrc2(DstCoeff)),
        SkASSERT(PrimaryOut != SecondaryOut || kNone_OutputType == PrimaryOut),
        SkASSERT(kNone_OutputType != PrimaryOut || kNone_OutputType == SecondaryOut),

        static_cast<Properties>(
            (skgpu::BlendModifiesDst(BlendEquation, SrcCoeff, DstCoeff)
                        ? kModifiesDst_Property
                        : 0) |
            (!skgpu::BlendCoeffsUseDstColor(SrcCoeff, DstCoeff, false/*srcColorIsOpaque*/)
                        ? kUnaffectedByDst_Property
                        : 0) |
            (!skgpu::BlendCoeffsUseDstColor(SrcCoeff, DstCoeff, true/*srcColorIsOpaque*/)
                        ? kUnaffectedByDstIfOpaque_Property
                        : 0) |
            ((PrimaryOut >= kModulate_OutputType &&
                                skgpu::BlendCoeffsUseSrcColor(SrcCoeff, DstCoeff)) ||
                                (SecondaryOut >= kModulate_OutputType &&
                                skgpu::BlendCoeffRefsSrc2(DstCoeff))
                        ? kUsesInputColor_Property
                        : 0) |  // We assert later that SrcCoeff doesn't ref src2.
            ((kModulate_OutputType == PrimaryOut || kNone_OutputType == PrimaryOut) &&
                                kNone_OutputType == SecondaryOut &&
                                skgpu::BlendAllowsCoverageAsAlpha(BlendEquation, SrcCoeff, DstCoeff)
                        ? kCanTweakAlphaForCoverage_Property
                        : 0));
    }

    struct {
        // We allot the enums one more bit than they require because MSVC seems to sign-extend
        // them when the top bit is set. (This is in violation of the C++03 standard 9.6/4)
        OutputType fPrimaryOutputType   : 4;
        OutputType fSecondaryOutputType : 4;
        uint32_t   fBlendEquation       : 6;
        uint32_t   fSrcCoeff            : 6;
        uint32_t   fDstCoeff            : 6;
        Properties fProps               : 32 - (4 + 4 + 6 + 6 + 6);
    };

    static_assert(kLast_OutputType                              < (1 << 3));
    static_assert(static_cast<int>(skgpu::BlendEquation::kLast) < (1 << 5));
    static_assert(static_cast<int>(skgpu::BlendCoeff::kLast)    < (1 << 5));
    static_assert(kLast_Property                                < (1 << 6));
};

static_assert(4 == sizeof(BlendFormula));

SK_MAKE_BITFIELD_OPS(BlendFormula::Properties)

BlendFormula GetBlendFormula(bool isOpaque, bool hasCoverage, SkBlendMode xfermode);

BlendFormula GetLCDBlendFormula(SkBlendMode xfermode);

}  // namespace skgpu

#endif  // skgpu_BlendFormula_DEFINED
