1 /*
2  * Copyright 2015 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #ifndef GrPipeline_DEFINED
9 #define GrPipeline_DEFINED
10 
11 #include "include/core/SkMatrix.h"
12 #include "include/core/SkRefCnt.h"
13 #include "src/gpu/GrColor.h"
14 #include "src/gpu/GrFragmentProcessor.h"
15 #include "src/gpu/GrProcessorSet.h"
16 #include "src/gpu/GrScissorState.h"
17 #include "src/gpu/GrSurfaceProxyView.h"
18 #include "src/gpu/GrUserStencilSettings.h"
19 #include "src/gpu/GrWindowRectsState.h"
20 #include "src/gpu/effects/GrCoverageSetOpXP.h"
21 #include "src/gpu/effects/GrDisableColorXP.h"
22 #include "src/gpu/effects/GrPorterDuffXferProcessor.h"
23 #include "src/gpu/effects/GrTextureEffect.h"
24 #include "src/gpu/geometry/GrRect.h"
25 
26 class GrAppliedClip;
27 class GrAppliedHardClip;
28 class GrOp;
29 class GrRenderTargetContext;
30 
31 /**
32  * This immutable object contains information needed to set build a shader program and set API
33  * state for a draw. It is used along with a GrPrimitiveProcessor and a source of geometric
34  * data to draw.
35  */
36 class GrPipeline {
37 public:
38     ///////////////////////////////////////////////////////////////////////////
39     /// @name Creation
40 
41     // Pipeline options that the caller may enable.
42     // NOTE: This enum is extended later by GrPipeline::Flags.
43     enum class InputFlags : uint8_t {
44         kNone = 0,
45         /**
46          * Perform HW anti-aliasing. This means either HW FSAA, if supported by the render target,
47          * or smooth-line rendering if a line primitive is drawn and line smoothing is supported by
48          * the 3D API.
49          */
50         kHWAntialias = (1 << 0),
51         /**
52          * Cause every pixel to be rasterized that is touched by the triangle anywhere (not just at
53          * pixel center). Additionally, if using MSAA, the sample mask will always have 100%
54          * coverage.
55          * NOTE: The primitive type must be a triangle type.
56          */
57         kConservativeRaster = (1 << 1),
58         /**
59          * Draws triangles as outlines.
60          */
61         kWireframe = (1 << 2),
62         /**
63          * Modifies the vertex shader so that vertices will be positioned at pixel centers.
64          */
65         kSnapVerticesToPixelCenters = (1 << 3),  // This value must be last. (See kLastInputFlag.)
66     };
67 
68     struct InitArgs {
69         InputFlags fInputFlags = InputFlags::kNone;
70         const GrCaps* fCaps = nullptr;
71         GrXferProcessor::DstProxyView fDstProxyView;
72         GrSwizzle fWriteSwizzle;
73     };
74 
75     /**
76      * Creates a simple pipeline with default settings and no processors. The provided blend mode
77      * must be "Porter Duff" (<= kLastCoeffMode). If using GrScissorTest::kEnabled, the caller must
78      * specify a scissor rectangle through the DynamicState struct.
79      **/
80     GrPipeline(GrScissorTest scissor,
81                SkBlendMode blend,
82                const GrSwizzle& writeSwizzle,
83                InputFlags flags = InputFlags::kNone)
GrPipeline(scissor,GrPorterDuffXPFactory::MakeNoCoverageXP (blend),writeSwizzle,flags)84             : GrPipeline(scissor,
85                          GrPorterDuffXPFactory::MakeNoCoverageXP(blend),
86                          writeSwizzle,
87                          flags) {}
88 
89     GrPipeline(GrScissorTest,
90                sk_sp<const GrXferProcessor>,
91                const GrSwizzle& writeSwizzle,
92                InputFlags = InputFlags::kNone);
93 
94     GrPipeline(const InitArgs& args, sk_sp<const GrXferProcessor>, const GrAppliedHardClip&);
95     GrPipeline(const InitArgs&, GrProcessorSet&&, GrAppliedClip&&);
96 
97     GrPipeline(const GrPipeline&) = delete;
98     GrPipeline& operator=(const GrPipeline&) = delete;
99 
100     /// @}
101 
102     ///////////////////////////////////////////////////////////////////////////
103     /// @name GrFragmentProcessors
104 
numFragmentProcessors()105     int numFragmentProcessors() const { return fFragmentProcessors.count(); }
isColorFragmentProcessor(int idx)106     bool isColorFragmentProcessor(int idx) const { return idx < fNumColorProcessors; }
isCoverageFragmentProcessor(int idx)107     bool isCoverageFragmentProcessor(int idx) const { return idx >= fNumColorProcessors; }
108 
109     void visitTextureEffects(const std::function<void(const GrTextureEffect&)>&) const;
110 
getXferProcessor()111     const GrXferProcessor& getXferProcessor() const {
112         if (fXferProcessor) {
113             return *fXferProcessor;
114         } else {
115             // A null xp member means the common src-over case. GrXferProcessor's ref'ing
116             // mechanism is not thread safe so we do not hold a ref on this global.
117             return GrPorterDuffXPFactory::SimpleSrcOverXP();
118         }
119     }
120 
dstSampleType()121     GrDstSampleType dstSampleType() const {
122         return fDstSampleType;
123     }
124 
125     // Helper functions to quickly know if this GrPipeline will access the dst as a texture or an
126     // input attachment.
usesDstTexture()127     bool usesDstTexture() const {
128         return GrDstSampleTypeUsesTexture(fDstSampleType);
129     }
usesInputAttachment()130     bool usesInputAttachment() const {
131         return fDstSampleType == GrDstSampleType::kAsInputAttachment;
132     }
133 
134     /**
135      * This returns the GrSurfaceProxyView for the texture used to access the dst color. If the
136      * GrXferProcessor does not use the dst color then the proxy on the GrSurfaceProxyView will be
137      * nullptr.
138      */
dstProxyView()139     const GrSurfaceProxyView& dstProxyView() const { return fDstProxyView; }
140 
141     /**
142      * If the GrXferProcessor uses a texture to access the dst color, then this returns that
143      * texture and the offset to the dst contents within that texture.
144      */
145     GrTexture* peekDstTexture(SkIPoint* offset = nullptr) const {
146         if (!this->usesDstTexture()) {
147             return nullptr;
148         }
149         if (offset) {
150             *offset = fDstTextureOffset;
151         }
152 
153         if (GrTextureProxy* dstProxy = fDstProxyView.asTextureProxy()) {
154             return dstProxy->peekTexture();
155         }
156 
157         return nullptr;
158     }
159 
getFragmentProcessor(int idx)160     const GrFragmentProcessor& getFragmentProcessor(int idx) const {
161         return *fFragmentProcessors[idx];
162     }
163 
164     /// @}
165 
isScissorTestEnabled()166     bool isScissorTestEnabled() const {
167         return SkToBool(fFlags & Flags::kScissorTestEnabled);
168     }
169 
getWindowRectsState()170     const GrWindowRectsState& getWindowRectsState() const { return fWindowRectsState; }
171 
isHWAntialiasState()172     bool isHWAntialiasState() const { return fFlags & InputFlags::kHWAntialias; }
usesConservativeRaster()173     bool usesConservativeRaster() const { return fFlags & InputFlags::kConservativeRaster; }
isWireframe()174     bool isWireframe() const { return fFlags & InputFlags::kWireframe; }
snapVerticesToPixelCenters()175     bool snapVerticesToPixelCenters() const {
176         return fFlags & InputFlags::kSnapVerticesToPixelCenters;
177     }
hasStencilClip()178     bool hasStencilClip() const {
179         return SkToBool(fFlags & Flags::kHasStencilClip);
180     }
181 #ifdef SK_DEBUG
allProxiesInstantiated()182     bool allProxiesInstantiated() const {
183         for (int i = 0; i < fFragmentProcessors.count(); ++i) {
184             if (!fFragmentProcessors[i]->isInstantiated()) {
185                 return false;
186             }
187         }
188         if (fDstProxyView.proxy()) {
189             return fDstProxyView.proxy()->isInstantiated();
190         }
191 
192         return true;
193     }
194 #endif
195 
196     GrXferBarrierType xferBarrierType(const GrCaps&) const;
197 
198     // Used by Vulkan and Metal to cache their respective pipeline objects
199     void genKey(GrProcessorKeyBuilder*, const GrCaps&) const;
200 
writeSwizzle()201     const GrSwizzle& writeSwizzle() const { return fWriteSwizzle; }
202 
203     void visitProxies(const GrOp::VisitProxyFunc&) const;
204 
205 private:
206     static constexpr uint8_t kLastInputFlag = (uint8_t)InputFlags::kSnapVerticesToPixelCenters;
207 
208     /** This is a continuation of the public "InputFlags" enum. */
209     enum class Flags : uint8_t {
210         kHasStencilClip = (kLastInputFlag << 1),
211         kScissorTestEnabled = (kLastInputFlag << 2),
212     };
213 
214     GR_DECL_BITFIELD_CLASS_OPS_FRIENDS(Flags);
215 
216     friend bool operator&(Flags, InputFlags);
217 
218     // A pipeline can contain up to three processors: color, paint coverage, and clip coverage.
219     using FragmentProcessorArray = SkAutoSTArray<3, std::unique_ptr<const GrFragmentProcessor>>;
220 
221     GrSurfaceProxyView fDstProxyView;
222     SkIPoint fDstTextureOffset;
223     // This is the GrDstSampleType that is used for the render pass that this GrPipeline will be
224     // used in (i.e. if this GrPipeline does read the dst, it will do so using this
225     // GrDstSampleType).
226     GrDstSampleType fDstSampleType = GrDstSampleType::kNone;
227     GrWindowRectsState fWindowRectsState;
228     Flags fFlags;
229     sk_sp<const GrXferProcessor> fXferProcessor;
230     FragmentProcessorArray fFragmentProcessors;
231 
232     // This value is also the index in fFragmentProcessors where coverage processors begin.
233     int fNumColorProcessors = 0;
234 
235     GrSwizzle fWriteSwizzle;
236 };
237 
238 GR_MAKE_BITFIELD_CLASS_OPS(GrPipeline::InputFlags);
239 GR_MAKE_BITFIELD_CLASS_OPS(GrPipeline::Flags);
240 
241 inline bool operator&(GrPipeline::Flags flags, GrPipeline::InputFlags inputFlag) {
242     return (flags & (GrPipeline::Flags)inputFlag);
243 }
244 
245 #endif
246