blob: 8cb5cb17698f84464acc8ee14d27c337636b1a5f [file] [log] [blame]
egdaniel378092f2014-12-03 10:40:13 -08001/*
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"
egdanielc2304142014-12-11 13:15:13 -080012#include "GrProcessor.h"
bsalomon50785a32015-02-06 07:02:37 -080013#include "GrTexture.h"
egdaniel378092f2014-12-03 10:40:13 -080014#include "GrTypes.h"
15#include "SkXfermode.h"
16
egdanielc2304142014-12-11 13:15:13 -080017class GrDrawTargetCaps;
18class GrGLCaps;
19class GrGLXferProcessor;
egdaniel95131432014-12-09 11:15:43 -080020class GrProcOptInfo;
21
egdaniel378092f2014-12-03 10:40:13 -080022/**
egdanielb197b8f2015-02-17 07:34:43 -080023 * Coeffecients for alpha-blending.
24 */
25enum GrBlendCoeff {
26 kInvalid_GrBlendCoeff = -1,
27
28 kZero_GrBlendCoeff, //<! 0
29 kOne_GrBlendCoeff, //<! 1
30 kSC_GrBlendCoeff, //<! src color
31 kISC_GrBlendCoeff, //<! one minus src color
32 kDC_GrBlendCoeff, //<! dst color
33 kIDC_GrBlendCoeff, //<! one minus dst color
34 kSA_GrBlendCoeff, //<! src alpha
35 kISA_GrBlendCoeff, //<! one minus src alpha
36 kDA_GrBlendCoeff, //<! dst alpha
37 kIDA_GrBlendCoeff, //<! one minus dst alpha
38 kConstC_GrBlendCoeff, //<! constant color
39 kIConstC_GrBlendCoeff, //<! one minus constant color
40 kConstA_GrBlendCoeff, //<! constant color alpha
41 kIConstA_GrBlendCoeff, //<! one minus constant color alpha
42 kS2C_GrBlendCoeff,
43 kIS2C_GrBlendCoeff,
44 kS2A_GrBlendCoeff,
45 kIS2A_GrBlendCoeff,
46
47 kTotalGrBlendCoeffCount
48};
49
50/**
egdaniel378092f2014-12-03 10:40:13 -080051 * GrXferProcessor is responsible for implementing the xfer mode that blends the src color and dst
52 * color. It does this by emitting fragment shader code and controlling the fixed-function blend
53 * state. The inputs to its shader code are the final computed src color and fractional pixel
54 * coverage. The GrXferProcessor's shader code writes the fragment shader output color that goes
55 * into the fixed-function blend. When dual-source blending is available, it may also write a
56 * seconday fragment shader output color. When allowed by the backend API, the GrXferProcessor may
57 * read the destination color. The GrXferProcessor is responsible for setting the blend coefficients
58 * and blend constant color.
59 *
60 * A GrXferProcessor is never installed directly into our draw state, but instead is created from a
61 * GrXPFactory once we have finalized the state of our draw.
62 */
egdanielc2304142014-12-11 13:15:13 -080063class GrXferProcessor : public GrProcessor {
egdaniel95131432014-12-09 11:15:43 -080064public:
65 /**
bsalomon50785a32015-02-06 07:02:37 -080066 * Sets a unique key on the GrProcessorKeyBuilder calls onGetGLProcessorKey(...) to get the
67 * specific subclass's key.
68 */
69 void getGLProcessorKey(const GrGLCaps& caps, GrProcessorKeyBuilder* b) const;
egdanielc2304142014-12-11 13:15:13 -080070
71 /** Returns a new instance of the appropriate *GL* implementation class
72 for the given GrXferProcessor; caller is responsible for deleting
73 the object. */
74 virtual GrGLXferProcessor* createGLInstance() const = 0;
75
76 /**
egdaniel95131432014-12-09 11:15:43 -080077 * Optimizations for blending / coverage that an OptDrawState should apply to itself.
78 */
79 enum OptFlags {
80 /**
81 * No optimizations needed
82 */
83 kNone_Opt = 0,
84 /**
85 * The draw can be skipped completely.
86 */
87 kSkipDraw_OptFlag = 0x1,
88 /**
joshualitt9b989322014-12-15 14:16:27 -080089 * GrXferProcessor will ignore color, thus no need to provide
egdaniel95131432014-12-09 11:15:43 -080090 */
joshualitt9b989322014-12-15 14:16:27 -080091 kIgnoreColor_OptFlag = 0x2,
egdaniel95131432014-12-09 11:15:43 -080092 /**
joshualitt9b989322014-12-15 14:16:27 -080093 * GrXferProcessor will ignore coverage, thus no need to provide
egdaniel95131432014-12-09 11:15:43 -080094 */
joshualitt9b989322014-12-15 14:16:27 -080095 kIgnoreCoverage_OptFlag = 0x4,
egdaniel95131432014-12-09 11:15:43 -080096 /**
egdaniel54160f32014-12-15 12:38:53 -080097 * Clear color stages and override input color to that returned by getOptimizations
98 */
99 kOverrideColor_OptFlag = 0x8,
100 /**
egdaniel95131432014-12-09 11:15:43 -0800101 * Set CoverageDrawing_StateBit
102 */
egdaniel54160f32014-12-15 12:38:53 -0800103 kSetCoverageDrawing_OptFlag = 0x10,
egdanielf7c2d552015-02-13 12:11:00 -0800104 /**
105 * Can tweak alpha for coverage. Currently this flag should only be used by a batch
106 */
107 kCanTweakAlphaForCoverage_OptFlag = 0x20,
egdaniel95131432014-12-09 11:15:43 -0800108 };
109
110 GR_DECL_BITFIELD_OPS_FRIENDS(OptFlags);
111
112 /**
113 * Determines which optimizations (as described by the ptFlags above) can be performed by
114 * the draw with this xfer processor. If this function is called, the xfer processor may change
egdaniel54160f32014-12-15 12:38:53 -0800115 * its state to reflected the given blend optimizations. If the XP needs to see a specific input
116 * color to blend correctly, it will set the OverrideColor flag and the output parameter
117 * overrideColor will be the required value that should be passed into the XP.
egdaniel95131432014-12-09 11:15:43 -0800118 * A caller who calls this function on a XP is required to honor the returned OptFlags
egdaniel54160f32014-12-15 12:38:53 -0800119 * and color values for its draw.
egdaniel95131432014-12-09 11:15:43 -0800120 */
egdaniel95131432014-12-09 11:15:43 -0800121 virtual OptFlags getOptimizations(const GrProcOptInfo& colorPOI,
122 const GrProcOptInfo& coveragePOI,
egdaniel95131432014-12-09 11:15:43 -0800123 bool doesStencilWrite,
egdaniel54160f32014-12-15 12:38:53 -0800124 GrColor* overrideColor,
egdanielc2304142014-12-11 13:15:13 -0800125 const GrDrawTargetCaps& caps) = 0;
egdaniel95131432014-12-09 11:15:43 -0800126
127 struct BlendInfo {
egdaniel080e6732014-12-22 07:35:52 -0800128 BlendInfo() : fWriteColor(true) {}
129
egdaniel95131432014-12-09 11:15:43 -0800130 GrBlendCoeff fSrcBlend;
131 GrBlendCoeff fDstBlend;
132 GrColor fBlendConstant;
egdaniel080e6732014-12-22 07:35:52 -0800133 bool fWriteColor;
egdaniel95131432014-12-09 11:15:43 -0800134 };
135
136 virtual void getBlendInfo(BlendInfo* blendInfo) const = 0;
137
egdaniel95131432014-12-09 11:15:43 -0800138 bool willReadDstColor() const { return fWillReadDstColor; }
139
bsalomon50785a32015-02-06 07:02:37 -0800140 /**
141 * Returns the texture to be used as the destination when reading the dst in the fragment
142 * shader. If the returned texture is NULL then the XP is either not reading the dst or we have
143 * extentions that support framebuffer fetching and thus don't need a copy of the dst texture.
144 */
145 const GrTexture* getDstCopyTexture() const { return fDstCopy.getTexture(); }
146
147 /**
148 * Returns the offset into the DstCopyTexture to use when reading it in the shader. This value
149 * is only valid if getDstCopyTexture() != NULL.
150 */
151 const SkIPoint& dstCopyTextureOffset() const {
152 SkASSERT(this->getDstCopyTexture());
153 return fDstCopyTextureOffset;
154 }
155
egdanielc2304142014-12-11 13:15:13 -0800156 /**
157 * Returns whether or not this xferProcossor will set a secondary output to be used with dual
158 * source blending.
159 */
160 virtual bool hasSecondaryOutput() const { return false; }
161
162 /** Returns true if this and other processor conservatively draw identically. It can only return
163 true when the two processor are of the same subclass (i.e. they return the same object from
164 from getFactory()).
165
166 A return value of true from isEqual() should not be used to test whether the processor would
167 generate the same shader code. To test for identical code generation use getGLProcessorKey*/
168
169 bool isEqual(const GrXferProcessor& that) const {
170 if (this->classID() != that.classID()) {
171 return false;
172 }
bsalomon50785a32015-02-06 07:02:37 -0800173 if (this->fWillReadDstColor != that.fWillReadDstColor) {
174 return false;
175 }
176 if (this->fDstCopy.getTexture() != that.fDstCopy.getTexture()) {
177 return false;
178 }
179 if (this->fDstCopyTextureOffset != that.fDstCopyTextureOffset) {
180 return false;
181 }
egdanielc2304142014-12-11 13:15:13 -0800182 return this->onIsEqual(that);
183 }
184
egdaniel95131432014-12-09 11:15:43 -0800185protected:
bsalomon50785a32015-02-06 07:02:37 -0800186 GrXferProcessor();
187 GrXferProcessor(const GrDeviceCoordTexture* dstCopy, bool willReadDstColor);
egdaniel95131432014-12-09 11:15:43 -0800188
egdaniel378092f2014-12-03 10:40:13 -0800189private:
bsalomon50785a32015-02-06 07:02:37 -0800190 /**
191 * Sets a unique key on the GrProcessorKeyBuilder that is directly associated with this xfer
192 * processor's GL backend implementation.
193 */
194 virtual void onGetGLProcessorKey(const GrGLCaps& caps,
195 GrProcessorKeyBuilder* b) const = 0;
196
egdanielc2304142014-12-11 13:15:13 -0800197 virtual bool onIsEqual(const GrXferProcessor&) const = 0;
egdaniel378092f2014-12-03 10:40:13 -0800198
bsalomon50785a32015-02-06 07:02:37 -0800199 bool fWillReadDstColor;
200 SkIPoint fDstCopyTextureOffset;
201 GrTextureAccess fDstCopy;
egdaniel95131432014-12-09 11:15:43 -0800202
egdaniel378092f2014-12-03 10:40:13 -0800203 typedef GrFragmentProcessor INHERITED;
204};
205
egdaniel95131432014-12-09 11:15:43 -0800206GR_MAKE_BITFIELD_OPS(GrXferProcessor::OptFlags);
207
bsalomon50785a32015-02-06 07:02:37 -0800208///////////////////////////////////////////////////////////////////////////////
209
egdaniel378092f2014-12-03 10:40:13 -0800210/**
211 * We install a GrXPFactory (XPF) early on in the pipeline before all the final draw information is
212 * known (e.g. whether there is fractional pixel coverage, will coverage be 1 or 4 channel, is the
213 * draw opaque, etc.). Once the state of the draw is finalized, we use the XPF along with all the
214 * draw information to create a GrXferProcessor (XP) which can implement the desired blending for
215 * the draw.
216 *
217 * Before the XP is created, the XPF is able to answer queries about what functionality the XPs it
218 * creates will have. For example, can it create an XP that supports RGB coverage or will the XP
219 * blend with the destination color.
220 */
egdanielc016fb82014-12-03 11:41:54 -0800221class GrXPFactory : public SkRefCnt {
egdaniel378092f2014-12-03 10:40:13 -0800222public:
bsalomon50785a32015-02-06 07:02:37 -0800223 GrXferProcessor* createXferProcessor(const GrProcOptInfo& colorPOI,
224 const GrProcOptInfo& coveragePOI,
225 const GrDeviceCoordTexture* dstCopy,
226 const GrDrawTargetCaps& caps) const;
egdaniel378092f2014-12-03 10:40:13 -0800227
228 /**
229 * This function returns true if the GrXferProcessor generated from this factory will be able to
230 * correctly blend when using RGB coverage. The knownColor and knownColorFlags represent the
231 * final computed color from the color stages.
232 */
233 virtual bool supportsRGBCoverage(GrColor knownColor, uint32_t knownColorFlags) const = 0;
234
egdaniel95131432014-12-09 11:15:43 -0800235 /**
236 * Depending on color blend mode requested it may or may not be possible to correctly blend with
237 * fractional pixel coverage generated by the fragment shader.
238 *
239 * This function considers the known color and coverage input into the xfer processor and
egdaniel87509242014-12-17 13:37:13 -0800240 * certain state information (colorWriteDisabled) to determine whether
egdaniel95131432014-12-09 11:15:43 -0800241 * coverage can be handled correctly.
242 */
egdaniel080e6732014-12-22 07:35:52 -0800243 virtual bool canApplyCoverage(const GrProcOptInfo& colorPOI,
244 const GrProcOptInfo& coveragePOI) const = 0;
egdaniel95131432014-12-09 11:15:43 -0800245
egdaniel9e4ecdc2014-12-18 12:44:55 -0800246
247 struct InvariantOutput {
248 bool fWillBlendWithDst;
249 GrColor fBlendedColor;
250 uint32_t fBlendedColorFlags;
251 };
252
253 /**
254 * This function returns known information about the output of the xfer processor produced by
255 * this xp factory. The invariant color information returned by this function refers to the
256 * final color produced after all blending.
egdaniel95131432014-12-09 11:15:43 -0800257 */
egdaniel9e4ecdc2014-12-18 12:44:55 -0800258 virtual void getInvariantOutput(const GrProcOptInfo& colorPOI, const GrProcOptInfo& coveragePOI,
egdaniel080e6732014-12-22 07:35:52 -0800259 InvariantOutput*) const = 0;
egdaniel95131432014-12-09 11:15:43 -0800260
261 /**
262 * Determines whether multiplying the computed per-pixel color by the pixel's fractional
263 * coverage before the blend will give the correct final destination color. In general it
264 * will not as coverage is applied after blending.
265 */
egdaniel87509242014-12-17 13:37:13 -0800266 virtual bool canTweakAlphaForCoverage() const = 0;
egdaniel95131432014-12-09 11:15:43 -0800267
egdaniele36914c2015-02-13 09:00:33 -0800268 bool willNeedDstCopy(const GrDrawTargetCaps& caps, const GrProcOptInfo& colorPOI,
269 const GrProcOptInfo& coveragePOI) const;
egdaniel080e6732014-12-22 07:35:52 -0800270
egdaniel915187b2014-12-05 12:58:28 -0800271 bool isEqual(const GrXPFactory& that) const {
272 if (this->classID() != that.classID()) {
273 return false;
274 }
275 return this->onIsEqual(that);
276 }
277
278 /**
279 * Helper for down-casting to a GrXPFactory subclass
280 */
281 template <typename T> const T& cast() const { return *static_cast<const T*>(this); }
282
283 uint32_t classID() const { SkASSERT(kIllegalXPFClassID != fClassID); return fClassID; }
284
285protected:
286 GrXPFactory() : fClassID(kIllegalXPFClassID) {}
287
288 template <typename XPF_SUBCLASS> void initClassID() {
289 static uint32_t kClassID = GenClassID();
290 fClassID = kClassID;
291 }
292
293 uint32_t fClassID;
294
egdaniel378092f2014-12-03 10:40:13 -0800295private:
egdaniel3ad65702015-02-17 11:15:47 -0800296 virtual GrXferProcessor* onCreateXferProcessor(const GrDrawTargetCaps& caps,
297 const GrProcOptInfo& colorPOI,
bsalomon50785a32015-02-06 07:02:37 -0800298 const GrProcOptInfo& coveragePOI,
299 const GrDeviceCoordTexture* dstCopy) const = 0;
300 /**
301 * Returns true if the XP generated by this factory will explicitly read dst in the fragment
302 * shader.
303 */
egdaniel3ad65702015-02-17 11:15:47 -0800304 virtual bool willReadDstColor(const GrDrawTargetCaps& caps,
305 const GrProcOptInfo& colorPOI,
egdaniele36914c2015-02-13 09:00:33 -0800306 const GrProcOptInfo& coveragePOI) const = 0;
bsalomon50785a32015-02-06 07:02:37 -0800307
egdaniel915187b2014-12-05 12:58:28 -0800308 virtual bool onIsEqual(const GrXPFactory&) const = 0;
309
310 static uint32_t GenClassID() {
311 // fCurrXPFactoryID has been initialized to kIllegalXPFactoryID. The
312 // atomic inc returns the old value not the incremented value. So we add
313 // 1 to the returned value.
314 uint32_t id = static_cast<uint32_t>(sk_atomic_inc(&gCurrXPFClassID)) + 1;
315 if (!id) {
316 SkFAIL("This should never wrap as it should only be called once for each GrXPFactory "
317 "subclass.");
318 }
319 return id;
320 }
321
322 enum {
323 kIllegalXPFClassID = 0,
324 };
325 static int32_t gCurrXPFClassID;
326
egdaniel378092f2014-12-03 10:40:13 -0800327 typedef GrProgramElement INHERITED;
328};
329
330#endif
331