/*
 * 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 "src/core/SkBlendModePriv.h"
#include "src/gpu/GrAppliedClip.h"
#include "src/gpu/GrCaps.h"
#include "src/gpu/GrProcessorSet.h"
#include "src/gpu/GrUserStencilSettings.h"
#include "src/gpu/GrXferProcessor.h"
#include "src/gpu/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;
    }
    SkDEBUGCODE(paint.fAlive = false;)
}

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.fFragmentProcessors.reset(0);
    that.fColorFragmentProcessorCnt = 0;
    that.fFragmentProcessorOffset = 0;
}

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

#ifdef SK_DEBUG
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;
}
#endif

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, const GrUserStencilSettings* userStencil,
        bool hasMixedSampledCoverage, const GrCaps& caps, GrClampType clampType,
        SkPMColor4f* overrideInputColor) {
    SkASSERT(!this->isFinalized());
    SkASSERT(!fFragmentProcessorOffset);

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

    const std::unique_ptr<GrFragmentProcessor>* fps =
            fFragmentProcessors.get() + fFragmentProcessorOffset;
    GrColorFragmentProcessorAnalysis colorAnalysis(colorInput, fps, fColorFragmentProcessorCnt);
    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;
        }
        coverageUsesLocalCoords |= fps[i]->sampleCoordsDependOnLocalCoords();
    }
    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->sampleCoordsDependOnLocalCoords();
        }
    }
    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, clampType);
    if (!this->numCoverageFragmentProcessors() &&
        GrProcessorAnalysisCoverage::kNone == coverageInput) {
    }
    analysis.fRequiresDstTexture =
            SkToBool(props & GrXPFactory::AnalysisProperties::kRequiresDstTexture);
    analysis.fCompatibleWithCoverageAsAlpha &=
            SkToBool(props & GrXPFactory::AnalysisProperties::kCompatibleWithCoverageAsAlpha);
    analysis.fRequiresNonOverlappingDraws = SkToBool(
            props & GrXPFactory::AnalysisProperties::kRequiresNonOverlappingDraws);
    if (props & GrXPFactory::AnalysisProperties::kIgnoresInputColor) {
        colorFPsToEliminate = this->numColorFragmentProcessors();
        analysis.fInputColorType =
                static_cast<Analysis::PackedInputColorType>(Analysis::kIgnored_InputColorType);
        analysis.fUsesLocalCoords = coverageUsesLocalCoords;
    } else {
        analysis.fCompatibleWithCoverageAsAlpha &=
            colorAnalysis.allProcessorsCompatibleWithCoverageAsAlpha();
        analysis.fUsesLocalCoords = coverageUsesLocalCoords | colorAnalysis.usesLocalCoords();
    }
    for (int i = 0; i < colorFPsToEliminate; ++i) {
        fFragmentProcessors[i].reset(nullptr);
    }
    fFragmentProcessorOffset = colorFPsToEliminate;
    fColorFragmentProcessorCnt -= colorFPsToEliminate;
    analysis.fHasColorFragmentProcessor = (fColorFragmentProcessorCnt != 0);

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

    fFlags |= kFinalized_Flag;
    analysis.fIsInitialized = true;
#ifdef SK_DEBUG
    bool hasXferBarrier =
            fXP.fProcessor &&
            GrXferBarrierType::kNone_GrXferBarrierType != fXP.fProcessor->xferBarrierType(caps);
    bool needsNonOverlappingDraws = analysis.fRequiresDstTexture || hasXferBarrier;
    SkASSERT(analysis.fRequiresNonOverlappingDraws == needsNonOverlappingDraws);
#endif
    return analysis;
}

void GrProcessorSet::visitProxies(const GrOp::VisitProxyFunc& func) const {
    for (auto [sampler, fp] : GrFragmentProcessor::ProcessorSetTextureSamplerRange(*this)) {
        bool mipped = (GrSamplerState::Filter::kMipMap == sampler.samplerState().filter());
        func(sampler.view().proxy(), GrMipMapped(mipped));
    }
}
