/* * Copyright 2015 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #ifndef GrPipeline_DEFINED #define GrPipeline_DEFINED #include "include/core/SkRefCnt.h" #include "src/gpu/GrColor.h" #include "src/gpu/GrDstProxyView.h" #include "src/gpu/GrFragmentProcessor.h" #include "src/gpu/GrProcessorSet.h" #include "src/gpu/GrScissorState.h" #include "src/gpu/GrSurfaceProxyView.h" #include "src/gpu/GrUserStencilSettings.h" #include "src/gpu/GrWindowRectsState.h" #include "src/gpu/effects/GrPorterDuffXferProcessor.h" class GrAppliedClip; class GrAppliedHardClip; struct GrGLSLBuiltinUniformHandles; class GrGLSLProgramDataManager; class GrOp; class GrTextureEffect; /** * This immutable object contains information needed to build a shader program and set API * state for a draw. It is used along with a GrGeometryProcessor and a source of geometric * data to draw. */ class GrPipeline { public: /////////////////////////////////////////////////////////////////////////// /// @name Creation // Pipeline options that the caller may enable. // NOTE: This enum is extended later by GrPipeline::Flags. enum class InputFlags : uint8_t { kNone = 0, /** * Cause every pixel to be rasterized that is touched by the triangle anywhere (not just at * pixel center). Additionally, if using MSAA, the sample mask will always have 100% * coverage. * NOTE: The primitive type must be a triangle type. */ kConservativeRaster = (1 << 1), /** * Draws triangles as outlines. */ kWireframe = (1 << 2), /** * Modifies the vertex shader so that vertices will be positioned at pixel centers. */ kSnapVerticesToPixelCenters = (1 << 3), // This value must be last. (See kLastInputFlag.) }; struct InitArgs { InputFlags fInputFlags = InputFlags::kNone; const GrCaps* fCaps = nullptr; GrDstProxyView fDstProxyView; GrSwizzle fWriteSwizzle; }; /** * Creates a simple pipeline with default settings and no processors. The provided blend mode * must be "Porter Duff" (<= kLastCoeffMode). If using GrScissorTest::kEnabled, the caller must * specify a scissor rectangle through the DynamicState struct. **/ GrPipeline(GrScissorTest scissor, SkBlendMode blend, const GrSwizzle& writeSwizzle, InputFlags flags = InputFlags::kNone) : GrPipeline(scissor, GrPorterDuffXPFactory::MakeNoCoverageXP(blend), writeSwizzle, flags) {} GrPipeline(GrScissorTest, sk_sp, const GrSwizzle& writeSwizzle, InputFlags = InputFlags::kNone); GrPipeline(const InitArgs& args, sk_sp, const GrAppliedHardClip&); GrPipeline(const InitArgs&, GrProcessorSet&&, GrAppliedClip&&); GrPipeline(const GrPipeline&) = delete; GrPipeline& operator=(const GrPipeline&) = delete; /// @} /////////////////////////////////////////////////////////////////////////// /// @name GrFragmentProcessors int numFragmentProcessors() const { return fFragmentProcessors.count(); } int numColorFragmentProcessors() const { return fNumColorProcessors; } bool isColorFragmentProcessor(int idx) const { return idx < fNumColorProcessors; } bool isCoverageFragmentProcessor(int idx) const { return idx >= fNumColorProcessors; } bool usesLocalCoords() const { // The sample coords for the top level FPs are implicitly the GP's local coords. for (const auto& fp : fFragmentProcessors) { if (fp->usesSampleCoords()) { return true; } } return false; } void visitTextureEffects(const std::function&) const; const GrXferProcessor& getXferProcessor() const { if (fXferProcessor) { return *fXferProcessor; } else { // A null xp member means the common src-over case. GrXferProcessor's ref'ing // mechanism is not thread safe so we do not hold a ref on this global. return GrPorterDuffXPFactory::SimpleSrcOverXP(); } } // Helper functions to quickly know if this GrPipeline will access the dst as a texture or an // input attachment. bool usesDstTexture() const { return this->dstProxyView() && !this->usesDstInputAttachment(); } bool usesDstInputAttachment() const { return this->dstSampleFlags() & GrDstSampleFlags::kAsInputAttachment; } /** * This returns the GrSurfaceProxyView for the texture used to access the dst color. If the * GrXferProcessor does not use the dst color then the proxy on the GrSurfaceProxyView will be * nullptr. */ const GrSurfaceProxyView& dstProxyView() const { return fDstProxy.proxyView(); } SkIPoint dstTextureOffset() const { return fDstProxy.offset(); } GrDstSampleFlags dstSampleFlags() const { return fDstProxy.dstSampleFlags(); } /** If this GrXferProcessor uses a texture to access the dst color, returns that texture. */ GrTexture* peekDstTexture() const { if (!this->usesDstTexture()) { return nullptr; } if (GrTextureProxy* dstProxy = this->dstProxyView().asTextureProxy()) { return dstProxy->peekTexture(); } return nullptr; } const GrFragmentProcessor& getFragmentProcessor(int idx) const { return *fFragmentProcessors[idx]; } /// @} bool isScissorTestEnabled() const { return SkToBool(fFlags & Flags::kScissorTestEnabled); } const GrWindowRectsState& getWindowRectsState() const { return fWindowRectsState; } bool usesConservativeRaster() const { return fFlags & InputFlags::kConservativeRaster; } bool isWireframe() const { return fFlags & InputFlags::kWireframe; } bool snapVerticesToPixelCenters() const { return fFlags & InputFlags::kSnapVerticesToPixelCenters; } bool hasStencilClip() const { return SkToBool(fFlags & Flags::kHasStencilClip); } #ifdef SK_DEBUG bool allProxiesInstantiated() const { for (int i = 0; i < fFragmentProcessors.count(); ++i) { if (!fFragmentProcessors[i]->isInstantiated()) { return false; } } if (this->dstProxyView().proxy()) { return this->dstProxyView().proxy()->isInstantiated(); } return true; } #endif GrXferBarrierType xferBarrierType(const GrCaps&) const; // Used by Vulkan and Metal to cache their respective pipeline objects void genKey(GrProcessorKeyBuilder*, const GrCaps&) const; const GrSwizzle& writeSwizzle() const { return fWriteSwizzle; } void visitProxies(const GrVisitProxyFunc&) const; void setDstTextureUniforms(const GrGLSLProgramDataManager& pdm, GrGLSLBuiltinUniformHandles* fBuiltinUniformHandles) const; private: inline static constexpr uint8_t kLastInputFlag = (uint8_t)InputFlags::kSnapVerticesToPixelCenters; /** This is a continuation of the public "InputFlags" enum. */ enum class Flags : uint8_t { kHasStencilClip = (kLastInputFlag << 1), kScissorTestEnabled = (kLastInputFlag << 2), }; GR_DECL_BITFIELD_CLASS_OPS_FRIENDS(Flags); friend bool operator&(Flags, InputFlags); // A pipeline can contain up to three processors: color, paint coverage, and clip coverage. using FragmentProcessorArray = SkAutoSTArray<3, std::unique_ptr>; GrDstProxyView fDstProxy; GrWindowRectsState fWindowRectsState; Flags fFlags; sk_sp fXferProcessor; FragmentProcessorArray fFragmentProcessors; // This value is also the index in fFragmentProcessors where coverage processors begin. int fNumColorProcessors = 0; GrSwizzle fWriteSwizzle; }; GR_MAKE_BITFIELD_CLASS_OPS(GrPipeline::InputFlags) GR_MAKE_BITFIELD_CLASS_OPS(GrPipeline::Flags) inline bool operator&(GrPipeline::Flags flags, GrPipeline::InputFlags inputFlag) { return (flags & (GrPipeline::Flags)inputFlag); } #endif