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