/*
 * 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 GrProcessorSet_DEFINED
#define GrProcessorSet_DEFINED

#include "include/private/SkTemplates.h"
#include "src/gpu/GrFragmentProcessor.h"
#include "src/gpu/GrPaint.h"
#include "src/gpu/GrProcessorAnalysis.h"
#include "src/gpu/GrXferProcessor.h"

struct GrUserStencilSettings;
class GrAppliedClip;
class GrXPFactory;

class GrProcessorSet {
private:
    // Arbitrary constructor arg for empty set and analysis
    enum class Empty { kEmpty };

public:
    GrProcessorSet(GrPaint&&);
    GrProcessorSet(SkBlendMode);
    GrProcessorSet(std::unique_ptr<GrFragmentProcessor> colorFP);
    GrProcessorSet(GrProcessorSet&&);
    GrProcessorSet(const GrProcessorSet&) = delete;
    GrProcessorSet& operator=(const GrProcessorSet&) = delete;

    ~GrProcessorSet();

    int numColorFragmentProcessors() const { return fColorFragmentProcessorCnt; }
    int numCoverageFragmentProcessors() const {
        return this->numFragmentProcessors() - fColorFragmentProcessorCnt;
    }

    const GrFragmentProcessor* colorFragmentProcessor(int idx) const {
        SkASSERT(idx < fColorFragmentProcessorCnt);
        return fFragmentProcessors[idx + fFragmentProcessorOffset].get();
    }
    const GrFragmentProcessor* coverageFragmentProcessor(int idx) const {
        return fFragmentProcessors[idx + fColorFragmentProcessorCnt +
                                   fFragmentProcessorOffset].get();
    }

    const GrXferProcessor* xferProcessor() const {
        SkASSERT(this->isFinalized());
        return fXP.fProcessor;
    }
    sk_sp<const GrXferProcessor> refXferProcessor() const {
        SkASSERT(this->isFinalized());
        return sk_ref_sp(fXP.fProcessor);
    }

    std::unique_ptr<const GrFragmentProcessor> detachColorFragmentProcessor(int idx) {
        SkASSERT(idx < fColorFragmentProcessorCnt);
        return std::move(fFragmentProcessors[idx + fFragmentProcessorOffset]);
    }

    std::unique_ptr<const GrFragmentProcessor> detachCoverageFragmentProcessor(int idx) {
        return std::move(
                fFragmentProcessors[idx + fFragmentProcessorOffset + fColorFragmentProcessorCnt]);
    }

    /** Comparisons are only legal on finalized processor sets. */
    bool operator==(const GrProcessorSet& that) const;
    bool operator!=(const GrProcessorSet& that) const { return !(*this == that); }

    /**
     * This is used to report results of processor analysis when a processor set is finalized (see
     * below).
     */
    class Analysis {
    public:
        Analysis(const Analysis&) = default;
        Analysis() { *reinterpret_cast<uint32_t*>(this) = 0; }

        bool isInitialized() const { return fIsInitialized; }
        bool usesLocalCoords() const { return fUsesLocalCoords; }
        bool requiresDstTexture() const { return fRequiresDstTexture; }
        bool requiresNonOverlappingDraws() const { return fRequiresNonOverlappingDraws; }
        bool isCompatibleWithCoverageAsAlpha() const { return fCompatibleWithCoverageAsAlpha; }
        // Indicates whether all color fragment processors were eliminated in the analysis.
        bool hasColorFragmentProcessor() const { return fHasColorFragmentProcessor; }

        bool inputColorIsIgnored() const { return fInputColorType == kIgnored_InputColorType; }
        bool inputColorIsOverridden() const {
            return fInputColorType == kOverridden_InputColorType;
        }

    private:
        constexpr Analysis(Empty)
                : fUsesLocalCoords(false)
                , fCompatibleWithCoverageAsAlpha(true)
                , fRequiresDstTexture(false)
                , fRequiresNonOverlappingDraws(false)
                , fHasColorFragmentProcessor(false)
                , fIsInitialized(true)
                , fInputColorType(kOriginal_InputColorType) {}
        enum InputColorType : uint32_t {
            kOriginal_InputColorType,
            kOverridden_InputColorType,
            kIgnored_InputColorType
        };

        // MSVS 2015 won't pack different underlying types
        using PackedBool = uint32_t;
        using PackedInputColorType = uint32_t;

        PackedBool fUsesLocalCoords : 1;
        PackedBool fCompatibleWithCoverageAsAlpha : 1;
        PackedBool fRequiresDstTexture : 1;
        PackedBool fRequiresNonOverlappingDraws : 1;
        PackedBool fHasColorFragmentProcessor : 1;
        PackedBool fIsInitialized : 1;
        PackedInputColorType fInputColorType : 2;

        friend class GrProcessorSet;
    };
    GR_STATIC_ASSERT(sizeof(Analysis) <= sizeof(uint32_t));

    /**
     * This analyzes the processors given an op's input color and coverage as well as a clip. The
     * state of the processor set may change to an equivalent but more optimal set of processors.
     * This new state requires that the caller respect the returned 'inputColorOverride'. This is
     * indicated by the returned Analysis's inputColorIsOverridden(). 'inputColorOverride' will not
     * be written if the analysis does not override the input color.
     *
     * This must be called before the processor set is used to construct a GrPipeline and may only
     * be called once.
     *
     * This also puts the processors in "pending execution" state and must be called when an op
     * that owns a processor set is recorded to ensure pending and writes are propagated to
     * resources referred to by the processors. Otherwise, data hazards may occur.
     */
    Analysis finalize(
            const GrProcessorAnalysisColor&, const GrProcessorAnalysisCoverage,
            const GrAppliedClip*, const GrUserStencilSettings*, bool hasMixedSampledCoverage,
            const GrCaps&, GrClampType, SkPMColor4f* inputColorOverride);

    bool isFinalized() const { return SkToBool(kFinalized_Flag & fFlags); }

    /** These are valid only for non-LCD coverage. */
    static const GrProcessorSet& EmptySet();
    static GrProcessorSet MakeEmptySet();
    static constexpr const Analysis EmptySetAnalysis() { return Analysis(Empty::kEmpty); }

