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

#include "src/gpu/GrPipeline.h"

#include "src/gpu/GrAppliedClip.h"
#include "src/gpu/GrCaps.h"
#include "src/gpu/GrXferProcessor.h"
#include "src/gpu/KeyBuilder.h"
#include "src/gpu/glsl/GrGLSLProgramDataManager.h"
#include "src/gpu/glsl/GrGLSLUniformHandler.h"

GrPipeline::GrPipeline(const InitArgs& args,
                       sk_sp<const GrXferProcessor> xferProcessor,
                       const GrAppliedHardClip& hardClip)
        : fDstProxy(args.fDstProxyView)
        , fWindowRectsState(hardClip.windowRectsState())
        , fXferProcessor(std::move(xferProcessor))
        , fWriteSwizzle(args.fWriteSwizzle) {
    fFlags = (Flags)args.fInputFlags;
    if (hardClip.hasStencilClip()) {
        fFlags |= Flags::kHasStencilClip;
    }
    if (hardClip.scissorState().enabled()) {
        fFlags |= Flags::kScissorTestEnabled;
    }
    // If we have any special dst sample flags we better also have a dst proxy
    SkASSERT(this->dstSampleFlags() == GrDstSampleFlags::kNone || this->dstProxyView());
}

GrPipeline::GrPipeline(const InitArgs& args, GrProcessorSet&& processors,
                       GrAppliedClip&& appliedClip)
        : GrPipeline(args, processors.refXferProcessor(), appliedClip.hardClip()) {
    SkASSERT(processors.isFinalized());
    // Copy GrFragmentProcessors from GrProcessorSet to Pipeline
    fNumColorProcessors = processors.hasColorFragmentProcessor() ? 1 : 0;
    int numTotalProcessors = fNumColorProcessors +
                             (processors.hasCoverageFragmentProcessor() ? 1 : 0) +
                             (appliedClip.hasCoverageFragmentProcessor() ? 1 : 0);
    fFragmentProcessors.reset(numTotalProcessors);

    int currFPIdx = 0;
    if (processors.hasColorFragmentProcessor()) {
        fFragmentProcessors[currFPIdx++] = processors.detachColorFragmentProcessor();
    }
    if (processors.hasCoverageFragmentProcessor()) {
        fFragmentProcessors[currFPIdx++] = processors.detachCoverageFragmentProcessor();
    }
    if (appliedClip.hasCoverageFragmentProcessor()) {
        fFragmentProcessors[currFPIdx++] = appliedClip.detachCoverageFragmentProcessor();
    }
}

GrXferBarrierType GrPipeline::xferBarrierType(const GrCaps& caps) const {
    if (this->dstSampleFlags() & GrDstSampleFlags::kRequiresTextureBarrier) {
        return kTexture_GrXferBarrierType;
    }
    return this->getXferProcessor().xferBarrierType(caps);
}

GrPipeline::GrPipeline(GrScissorTest scissorTest,
                       sk_sp<const GrXferProcessor> xp,
                       const GrSwizzle& writeSwizzle,
                       InputFlags inputFlags)
        : fWindowRectsState()
        , fFlags((Flags)inputFlags)
        , fXferProcessor(std::move(xp))
        , fWriteSwizzle(writeSwizzle) {
    if (GrScissorTest::kEnabled == scissorTest) {
        fFlags |= Flags::kScissorTestEnabled;
    }
}

void GrPipeline::genKey(skgpu::KeyBuilder* b, const GrCaps& caps) const {
    // kSnapVerticesToPixelCenters is implemented in a shader.
    InputFlags ignoredFlags = InputFlags::kSnapVerticesToPixelCenters;
    b->add32((uint32_t)fFlags & ~(uint32_t)ignoredFlags, "flags");

    const GrXferProcessor::BlendInfo& blendInfo = this->getXferProcessor().getBlendInfo();

    static constexpr uint32_t kBlendCoeffSize = 5;
    static constexpr uint32_t kBlendEquationSize = 5;
    static_assert(kLast_GrBlendCoeff < (1 << kBlendCoeffSize));
    static_assert(kLast_GrBlendEquation < (1 << kBlendEquationSize));

    b->addBool(blendInfo.fWriteColor, "writeColor");
    b->addBits(kBlendCoeffSize, blendInfo.fSrcBlend, "srcBlend");
    b->addBits(kBlendCoeffSize, blendInfo.fDstBlend, "dstBlend");
    b->addBits(kBlendEquationSize, blendInfo.fEquation, "equation");
    b->addBool(this->usesDstInputAttachment(), "inputAttach");
}

void GrPipeline::visitTextureEffects(
        const std::function<void(const GrTextureEffect&)>& func) const {
    for (auto& fp : fFragmentProcessors) {
        fp->visitTextureEffects(func);
    }
}

void GrPipeline::visitProxies(const GrVisitProxyFunc& func) const {
    // This iteration includes any clip coverage FPs
    for (auto& fp : fFragmentProcessors) {
        fp->visitProxies(func);
    }
    if (this->usesDstTexture()) {
        func(this->dstProxyView().proxy(), GrMipmapped::kNo);
    }
}

void GrPipeline::setDstTextureUniforms(const GrGLSLProgramDataManager& pdm,
                                       GrGLSLBuiltinUniformHandles* fBuiltinUniformHandles) const {
    GrTexture* dstTexture = this->peekDstTexture();

    if (dstTexture) {
        if (fBuiltinUniformHandles->fDstTextureCoordsUni.isValid()) {
            pdm.set4f(fBuiltinUniformHandles->fDstTextureCoordsUni,
                      static_cast<float>(this->dstTextureOffset().fX),
                      static_cast<float>(this->dstTextureOffset().fY),
                      1.f / dstTexture->width(),
                      1.f / dstTexture->height());
        }
    } else {
        SkASSERT(!fBuiltinUniformHandles->fDstTextureCoordsUni.isValid());
    }
}
