GrXferProcessor.h revision 4dce32c46675efb901618161771d450241af4307
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 "GrTypes.h"
14#include "SkXfermode.h"
15
16class GrDrawTargetCaps;
17class GrGLCaps;
18class GrGLXferProcessor;
19class GrProcOptInfo;
20
21/**
22 * GrXferProcessor is responsible for implementing the xfer mode that blends the src color and dst
23 * color. It does this by emitting fragment shader code and controlling the fixed-function blend
24 * state. The inputs to its shader code are the final computed src color and fractional pixel
25 * coverage. The GrXferProcessor's shader code writes the fragment shader output color that goes
26 * into the fixed-function blend. When dual-source blending is available, it may also write a
27 * seconday fragment shader output color. When allowed by the backend API, the GrXferProcessor may
28 * read the destination color. The GrXferProcessor is responsible for setting the blend coefficients
29 * and blend constant color.
30 *
31 * A GrXferProcessor is never installed directly into our draw state, but instead is created from a
32 * GrXPFactory once we have finalized the state of our draw.
33 */
34class GrXferProcessor : public GrProcessor {
35public:
36    /**
37     * Sets a unique key on the GrProcessorKeyBuilder that is directly associated with this xfer
38     * processor's GL backend implementation.
39     */
40    virtual void getGLProcessorKey(const GrGLCaps& caps,
41                                   GrProcessorKeyBuilder* b) const = 0;
42
43    /** Returns a new instance of the appropriate *GL* implementation class
44        for the given GrXferProcessor; caller is responsible for deleting
45        the object. */
46    virtual GrGLXferProcessor* createGLInstance() const = 0;
47
48    /**
49     * Optimizations for blending / coverage that an OptDrawState should apply to itself.
50     */
51    enum OptFlags {
52        /**
53         * No optimizations needed
54         */
55        kNone_Opt                         = 0,
56        /**
57         * The draw can be skipped completely.
58         */
59        kSkipDraw_OptFlag                 = 0x1,
60        /**
61         * GrXferProcessor will ignore color, thus no need to provide
62         */
63        kIgnoreColor_OptFlag              = 0x2,
64        /**
65         * GrXferProcessor will ignore coverage, thus no need to provide
66         */
67        kIgnoreCoverage_OptFlag           = 0x4,
68        /**
69         * Clear color stages and override input color to that returned by getOptimizations
70         */
71        kOverrideColor_OptFlag            = 0x8,
72        /**
73         * Set CoverageDrawing_StateBit
74         */
75        kSetCoverageDrawing_OptFlag       = 0x10,
76    };
77
78    GR_DECL_BITFIELD_OPS_FRIENDS(OptFlags);
79
80    /**
81     * Determines which optimizations (as described by the ptFlags above) can be performed by
82     * the draw with this xfer processor. If this function is called, the xfer processor may change
83     * its state to reflected the given blend optimizations. If the XP needs to see a specific input
84     * color to blend correctly, it will set the OverrideColor flag and the output parameter
85     * overrideColor will be the required value that should be passed into the XP.
86     * A caller who calls this function on a XP is required to honor the returned OptFlags
87     * and color values for its draw.
88     */
89    virtual OptFlags getOptimizations(const GrProcOptInfo& colorPOI,
90                                      const GrProcOptInfo& coveragePOI,
91                                      bool doesStencilWrite,
92                                      GrColor* overrideColor,
93                                      const GrDrawTargetCaps& caps) = 0;
94
95    struct BlendInfo {
96        BlendInfo() : fWriteColor(true) {}
97
98        GrBlendCoeff fSrcBlend;
99        GrBlendCoeff fDstBlend;
100        GrColor      fBlendConstant;
101        bool         fWriteColor;
102    };
103
104    virtual void getBlendInfo(BlendInfo* blendInfo) const = 0;
105
106    /** Will this prceossor read the destination pixel value? */
107    bool willReadDstColor() const { return fWillReadDstColor; }
108
109    /**
110     * Returns whether or not this xferProcossor will set a secondary output to be used with dual
111     * source blending.
112     */
113    virtual bool hasSecondaryOutput() const { return false; }
114
115    /** Returns true if this and other processor conservatively draw identically. It can only return
116        true when the two processor are of the same subclass (i.e. they return the same object from
117        from getFactory()).
118
119        A return value of true from isEqual() should not be used to test whether the processor would
120        generate the same shader code. To test for identical code generation use getGLProcessorKey*/
121
122    bool isEqual(const GrXferProcessor& that) const {
123        if (this->classID() != that.classID()) {
124            return false;
125        }
126        return this->onIsEqual(that);
127    }
128
129protected:
130    GrXferProcessor() : fWillReadDstColor(false) {}
131
132    /**
133     * If the prceossor subclass will read the destination pixel value then it must call this
134     * function from its constructor. Otherwise, when its generated backend-specific prceossor class
135     * attempts to generate code that reads the destination pixel it will fail.
136     */
137    void setWillReadDstColor() { fWillReadDstColor = true; }
138
139private:
140    virtual bool onIsEqual(const GrXferProcessor&) const = 0;
141
142    bool         fWillReadDstColor;
143
144    typedef GrFragmentProcessor INHERITED;
145};
146
147GR_MAKE_BITFIELD_OPS(GrXferProcessor::OptFlags);
148
149/**
150 * We install a GrXPFactory (XPF) early on in the pipeline before all the final draw information is
151 * known (e.g. whether there is fractional pixel coverage, will coverage be 1 or 4 channel, is the
152 * draw opaque, etc.). Once the state of the draw is finalized, we use the XPF along with all the
153 * draw information to create a GrXferProcessor (XP) which can implement the desired blending for
154 * the draw.
155 *
156 * Before the XP is created, the XPF is able to answer queries about what functionality the XPs it
157 * creates will have. For example, can it create an XP that supports RGB coverage or will the XP
158 * blend with the destination color.
159 */
160class GrXPFactory : public SkRefCnt {
161public:
162    virtual GrXferProcessor* createXferProcessor(const GrProcOptInfo& colorPOI,
163                                                 const GrProcOptInfo& coveragePOI) const = 0;
164
165    /**
166     * This function returns true if the GrXferProcessor generated from this factory will be able to
167     * correctly blend when using RGB coverage. The knownColor and knownColorFlags represent the
168     * final computed color from the color stages.
169     */
170    virtual bool supportsRGBCoverage(GrColor knownColor, uint32_t knownColorFlags) const = 0;
171
172    /**
173     * Depending on color blend mode requested it may or may not be possible to correctly blend with
174     * fractional pixel coverage generated by the fragment shader.
175     *
176     * This function considers the known color and coverage input into the xfer processor and
177     * certain state information (colorWriteDisabled) to determine whether
178     * coverage can be handled correctly.
179     */
180    virtual bool canApplyCoverage(const GrProcOptInfo& colorPOI,
181                                  const GrProcOptInfo& coveragePOI) const = 0;
182
183
184    struct InvariantOutput {
185        bool        fWillBlendWithDst;
186        GrColor     fBlendedColor;
187        uint32_t    fBlendedColorFlags;
188    };
189
190    /**
191     * This function returns known information about the output of the xfer processor produced by
192     * this xp factory. The invariant color information returned by this function refers to the
193     * final color produced after all blending.
194     */
195    virtual void getInvariantOutput(const GrProcOptInfo& colorPOI, const GrProcOptInfo& coveragePOI,
196                                    InvariantOutput*) const = 0;
197
198    /**
199     * Determines whether multiplying the computed per-pixel color by the pixel's fractional
200     * coverage before the blend will give the correct final destination color. In general it
201     * will not as coverage is applied after blending.
202     */
203    virtual bool canTweakAlphaForCoverage() const = 0;
204
205    /**
206     *  Returns true if the XP generated by this factory will read dst.
207     */
208    virtual bool willReadDst() const = 0;
209
210    bool isEqual(const GrXPFactory& that) const {
211        if (this->classID() != that.classID()) {
212            return false;
213        }
214        return this->onIsEqual(that);
215    }
216
217    /**
218      * Helper for down-casting to a GrXPFactory subclass
219      */
220    template <typename T> const T& cast() const { return *static_cast<const T*>(this); }
221
222    uint32_t classID() const { SkASSERT(kIllegalXPFClassID != fClassID); return fClassID; }
223
224protected:
225    GrXPFactory() : fClassID(kIllegalXPFClassID) {}
226
227    template <typename XPF_SUBCLASS> void initClassID() {
228         static uint32_t kClassID = GenClassID();
229         fClassID = kClassID;
230    }
231
232    uint32_t fClassID;
233
234private:
235    virtual bool onIsEqual(const GrXPFactory&) const = 0;
236
237    static uint32_t GenClassID() {
238        // fCurrXPFactoryID has been initialized to kIllegalXPFactoryID. The
239        // atomic inc returns the old value not the incremented value. So we add
240        // 1 to the returned value.
241        uint32_t id = static_cast<uint32_t>(sk_atomic_inc(&gCurrXPFClassID)) + 1;
242        if (!id) {
243            SkFAIL("This should never wrap as it should only be called once for each GrXPFactory "
244                   "subclass.");
245        }
246        return id;
247    }
248
249    enum {
250        kIllegalXPFClassID = 0,
251    };
252    static int32_t gCurrXPFClassID;
253
254    typedef GrProgramElement INHERITED;
255};
256
257#endif
258
259