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 GrPipelineBuilder_DEFINED
9 #define GrPipelineBuilder_DEFINED
10 
11 #include "GrBlend.h"
12 #include "GrCaps.h"
13 #include "GrClip.h"
14 #include "GrGpuResourceRef.h"
15 #include "GrProcOptInfo.h"
16 #include "GrRenderTarget.h"
17 #include "GrStencil.h"
18 #include "GrXferProcessor.h"
19 #include "SkMatrix.h"
20 #include "effects/GrCoverageSetOpXP.h"
21 #include "effects/GrDisableColorXP.h"
22 #include "effects/GrPorterDuffXferProcessor.h"
23 #include "effects/GrSimpleTextureEffect.h"
24 
25 class GrDrawBatch;
26 class GrCaps;
27 class GrPaint;
28 class GrTexture;
29 
30 class GrPipelineBuilder : public SkNoncopyable {
31 public:
32     GrPipelineBuilder();
33 
34     /**
35      * Initializes the GrPipelineBuilder based on a GrPaint, render target, and clip. Note
36      * that GrPipelineBuilder encompasses more than GrPaint. Aspects of GrPipelineBuilder that have
37      * no GrPaint equivalents are set to default values with the exception of vertex attribute state
38      * which is unmodified by this function and clipping which will be enabled.
39      */
40     GrPipelineBuilder(const GrPaint&, GrRenderTarget*, const GrClip&);
41 
42     virtual ~GrPipelineBuilder();
43 
44     ///////////////////////////////////////////////////////////////////////////
45     /// @name Fragment Processors
46     ///
47     /// GrFragmentProcessors are used to compute per-pixel color and per-pixel fractional coverage.
48     /// There are two chains of FPs, one for color and one for coverage. The first FP in each
49     /// chain gets the initial color/coverage from the GrPrimitiveProcessor. It computes an output
50     /// color/coverage which is fed to the next FP in the chain. The last color and coverage FPs
51     /// feed their output to the GrXferProcessor which controls blending.
52     ////
53 
numColorFragmentProcessors()54     int numColorFragmentProcessors() const { return fColorFragmentProcessors.count(); }
numCoverageFragmentProcessors()55     int numCoverageFragmentProcessors() const { return fCoverageFragmentProcessors.count(); }
numFragmentProcessors()56     int numFragmentProcessors() const { return this->numColorFragmentProcessors() +
57                                                this->numCoverageFragmentProcessors(); }
58 
getColorFragmentProcessor(int idx)59     const GrFragmentProcessor* getColorFragmentProcessor(int idx) const {
60         return fColorFragmentProcessors[idx];
61     }
getCoverageFragmentProcessor(int idx)62     const GrFragmentProcessor* getCoverageFragmentProcessor(int idx) const {
63         return fCoverageFragmentProcessors[idx];
64     }
65 
addColorFragmentProcessor(const GrFragmentProcessor * processor)66     const GrFragmentProcessor* addColorFragmentProcessor(const GrFragmentProcessor* processor) {
67         SkASSERT(processor);
68         fColorFragmentProcessors.push_back(SkRef(processor));
69         return processor;
70     }
71 
addCoverageFragmentProcessor(const GrFragmentProcessor * processor)72     const GrFragmentProcessor* addCoverageFragmentProcessor(const GrFragmentProcessor* processor) {
73         SkASSERT(processor);
74         fCoverageFragmentProcessors.push_back(SkRef(processor));
75         return processor;
76     }
77 
78     /**
79      * Creates a GrSimpleTextureEffect that uses local coords as texture coordinates.
80      */
addColorTextureProcessor(GrTexture * texture,const SkMatrix & matrix)81     void addColorTextureProcessor(GrTexture* texture, const SkMatrix& matrix) {
82         this->addColorFragmentProcessor(GrSimpleTextureEffect::Create(texture, matrix))->unref();
83     }
84 
addCoverageTextureProcessor(GrTexture * texture,const SkMatrix & matrix)85     void addCoverageTextureProcessor(GrTexture* texture, const SkMatrix& matrix) {
86         this->addCoverageFragmentProcessor(GrSimpleTextureEffect::Create(texture, matrix))->unref();
87     }
88 
addColorTextureProcessor(GrTexture * texture,const SkMatrix & matrix,const GrTextureParams & params)89     void addColorTextureProcessor(GrTexture* texture,
90                                   const SkMatrix& matrix,
91                                   const GrTextureParams& params) {
92         this->addColorFragmentProcessor(GrSimpleTextureEffect::Create(texture, matrix,
93                                                                       params))->unref();
94     }
95 
addCoverageTextureProcessor(GrTexture * texture,const SkMatrix & matrix,const GrTextureParams & params)96     void addCoverageTextureProcessor(GrTexture* texture,
97                                      const SkMatrix& matrix,
98                                      const GrTextureParams& params) {
99         this->addCoverageFragmentProcessor(GrSimpleTextureEffect::Create(texture, matrix,
100                                                                          params))->unref();
101     }
102 
103     /**
104      * When this object is destroyed it will remove any color/coverage FPs from the pipeline builder
105      * that were added after its constructor.
106      * This class can transiently modify its "const" GrPipelineBuilder object but will restore it
107      * when done - so it is notionally "const" correct.
108      */
109     class AutoRestoreFragmentProcessorState : public ::SkNoncopyable {
110     public:
AutoRestoreFragmentProcessorState()111         AutoRestoreFragmentProcessorState()
112             : fPipelineBuilder(nullptr)
113             , fColorEffectCnt(0)
114             , fCoverageEffectCnt(0) {}
115 
AutoRestoreFragmentProcessorState(const GrPipelineBuilder & ds)116         AutoRestoreFragmentProcessorState(const GrPipelineBuilder& ds)
117             : fPipelineBuilder(nullptr)
118             , fColorEffectCnt(0)
119             , fCoverageEffectCnt(0) {
120             this->set(&ds);
121         }
122 
~AutoRestoreFragmentProcessorState()123         ~AutoRestoreFragmentProcessorState() { this->set(nullptr); }
124 
125         void set(const GrPipelineBuilder* ds);
126 
isSet()127         bool isSet() const { return SkToBool(fPipelineBuilder); }
128 
addCoverageFragmentProcessor(const GrFragmentProcessor * processor)129         const GrFragmentProcessor* addCoverageFragmentProcessor(
130             const GrFragmentProcessor* processor) {
131             SkASSERT(this->isSet());
132             return fPipelineBuilder->addCoverageFragmentProcessor(processor);
133         }
134 
135     private:
136         // notionally const (as marginalia)
137         GrPipelineBuilder*    fPipelineBuilder;
138         int                   fColorEffectCnt;
139         int                   fCoverageEffectCnt;
140     };
141 
142     /// @}
143 
144     ///////////////////////////////////////////////////////////////////////////
145     /// @name Blending
146     ////
147 
148     /**
149      * Installs a GrXPFactory. This object controls how src color, fractional pixel coverage,
150      * and the dst color are blended.
151      */
setXPFactory(const GrXPFactory * xpFactory)152     const GrXPFactory* setXPFactory(const GrXPFactory* xpFactory) {
153         fXPFactory.reset(SkSafeRef(xpFactory));
154         return xpFactory;
155     }
156 
157     /**
158      * Sets a GrXPFactory that will ignore src color and perform a set operation between the draws
159      * output coverage and the destination. This is useful to render coverage masks as CSG.
160      */
161     void setCoverageSetOpXPFactory(SkRegion::Op regionOp, bool invertCoverage = false) {
162         fXPFactory.reset(GrCoverageSetOpXPFactory::Create(regionOp, invertCoverage));
163     }
164 
165     /**
166      * Sets a GrXPFactory that disables color writes to the destination. This is useful when
167      * rendering to the stencil buffer.
168      */
setDisableColorXPFactory()169     void setDisableColorXPFactory() {
170         fXPFactory.reset(GrDisableColorXPFactory::Create());
171     }
172 
getXPFactory()173     const GrXPFactory* getXPFactory() const {
174         return fXPFactory;
175     }
176 
177     /**
178      * Checks whether the xp will need destination in a texture to correctly blend.
179      */
180     bool willXPNeedDstTexture(const GrCaps& caps,
181                               const GrPipelineOptimizations& optimizations) const;
182 
183     /// @}
184 
185 
186     ///////////////////////////////////////////////////////////////////////////
187     /// @name Render Target
188     ////
189 
190     /**
191      * Retrieves the currently set render-target.
192      *
193      * @return    The currently set render target.
194      */
getRenderTarget()195     GrRenderTarget* getRenderTarget() const { return fRenderTarget.get(); }
196 
197     /**
198      * Sets the render-target used at the next drawing call
199      *
200      * @param target  The render target to set.
201      */
setRenderTarget(GrRenderTarget * target)202     void setRenderTarget(GrRenderTarget* target) { fRenderTarget.reset(SkSafeRef(target)); }
203 
204     /**
205      * Returns whether the rasterizer and stencil test (if any) will run at a higher sample rate
206      * than the color buffer. In is scenario, the higher sample rate is resolved during blending.
207      */
hasMixedSamples()208     bool hasMixedSamples() const {
209         return fRenderTarget->hasMixedSamples() &&
210                (this->isHWAntialias() || !fStencilSettings.isDisabled());
211     }
212 
213     /// @}
214 
215     ///////////////////////////////////////////////////////////////////////////
216     /// @name Stencil
217     ////
218 
getStencil()219     const GrStencilSettings& getStencil() const { return fStencilSettings; }
220 
221     /**
222      * Sets the stencil settings to use for the next draw.
223      * Changing the clip has the side-effect of possibly zeroing
224      * out the client settable stencil bits. So multipass algorithms
225      * using stencil should not change the clip between passes.
226      * @param settings  the stencil settings to use.
227      */
setStencil(const GrStencilSettings & settings)228     void setStencil(const GrStencilSettings& settings) { fStencilSettings = settings; }
229 
stencil()230     GrStencilSettings* stencil() { return &fStencilSettings; }
231 
232     /**
233      * AutoRestoreStencil
234      *
235      * This simple struct saves and restores the stencil settings
236      * This class can transiently modify its "const" GrPipelineBuilder object but will restore it
237      * when done - so it is notionally "const" correct.
238      */
239     class AutoRestoreStencil : public ::SkNoncopyable {
240     public:
AutoRestoreStencil()241         AutoRestoreStencil() : fPipelineBuilder(nullptr) {}
242 
AutoRestoreStencil(const GrPipelineBuilder & ds)243         AutoRestoreStencil(const GrPipelineBuilder& ds) : fPipelineBuilder(nullptr) { this->set(&ds); }
244 
~AutoRestoreStencil()245         ~AutoRestoreStencil() { this->set(nullptr); }
246 
set(const GrPipelineBuilder * ds)247         void set(const GrPipelineBuilder* ds) {
248             if (fPipelineBuilder) {
249                 fPipelineBuilder->setStencil(fStencilSettings);
250             }
251             fPipelineBuilder = const_cast<GrPipelineBuilder*>(ds);
252             if (ds) {
253                 fStencilSettings = ds->getStencil();
254             }
255         }
256 
isSet()257         bool isSet() const { return SkToBool(fPipelineBuilder); }
258 
setStencil(const GrStencilSettings & settings)259         void setStencil(const GrStencilSettings& settings) {
260             SkASSERT(this->isSet());
261             fPipelineBuilder->setStencil(settings);
262         }
263 
264     private:
265         // notionally const (as marginalia)
266         GrPipelineBuilder*  fPipelineBuilder;
267         GrStencilSettings   fStencilSettings;
268     };
269 
270 
271     /// @}
272 
273     ///////////////////////////////////////////////////////////////////////////
274     /// @name State Flags
275     ////
276 
277     /**
278      *  Flags that affect rendering. Controlled using enable/disableState(). All
279      *  default to disabled.
280      */
281     enum Flags {
282         /**
283          * Perform HW anti-aliasing. This means either HW FSAA, if supported by the render target,
284          * or smooth-line rendering if a line primitive is drawn and line smoothing is supported by
285          * the 3D API.
286          */
287         kHWAntialias_Flag   = 0x01,
288 
289         /**
290          * Modifies the vertex shader so that vertices will be positioned at pixel centers.
291          */
292         kSnapVerticesToPixelCenters_Flag = 0x02,
293 
294         kLast_Flag = kSnapVerticesToPixelCenters_Flag,
295     };
296 
isHWAntialias()297     bool isHWAntialias() const { return SkToBool(fFlags & kHWAntialias_Flag); }
snapVerticesToPixelCenters()298     bool snapVerticesToPixelCenters() const {
299         return SkToBool(fFlags & kSnapVerticesToPixelCenters_Flag); }
300 
301     /**
302      * Enable render state settings.
303      *
304      * @param flags bitfield of Flags specifying the states to enable
305      */
enableState(uint32_t flags)306     void enableState(uint32_t flags) { fFlags |= flags; }
307 
308     /**
309      * Disable render state settings.
310      *
311      * @param flags bitfield of Flags specifying the states to disable
312      */
disableState(uint32_t flags)313     void disableState(uint32_t flags) { fFlags &= ~(flags); }
314 
315     /**
316      * Enable or disable flags based on a boolean.
317      *
318      * @param flags bitfield of Flags to enable or disable
319      * @param enable    if true enable stateBits, otherwise disable
320      */
setState(uint32_t flags,bool enable)321     void setState(uint32_t flags, bool enable) {
322         if (enable) {
323             this->enableState(flags);
324         } else {
325             this->disableState(flags);
326         }
327     }
328 
329     /// @}
330 
331     ///////////////////////////////////////////////////////////////////////////
332     /// @name Face Culling
333     ////
334 
335     enum DrawFace {
336         kInvalid_DrawFace = -1,
337 
338         kBoth_DrawFace,
339         kCCW_DrawFace,
340         kCW_DrawFace,
341     };
342 
343     /**
344      * Gets whether the target is drawing clockwise, counterclockwise,
345      * or both faces.
346      * @return the current draw face(s).
347      */
getDrawFace()348     DrawFace getDrawFace() const { return fDrawFace; }
349 
350     /**
351      * Controls whether clockwise, counterclockwise, or both faces are drawn.
352      * @param face  the face(s) to draw.
353      */
setDrawFace(DrawFace face)354     void setDrawFace(DrawFace face) {
355         SkASSERT(kInvalid_DrawFace != face);
356         fDrawFace = face;
357     }
358 
359     /// @}
360 
361     ///////////////////////////////////////////////////////////////////////////
362 
363     bool usePLSDstRead(const GrDrawBatch* batch) const;
364 
setClip(const GrClip & clip)365     void setClip(const GrClip& clip) { fClip = clip; }
clip()366     const GrClip& clip() const { return fClip; }
367 
368 private:
369     // Some of the auto restore objects assume that no effects are removed during their lifetime.
370     // This is used to assert that this condition holds.
371     SkDEBUGCODE(mutable int fBlockEffectRemovalCnt;)
372 
373     typedef SkSTArray<4, const GrFragmentProcessor*, true> FragmentProcessorArray;
374 
375     SkAutoTUnref<GrRenderTarget>            fRenderTarget;
376     uint32_t                                fFlags;
377     GrStencilSettings                       fStencilSettings;
378     DrawFace                                fDrawFace;
379     mutable SkAutoTUnref<const GrXPFactory> fXPFactory;
380     FragmentProcessorArray                  fColorFragmentProcessors;
381     FragmentProcessorArray                  fCoverageFragmentProcessors;
382     GrClip                                  fClip;
383 
384     friend class GrPipeline;
385     friend class GrDrawTarget;
386 };
387 
388 #endif
389