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 "GrPendingProgramElement.h"
15 #include "GrPrimitiveProcessor.h"
16 #include "GrProcessorSet.h"
17 #include "GrProgramDesc.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 GrDeviceCoordTexture;
30 class GrOp;
31 class GrPipelineBuilder;
32 class GrRenderTargetContext;
33 
34 /**
35  * Class that holds an optimized version of a GrPipelineBuilder. It is meant to be an immutable
36  * class, and contains all data needed to set the state for a gpu draw.
37  */
38 class GrPipeline : public GrNonAtomicRef<GrPipeline> {
39 public:
40     ///////////////////////////////////////////////////////////////////////////
41     /// @name Creation
42 
43     enum Flags {
44         /**
45          * Perform HW anti-aliasing. This means either HW FSAA, if supported by the render target,
46          * or smooth-line rendering if a line primitive is drawn and line smoothing is supported by
47          * the 3D API.
48          */
49         kHWAntialias_Flag = 0x1,
50 
51         /**
52          * Modifies the vertex shader so that vertices will be positioned at pixel centers.
53          */
54         kSnapVerticesToPixelCenters_Flag = 0x2,
55     };
56 
57     struct InitArgs {
58         uint32_t fFlags = 0;
59         GrDrawFace fDrawFace = GrDrawFace::kBoth;
60         const GrProcessorSet* fProcessors = nullptr;
61         const GrProcessorSet::FragmentProcessorAnalysis* fAnalysis;
62         const GrUserStencilSettings* fUserStencil = &GrUserStencilSettings::kUnused;
63         const GrAppliedClip* fAppliedClip = nullptr;
64         GrRenderTarget* fRenderTarget = nullptr;
65         const GrCaps* fCaps = nullptr;
66         GrXferProcessor::DstTexture fDstTexture;
67     };
68 
69     /**
70      * A Default constructed pipeline is unusable until init() is called.
71      **/
72     GrPipeline() = default;
73 
74     /**
75      * Creates a simple pipeline with default settings and no processors. The provided blend mode
76      * must be "Porter Duff" (<= kLastCoeffMode). This pipeline is initialized without requiring
77      * a call to init().
78      **/
79     GrPipeline(GrRenderTarget*, SkBlendMode);
80 
81     /** (Re)initializes a pipeline. After initialization the pipeline can be used. */
82     GrPipelineOptimizations init(const InitArgs&);
83 
84     /** True if the pipeline has been initialized. */
isInitialized()85     bool isInitialized() const { return SkToBool(fRenderTarget.get()); }
86 
87     /// @}
88 
89     ///////////////////////////////////////////////////////////////////////////
90     /// @name Comparisons
91 
92     /**
93      * Returns true if these pipelines are equivalent.  Coord transforms may be applied either on
94      * the GPU or the CPU. When we apply them on the CPU then the matrices need not agree in order
95      * to combine draws. Therefore we take a param that indicates whether coord transforms should be
96      * compared."
97      */
98     static bool AreEqual(const GrPipeline& a, const GrPipeline& b);
99 
100     /**
101      * Allows a GrOp subclass to determine whether two GrOp instances can combine. This is a
102      * stricter test than isEqual because it also considers blend barriers when the two ops'
103      * bounds overlap
104      */
CanCombine(const GrPipeline & a,const SkRect & aBounds,const GrPipeline & b,const SkRect & bBounds,const GrCaps & caps)105     static bool CanCombine(const GrPipeline& a, const SkRect& aBounds,
106                            const GrPipeline& b, const SkRect& bBounds,
107                            const GrCaps& caps)  {
108         if (!AreEqual(a, b)) {
109             return false;
110         }
111         if (a.xferBarrierType(caps)) {
112             return aBounds.fRight <= bBounds.fLeft ||
113                    aBounds.fBottom <= bBounds.fTop ||
114                    bBounds.fRight <= aBounds.fLeft ||
115                    bBounds.fBottom <= aBounds.fTop;
116         }
117         return true;
118     }
119 
120     /// @}
121 
122     ///////////////////////////////////////////////////////////////////////////
123     /// @name GrFragmentProcessors
124 
125     // Make the renderTarget's GrOpList (if it exists) be dependent on any
126     // GrOpLists in this pipeline
127     void addDependenciesTo(GrRenderTarget* rt) const;
128 
numColorFragmentProcessors()129     int numColorFragmentProcessors() const { return fNumColorProcessors; }
numCoverageFragmentProcessors()130     int numCoverageFragmentProcessors() const {
131         return fFragmentProcessors.count() - fNumColorProcessors;
132     }
numFragmentProcessors()133     int numFragmentProcessors() const { return fFragmentProcessors.count(); }
134 
getXferProcessor()135     const GrXferProcessor& getXferProcessor() const {
136         if (fXferProcessor.get()) {
137             return *fXferProcessor.get();
138         } else {
139             // A null xp member means the common src-over case. GrXferProcessor's ref'ing
140             // mechanism is not thread safe so we do not hold a ref on this global.
141             return GrPorterDuffXPFactory::SimpleSrcOverXP();
142         }
143     }
144 
getColorFragmentProcessor(int idx)145     const GrFragmentProcessor& getColorFragmentProcessor(int idx) const {
146         SkASSERT(idx < this->numColorFragmentProcessors());
147         return *fFragmentProcessors[idx].get();
148     }
149 
getCoverageFragmentProcessor(int idx)150     const GrFragmentProcessor& getCoverageFragmentProcessor(int idx) const {
151         SkASSERT(idx < this->numCoverageFragmentProcessors());
152         return *fFragmentProcessors[fNumColorProcessors + idx].get();
153     }
154 
getFragmentProcessor(int idx)155     const GrFragmentProcessor& getFragmentProcessor(int idx) const {
156         return *fFragmentProcessors[idx].get();
157     }
158 
159     /// @}
160 
161     /**
162      * Retrieves the currently set render-target.
163      *
164      * @return    The currently set render target.
165      */
getRenderTarget()166     GrRenderTarget* getRenderTarget() const { return fRenderTarget.get(); }
167 
getUserStencil()168     const GrUserStencilSettings* getUserStencil() const { return fUserStencilSettings; }
169 
getScissorState()170     const GrScissorState& getScissorState() const { return fScissorState; }
171 
getWindowRectsState()172     const GrWindowRectsState& getWindowRectsState() const { return fWindowRectsState; }
173 
isHWAntialiasState()174     bool isHWAntialiasState() const { return SkToBool(fFlags & kHWAntialias_Flag); }
snapVerticesToPixelCenters()175     bool snapVerticesToPixelCenters() const {
176         return SkToBool(fFlags & kSnapVerticesToPixelCenters_Flag);
177     }
getDisableOutputConversionToSRGB()178     bool getDisableOutputConversionToSRGB() const {
179         return SkToBool(fFlags & kDisableOutputConversionToSRGB_Flag);
180     }
getAllowSRGBInputs()181     bool getAllowSRGBInputs() const {
182         return SkToBool(fFlags & kAllowSRGBInputs_Flag);
183     }
usesDistanceVectorField()184     bool usesDistanceVectorField() const {
185         return SkToBool(fFlags & kUsesDistanceVectorField_Flag);
186     }
hasStencilClip()187     bool hasStencilClip() const {
188         return SkToBool(fFlags & kHasStencilClip_Flag);
189     }
isStencilEnabled()190     bool isStencilEnabled() const {
191         return SkToBool(fFlags & kStencilEnabled_Flag);
192     }
193 
xferBarrierType(const GrCaps & caps)194     GrXferBarrierType xferBarrierType(const GrCaps& caps) const {
195         return this->getXferProcessor().xferBarrierType(fRenderTarget.get(), caps);
196     }
197 
198     /**
199      * Gets whether the target is drawing clockwise, counterclockwise,
200      * or both faces.
201      * @return the current draw face(s).
202      */
getDrawFace()203     GrDrawFace getDrawFace() const { return static_cast<GrDrawFace>(fDrawFace); }
204 
205 private:
206     /** This is a continuation of the public "Flags" enum. */
207     enum PrivateFlags {
208         kDisableOutputConversionToSRGB_Flag = 0x4,
209         kAllowSRGBInputs_Flag = 0x8,
210         kUsesDistanceVectorField_Flag = 0x10,
211         kHasStencilClip_Flag = 0x20,
212         kStencilEnabled_Flag = 0x40,
213     };
214 
215     typedef GrPendingIOResource<GrRenderTarget, kWrite_GrIOType> RenderTarget;
216     typedef GrPendingProgramElement<const GrFragmentProcessor> PendingFragmentProcessor;
217     typedef SkAutoSTArray<8, PendingFragmentProcessor> FragmentProcessorArray;
218     typedef GrPendingProgramElement<const GrXferProcessor> ProgramXferProcessor;
219     RenderTarget                        fRenderTarget;
220     GrScissorState                      fScissorState;
221     GrWindowRectsState                  fWindowRectsState;
222     const GrUserStencilSettings*        fUserStencilSettings;
223     uint16_t                            fDrawFace;
224     uint16_t                            fFlags;
225     ProgramXferProcessor                fXferProcessor;
226     FragmentProcessorArray              fFragmentProcessors;
227 
228     // This value is also the index in fFragmentProcessors where coverage processors begin.
229     int                                 fNumColorProcessors;
230 
231     typedef SkRefCnt INHERITED;
232 };
233 
234 #endif
235