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