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

#include "include/private/SkColorData.h"

class GrDrawOp;
class GrFragmentProcessor;

class GrProcessorAnalysisColor {
public:
    enum class Opaque {
        kNo,
        kYes,
    };

    constexpr GrProcessorAnalysisColor(Opaque opaque = Opaque::kNo)
            : fFlags(opaque == Opaque::kYes ? kIsOpaque_Flag : 0)
            , fColor(SK_PMColor4fTRANSPARENT) {}

    GrProcessorAnalysisColor(const SkPMColor4f& color) { this->setToConstant(color); }

    void setToConstant(const SkPMColor4f& color) {
        fColor = color;
        if (color.isOpaque()) {
            fFlags = kColorIsKnown_Flag | kIsOpaque_Flag;
        } else {
            fFlags = kColorIsKnown_Flag;
        }
    }

    void setToUnknown() { fFlags = 0; }

    void setToUnknownOpaque() { fFlags = kIsOpaque_Flag; }

    bool isUnknown() const { return SkToBool(fFlags == 0); }

    bool isOpaque() const { return SkToBool(kIsOpaque_Flag & fFlags); }

    bool isConstant(SkPMColor4f* color = nullptr) const {
        if (kColorIsKnown_Flag & fFlags) {
            if (color) {
                *color = fColor;
            }
            return true;
        }
        return false;
    }

    bool operator==(const GrProcessorAnalysisColor& that) const {
        if (fFlags != that.fFlags) {
            return false;
        }
        return (kColorIsKnown_Flag & fFlags) ? fColor == that.fColor : true;
    }

    /** The returned value reflects the common properties of the two inputs. */
    static GrProcessorAnalysisColor Combine(const GrProcessorAnalysisColor& a,
                                            const GrProcessorAnalysisColor& b) {
        GrProcessorAnalysisColor result;
        uint32_t commonFlags = a.fFlags & b.fFlags;
        if ((kColorIsKnown_Flag & commonFlags) && a.fColor == b.fColor) {
            result.fColor = a.fColor;
            result.fFlags = a.fFlags;
        } else if (kIsOpaque_Flag & commonFlags) {
            result.fFlags = kIsOpaque_Flag;
        }
        return result;
    }

private:
    enum Flags {
        kColorIsKnown_Flag = 0x1,
        kIsOpaque_Flag = 0x2,
    };
    uint32_t fFlags;
    SkPMColor4f fColor;
};

enum class GrProcessorAnalysisCoverage { kNone, kSingleChannel, kLCD };

/**
 * GrColorFragmentProcessorAnalysis gathers invariant data from a set of color fragment processor.
 * It is used to recognize optimizations that can simplify the generated shader or make blending
 * more effecient.
 */
class GrColorFragmentProcessorAnalysis {
public:
    GrColorFragmentProcessorAnalysis() = delete;

    GrColorFragmentProcessorAnalysis(const GrProcessorAnalysisColor& input,
                                     std::unique_ptr<GrFragmentProcessor> const fps[],
                                     int cnt);

    bool isOpaque() const { return fIsOpaque; }

    /**
     * Are all the fragment processors compatible with conflating coverage with color prior to the
     * the first fragment processor. This result assumes that processors that should be eliminated
     * as indicated by initialProcessorsToEliminate() are in fact eliminated.
     */
    bool allProcessorsCompatibleWithCoverageAsAlpha() const {
        return fCompatibleWithCoverageAsAlpha;
    }

    /**
     * Do any of the fragment processors require local coords. This result assumes that
     * processors that should be eliminated as indicated by initialProcessorsToEliminate() are in
     * fact eliminated.
     */
    bool usesLocalCoords() const { return fUsesLocalCoords; }

    /**
     * If we detected that the result after the first N processors is a known color then we
     * eliminate those N processors and replace the GrDrawOp's color input to the GrPipeline with
     * the known output of the Nth processor, so that the Nth+1 fragment processor (or the XP if
     * there are only N processors) sees its expected input. If this returns 0 then there are no
     * processors to eliminate.
     */
    int initialProcessorsToEliminate(SkPMColor4f* newPipelineInputColor) const {
        if (fProcessorsToEliminate > 0) {
            *newPipelineInputColor = fLastKnownOutputColor;
        }
        return fProcessorsToEliminate;
    }

    /**
     * Provides known information about the last processor's output color.
     */
    GrProcessorAnalysisColor outputColor() const {
        if (fKnowOutputColor) {
            return fLastKnownOutputColor;
        }
        return fIsOpaque ? GrProcessorAnalysisColor::Opaque::kYes
                         : GrProcessorAnalysisColor::Opaque::kNo;
    }

private:
    bool fIsOpaque;
    bool fCompatibleWithCoverageAsAlpha;
    bool fUsesLocalCoords;
    bool fKnowOutputColor;
    int fProcessorsToEliminate;
    SkPMColor4f fLastKnownOutputColor;
};

#endif
