Home | History | Annotate | Download | only in gpu
      1 /*
      2  * Copyright 2014 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 GrXferProcessor_DEFINED
      9 #define GrXferProcessor_DEFINED
     10 
     11 #include "GrColor.h"
     12 #include "GrProcessor.h"
     13 #include "GrTexture.h"
     14 #include "GrTypes.h"
     15 #include "SkXfermode.h"
     16 
     17 class GrShaderCaps;
     18 class GrGLSLCaps;
     19 class GrGLXferProcessor;
     20 class GrProcOptInfo;
     21 
     22 /**
     23  * Equations for alpha-blending.
     24  */
     25 enum GrBlendEquation {
     26     // Basic blend equations.
     27     kAdd_GrBlendEquation,             //<! Cs*S + Cd*D
     28     kSubtract_GrBlendEquation,        //<! Cs*S - Cd*D
     29     kReverseSubtract_GrBlendEquation, //<! Cd*D - Cs*S
     30 
     31     // Advanced blend equations. These are described in the SVG and PDF specs.
     32     kScreen_GrBlendEquation,
     33     kOverlay_GrBlendEquation,
     34     kDarken_GrBlendEquation,
     35     kLighten_GrBlendEquation,
     36     kColorDodge_GrBlendEquation,
     37     kColorBurn_GrBlendEquation,
     38     kHardLight_GrBlendEquation,
     39     kSoftLight_GrBlendEquation,
     40     kDifference_GrBlendEquation,
     41     kExclusion_GrBlendEquation,
     42     kMultiply_GrBlendEquation,
     43     kHSLHue_GrBlendEquation,
     44     kHSLSaturation_GrBlendEquation,
     45     kHSLColor_GrBlendEquation,
     46     kHSLLuminosity_GrBlendEquation,
     47 
     48     kFirstAdvancedGrBlendEquation = kScreen_GrBlendEquation,
     49     kLast_GrBlendEquation = kHSLLuminosity_GrBlendEquation
     50 };
     51 
     52 static const int kGrBlendEquationCnt = kLast_GrBlendEquation + 1;
     53 
     54 inline bool GrBlendEquationIsAdvanced(GrBlendEquation equation) {
     55     return equation >= kFirstAdvancedGrBlendEquation;
     56 }
     57 
     58 /**
     59  * Coeffecients for alpha-blending.
     60  */
     61 enum GrBlendCoeff {
     62     kZero_GrBlendCoeff,    //<! 0
     63     kOne_GrBlendCoeff,     //<! 1
     64     kSC_GrBlendCoeff,      //<! src color
     65     kISC_GrBlendCoeff,     //<! one minus src color
     66     kDC_GrBlendCoeff,      //<! dst color
     67     kIDC_GrBlendCoeff,     //<! one minus dst color
     68     kSA_GrBlendCoeff,      //<! src alpha
     69     kISA_GrBlendCoeff,     //<! one minus src alpha
     70     kDA_GrBlendCoeff,      //<! dst alpha
     71     kIDA_GrBlendCoeff,     //<! one minus dst alpha
     72     kConstC_GrBlendCoeff,  //<! constant color
     73     kIConstC_GrBlendCoeff, //<! one minus constant color
     74     kConstA_GrBlendCoeff,  //<! constant color alpha
     75     kIConstA_GrBlendCoeff, //<! one minus constant color alpha
     76     kS2C_GrBlendCoeff,
     77     kIS2C_GrBlendCoeff,
     78     kS2A_GrBlendCoeff,
     79     kIS2A_GrBlendCoeff,
     80 
     81     kLast_GrBlendCoeff = kIS2A_GrBlendCoeff
     82 };
     83 
     84 static const int kGrBlendCoeffCnt = kLast_GrBlendCoeff + 1;
     85 
     86 /**
     87  * Barriers for blending. When a shader reads the dst directly, an Xfer barrier is sometimes
     88  * required after a pixel has been written, before it can be safely read again.
     89  */
     90 enum GrXferBarrierType {
     91     kTexture_GrXferBarrierType, //<! Required when a shader reads and renders to the same texture.
     92     kBlend_GrXferBarrierType,   //<! Required by certain blend extensions.
     93 };
     94 
     95 /**
     96  * GrXferProcessor is responsible for implementing the xfer mode that blends the src color and dst
     97  * color. It does this by emitting fragment shader code and controlling the fixed-function blend
     98  * state. The inputs to its shader code are the final computed src color and fractional pixel
     99  * coverage. The GrXferProcessor's shader code writes the fragment shader output color that goes
    100  * into the fixed-function blend. When dual-source blending is available, it may also write a
    101  * seconday fragment shader output color. When allowed by the backend API, the GrXferProcessor may
    102  * read the destination color. The GrXferProcessor is responsible for setting the blend coefficients
    103  * and blend constant color.
    104  *
    105  * A GrXferProcessor is never installed directly into our draw state, but instead is created from a
    106  * GrXPFactory once we have finalized the state of our draw.
    107  */
    108 class GrXferProcessor : public GrProcessor {
    109 public:
    110     /**
    111      * Sets a unique key on the GrProcessorKeyBuilder calls onGetGLProcessorKey(...) to get the
    112      * specific subclass's key.
    113      */
    114     void getGLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const;
    115 
    116     /** Returns a new instance of the appropriate *GL* implementation class
    117         for the given GrXferProcessor; caller is responsible for deleting
    118         the object. */
    119     virtual GrGLXferProcessor* createGLInstance() const = 0;
    120 
    121     /**
    122      * Optimizations for blending / coverage that an OptDrawState should apply to itself.
    123      */
    124     enum OptFlags {
    125         /**
    126          * No optimizations needed
    127          */
    128         kNone_Opt                         = 0,
    129         /**
    130          * The draw can be skipped completely.
    131          */
    132         kSkipDraw_OptFlag                 = 0x1,
    133         /**
    134          * GrXferProcessor will ignore color, thus no need to provide
    135          */
    136         kIgnoreColor_OptFlag              = 0x2,
    137         /**
    138          * GrXferProcessor will ignore coverage, thus no need to provide
    139          */
    140         kIgnoreCoverage_OptFlag           = 0x4,
    141         /**
    142          * Clear color stages and override input color to that returned by getOptimizations
    143          */
    144         kOverrideColor_OptFlag            = 0x8,
    145         /**
    146          * Set CoverageDrawing_StateBit
    147          */
    148         kSetCoverageDrawing_OptFlag       = 0x10,
    149         /**
    150          * Can tweak alpha for coverage. Currently this flag should only be used by a batch
    151          */
    152         kCanTweakAlphaForCoverage_OptFlag = 0x20,
    153     };
    154 
    155     GR_DECL_BITFIELD_OPS_FRIENDS(OptFlags);
    156 
    157     /**
    158      * Determines which optimizations (as described by the ptFlags above) can be performed by
    159      * the draw with this xfer processor. If this function is called, the xfer processor may change
    160      * its state to reflected the given blend optimizations. If the XP needs to see a specific input
    161      * color to blend correctly, it will set the OverrideColor flag and the output parameter
    162      * overrideColor will be the required value that should be passed into the XP.
    163      * A caller who calls this function on a XP is required to honor the returned OptFlags
    164      * and color values for its draw.
    165      */
    166     OptFlags getOptimizations(const GrProcOptInfo& colorPOI,
    167                               const GrProcOptInfo& coveragePOI,
    168                               bool doesStencilWrite,
    169                               GrColor* overrideColor,
    170                               const GrDrawTargetCaps& caps);
    171 
    172     /**
    173      * Returns whether this XP will require an Xfer barrier on the given rt. If true, outBarrierType
    174      * is updated to contain the type of barrier needed.
    175      */
    176     bool willNeedXferBarrier(const GrRenderTarget* rt,
    177                              const GrDrawTargetCaps& caps,
    178                              GrXferBarrierType* outBarrierType) const;
    179 
    180     struct BlendInfo {
    181         void reset() {
    182             fEquation = kAdd_GrBlendEquation;
    183             fSrcBlend = kOne_GrBlendCoeff;
    184             fDstBlend = kZero_GrBlendCoeff;
    185             fBlendConstant = 0;
    186             fWriteColor = true;
    187         }
    188 
    189         SkDEBUGCODE(SkString dump() const;)
    190 
    191         GrBlendEquation fEquation;
    192         GrBlendCoeff    fSrcBlend;
    193         GrBlendCoeff    fDstBlend;
    194         GrColor         fBlendConstant;
    195         bool            fWriteColor;
    196     };
    197 
    198     void getBlendInfo(BlendInfo* blendInfo) const {
    199         blendInfo->reset();
    200         this->onGetBlendInfo(blendInfo);
    201     }
    202 
    203     bool willReadDstColor() const { return fWillReadDstColor; }
    204 
    205     /**
    206      * Returns the texture to be used as the destination when reading the dst in the fragment
    207      * shader. If the returned texture is NULL then the XP is either not reading the dst or we have
    208      * extentions that support framebuffer fetching and thus don't need a copy of the dst texture.
    209      */
    210     const GrTexture* getDstCopyTexture() const { return fDstCopy.getTexture(); }
    211 
    212     /**
    213      * Returns the offset into the DstCopyTexture to use when reading it in the shader. This value
    214      * is only valid if getDstCopyTexture() != NULL.
    215      */
    216     const SkIPoint& dstCopyTextureOffset() const {
    217         SkASSERT(this->getDstCopyTexture());
    218         return fDstCopyTextureOffset;
    219     }
    220 
    221     /**
    222      * Returns whether or not the XP will look at coverage when doing its blending.
    223      */
    224     bool readsCoverage() const { return fReadsCoverage; }
    225 
    226     /**
    227      * Returns whether or not this xferProcossor will set a secondary output to be used with dual
    228      * source blending.
    229      */
    230     virtual bool hasSecondaryOutput() const { return false; }
    231 
    232     /** Returns true if this and other processor conservatively draw identically. It can only return
    233         true when the two processor are of the same subclass (i.e. they return the same object from
    234         from getFactory()).
    235 
    236         A return value of true from isEqual() should not be used to test whether the processor would
    237         generate the same shader code. To test for identical code generation use getGLProcessorKey*/
    238 
    239     bool isEqual(const GrXferProcessor& that) const {
    240         if (this->classID() != that.classID()) {
    241             return false;
    242         }
    243         if (this->fWillReadDstColor != that.fWillReadDstColor) {
    244             return false;
    245         }
    246         if (this->fReadsCoverage != that.fReadsCoverage) {
    247             return false;
    248         }
    249         if (this->fDstCopy.getTexture() != that.fDstCopy.getTexture()) {
    250             return false;
    251         }
    252         if (this->fDstCopyTextureOffset != that.fDstCopyTextureOffset) {
    253             return false;
    254         }
    255         return this->onIsEqual(that);
    256     }
    257 
    258 protected:
    259     GrXferProcessor();
    260     GrXferProcessor(const GrDeviceCoordTexture* dstCopy, bool willReadDstColor);
    261 
    262 private:
    263     virtual OptFlags onGetOptimizations(const GrProcOptInfo& colorPOI,
    264                                         const GrProcOptInfo& coveragePOI,
    265                                         bool doesStencilWrite,
    266                                         GrColor* overrideColor,
    267                                         const GrDrawTargetCaps& caps) = 0;
    268 
    269     /**
    270      * Sets a unique key on the GrProcessorKeyBuilder that is directly associated with this xfer
    271      * processor's GL backend implementation.
    272      */
    273     virtual void onGetGLProcessorKey(const GrGLSLCaps& caps,
    274                                      GrProcessorKeyBuilder* b) const = 0;
    275 
    276     /**
    277      * If not using a texture barrier, retrieves whether the subclass will require a different type
    278      * of barrier.
    279      */
    280     virtual bool onWillNeedXferBarrier(const GrRenderTarget*,
    281                                        const GrDrawTargetCaps&,
    282                                        GrXferBarrierType* outBarrierType SK_UNUSED) const {
    283         return false;
    284     }
    285 
    286     /**
    287      * Retrieves the hardware blend state required by this Xfer processor. The BlendInfo struct
    288      * comes initialized to default values, so the Xfer processor only needs to set the state it
    289      * needs. It may not even need to override this method at all.
    290      */
    291     virtual void onGetBlendInfo(BlendInfo*) const {}
    292 
    293     virtual bool onIsEqual(const GrXferProcessor&) const = 0;
    294 
    295     bool                    fWillReadDstColor;
    296     bool                    fReadsCoverage;
    297     SkIPoint                fDstCopyTextureOffset;
    298     GrTextureAccess         fDstCopy;
    299 
    300     typedef GrFragmentProcessor INHERITED;
    301 };
    302 
    303 GR_MAKE_BITFIELD_OPS(GrXferProcessor::OptFlags);
    304 
    305 ///////////////////////////////////////////////////////////////////////////////
    306 
    307 /**
    308  * We install a GrXPFactory (XPF) early on in the pipeline before all the final draw information is
    309  * known (e.g. whether there is fractional pixel coverage, will coverage be 1 or 4 channel, is the
    310  * draw opaque, etc.). Once the state of the draw is finalized, we use the XPF along with all the
    311  * draw information to create a GrXferProcessor (XP) which can implement the desired blending for
    312  * the draw.
    313  *
    314  * Before the XP is created, the XPF is able to answer queries about what functionality the XPs it
    315  * creates will have. For example, can it create an XP that supports RGB coverage or will the XP
    316  * blend with the destination color.
    317  */
    318 class GrXPFactory : public SkRefCnt {
    319 public:
    320     GrXferProcessor* createXferProcessor(const GrProcOptInfo& colorPOI,
    321                                          const GrProcOptInfo& coveragePOI,
    322                                          const GrDeviceCoordTexture* dstCopy,
    323                                          const GrDrawTargetCaps& caps) const;
    324 
    325     /**
    326      * This function returns true if the GrXferProcessor generated from this factory will be able to
    327      * correctly blend when using RGB coverage. The knownColor and knownColorFlags represent the
    328      * final computed color from the color stages.
    329      */
    330     virtual bool supportsRGBCoverage(GrColor knownColor, uint32_t knownColorFlags) const = 0;
    331 
    332     struct InvariantOutput {
    333         bool        fWillBlendWithDst;
    334         GrColor     fBlendedColor;
    335         uint32_t    fBlendedColorFlags;
    336     };
    337 
    338     /**
    339      * This function returns known information about the output of the xfer processor produced by
    340      * this xp factory. The invariant color information returned by this function refers to the
    341      * final color produced after all blending.
    342      */
    343     virtual void getInvariantOutput(const GrProcOptInfo& colorPOI, const GrProcOptInfo& coveragePOI,
    344                                     InvariantOutput*) const = 0;
    345 
    346     bool willNeedDstCopy(const GrDrawTargetCaps& caps, const GrProcOptInfo& colorPOI,
    347                          const GrProcOptInfo& coveragePOI) const;
    348 
    349     bool isEqual(const GrXPFactory& that) const {
    350         if (this->classID() != that.classID()) {
    351             return false;
    352         }
    353         return this->onIsEqual(that);
    354     }
    355 
    356     /**
    357       * Helper for down-casting to a GrXPFactory subclass
    358       */
    359     template <typename T> const T& cast() const { return *static_cast<const T*>(this); }
    360 
    361     uint32_t classID() const { SkASSERT(kIllegalXPFClassID != fClassID); return fClassID; }
    362 
    363 protected:
    364     GrXPFactory() : fClassID(kIllegalXPFClassID) {}
    365 
    366     template <typename XPF_SUBCLASS> void initClassID() {
    367          static uint32_t kClassID = GenClassID();
    368          fClassID = kClassID;
    369     }
    370 
    371     uint32_t fClassID;
    372 
    373 private:
    374     virtual GrXferProcessor* onCreateXferProcessor(const GrDrawTargetCaps& caps,
    375                                                    const GrProcOptInfo& colorPOI,
    376                                                    const GrProcOptInfo& coveragePOI,
    377                                                    const GrDeviceCoordTexture* dstCopy) const = 0;
    378     /**
    379      *  Returns true if the XP generated by this factory will explicitly read dst in the fragment
    380      *  shader.
    381      */
    382     virtual bool willReadDstColor(const GrDrawTargetCaps& caps,
    383                                   const GrProcOptInfo& colorPOI,
    384                                   const GrProcOptInfo& coveragePOI) const = 0;
    385 
    386     virtual bool onIsEqual(const GrXPFactory&) const = 0;
    387 
    388     static uint32_t GenClassID() {
    389         // fCurrXPFactoryID has been initialized to kIllegalXPFactoryID. The
    390         // atomic inc returns the old value not the incremented value. So we add
    391         // 1 to the returned value.
    392         uint32_t id = static_cast<uint32_t>(sk_atomic_inc(&gCurrXPFClassID)) + 1;
    393         if (!id) {
    394             SkFAIL("This should never wrap as it should only be called once for each GrXPFactory "
    395                    "subclass.");
    396         }
    397         return id;
    398     }
    399 
    400     enum {
    401         kIllegalXPFClassID = 0,
    402     };
    403     static int32_t gCurrXPFClassID;
    404 
    405     typedef GrProgramElement INHERITED;
    406 };
    407 
    408 #endif
    409 
    410