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

#ifndef GrProcOptInfo_DEFINED
#define GrProcOptInfo_DEFINED

#include "GrColor.h"
#include "GrInvariantOutput.h"

class GrDrawOp;
class GrFragmentProcessor;
class GrPrimitiveProcessor;

/**
 * GrProcOptInfo gathers invariant data from a set of processor stages.It is used to recognize
 * optimizations related to eliminating stages and vertex attributes that aren't necessary for a
 * draw.
 */
class GrProcOptInfo {
public:
    GrProcOptInfo() : fInOut(0, static_cast<GrColorComponentFlags>(0)) {}

    GrProcOptInfo(GrColor color, GrColorComponentFlags colorFlags)
            : fInOut(color, colorFlags), fInputColor(color) {}

    void resetToLCDCoverage(GrColor color, GrColorComponentFlags colorFlags) {
        this->internalReset(color, colorFlags, true);
    }

    void reset(GrColor color, GrColorComponentFlags colorFlags) {
        this->internalReset(color, colorFlags, false);
    }

    void reset(const GrPipelineInput& input) {
        this->internalReset(input.fColor, input.fValidFlags, input.fIsLCDCoverage);
    }

    /**
     * Runs through a series of processors and updates calculated values. This can be called
     * repeatedly for cases when the sequence of processors is not in a contiguous array.
     */
    void analyzeProcessors(const GrFragmentProcessor* const* processors, int cnt);

    bool isSolidWhite() const { return fInOut.isSolidWhite(); }
    bool isOpaque() const { return fInOut.isOpaque(); }
    bool allStagesMultiplyInput() const { return fInOut.allStagesMulInput(); }
    bool isLCDCoverage() const { return fIsLCDCoverage; }
    GrColor color() const { return fInOut.color(); }
    GrColorComponentFlags validFlags() const { return fInOut.validFlags(); }

    /**
     * Returns the index of the first effective color processor. If an intermediate processor
     * doesn't read its input or has a known output, then we can ignore all earlier processors
     * since they will not affect the final output. Thus the first effective processors index is
     * the index to the first processor that will have an effect on the final output.
     *
     * If processors before the firstEffectiveProcessorIndex() are removed, corresponding values
     * from inputColorIsUsed(), inputColorToEffectiveProcessor(), removeVertexAttribs(), and
     * readsDst() must be used when setting up the draw to ensure correct drawing.
     */
    int firstEffectiveProcessorIndex() const { return fFirstEffectiveProcessorIndex; }

    /**
     * If input color is used and per-vertex colors are not used, this is the input color to the
     * first effective processor.
     */
    GrColor inputColorToFirstEffectiveProccesor() const { return fInputColor; }

private:
    void internalReset(GrColor color, GrColorComponentFlags colorFlags, bool isLCDCoverage) {
        fInOut.reset(color, colorFlags);
        fFirstEffectiveProcessorIndex = 0;
        fInputColor = color;
        fIsLCDCoverage = isLCDCoverage;
    }

    void internalCalc(const GrFragmentProcessor* const[], int cnt);

    GrInvariantOutput fInOut;
    int fFirstEffectiveProcessorIndex = 0;
    bool fIsLCDCoverage = false;
    GrColor fInputColor = 0;
};

#endif
