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

#include "GrProcessorSet.h"
#include "GrAppliedClip.h"
#include "GrCaps.h"
#include "GrXferProcessor.h"
#include "SkBlendModePriv.h"
#include "effects/GrPorterDuffXferProcessor.h"

const GrProcessorSet& GrProcessorSet::EmptySet() {
    static GrProcessorSet gEmpty(GrProcessorSet::Empty::kEmpty);
    return gEmpty;
}

GrProcessorSet GrProcessorSet::MakeEmptySet() {
    return GrProcessorSet(GrProcessorSet::Empty::kEmpty);
}

GrProcessorSet::GrProcessorSet(GrPaint&& paint) : fXP(paint.getXPFactory()) {
    fFlags = 0;
    if (paint.numColorFragmentProcessors() <= kMaxColorProcessors) {
        fColorFragmentProcessorCnt = paint.numColorFragmentProcessors();
        fFragmentProcessors.reset(paint.numTotalFragmentProcessors());
        int i = 0;
        for (auto& fp : paint.fColorFragmentProcessors) {
            SkASSERT(fp.get());
            fFragmentProcessors[i++] = std::move(fp);
        }
        for (auto& fp : paint.fCoverageFragmentProcessors) {
            SkASSERT(fp.get());
            fFragmentProcessors[i++] = std::move(fp);
        }
    } else {
        SkDebugf("Insane number of color fragment processors in paint. Dropping all processors.");
        fColorFragmentProcessorCnt = 0;
    }
}

GrProcessorSet::GrProcessorSet(SkBlendMode mode)
        : fXP(SkBlendMode_AsXPFactory(mode))
        , fColorFragmentProcessorCnt(0)
        , fFragmentProcessorOffset(0)
        , fFlags(0) {}

GrProcessorSet::GrProcessorSet(std::unique_ptr<GrFragmentProcessor> colorFP)
        : fFragmentProcessors(1)
        , fXP((const GrXPFactory*)nullptr)
        , fColorFragmentProcessorCnt(1)
        , fFragmentProcessorOffset(0)
        , fFlags(0) {
    SkASSERT(colorFP);
    fFragmentProcessors[0] = std::move(colorFP);
}

GrProcessorSet::GrProcessorSet(GrProcessorSet&& that)
        : fXP(std::move(that.fXP))
        , fColorFragmentProcessorCnt(that.fColorFragmentProcessorCnt)
        , fFragmentProcessorOffset(0)
        , fFlags(that.fFlags) {
    fFragmentProcessors.reset(that.fFragmentProcessors.count() - that.fFragmentProcessorOffset);
    for (int i = 0; i < fFragmentProcessors.count(); ++i) {
        fFragmentProcessors[i] =
                std::move(that.fFragmentProcessors[i + that.fFragmentProcessorOffset]);
    }
    that.fColorFragmentProcessorCnt = 0;
    that.fFragmentProcessors.reset(0);
}

GrProcessorSet::~GrProcessorSet() {
    if (this->isFinalized() && this->xferProcessor()) {
        this->xferProcessor()->unref();
    }
}

SkString dump_fragment_processor_tree(const GrFragmentProcessor* fp, int indentCnt) {
    SkString result;
    SkString indentString;
    for (int i = 0; i < indentCnt; ++i) {
        indentString.append("    ");
    }
    result.appendf("%s%s %s \n", indentString.c_str(), fp->name(), fp->dumpInfo().c_str());
    if (fp->numChildProcessors()) {
        for (int i = 0; i < fp->numChildProcessors(); ++i) {
            result += dump_fragment_processor_tree(&fp->childProcessor(i), indentCnt + 1);
        }
    }
    return result;
}

