/*
 * 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 "GrFragmentProcessor.h"
#include "GrPaint.h"
#include "GrPipelineInput.h"
#include "SkTemplates.h"

class GrAppliedClip;
class GrXPFactory;

class GrProcessorSet : private SkNoncopyable {
public:
    GrProcessorSet(GrPaint&& paint);

    ~GrProcessorSet() {
        // We are deliberately not using sk_sp here because this will be updated to work with
        // "pending execution" refs.
        for (auto fp : fFragmentProcessors) {
            fp->unref();
        }
    }

    int numColorFragmentProcessors() const { return fColorFragmentProcessorCnt; }
    int numCoverageFragmentProcessors() const {
        return fFragmentProcessors.count() - fColorFragmentProcessorCnt;
    }
    int numFragmentProcessors() const { return fFragmentProcessors.count(); }

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

    const GrXPFactory* xpFactory() const { return fXPFactory; }

    bool usesDistanceVectorField() const { return SkToBool(fFlags & kUseDistanceVectorField_Flag); }
    bool disableOutputConversionToSRGB() const {
        return SkToBool(fFlags & kDisableOutputConversionToSRGB_Flag);
    }
    bool allowSRGBInputs() const { return SkToBool(fFlags & kAllowSRGBInputs_Flag); }

    /**
     * This is used to track analysis of color and coverage values through the fragment processors.
     */
    class FragmentProcessorAnalysis {
    public:
        FragmentProcessorAnalysis() = default;
        // This version is used by a unit test that assumes no clip, no processors, and no PLS.
        FragmentProcessorAnalysis(const GrPipelineInput& colorInput,
                                  const GrPipelineInput coverageInput, const GrCaps&);

        void reset(const GrPipelineInput& colorInput, const GrPipelineInput coverageInput,
                   const GrProcessorSet&, bool usesPLSDstRead, const GrAppliedClip&, const GrCaps&);

        int initialColorProcessorsToEliminate(GrColor* newInputColor) const {
            if (fInitialColorProcessorsToEliminate > 0) {
                *newInputColor = fOverrideInputColor;
            }
            return fInitialColorProcessorsToEliminate;
        }

        bool usesPLSDstRead() const { return fUsesPLSDstRead; }
        bool isCompatibleWithCoverageAsAlpha() const { return fCompatibleWithCoverageAsAlpha; }
        bool isOutputColorOpaque() const {
            return ColorType::kOpaque == fColorType || ColorType::kOpaqueConstant == fColorType;
        }
        bool hasKnownOutputColor(GrColor* color = nullptr) const {
            bool constant =
                    ColorType::kConstant == fColorType || ColorType::kOpaqueConstant == fColorType;
            if (constant && color) {
                *color = fKnownOutputColor;
            }
            return constant;
        }
        bool hasCoverage() const { return CoverageType::kNone != fCoverageType; }
        bool hasLCDCoverage() const { return CoverageType::kLCD == fCoverageType; }

    private:
        void internalReset(const GrPipelineInput& colorInput, const GrPipelineInput coverageInput,
                           const GrProcessorSet&, bool usesPLSDstRead,
                           const GrFragmentProcessor* clipFP, const GrCaps&);

        enum class ColorType { kUnknown, kOpaqueConstant, kConstant, kOpaque };
        enum class CoverageType { kNone, kSingleChannel, kLCD };

        bool fUsesPLSDstRead = false;
        bool fCompatibleWithCoverageAsAlpha = true;
        CoverageType fCoverageType = CoverageType::kNone;
        ColorType fColorType = ColorType::kUnknown;
        int fInitialColorProcessorsToEliminate = 0;
        GrColor fOverrideInputColor;
        GrColor fKnownOutputColor;
    };

private:
    const GrXPFactory* fXPFactory = nullptr;
    SkAutoSTArray<4, const GrFragmentProcessor*> fFragmentProcessors;
    int fColorFragmentProcessorCnt;
    enum Flags : uint32_t {
        kUseDistanceVectorField_Flag = 0x1,
        kDisableOutputConversionToSRGB_Flag = 0x2,
        kAllowSRGBInputs_Flag = 0x4
    };
    uint32_t fFlags;
};

#endif
