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 "GrColor.h"
12 #include "GrFragmentProcessor.h"
13 #include "GrNonAtomicRef.h"
14 #include "GrPendingIOResource.h"
15 #include "GrProcessorSet.h"
16 #include "GrProgramDesc.h"
17 #include "GrRect.h"
18 #include "GrScissorState.h"
19 #include "GrUserStencilSettings.h"
20 #include "GrWindowRectsState.h"
21 #include "SkMatrix.h"
22 #include "SkRefCnt.h"
23 #include "effects/GrCoverageSetOpXP.h"
24 #include "effects/GrDisableColorXP.h"
25 #include "effects/GrPorterDuffXferProcessor.h"
26 #include "effects/GrSimpleTextureEffect.h"
27 
28 class GrAppliedClip;
29 class GrOp;
30 class GrRenderTargetContext;
31 
32 /**
33  * This immutable object contains information needed to set build a shader program and set API
34  * state for a draw. It is used along with a GrPrimitiveProcessor and a source of geometric
35  * data (GrMesh or GrPath) to draw.
36  */
37 class GrPipeline {
38 public:
39     ///////////////////////////////////////////////////////////////////////////
40     /// @name Creation
41 
42     enum Flags {
43         /**
44          * Perform HW anti-aliasing. This means either HW FSAA, if supported by the render target,
45          * or smooth-line rendering if a line primitive is drawn and line smoothing is supported by
46          * the 3D API.
47          */
48         kHWAntialias_Flag = 0x1,
49         /**
50          * Modifies the vertex shader so that vertices will be positioned at pixel centers.
51          */
52         kSnapVerticesToPixelCenters_Flag = 0x2,
53     };
54 
55     struct InitArgs {
56         uint32_t fFlags = 0;
57         const GrUserStencilSettings* fUserStencil = &GrUserStencilSettings::kUnused;
58         const GrCaps* fCaps = nullptr;
59         GrResourceProvider* fResourceProvider = nullptr;
60         GrXferProcessor::DstProxy fDstProxy;
61     };
62 
63     /**
64      * Some state can be changed between GrMeshes without changing GrPipelines. This is generally
65      * less expensive then using multiple pipelines. Such state is called "dynamic state". It can
66      * be specified in two ways:
67      * 1) FixedDynamicState - use this to specify state that does not vary between GrMeshes.
68      * 2) DynamicStateArrays - use this to specify per mesh values for dynamic state.
69      **/
70     struct FixedDynamicState {
FixedDynamicStateFixedDynamicState71         explicit FixedDynamicState(const SkIRect& scissorRect) : fScissorRect(scissorRect) {}
72         FixedDynamicState() = default;
73         SkIRect fScissorRect = SkIRect::EmptyIRect();
74         // Must have GrPrimitiveProcessor::numTextureSamplers() entries. Can be null if no samplers
75         // or textures are passed using DynamicStateArrays.
76         GrTextureProxy** fPrimitiveProcessorTextures = nullptr;
77     };
78 
79     /**
80      * Any non-null array overrides the FixedDynamicState on a mesh-by-mesh basis. Arrays must
81      * have one entry for each GrMesh.
82      */
83     struct DynamicStateArrays {
84         const SkIRect* fScissorRects = nullptr;
85         // Must have GrPrimitiveProcessor::numTextureSamplers() * num_meshes entries.
86         // Can be null if no samplers or to use the same textures for all meshes via'
87         // FixedDynamicState.
88         GrTextureProxy** fPrimitiveProcessorTextures = nullptr;
89     };
90 
91     /**
92      * Creates a simple pipeline with default settings and no processors. The provided blend mode
93      * must be "Porter Duff" (<= kLastCoeffMode). If using GrScissorTest::kEnabled, the caller must
94      * specify a scissor rectangle through the DynamicState struct.
95      **/
96     GrPipeline(GrScissorTest, SkBlendMode);
97 
98     GrPipeline(const InitArgs&, GrProcessorSet&&, GrAppliedClip&&);
99 
100     GrPipeline(const GrPipeline&) = delete;
101     GrPipeline& operator=(const GrPipeline&) = delete;
102 
103     /// @}
104 
105     ///////////////////////////////////////////////////////////////////////////
106     /// @name GrFragmentProcessors
107 
108     // Make the renderTargetContext's GrOpList be dependent on any GrOpLists in this pipeline
109     void addDependenciesTo(GrOpList* recipient, const GrCaps&) const;
110 
numColorFragmentProcessors()111     int numColorFragmentProcessors() const { return fNumColorProcessors; }
numCoverageFragmentProcessors()112     int numCoverageFragmentProcessors() const {
113         return fFragmentProcessors.count() - fNumColorProcessors;
114     }
numFragmentProcessors()115     int numFragmentProcessors() const { return fFragmentProcessors.count(); }
116 
getXferProcessor()117     const GrXferProcessor& getXferProcessor() const {
118         if (fXferProcessor) {
119             return *fXferProcessor.get();
120         } else {
121             // A null xp member means the common src-over case. GrXferProcessor's ref'ing
122             // mechanism is not thread safe so we do not hold a ref on this global.
123             return GrPorterDuffXPFactory::SimpleSrcOverXP();
124         }
125     }
126 
127     /**
128      * If the GrXferProcessor uses a texture to access the dst color, then this returns that
129      * texture and the offset to the dst contents within that texture.
130      */
131     GrTextureProxy* dstTextureProxy(SkIPoint* offset = nullptr) const {
132         if (offset) {
133             *offset = fDstTextureOffset;
134         }
135         return fDstTextureProxy.get();
136     }
137 
138     GrTexture* peekDstTexture(SkIPoint* offset = nullptr) const {
139         if (GrTextureProxy* dstProxy = this->dstTextureProxy(offset)) {
140             return dstProxy->peekTexture();
141         }
142 
143         return nullptr;
144     }
145 
getColorFragmentProcessor(int idx)146     const GrFragmentProcessor& getColorFragmentProcessor(int idx) const {
147         SkASSERT(idx < this->numColorFragmentProcessors());
148         return *fFragmentProcessors[idx].get();
149     }
150 
getCoverageFragmentProcessor(int idx)151     const GrFragmentProcessor& getCoverageFragmentProcessor(int idx) const {
152         SkASSERT(idx < this->numCoverageFragmentProcessors());
153         return *fFragmentProcessors[fNumColorProcessors + idx].get();
154     }
155 
getFragmentProcessor(int idx)156     const GrFragmentProcessor& getFragmentProcessor(int idx) const {
157         return *fFragmentProcessors[idx].get();
158     }
159 
160     /// @}
161 
getUserStencil()162     const GrUserStencilSettings* getUserStencil() const { return fUserStencilSettings; }
163 
isScissorEnabled()164     bool isScissorEnabled() const {
165         return SkToBool(fFlags & kScissorEnabled_Flag);
166     }
167 
getWindowRectsState()168     const GrWindowRectsState& getWindowRectsState() const { return fWindowRectsState; }
169 
isHWAntialiasState()170     bool isHWAntialiasState() const { return SkToBool(fFlags & kHWAntialias_Flag); }
snapVerticesToPixelCenters()171     bool snapVerticesToPixelCenters() const {
172         return SkToBool(fFlags & kSnapVerticesToPixelCenters_Flag);
173     }
hasStencilClip()174     bool hasStencilClip() const {
175         return SkToBool(fFlags & kHasStencilClip_Flag);
176     }
isStencilEnabled()177     bool isStencilEnabled() const {
178         return SkToBool(fFlags & kStencilEnabled_Flag);
179     }
isBad()180     bool isBad() const { return SkToBool(fFlags & kIsBad_Flag); }
181 
182     GrXferBarrierType xferBarrierType(GrTexture*, const GrCaps&) const;
183 
DumpFlags(uint32_t flags)184     static SkString DumpFlags(uint32_t flags) {
185         if (flags) {
186             SkString result;
187             if (flags & GrPipeline::kSnapVerticesToPixelCenters_Flag) {
188                 result.append("Snap vertices to pixel center.\n");
189             }
190             if (flags & GrPipeline::kHWAntialias_Flag) {
191                 result.append("HW Antialiasing enabled.\n");
192             }
193             return result;
194         }
195         return SkString("No pipeline flags\n");
196     }
197 
198 private:
markAsBad()199     void markAsBad() { fFlags |= kIsBad_Flag; }
200 
201     /** This is a continuation of the public "Flags" enum. */
202     enum PrivateFlags {
203         kHasStencilClip_Flag = 0x10,
204         kStencilEnabled_Flag = 0x20,
205         kScissorEnabled_Flag = 0x40,
206         kIsBad_Flag = 0x80,
207     };
208 
209     using DstTextureProxy = GrPendingIOResource<GrTextureProxy, kRead_GrIOType>;
210     using FragmentProcessorArray = SkAutoSTArray<8, std::unique_ptr<const GrFragmentProcessor>>;
211 
212     DstTextureProxy fDstTextureProxy;
213     SkIPoint fDstTextureOffset;
214     GrWindowRectsState fWindowRectsState;
215     const GrUserStencilSettings* fUserStencilSettings;
216     uint16_t fFlags;
217     sk_sp<const GrXferProcessor> fXferProcessor;
218     FragmentProcessorArray fFragmentProcessors;
219 
220     // This value is also the index in fFragmentProcessors where coverage processors begin.
221     int fNumColorProcessors;
222 };
223 
224 #endif
225