SkString GrProcessorSet::dumpProcessors() const {
    SkString result;
    if (this->numFragmentProcessors()) {
        if (this->numColorFragmentProcessors()) {
            result.append("Color Fragment Processors:\n");
            for (int i = 0; i < this->numColorFragmentProcessors(); ++i) {
                result += dump_fragment_processor_tree(this->colorFragmentProcessor(i), 1);
            }
        } else {
            result.append("No color fragment processors.\n");
        }
        if (this->numCoverageFragmentProcessors()) {
            result.append("Coverage Fragment Processors:\n");
            for (int i = 0; i < this->numColorFragmentProcessors(); ++i) {
                result += dump_fragment_processor_tree(this->coverageFragmentProcessor(i), 1);
            }
        } else {
            result.append("No coverage fragment processors.\n");
        }
    } else {
        result.append("No color or coverage fragment processors.\n");
    }
    if (this->isFinalized()) {
        result.append("Xfer Processor: ");
        if (this->xferProcessor()) {
            result.appendf("%s\n", this->xferProcessor()->name());
        } else {
            result.append("SrcOver\n");
        }
    } else {
        result.append("XP Factory dumping not implemented.\n");
    }
    return result;
}

bool GrProcessorSet::operator==(const GrProcessorSet& that) const {
    SkASSERT(this->isFinalized());
    SkASSERT(that.isFinalized());
    int fpCount = this->numFragmentProcessors();
    if (((fFlags ^ that.fFlags) & ~kFinalized_Flag) || fpCount != that.numFragmentProcessors() ||
        fColorFragmentProcessorCnt != that.fColorFragmentProcessorCnt) {
        return false;
    }

    for (int i = 0; i < fpCount; ++i) {
        int a = i + fFragmentProcessorOffset;
        int b = i + that.fFragmentProcessorOffset;
        if (!fFragmentProcessors[a]->isEqual(*that.fFragmentProcessors[b])) {
            return false;
        }
    }
    // Most of the time both of these are null
    if (!this->xferProcessor() && !that.xferProcessor()) {
        return true;
    }
    const GrXferProcessor& thisXP = this->xferProcessor()
                                            ? *this->xferProcessor()
                                            : GrPorterDuffXPFactory::SimpleSrcOverXP();
    const GrXferProcessor& thatXP = that.xferProcessor()
                                            ? *that.xferProcessor()
                                            : GrPorterDuffXPFactory::SimpleSrcOverXP();
    return thisXP.isEqual(thatXP);
}

