• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "GrProcessorSet.h"
16 #include "GrProgramDesc.h"
17 #include "GrRect.h"
18 #include "GrRenderTarget.h"
19 #include "GrScissorState.h"
20 #include "GrUserStencilSettings.h"
21 #include "GrWindowRectsState.h"
22 #include "SkMatrix.h"
23 #include "SkRefCnt.h"
24 #include "effects/GrCoverageSetOpXP.h"
25 #include "effects/GrDisableColorXP.h"
26 #include "effects/GrPorterDuffXferProcessor.h"
27 #include "effects/GrSimpleTextureEffect.h"
28 
29 class GrAppliedClip;
30 class GrDeviceCoordTexture;
31 class GrOp;
32 class GrRenderTargetContext;
33 
34 /**
35  * This immutable object contains information needed to set build a shader program and set API
36  * state for a draw. It is used along with a GrPrimitiveProcessor and a source of geometric
37  * data (GrMesh or GrPath) to draw.
38  */
39 class GrPipeline : public GrNonAtomicRef<GrPipeline> {
40 public:
41     ///////////////////////////////////////////////////////////////////////////
42     /// @name Creation
43 
44     enum Flags {
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_Flag = 0x1,
51         /**
52          * Modifies the vertex shader so that vertices will be positioned at pixel centers.
53          */
54         kSnapVerticesToPixelCenters_Flag = 0x2,
55         /** Disables conversion to sRGB from linear when writing to a sRGB destination. */
56         kDisableOutputConversionToSRGB_Flag = 0x4,
57         /** Allows conversion from sRGB to linear when reading from processor's sRGB texture. */
58         kAllowSRGBInputs_Flag = 0x8,
59     };
60 
SRGBFlagsFromPaint(const GrPaint & paint)61     static uint32_t SRGBFlagsFromPaint(const GrPaint& paint) {
62         uint32_t flags = 0;
63         if (paint.getAllowSRGBInputs()) {
64             flags |= kAllowSRGBInputs_Flag;
65         }
66         if (paint.getDisableOutputConversionToSRGB()) {
67             flags |= kDisableOutputConversionToSRGB_Flag;
68         }
69         return flags;
70     }
71 
72     enum ScissorState : bool {
73         kEnabled = true,
74         kDisabled = false
75     };
76 
77     struct InitArgs {
78         uint32_t fFlags = 0;
79         const GrProcessorSet* fProcessors = nullptr;  // Must be finalized
80         const GrUserStencilSettings* fUserStencil = &GrUserStencilSettings::kUnused;
81         const GrAppliedClip* fAppliedClip = nullptr;
82         GrRenderTarget* fRenderTarget = nullptr;
83         const GrCaps* fCaps = nullptr;
84         GrResourceProvider* fResourceProvider = nullptr;
85         GrXferProcessor::DstProxy fDstProxy;
86     };
87 
88     /**
89      *  Graphics state that can change dynamically without creating a new pipeline.
90      **/
91     struct DynamicState {
92         // Overrides the scissor rectangle (if scissor is enabled in the pipeline).
93         // TODO: eventually this should be the only way to specify a scissor rectangle, as is the
94         // case with the simple constructor.
95         SkIRect fScissorRect;
96     };
97 
98     /**
99      * A Default constructed pipeline is unusable until init() is called.
100      **/
101     GrPipeline() = default;
102 
103     /**
104      * Creates a simple pipeline with default settings and no processors. The provided blend mode
105      * must be "Porter Duff" (<= kLastCoeffMode). If using ScissorState::kEnabled, the caller must
106      * specify a scissor rectangle through the DynamicState struct.
107      **/
108     GrPipeline(GrRenderTarget*, ScissorState, SkBlendMode);
109 
GrPipeline(const InitArgs & args)110     GrPipeline(const InitArgs& args) { this->init(args); }
111 
112     /** (Re)initializes a pipeline. After initialization the pipeline can be used. */
113     void init(const InitArgs&);
114 
115     /** True if the pipeline has been initialized. */
isInitialized()116     bool isInitialized() const { return SkToBool(fRenderTarget.get()); }
117 
118     /// @}
119 
120     ///////////////////////////////////////////////////////////////////////////
121     /// @name Comparisons
122 
123     /**
124      * Returns true if these pipelines are equivalent.  Coord transforms may be applied either on
125      * the GPU or the CPU. When we apply them on the CPU then the matrices need not agree in order
126      * to combine draws. Therefore we take a param that indicates whether coord transforms should be
127      * compared."
128      */
129     static bool AreEqual(const GrPipeline& a, const GrPipeline& b);
130 
131     /**
132      * Allows a GrOp subclass to determine whether two GrOp instances can combine. This is a
133      * stricter test than isEqual because it also considers blend barriers when the two ops'
134      * bounds overlap
135      */
CanCombine(const GrPipeline & a,const SkRect & aBounds,const GrPipeline & b,const SkRect & bBounds,const GrCaps & caps)136     static bool CanCombine(const GrPipeline& a, const SkRect& aBounds,
137                            const GrPipeline& b, const SkRect& bBounds,
138                            const GrCaps& caps)  {
139         if (!AreEqual(a, b)) {
140             return false;
141         }
142         if (a.xferBarrierType(caps)) {
143             return !GrRectsTouchOrOverlap(aBounds, bBounds);
144         }
145         return true;
146     }
147 
148     /// @}
149 
150     ///////////////////////////////////////////////////////////////////////////
151     /// @name GrFragmentProcessors
152 
153     // Make the renderTargetContext's GrOpList be dependent on any GrOpLists in this pipeline
154     void addDependenciesTo(GrOpList* recipient, const GrCaps&) const;
155 
numColorFragmentProcessors()156     int numColorFragmentProcessors() const { return fNumColorProcessors; }
numCoverageFragmentProcessors()157     int numCoverageFragmentProcessors() const {
158         return fFragmentProcessors.count() - fNumColorProcessors;
159     }
numFragmentProcessors()160     int numFragmentProcessors() const { return fFragmentProcessors.count(); }
161 
getXferProcessor()162     const GrXferProcessor& getXferProcessor() const {
163         if (fXferProcessor) {
164             return *fXferProcessor.get();
165         } else {
166             // A null xp member means the common src-over case. GrXferProcessor's ref'ing
167             // mechanism is not thread safe so we do not hold a ref on this global.
168             return GrPorterDuffXPFactory::SimpleSrcOverXP();
169         }
170     }
171 
172     /**
173      * If the GrXferProcessor uses a texture to access the dst color, then this returns that
174      * texture and the offset to the dst contents within that texture.
175      */
176     GrTextureProxy* dstTextureProxy(SkIPoint* offset = nullptr) const {
177         if (offset) {
178             *offset = fDstTextureOffset;
179         }
180         return fDstTextureProxy.get();
181     }
182 
183     GrTexture* peekDstTexture(SkIPoint* offset = nullptr) const {
184         if (GrTextureProxy* dstProxy = this->dstTextureProxy(offset)) {
185             return dstProxy->priv().peekTexture();
186         }
187 
188         return nullptr;
189     }
190 
getColorFragmentProcessor(int idx)191     const GrFragmentProcessor& getColorFragmentProcessor(int idx) const {
192         SkASSERT(idx < this->numColorFragmentProcessors());
193         return *fFragmentProcessors[idx].get();
194     }
195 
getCoverageFragmentProcessor(int idx)196     const GrFragmentProcessor& getCoverageFragmentProcessor(int idx) const {
197         SkASSERT(idx < this->numCoverageFragmentProcessors());
198         return *fFragmentProcessors[fNumColorProcessors + idx].get();
199     }
200 
getFragmentProcessor(int idx)201     const GrFragmentProcessor& getFragmentProcessor(int idx) const {
202         return *fFragmentProcessors[idx].get();
203     }
204 
205     /// @}
206 
207     /**
208      * Retrieves the currently set render-target.
209      *
210      * @return    The currently set render target.
211      */
getRenderTarget()212     GrRenderTarget* getRenderTarget() const { return fRenderTarget.get(); }
213 
getUserStencil()214     const GrUserStencilSettings* getUserStencil() const { return fUserStencilSettings; }
215 
getScissorState()216     const GrScissorState& getScissorState() const { return fScissorState; }
217 
getWindowRectsState()218     const GrWindowRectsState& getWindowRectsState() const { return fWindowRectsState; }
219 
isHWAntialiasState()220     bool isHWAntialiasState() const { return SkToBool(fFlags & kHWAntialias_Flag); }
snapVerticesToPixelCenters()221     bool snapVerticesToPixelCenters() const {
222         return SkToBool(fFlags & kSnapVerticesToPixelCenters_Flag);
223     }
getDisableOutputConversionToSRGB()224     bool getDisableOutputConversionToSRGB() const {
225         return SkToBool(fFlags & kDisableOutputConversionToSRGB_Flag);
226     }
getAllowSRGBInputs()227     bool getAllowSRGBInputs() const {
228         return SkToBool(fFlags & kAllowSRGBInputs_Flag);
229     }
hasStencilClip()230     bool hasStencilClip() const {
231         return SkToBool(fFlags & kHasStencilClip_Flag);
232     }
isStencilEnabled()233     bool isStencilEnabled() const {
234         return SkToBool(fFlags & kStencilEnabled_Flag);
235     }
isBad()236     bool isBad() const { return SkToBool(fFlags & kIsBad_Flag); }
237 
238     GrXferBarrierType xferBarrierType(const GrCaps& caps) const;
239 
DumpFlags(uint32_t flags)240     static SkString DumpFlags(uint32_t flags) {
241         if (flags) {
242             SkString result;
243             if (flags & GrPipeline::kSnapVerticesToPixelCenters_Flag) {
244                 result.append("Snap vertices to pixel center.\n");
245             }
246             if (flags & GrPipeline::kHWAntialias_Flag) {
247                 result.append("HW Antialiasing enabled.\n");
248             }
249             if (flags & GrPipeline::kDisableOutputConversionToSRGB_Flag) {
250                 result.append("Disable output conversion to sRGB.\n");
251             }
252             if (flags & GrPipeline::kAllowSRGBInputs_Flag) {
253                 result.append("Allow sRGB Inputs.\n");
254             }
255             return result;
256         }
257         return SkString("No pipeline flags\n");
258     }
259 
260 private:
markAsBad()261     void markAsBad() { fFlags |= kIsBad_Flag; }
262 
263     /** This is a continuation of the public "Flags" enum. */
264     enum PrivateFlags {
265         kHasStencilClip_Flag = 0x10,
266         kStencilEnabled_Flag = 0x20,
267         kIsBad_Flag = 0x40,
268     };
269 
270     using RenderTarget = GrPendingIOResource<GrRenderTarget, kWrite_GrIOType>;
271     using DstTextureProxy = GrPendingIOResource<GrTextureProxy, kRead_GrIOType>;
272     using PendingFragmentProcessor = GrPendingProgramElement<const GrFragmentProcessor>;
273     using FragmentProcessorArray = SkAutoSTArray<8, PendingFragmentProcessor>;
274 
275     DstTextureProxy fDstTextureProxy;
276     SkIPoint fDstTextureOffset;
277     RenderTarget fRenderTarget;
278     GrScissorState fScissorState;
279     GrWindowRectsState fWindowRectsState;
280     const GrUserStencilSettings* fUserStencilSettings;
281     uint16_t fFlags;
282     sk_sp<const GrXferProcessor> fXferProcessor;
283     FragmentProcessorArray fFragmentProcessors;
284 
285     // This value is also the index in fFragmentProcessors where coverage processors begin.
286     int fNumColorProcessors;
287 
288     typedef SkRefCnt INHERITED;
289 };
290 
291 #endif
292