| /* |
| * 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/SkMatrix.h" |
| #include "include/core/SkRefCnt.h" |
| #include "src/gpu/GrColor.h" |
| #include "src/gpu/GrFragmentProcessor.h" |
| #include "src/gpu/GrNonAtomicRef.h" |
| #include "src/gpu/GrPendingIOResource.h" |
| #include "src/gpu/GrProcessorSet.h" |
| #include "src/gpu/GrProgramDesc.h" |
| #include "src/gpu/GrScissorState.h" |
| #include "src/gpu/GrUserStencilSettings.h" |
| #include "src/gpu/GrWindowRectsState.h" |
| #include "src/gpu/effects/GrCoverageSetOpXP.h" |
| #include "src/gpu/effects/GrDisableColorXP.h" |
| #include "src/gpu/effects/GrPorterDuffXferProcessor.h" |
| #include "src/gpu/effects/generated/GrSimpleTextureEffect.h" |
| #include "src/gpu/geometry/GrRect.h" |
| |
| class GrAppliedClip; |
| class GrOp; |
| class GrRenderTargetContext; |
| |
| /** |
| * This immutable object contains information needed to set build a shader program and set API |
| * state for a draw. It is used along with a GrPrimitiveProcessor and a source of geometric |
| * data (GrMesh or GrPath) 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, |
| /** |
| * Perform HW anti-aliasing. This means either HW FSAA, if supported by the render target, |
| * or smooth-line rendering if a line primitive is drawn and line smoothing is supported by |
| * the 3D API. |
| */ |
| kHWAntialias = (1 << 0), |
| /** |
| * Modifies the vertex shader so that vertices will be positioned at pixel centers. |
| */ |
| kSnapVerticesToPixelCenters = (1 << 1), // This value must be last. (See kLastInputFlag.) |
| }; |
| |
| struct InitArgs { |
| InputFlags fInputFlags = InputFlags::kNone; |
| const GrUserStencilSettings* fUserStencil = &GrUserStencilSettings::kUnused; |
| const GrCaps* fCaps = nullptr; |
| GrXferProcessor::DstProxy fDstProxy; |
| GrSwizzle fOutputSwizzle; |
| }; |
| |
| /** |
| * Some state can be changed between GrMeshes without changing GrPipelines. This is generally |
| * less expensive then using multiple pipelines. Such state is called "dynamic state". It can |
| * be specified in two ways: |
| * 1) FixedDynamicState - use this to specify state that does not vary between GrMeshes. |
| * 2) DynamicStateArrays - use this to specify per mesh values for dynamic state. |
| **/ |
| struct FixedDynamicState { |
| explicit FixedDynamicState(const SkIRect& scissorRect) : fScissorRect(scissorRect) {} |
| FixedDynamicState() = default; |
| SkIRect fScissorRect = SkIRect::EmptyIRect(); |
| // Must have GrPrimitiveProcessor::numTextureSamplers() entries. Can be null if no samplers |
| // or textures are passed using DynamicStateArrays. |
| GrTextureProxy** fPrimitiveProcessorTextures = nullptr; |
| }; |
| |
| /** |
| * Any non-null array overrides the FixedDynamicState on a mesh-by-mesh basis. Arrays must |
| * have one entry for each GrMesh. |
| */ |
| struct DynamicStateArrays { |
| const SkIRect* fScissorRects = nullptr; |
| // Must have GrPrimitiveProcessor::numTextureSamplers() * num_meshes entries. |
| // Can be null if no samplers or to use the same textures for all meshes via' |
| // FixedDynamicState. |
| GrTextureProxy** fPrimitiveProcessorTextures = nullptr; |
| }; |
| |
| /** |
| * 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& outputSwizzle, |
| InputFlags flags = InputFlags::kNone, |
| const GrUserStencilSettings* stencil = &GrUserStencilSettings::kUnused) |
| : GrPipeline(scissor, GrPorterDuffXPFactory::MakeNoCoverageXP(blend), outputSwizzle, |
| flags, stencil) { |
| } |
| |
| GrPipeline(GrScissorTest, sk_sp<const GrXferProcessor>, const GrSwizzle& outputSwizzle, |
| InputFlags = InputFlags::kNone, |
| const GrUserStencilSettings* = &GrUserStencilSettings::kUnused); |
| |
| GrPipeline(const InitArgs&, GrProcessorSet&&, GrAppliedClip&&); |
| |
| GrPipeline(const GrPipeline&) = delete; |
| GrPipeline& operator=(const GrPipeline&) = delete; |
| |
| /// @} |
| |
| /////////////////////////////////////////////////////////////////////////// |
| /// @name GrFragmentProcessors |
| |
| // Make the renderTargetContext's GrOpList be dependent on any GrOpLists in this pipeline |
| void addDependenciesTo(GrOpList* recipient, const GrCaps&) const; |
| |
| int numColorFragmentProcessors() const { return fNumColorProcessors; } |
| int numCoverageFragmentProcessors() const { |
| return fFragmentProcessors.count() - fNumColorProcessors; |
| } |
| int numFragmentProcessors() const { return fFragmentProcessors.count(); } |
| |
| const GrXferProcessor& getXferProcessor() const { |
| if (fXferProcessor) { |
| return *fXferProcessor.get(); |
| } 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(); |
| } |
| } |
| |
| /** |
| * If the GrXferProcessor uses a texture to access the dst color, then this returns that |
| * texture and the offset to the dst contents within that texture. |
| */ |
| GrTextureProxy* dstTextureProxy(SkIPoint* offset = nullptr) const { |
| if (offset) { |
| *offset = fDstTextureOffset; |
| } |
| |
| return fDstTextureProxy ? fDstTextureProxy->asTextureProxy() : nullptr; |
| } |
| |
| GrTexture* peekDstTexture(SkIPoint* offset = nullptr) const { |
| if (GrTextureProxy* dstProxy = this->dstTextureProxy(offset)) { |
| return dstProxy->peekTexture(); |
| } |
| |
| return nullptr; |
| } |
| |
| const GrFragmentProcessor& getColorFragmentProcessor(int idx) const { |
| SkASSERT(idx < this->numColorFragmentProcessors()); |
| return *fFragmentProcessors[idx].get(); |
| } |
| |
| const GrFragmentProcessor& getCoverageFragmentProcessor(int idx) const { |
| SkASSERT(idx < this->numCoverageFragmentProcessors()); |
| return *fFragmentProcessors[fNumColorProcessors + idx].get(); |
| } |
| |
| const GrFragmentProcessor& getFragmentProcessor(int idx) const { |
| return *fFragmentProcessors[idx].get(); |
| } |
| |
| /// @} |
| |
| const GrUserStencilSettings* getUserStencil() const { return fUserStencilSettings; } |
| |
| bool isScissorEnabled() const { |
| return SkToBool(fFlags & Flags::kScissorEnabled); |
| } |
| |
| const GrWindowRectsState& getWindowRectsState() const { return fWindowRectsState; } |
| |
| bool isHWAntialiasState() const { return SkToBool(fFlags & InputFlags::kHWAntialias); } |
| bool snapVerticesToPixelCenters() const { |
| return SkToBool(fFlags & InputFlags::kSnapVerticesToPixelCenters); |
| } |
| bool hasStencilClip() const { |
| return SkToBool(fFlags & Flags::kHasStencilClip); |
| } |
| bool isStencilEnabled() const { |
| return SkToBool(fFlags & Flags::kStencilEnabled); |
| } |
| SkDEBUGCODE(bool isBad() const { return SkToBool(fFlags & Flags::kIsBad); }) |
| |
| GrXferBarrierType xferBarrierType(GrTexture*, const GrCaps&) const; |
| |
| // Used by Vulkan and Metal to cache their respective pipeline objects |
| uint32_t getBlendInfoKey() const; |
| |
| const GrSwizzle& outputSwizzle() const { return fOutputSwizzle; } |
| |
| private: |
| |
| SkDEBUGCODE(void markAsBad() { fFlags |= Flags::kIsBad; }) |
| |
| 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), |
| kStencilEnabled = (kLastInputFlag << 2), |
| kScissorEnabled = (kLastInputFlag << 3), |
| #ifdef SK_DEBUG |
| kIsBad = (kLastInputFlag << 4), |
| #endif |
| }; |
| |
| GR_DECL_BITFIELD_CLASS_OPS_FRIENDS(Flags); |
| |
| friend bool operator&(Flags, InputFlags); |
| |
| using FragmentProcessorArray = SkAutoSTArray<8, std::unique_ptr<const GrFragmentProcessor>>; |
| |
| GrProxyPendingIO fDstTextureProxy; |
| SkIPoint fDstTextureOffset; |
| GrWindowRectsState fWindowRectsState; |
| const GrUserStencilSettings* fUserStencilSettings; |
| Flags fFlags; |
| sk_sp<const GrXferProcessor> fXferProcessor; |
| FragmentProcessorArray fFragmentProcessors; |
| |
| // This value is also the index in fFragmentProcessors where coverage processors begin. |
| int fNumColorProcessors; |
| |
| GrSwizzle fOutputSwizzle; |
| }; |
| |
| 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 |