GrProcessorSet::Analysis GrProcessorSet::finalize(const GrProcessorAnalysisColor& colorInput,
                                                  const GrProcessorAnalysisCoverage coverageInput,
                                                  const GrAppliedClip* clip, bool isMixedSamples,
                                                  const GrCaps& caps,
                                                  GrPixelConfigIsClamped dstIsClamped,
                                                  GrColor* overrideInputColor) {
    SkASSERT(!this->isFinalized());
    SkASSERT(!fFragmentProcessorOffset);

    GrProcessorSet::Analysis analysis;
    analysis.fCompatibleWithCoverageAsAlpha = GrProcessorAnalysisCoverage::kLCD != coverageInput;

    const std::unique_ptr<const GrFragmentProcessor>* fps =
            fFragmentProcessors.get() + fFragmentProcessorOffset;
    GrColorFragmentProcessorAnalysis colorAnalysis(
            colorInput, unique_ptr_address_as_pointer_address(fps), fColorFragmentProcessorCnt);
    analysis.fCompatibleWithCoverageAsAlpha &=
            colorAnalysis.allProcessorsCompatibleWithCoverageAsAlpha();
    fps += fColorFragmentProcessorCnt;
    int n = this->numCoverageFragmentProcessors();
    bool hasCoverageFP = n > 0;
    bool coverageUsesLocalCoords = false;
    for (int i = 0; i < n; ++i) {
        if (!fps[i]->compatibleWithCoverageAsAlpha()) {
            analysis.fCompatibleWithCoverageAsAlpha = false;
            // Other than tests that exercise atypical behavior we expect all coverage FPs to be
            // compatible with the coverage-as-alpha optimization.
            GrCapsDebugf(&caps, "Coverage FP is not compatible with coverage as alpha.\n");
        }
        coverageUsesLocalCoords |= fps[i]->usesLocalCoords();
    }
    if (clip) {
        hasCoverageFP = hasCoverageFP || clip->numClipCoverageFragmentProcessors();
        for (int i = 0; i < clip->numClipCoverageFragmentProcessors(); ++i) {
            const GrFragmentProcessor* clipFP = clip->clipCoverageFragmentProcessor(i);
            analysis.fCompatibleWithCoverageAsAlpha &= clipFP->compatibleWithCoverageAsAlpha();
            coverageUsesLocalCoords |= clipFP->usesLocalCoords();
        }
    }
    int colorFPsToEliminate = colorAnalysis.initialProcessorsToEliminate(overrideInputColor);
    analysis.fInputColorType = static_cast<Analysis::PackedInputColorType>(
            colorFPsToEliminate ? Analysis::kOverridden_InputColorType
                                : Analysis::kOriginal_InputColorType);

    GrProcessorAnalysisCoverage outputCoverage;
    if (GrProcessorAnalysisCoverage::kLCD == coverageInput) {
        outputCoverage = GrProcessorAnalysisCoverage::kLCD;
    } else if (hasCoverageFP || GrProcessorAnalysisCoverage::kSingleChannel == coverageInput) {
        outputCoverage = GrProcessorAnalysisCoverage::kSingleChannel;
    } else {
        outputCoverage = GrProcessorAnalysisCoverage::kNone;
    }

    GrXPFactory::AnalysisProperties props = GrXPFactory::GetAnalysisProperties(
            this->xpFactory(), colorAnalysis.outputColor(), outputCoverage, caps, dstIsClamped);
    if (!this->numCoverageFragmentProcessors() &&
        GrProcessorAnalysisCoverage::kNone == coverageInput) {
        analysis.fCanCombineOverlappedStencilAndCover = SkToBool(
                props & GrXPFactory::AnalysisProperties::kCanCombineOverlappedStencilAndCover);
    } else {
        // If we have non-clipping coverage processors we don't try to merge stencil steps as its
        // unclear whether it will be correct. We don't expect this to happen in practice.
        analysis.fCanCombineOverlappedStencilAndCover = false;
    }
    analysis.fRequiresDstTexture =
            SkToBool(props & GrXPFactory::AnalysisProperties::kRequiresDstTexture);
    analysis.fCompatibleWithCoverageAsAlpha &=
            SkToBool(props & GrXPFactory::AnalysisProperties::kCompatibleWithAlphaAsCoverage);
    analysis.fRequiresBarrierBetweenOverlappingDraws = SkToBool(
            props & GrXPFactory::AnalysisProperties::kRequiresBarrierBetweenOverlappingDraws);
    if (props & GrXPFactory::AnalysisProperties::kIgnoresInputColor) {
        colorFPsToEliminate = this->numColorFragmentProcessors();
        analysis.fInputColorType =
                static_cast<Analysis::PackedInputColorType>(Analysis::kIgnored_InputColorType);
        analysis.fUsesLocalCoords = coverageUsesLocalCoords;
    } else {
        analysis.fUsesLocalCoords = coverageUsesLocalCoords | colorAnalysis.usesLocalCoords();
    }
    for (int i = 0; i < colorFPsToEliminate; ++i) {
        fFragmentProcessors[i].reset(nullptr);
    }
    for (int i = colorFPsToEliminate; i < fFragmentProcessors.count(); ++i) {
        fFragmentProcessors[i]->markPendingExecution();
    }
    fFragmentProcessorOffset = colorFPsToEliminate;
    fColorFragmentProcessorCnt -= colorFPsToEliminate;

    auto xp = GrXPFactory::MakeXferProcessor(this->xpFactory(), colorAnalysis.outputColor(),
                                             outputCoverage, isMixedSamples, caps, dstIsClamped);
    fXP.fProcessor = xp.release();

    fFlags |= kFinalized_Flag;
    analysis.fIsInitialized = true;
    return analysis;
}
