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

#include "include/gpu/graphite/precompile/PrecompileBlender.h"

#include "include/effects/SkRuntimeEffect.h"
#include "include/gpu/graphite/precompile/PrecompileRuntimeEffect.h"
#include "src/core/SkKnownRuntimeEffects.h"
#include "src/gpu/Blend.h"
#include "src/gpu/graphite/KeyHelpers.h"
#include "src/gpu/graphite/PaintParams.h"
#include "src/gpu/graphite/precompile/PrecompileBaseComplete.h"
#include "src/gpu/graphite/precompile/PrecompileBlenderPriv.h"

namespace skgpu::graphite {

PrecompileBlender::~PrecompileBlender() = default;

//--------------------------------------------------------------------------------------------------
class PrecompileBlendModeBlender final : public PrecompileBlender {
public:
    PrecompileBlendModeBlender(SkBlendMode blendMode) : fBlendMode(blendMode) {}

protected:
    std::optional<SkBlendMode> asBlendMode() const final { return fBlendMode; }

    void addToKey(const KeyContext& keyContext, int desiredCombination) const final {
        SkASSERT(desiredCombination == 0); // The blend mode blender only ever has one combination
        AddBlendMode(keyContext, fBlendMode);
    }

private:
    SkBlendMode fBlendMode;
};

sk_sp<PrecompileBlender> PrecompileBlenders::Mode(SkBlendMode blendMode) {
    return sk_make_sp<PrecompileBlendModeBlender>(blendMode);
}

//--------------------------------------------------------------------------------------------------
sk_sp<PrecompileBlender> PrecompileBlenders::Arithmetic() {
    const SkRuntimeEffect* arithmeticEffect =
            GetKnownRuntimeEffect(SkKnownRuntimeEffects::StableKey::kArithmetic);

    return PrecompileRuntimeEffects::MakePrecompileBlender(sk_ref_sp(arithmeticEffect));
}

//--------------------------------------------------------------------------------------------------
PrecompileBlenderList::PrecompileBlenderList(SkSpan<const sk_sp<PrecompileBlender>> blenders) {
    for (const auto& b : blenders) {
        if (!b) {
            // A null SkBlender is equivalent to kSrcOver
            fHasPorterDuffBlender = true;
        } else if (b->priv().asBlendMode().has_value()) {
            SkBlendMode bm = b->priv().asBlendMode().value();

            SkSpan<const float> coeffs = skgpu::GetPorterDuffBlendConstants(bm);
            if (!coeffs.empty()) {
                fHasPorterDuffBlender = true;
            } else if (bm >= SkBlendMode::kHue) {
                fHasHSLCBlender = true;
            } else {
                SkASSERT(b->priv().numCombinations() == 1);
                fFixedBlenderEffects.push_back(b); // No reduced shader snippet for this blend mode
                fNumCombos++;
            }
        } else {
            // Runtime blenders are always fixed
            fFixedBlenderEffects.push_back(b);
            fNumCombos += b->priv().numCombinations();
        }
    }

    if (!fHasPorterDuffBlender && !fHasHSLCBlender && fFixedBlenderEffects.empty()) {
        fHasPorterDuffBlender = true; // Fallback to kSrcOver
    }

    if (fHasPorterDuffBlender) {
        fNumCombos++;
    }
    if (fHasHSLCBlender) {
        fNumCombos++;
    }
}

PrecompileBlenderList::PrecompileBlenderList(SkSpan<const SkBlendMode> blendModes) {
    for (SkBlendMode bm : blendModes) {
        SkSpan<const float> coeffs = skgpu::GetPorterDuffBlendConstants(bm);
        if (!coeffs.empty()) {
            fHasPorterDuffBlender = true;
        } else if (bm >= SkBlendMode::kHue) {
            fHasHSLCBlender = true;
        } else {
            fFixedBlenderEffects.push_back(PrecompileBlenders::Mode(bm));
        }
    }

    if (!fHasPorterDuffBlender && !fHasHSLCBlender && fFixedBlenderEffects.empty()) {
        fHasPorterDuffBlender = true; // Fallback to kSrcOver
    }

    fNumCombos = fHasPorterDuffBlender + fHasHSLCBlender + SkTo<int>(fFixedBlenderEffects.size());
}

std::pair<sk_sp<PrecompileBlender>, int> PrecompileBlenderList::selectOption(
        int desiredCombination) const {
    SkASSERT(desiredCombination >= 0 && desiredCombination < this->numCombinations());

    if (fHasPorterDuffBlender) {
        if (desiredCombination == 0) {
            // Porter-Duff constant consolidated blend option, pick kSrcOver as a stand-in
            return {PrecompileBlenders::Mode(SkBlendMode::kSrcOver), 0};
        } else {
            desiredCombination--;
        }
    }

    if (fHasHSLCBlender) {
        if (desiredCombination == 0) {
            // HSLC blend option, pick kHue arbitrarily
            return {PrecompileBlenders::Mode(SkBlendMode::kHue), 0};
        } else {
            desiredCombination--;
        }
    }

    if (!fFixedBlenderEffects.empty()) {
        auto [option, childCombination] =
                PrecompileBase::SelectOption<PrecompileBlender>(fFixedBlenderEffects,
                                                                desiredCombination);

        // Double-check that we aren't returning a blend mode that should have been consolidated.
        SkDEBUGCODE(auto bm = option->priv().asBlendMode();)
        SkASSERT(!bm || (*bm > SkBlendMode::kXor && *bm < SkBlendMode::kHue));
        return {option, childCombination};
    }

    SkUNREACHABLE;
}


} // namespace skgpu::graphite
