/* * 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/glsl/GrGLSLProgramDataManager.h" #include "src/gpu/glsl/GrGLSLUniformHandler.h" GrPipeline::GrPipeline(const InitArgs& args, sk_sp 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 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(GrProcessorKeyBuilder* 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& 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(this->dstTextureOffset().fX), static_cast(this->dstTextureOffset().fY), 1.f / dstTexture->width(), 1.f / dstTexture->height()); } } else { SkASSERT(!fBuiltinUniformHandles->fDstTextureCoordsUni.isValid()); } } // Advanced Filter bool GrPipeline::checkAFRecursively() const { for (const auto& fp : fFragmentProcessors) { if (fp != nullptr && fp->checkAFRecursively()) { return true; } } return false; }