Home | History | Annotate | Download | only in gpu
      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 
     54     int numColorFragmentProcessors() const { return fColorFragmentProcessors.count(); }
     55     int numCoverageFragmentProcessors() const { return fCoverageFragmentProcessors.count(); }
     56     int numFragmentProcessors() const { return this->numColorFragmentProcessors() +
     57                                                this->numCoverageFragmentProcessors(); }
     58 
     59     const GrFragmentProcessor* getColorFragmentProcessor(int idx) const {
     60         return fColorFragmentProcessors[idx];
     61     }
     62     const GrFragmentProcessor* getCoverageFragmentProcessor(int idx) const {
     63         return fCoverageFragmentProcessors[idx];
     64     }
     65 
     66     const GrFragmentProcessor* addColorFragmentProcessor(const GrFragmentProcessor* processor) {
     67         SkASSERT(processor);
     68         fColorFragmentProcessors.push_back(SkRef(processor));
     69         return processor;
     70     }
     71 
     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      */
     81     void addColorTextureProcessor(GrTexture* texture, const SkMatrix& matrix) {
     82         this->addColorFragmentProcessor(GrSimpleTextureEffect::Create(texture, matrix))->unref();
     83     }
     84 
     85     void addCoverageTextureProcessor(GrTexture* texture, const SkMatrix& matrix) {
     86         this->addCoverageFragmentProcessor(GrSimpleTextureEffect::Create(texture, matrix))->unref();
     87     }
     88 
     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 
     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:
    111         AutoRestoreFragmentProcessorState()
    112             : fPipelineBuilder(nullptr)
    113             , fColorEffectCnt(0)
    114             , fCoverageEffectCnt(0) {}
    115 
    116         AutoRestoreFragmentProcessorState(const GrPipelineBuilder& ds)
    117             : fPipelineBuilder(nullptr)
    118             , fColorEffectCnt(0)
    119             , fCoverageEffectCnt(0) {
    120             this->set(&ds);
    121         }
    122 
    123         ~AutoRestoreFragmentProcessorState() { this->set(nullptr); }
    124 
    125         void set(const GrPipelineBuilder* ds);
    126 
    127         bool isSet() const { return SkToBool(fPipelineBuilder); }
    128 
    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      */
    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      */
    169     void setDisableColorXPFactory() {
    170         fXPFactory.reset(GrDisableColorXPFactory::Create());
    171     }
    172 
    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      */
    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      */
    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      */
    208     bool hasMixedSamples() const {
    209         return fRenderTarget->hasMixedSamples() &&
    210                (this->isHWAntialias() || !fStencilSettings.isDisabled());
    211     }
    212 
    213     /// @}
    214 
    215     ///////////////////////////////////////////////////////////////////////////
    216     /// @name Stencil
    217     ////
    218 
    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      */
    228     void setStencil(const GrStencilSettings& settings) { fStencilSettings = settings; }
    229 
    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:
    241         AutoRestoreStencil() : fPipelineBuilder(nullptr) {}
    242 
    243         AutoRestoreStencil(const GrPipelineBuilder& ds) : fPipelineBuilder(nullptr) { this->set(&ds); }
    244 
    245         ~AutoRestoreStencil() { this->set(nullptr); }
    246 
    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 
    257         bool isSet() const { return SkToBool(fPipelineBuilder); }
    258 
    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 
    297     bool isHWAntialias() const { return SkToBool(fFlags & kHWAntialias_Flag); }
    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      */
    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      */
    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      */
    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      */
    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      */
    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 
    365     void setClip(const GrClip& clip) { fClip = 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