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 "GrClip.h"
13 #include "GrDrawTargetCaps.h"
14 #include "GrGpuResourceRef.h"
15 #include "GrFragmentStage.h"
16 #include "GrProcOptInfo.h"
17 #include "GrRenderTarget.h"
18 #include "GrStencil.h"
19 #include "GrXferProcessor.h"
20 #include "SkMatrix.h"
21 #include "effects/GrCoverageSetOpXP.h"
22 #include "effects/GrDisableColorXP.h"
23 #include "effects/GrPorterDuffXferProcessor.h"
24 #include "effects/GrSimpleTextureEffect.h"
25 
26 class GrBatch;
27 class GrDrawTargetCaps;
28 class GrPaint;
29 class GrTexture;
30 
31 class GrPipelineBuilder {
32 public:
33     GrPipelineBuilder();
34 
GrPipelineBuilder(const GrPipelineBuilder & pipelineBuilder)35     GrPipelineBuilder(const GrPipelineBuilder& pipelineBuilder) {
36         SkDEBUGCODE(fBlockEffectRemovalCnt = 0;)
37         *this = pipelineBuilder;
38     }
39 
40     virtual ~GrPipelineBuilder();
41 
42     /**
43      * Initializes the GrPipelineBuilder based on a GrPaint, view matrix and render target. Note
44      * that GrPipelineBuilder encompasses more than GrPaint. Aspects of GrPipelineBuilder that have
45      * no GrPaint equivalents are set to default values with the exception of vertex attribute state
46      * which is unmodified by this function and clipping which will be enabled.
47      */
48     void setFromPaint(const GrPaint&, GrRenderTarget*, const GrClip&);
49 
50     ///////////////////////////////////////////////////////////////////////////
51     /// @name Fragment Processors
52     ///
53     /// GrFragmentProcessors are used to compute per-pixel color and per-pixel fractional coverage.
54     /// There are two chains of FPs, one for color and one for coverage. The first FP in each
55     /// chain gets the initial color/coverage from the GrPrimitiveProcessor. It computes an output
56     /// color/coverage which is fed to the next FP in the chain. The last color and coverage FPs
57     /// feed their output to the GrXferProcessor which controls blending.
58     ////
59 
numColorFragmentStages()60     int numColorFragmentStages() const { return fColorStages.count(); }
numCoverageFragmentStages()61     int numCoverageFragmentStages() const { return fCoverageStages.count(); }
numFragmentStages()62     int numFragmentStages() const { return this->numColorFragmentStages() +
63                                                this->numCoverageFragmentStages(); }
64 
getColorFragmentStage(int idx)65     const GrFragmentStage& getColorFragmentStage(int idx) const { return fColorStages[idx]; }
getCoverageFragmentStage(int idx)66     const GrFragmentStage& getCoverageFragmentStage(int idx) const { return fCoverageStages[idx]; }
67 
addColorProcessor(const GrFragmentProcessor * effect)68     const GrFragmentProcessor* addColorProcessor(const GrFragmentProcessor* effect) {
69         SkASSERT(effect);
70         SkNEW_APPEND_TO_TARRAY(&fColorStages, GrFragmentStage, (effect));
71         fColorProcInfoValid = false;
72         return effect;
73     }
74 
addCoverageProcessor(const GrFragmentProcessor * effect)75     const GrFragmentProcessor* addCoverageProcessor(const GrFragmentProcessor* effect) {
76         SkASSERT(effect);
77         SkNEW_APPEND_TO_TARRAY(&fCoverageStages, GrFragmentStage, (effect));
78         fCoverageProcInfoValid = false;
79         return effect;
80     }
81 
82     /**
83      * Creates a GrSimpleTextureEffect that uses local coords as texture coordinates.
84      */
addColorTextureProcessor(GrTexture * texture,const SkMatrix & matrix)85     void addColorTextureProcessor(GrTexture* texture, const SkMatrix& matrix) {
86         this->addColorProcessor(GrSimpleTextureEffect::Create(texture, matrix))->unref();
87     }
88 
addCoverageTextureProcessor(GrTexture * texture,const SkMatrix & matrix)89     void addCoverageTextureProcessor(GrTexture* texture, const SkMatrix& matrix) {
90         this->addCoverageProcessor(GrSimpleTextureEffect::Create(texture, matrix))->unref();
91     }
92 
addColorTextureProcessor(GrTexture * texture,const SkMatrix & matrix,const GrTextureParams & params)93     void addColorTextureProcessor(GrTexture* texture,
94                                   const SkMatrix& matrix,
95                                   const GrTextureParams& params) {
96         this->addColorProcessor(GrSimpleTextureEffect::Create(texture, matrix, params))->unref();
97     }
98 
addCoverageTextureProcessor(GrTexture * texture,const SkMatrix & matrix,const GrTextureParams & params)99     void addCoverageTextureProcessor(GrTexture* texture,
100                                      const SkMatrix& matrix,
101                                      const GrTextureParams& params) {
102         this->addCoverageProcessor(GrSimpleTextureEffect::Create(texture, matrix, params))->unref();
103     }
104 
105     /**
106      * When this object is destroyed it will remove any color/coverage FPs from the pipeline builder
107      * that were added after its constructor.
108      */
109     class AutoRestoreFragmentProcessors : public ::SkNoncopyable {
110     public:
AutoRestoreFragmentProcessors()111         AutoRestoreFragmentProcessors()
112             : fPipelineBuilder(NULL)
113             , fColorEffectCnt(0)
114             , fCoverageEffectCnt(0) {}
115 
AutoRestoreFragmentProcessors(GrPipelineBuilder * ds)116         AutoRestoreFragmentProcessors(GrPipelineBuilder* ds)
117             : fPipelineBuilder(NULL)
118             , fColorEffectCnt(0)
119             , fCoverageEffectCnt(0) {
120             this->set(ds);
121         }
122 
~AutoRestoreFragmentProcessors()123         ~AutoRestoreFragmentProcessors() { this->set(NULL); }
124 
125         void set(GrPipelineBuilder* ds);
126 
isSet()127         bool isSet() const { return SkToBool(fPipelineBuilder); }
128 
129     private:
130         GrPipelineBuilder*    fPipelineBuilder;
131         int             fColorEffectCnt;
132         int             fCoverageEffectCnt;
133     };
134 
135     /// @}
136 
137     ///////////////////////////////////////////////////////////////////////////
138     /// @name Blending
139     ////
140 
141     /**
142      * This function returns true if the render target destination pixel values will be read for
143      * blending during draw.
144      */
145     bool willBlendWithDst(const GrPrimitiveProcessor*) const;
146 
147     /**
148      * Installs a GrXPFactory. This object controls how src color, fractional pixel coverage,
149      * and the dst color are blended.
150      */
setXPFactory(const GrXPFactory * xpFactory)151     const GrXPFactory* setXPFactory(const GrXPFactory* xpFactory) {
152         fXPFactory.reset(SkRef(xpFactory));
153         return xpFactory;
154     }
155 
156     /**
157      * Sets a GrXPFactory that will ignore src color and perform a set operation between the draws
158      * output coverage and the destination. This is useful to render coverage masks as CSG.
159      */
160     void setCoverageSetOpXPFactory(SkRegion::Op regionOp, bool invertCoverage = false) {
161         fXPFactory.reset(GrCoverageSetOpXPFactory::Create(regionOp, invertCoverage));
162     }
163 
164     /**
165      * Sets a GrXPFactory that disables color writes to the destination. This is useful when
166      * rendering to the stencil buffer.
167      */
setDisableColorXPFactory()168     void setDisableColorXPFactory() {
169         fXPFactory.reset(GrDisableColorXPFactory::Create());
170     }
171 
getXPFactory()172     const GrXPFactory* getXPFactory() const {
173         if (!fXPFactory) {
174             fXPFactory.reset(GrPorterDuffXPFactory::Create(SkXfermode::kSrc_Mode));
175         }
176         return fXPFactory.get();
177     }
178 
179     /**
180      * Checks whether the xp will need a copy of the destination to correctly blend.
181      */
182     bool willXPNeedDstCopy(const GrDrawTargetCaps& caps, const GrProcOptInfo& colorPOI,
183                            const GrProcOptInfo& coveragePOI) const;
184 
185     /// @}
186 
187 
188     ///////////////////////////////////////////////////////////////////////////
189     /// @name Render Target
190     ////
191 
192     /**
193      * Retrieves the currently set render-target.
194      *
195      * @return    The currently set render target.
196      */
getRenderTarget()197     GrRenderTarget* getRenderTarget() const { return fRenderTarget.get(); }
198 
199     /**
200      * Sets the render-target used at the next drawing call
201      *
202      * @param target  The render target to set.
203      */
setRenderTarget(GrRenderTarget * target)204     void setRenderTarget(GrRenderTarget* target) { fRenderTarget.reset(SkSafeRef(target)); }
205 
206     /// @}
207 
208     ///////////////////////////////////////////////////////////////////////////
209     /// @name Stencil
210     ////
211 
getStencil()212     const GrStencilSettings& getStencil() const { return fStencilSettings; }
213 
214     /**
215      * Sets the stencil settings to use for the next draw.
216      * Changing the clip has the side-effect of possibly zeroing
217      * out the client settable stencil bits. So multipass algorithms
218      * using stencil should not change the clip between passes.
219      * @param settings  the stencil settings to use.
220      */
setStencil(const GrStencilSettings & settings)221     void setStencil(const GrStencilSettings& settings) { fStencilSettings = settings; }
222 
223     /**
224      * Shortcut to disable stencil testing and ops.
225      */
disableStencil()226     void disableStencil() { fStencilSettings.setDisabled(); }
227 
stencil()228     GrStencilSettings* stencil() { return &fStencilSettings; }
229 
230     /**
231      * AutoRestoreStencil
232      *
233      * This simple struct saves and restores the stencil settings
234      */
235     class AutoRestoreStencil : public ::SkNoncopyable {
236     public:
AutoRestoreStencil()237         AutoRestoreStencil() : fPipelineBuilder(NULL) {}
238 
AutoRestoreStencil(GrPipelineBuilder * ds)239         AutoRestoreStencil(GrPipelineBuilder* ds) : fPipelineBuilder(NULL) { this->set(ds); }
240 
~AutoRestoreStencil()241         ~AutoRestoreStencil() { this->set(NULL); }
242 
set(GrPipelineBuilder * ds)243         void set(GrPipelineBuilder* ds) {
244             if (fPipelineBuilder) {
245                 fPipelineBuilder->setStencil(fStencilSettings);
246             }
247             fPipelineBuilder = ds;
248             if (ds) {
249                 fStencilSettings = ds->getStencil();
250             }
251         }
252 
isSet()253         bool isSet() const { return SkToBool(fPipelineBuilder); }
254 
255     private:
256         GrPipelineBuilder*  fPipelineBuilder;
257         GrStencilSettings   fStencilSettings;
258     };
259 
260 
261     /// @}
262 
263     ///////////////////////////////////////////////////////////////////////////
264     /// @name State Flags
265     ////
266 
267     /**
268      *  Flags that affect rendering. Controlled using enable/disableState(). All
269      *  default to disabled.
270      */
271     enum Flags {
272         /**
273          * Perform dithering. TODO: Re-evaluate whether we need this bit
274          */
275         kDither_Flag        = 0x01,
276         /**
277          * Perform HW anti-aliasing. This means either HW FSAA, if supported by the render target,
278          * or smooth-line rendering if a line primitive is drawn and line smoothing is supported by
279          * the 3D API.
280          */
281         kHWAntialias_Flag   = 0x02,
282 
283         /**
284          * Modifies the vertex shader so that vertices will be positioned at pixel centers.
285          */
286         kSnapVerticesToPixelCenters_Flag = 0x04,
287 
288         kLast_Flag = kSnapVerticesToPixelCenters_Flag,
289     };
290 
isDither()291     bool isDither() const { return SkToBool(fFlags & kDither_Flag); }
isHWAntialias()292     bool isHWAntialias() const { return SkToBool(fFlags & kHWAntialias_Flag); }
snapVerticesToPixelCenters()293     bool snapVerticesToPixelCenters() const {
294         return SkToBool(fFlags & kSnapVerticesToPixelCenters_Flag); }
295 
296     /**
297      * Enable render state settings.
298      *
299      * @param flags bitfield of Flags specifying the states to enable
300      */
enableState(uint32_t flags)301     void enableState(uint32_t flags) { fFlags |= flags; }
302 
303     /**
304      * Disable render state settings.
305      *
306      * @param flags bitfield of Flags specifying the states to disable
307      */
disableState(uint32_t flags)308     void disableState(uint32_t flags) { fFlags &= ~(flags); }
309 
310     /**
311      * Enable or disable flags based on a boolean.
312      *
313      * @param flags bitfield of Flags to enable or disable
314      * @param enable    if true enable stateBits, otherwise disable
315      */
setState(uint32_t flags,bool enable)316     void setState(uint32_t flags, bool enable) {
317         if (enable) {
318             this->enableState(flags);
319         } else {
320             this->disableState(flags);
321         }
322     }
323 
324     /// @}
325 
326     ///////////////////////////////////////////////////////////////////////////
327     /// @name Face Culling
328     ////
329 
330     enum DrawFace {
331         kInvalid_DrawFace = -1,
332 
333         kBoth_DrawFace,
334         kCCW_DrawFace,
335         kCW_DrawFace,
336     };
337 
338     /**
339      * Gets whether the target is drawing clockwise, counterclockwise,
340      * or both faces.
341      * @return the current draw face(s).
342      */
getDrawFace()343     DrawFace getDrawFace() const { return fDrawFace; }
344 
345     /**
346      * Controls whether clockwise, counterclockwise, or both faces are drawn.
347      * @param face  the face(s) to draw.
348      */
setDrawFace(DrawFace face)349     void setDrawFace(DrawFace face) {
350         SkASSERT(kInvalid_DrawFace != face);
351         fDrawFace = face;
352     }
353 
354     /// @}
355 
356     ///////////////////////////////////////////////////////////////////////////
357 
358     GrPipelineBuilder& operator=(const GrPipelineBuilder& that);
359 
360     // TODO delete when we have Batch
colorProcInfo(const GrPrimitiveProcessor * pp)361     const GrProcOptInfo& colorProcInfo(const GrPrimitiveProcessor* pp) const {
362         this->calcColorInvariantOutput(pp);
363         return fColorProcInfo;
364     }
365 
coverageProcInfo(const GrPrimitiveProcessor * pp)366     const GrProcOptInfo& coverageProcInfo(const GrPrimitiveProcessor* pp) const {
367         this->calcCoverageInvariantOutput(pp);
368         return fCoverageProcInfo;
369     }
370 
colorProcInfo(const GrBatch * batch)371     const GrProcOptInfo& colorProcInfo(const GrBatch* batch) const {
372         this->calcColorInvariantOutput(batch);
373         return fColorProcInfo;
374     }
375 
coverageProcInfo(const GrBatch * batch)376     const GrProcOptInfo& coverageProcInfo(const GrBatch* batch) const {
377         this->calcCoverageInvariantOutput(batch);
378         return fCoverageProcInfo;
379     }
380 
setClip(const GrClip & clip)381     void setClip(const GrClip& clip) { fClip = clip; }
clip()382     const GrClip& clip() const { return fClip; }
383 
384 private:
385     // Calculating invariant color / coverage information is expensive, so we partially cache the
386     // results.
387     //
388     // canUseFracCoveragePrimProc() - Called in regular skia draw, caches results but only for a
389     //                                specific color and coverage.  May be called multiple times
390     // willBlendWithDst() - only called by Nvpr, does not cache results
391     // GrOptDrawState constructor - never caches results
392 
393     /**
394      * Primproc variants of the calc functions
395      * TODO remove these when batch is everywhere
396      */
397     void calcColorInvariantOutput(const GrPrimitiveProcessor*) const;
398     void calcCoverageInvariantOutput(const GrPrimitiveProcessor*) const;
399 
400     /**
401      * GrBatch provides the initial seed for these loops based off of its initial geometry data
402      */
403     void calcColorInvariantOutput(const GrBatch*) const;
404     void calcCoverageInvariantOutput(const GrBatch*) const;
405 
406     /**
407      * If fColorProcInfoValid is false, function calculates the invariant output for the color
408      * processors and results are stored in fColorProcInfo.
409      */
410     void calcColorInvariantOutput(GrColor) const;
411 
412     /**
413      * If fCoverageProcInfoValid is false, function calculates the invariant output for the coverage
414      * processors and results are stored in fCoverageProcInfo.
415      */
416     void calcCoverageInvariantOutput(GrColor) const;
417 
418     // Some of the auto restore objects assume that no effects are removed during their lifetime.
419     // This is used to assert that this condition holds.
420     SkDEBUGCODE(int fBlockEffectRemovalCnt;)
421 
422     typedef SkSTArray<4, GrFragmentStage> FragmentStageArray;
423 
424     SkAutoTUnref<GrRenderTarget>            fRenderTarget;
425     uint32_t                                fFlags;
426     GrStencilSettings                       fStencilSettings;
427     DrawFace                                fDrawFace;
428     mutable SkAutoTUnref<const GrXPFactory> fXPFactory;
429     FragmentStageArray                      fColorStages;
430     FragmentStageArray                      fCoverageStages;
431     GrClip                                  fClip;
432 
433     mutable GrProcOptInfo fColorProcInfo;
434     mutable GrProcOptInfo fCoverageProcInfo;
435     mutable bool fColorProcInfoValid;
436     mutable bool fCoverageProcInfoValid;
437     mutable GrColor fColorCache;
438     mutable GrColor fCoverageCache;
439 
440     friend class GrPipeline;
441 };
442 
443 #endif
444