• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
GrBlendEquationIsAdvanced(GrBlendEquation equation)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 {
resetBlendInfo181         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 
getBlendInfo(BlendInfo * blendInfo)198     void getBlendInfo(BlendInfo* blendInfo) const {
199         blendInfo->reset();
200         this->onGetBlendInfo(blendInfo);
201     }
202 
willReadDstColor()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      */
getDstCopyTexture()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      */
dstCopyTextureOffset()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      */
readsCoverage()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      */
hasSecondaryOutput()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 
isEqual(const GrXferProcessor & that)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      */
onWillNeedXferBarrier(const GrRenderTarget *,const GrDrawTargetCaps &,GrXferBarrierType * outBarrierType SK_UNUSED)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      */
onGetBlendInfo(BlendInfo *)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 
isEqual(const GrXPFactory & that)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       */
cast()359     template <typename T> const T& cast() const { return *static_cast<const T*>(this); }
360 
classID()361     uint32_t classID() const { SkASSERT(kIllegalXPFClassID != fClassID); return fClassID; }
362 
363 protected:
GrXPFactory()364     GrXPFactory() : fClassID(kIllegalXPFClassID) {}
365 
initClassID()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 
GenClassID()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