#ifdef SK_DEBUG
    SkString dumpProcessors() const;
#endif

    void visitProxies(const GrOp::VisitProxyFunc& func) const {
        for (int i = 0; i < this->numFragmentProcessors(); ++i) {
            GrFragmentProcessor::TextureAccessIter iter(this->fragmentProcessor(i));
            while (const GrFragmentProcessor::TextureSampler* sampler = iter.next()) {
                bool mipped = (GrSamplerState::Filter::kMipMap == sampler->samplerState().filter());
                func(sampler->proxy(), GrMipMapped(mipped));
            }
        }
    }

private:
    GrProcessorSet(Empty) : fXP((const GrXferProcessor*)nullptr), fFlags(kFinalized_Flag) {}

    int numFragmentProcessors() const {
        return fFragmentProcessors.count() - fFragmentProcessorOffset;
    }

    const GrFragmentProcessor* fragmentProcessor(int idx) const {
        return fFragmentProcessors[idx + fFragmentProcessorOffset].get();
    }

    // This absurdly large limit allows Analysis and this to pack fields together.
    static constexpr int kMaxColorProcessors = UINT8_MAX;

    enum Flags : uint16_t { kFinalized_Flag = 0x1 };

    union XP {
        XP(const GrXPFactory* factory) : fFactory(factory) {}
        XP(const GrXferProcessor* processor) : fProcessor(processor) {}
        explicit XP(XP&& that) : fProcessor(that.fProcessor) {
            SkASSERT(fProcessor == that.fProcessor);
            that.fProcessor = nullptr;
        }
        const GrXPFactory* fFactory;
        const GrXferProcessor* fProcessor;
    };

    const GrXPFactory* xpFactory() const {
        SkASSERT(!this->isFinalized());
        return fXP.fFactory;
    }

    SkAutoSTArray<4, std::unique_ptr<const GrFragmentProcessor>> fFragmentProcessors;
    XP fXP;
    uint8_t fColorFragmentProcessorCnt = 0;
    uint8_t fFragmentProcessorOffset = 0;
    uint8_t fFlags;
};

#endif
