blob: 332d9d2e23cc865e3d3170a70a882fb2eb7f58e9 [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
cdaltonee0175f2015-06-12 08:21:26 -070011#include "GrBlend.h"
egdaniel378092f2014-12-03 10:40:13 -080012#include "GrColor.h"
egdanielc2304142014-12-11 13:15:13 -080013#include "GrProcessor.h"
bsalomon50785a32015-02-06 07:02:37 -080014#include "GrTexture.h"
egdaniel378092f2014-12-03 10:40:13 -080015#include "GrTypes.h"
16#include "SkXfermode.h"
17
jvanverthe9c0fc62015-04-29 11:18:05 -070018class GrShaderCaps;
19class GrGLSLCaps;
egdanielc2304142014-12-11 13:15:13 -080020class GrGLXferProcessor;
egdaniel95131432014-12-09 11:15:43 -080021class GrProcOptInfo;
22
egdaniel378092f2014-12-03 10:40:13 -080023/**
cdalton9954bc32015-04-29 14:17:00 -070024 * Barriers for blending. When a shader reads the dst directly, an Xfer barrier is sometimes
25 * required after a pixel has been written, before it can be safely read again.
26 */
27enum GrXferBarrierType {
28 kTexture_GrXferBarrierType, //<! Required when a shader reads and renders to the same texture.
cdalton8917d622015-05-06 13:40:21 -070029 kBlend_GrXferBarrierType, //<! Required by certain blend extensions.
cdalton9954bc32015-04-29 14:17:00 -070030};
31
32/**
egdaniel378092f2014-12-03 10:40:13 -080033 * GrXferProcessor is responsible for implementing the xfer mode that blends the src color and dst
cdaltonedbb31f2015-06-08 12:14:44 -070034 * color, and for applying any coverage. It does this by emitting fragment shader code and
35 * controlling the fixed-function blend state. When dual-source blending is available, it may also
36 * write a seconday fragment shader output color. GrXferProcessor has two modes of operation:
37 *
38 * Dst read: When allowed by the backend API, or when supplied a texture of the destination, the
39 * GrXferProcessor may read the destination color. While operating in this mode, the subclass only
40 * provides shader code that blends the src and dst colors, and the base class applies coverage.
41 *
42 * No dst read: When not performing a dst read, the subclass is given full control of the fixed-
43 * function blend state and/or secondary output, and is responsible to apply coverage on its own.
egdaniel378092f2014-12-03 10:40:13 -080044 *
45 * A GrXferProcessor is never installed directly into our draw state, but instead is created from a
46 * GrXPFactory once we have finalized the state of our draw.
47 */
egdanielc2304142014-12-11 13:15:13 -080048class GrXferProcessor : public GrProcessor {
egdaniel95131432014-12-09 11:15:43 -080049public:
50 /**
bsalomon6a44c6a2015-05-26 09:49:05 -070051 * A texture that contains the dst pixel values and an integer coord offset from device space
52 * to the space of the texture. Depending on GPU capabilities a DstTexture may be used by a
53 * GrXferProcessor for blending in the fragment shader.
54 */
55 class DstTexture {
56 public:
57 DstTexture() { fOffset.set(0, 0); }
58
59 DstTexture(const DstTexture& other) {
60 *this = other;
61 }
62
63 DstTexture(GrTexture* texture, const SkIPoint& offset)
64 : fTexture(SkSafeRef(texture))
65 , fOffset(offset) {
66 }
67
68 DstTexture& operator=(const DstTexture& other) {
69 fTexture.reset(SkSafeRef(other.fTexture.get()));
70 fOffset = other.fOffset;
71 return *this;
72 }
73
74 const SkIPoint& offset() const { return fOffset; }
75
76 void setOffset(const SkIPoint& offset) { fOffset = offset; }
77 void setOffset(int ox, int oy) { fOffset.set(ox, oy); }
78
79 GrTexture* texture() const { return fTexture.get(); }
80
81 GrTexture* setTexture(GrTexture* texture) {
82 fTexture.reset(SkSafeRef(texture));
83 return texture;
84 }
85
86 private:
87 SkAutoTUnref<GrTexture> fTexture;
88 SkIPoint fOffset;
89 };
90
91 /**
bsalomon50785a32015-02-06 07:02:37 -080092 * Sets a unique key on the GrProcessorKeyBuilder calls onGetGLProcessorKey(...) to get the
93 * specific subclass's key.
94 */
jvanverthcfc18862015-04-28 08:48:20 -070095 void getGLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const;
egdanielc2304142014-12-11 13:15:13 -080096
97 /** Returns a new instance of the appropriate *GL* implementation class
98 for the given GrXferProcessor; caller is responsible for deleting
99 the object. */
100 virtual GrGLXferProcessor* createGLInstance() const = 0;
101
102 /**
egdaniel95131432014-12-09 11:15:43 -0800103 * Optimizations for blending / coverage that an OptDrawState should apply to itself.
104 */
105 enum OptFlags {
106 /**
bsalomond07a2792015-07-08 10:20:21 -0700107 * No optimizations needed
108 */
109 kNone_Opt = 0,
110 /**
egdaniel95131432014-12-09 11:15:43 -0800111 * The draw can be skipped completely.
112 */
113 kSkipDraw_OptFlag = 0x1,
114 /**
joshualitt9b989322014-12-15 14:16:27 -0800115 * GrXferProcessor will ignore color, thus no need to provide
egdaniel95131432014-12-09 11:15:43 -0800116 */
joshualitt9b989322014-12-15 14:16:27 -0800117 kIgnoreColor_OptFlag = 0x2,
egdaniel95131432014-12-09 11:15:43 -0800118 /**
joshualitt9b989322014-12-15 14:16:27 -0800119 * GrXferProcessor will ignore coverage, thus no need to provide
egdaniel95131432014-12-09 11:15:43 -0800120 */
joshualitt9b989322014-12-15 14:16:27 -0800121 kIgnoreCoverage_OptFlag = 0x4,
egdaniel95131432014-12-09 11:15:43 -0800122 /**
egdaniel54160f32014-12-15 12:38:53 -0800123 * Clear color stages and override input color to that returned by getOptimizations
124 */
125 kOverrideColor_OptFlag = 0x8,
126 /**
egdanielf7c2d552015-02-13 12:11:00 -0800127 * Can tweak alpha for coverage. Currently this flag should only be used by a batch
128 */
129 kCanTweakAlphaForCoverage_OptFlag = 0x20,
egdaniel95131432014-12-09 11:15:43 -0800130 };
131
132 GR_DECL_BITFIELD_OPS_FRIENDS(OptFlags);
133
134 /**
135 * Determines which optimizations (as described by the ptFlags above) can be performed by
136 * the draw with this xfer processor. If this function is called, the xfer processor may change
egdaniel54160f32014-12-15 12:38:53 -0800137 * its state to reflected the given blend optimizations. If the XP needs to see a specific input
138 * color to blend correctly, it will set the OverrideColor flag and the output parameter
139 * overrideColor will be the required value that should be passed into the XP.
egdaniel95131432014-12-09 11:15:43 -0800140 * A caller who calls this function on a XP is required to honor the returned OptFlags
egdaniel54160f32014-12-15 12:38:53 -0800141 * and color values for its draw.
egdaniel95131432014-12-09 11:15:43 -0800142 */
egdanielc19cdc22015-05-10 08:45:18 -0700143 OptFlags getOptimizations(const GrProcOptInfo& colorPOI,
144 const GrProcOptInfo& coveragePOI,
145 bool doesStencilWrite,
146 GrColor* overrideColor,
bsalomon4b91f762015-05-19 09:29:46 -0700147 const GrCaps& caps);
egdaniel95131432014-12-09 11:15:43 -0800148
cdalton9954bc32015-04-29 14:17:00 -0700149 /**
150 * Returns whether this XP will require an Xfer barrier on the given rt. If true, outBarrierType
151 * is updated to contain the type of barrier needed.
152 */
153 bool willNeedXferBarrier(const GrRenderTarget* rt,
bsalomon4b91f762015-05-19 09:29:46 -0700154 const GrCaps& caps,
cdalton9954bc32015-04-29 14:17:00 -0700155 GrXferBarrierType* outBarrierType) const;
156
egdaniel95131432014-12-09 11:15:43 -0800157 struct BlendInfo {
cdaltonf4f2b442015-04-23 09:40:23 -0700158 void reset() {
cdalton8917d622015-05-06 13:40:21 -0700159 fEquation = kAdd_GrBlendEquation;
cdaltonf4f2b442015-04-23 09:40:23 -0700160 fSrcBlend = kOne_GrBlendCoeff;
161 fDstBlend = kZero_GrBlendCoeff;
162 fBlendConstant = 0;
163 fWriteColor = true;
164 }
egdaniel080e6732014-12-22 07:35:52 -0800165
bsalomonf7cc8772015-05-11 11:21:14 -0700166 SkDEBUGCODE(SkString dump() const;)
167
cdalton8917d622015-05-06 13:40:21 -0700168 GrBlendEquation fEquation;
169 GrBlendCoeff fSrcBlend;
170 GrBlendCoeff fDstBlend;
171 GrColor fBlendConstant;
172 bool fWriteColor;
egdaniel95131432014-12-09 11:15:43 -0800173 };
174
cdaltonedbb31f2015-06-08 12:14:44 -0700175 void getBlendInfo(BlendInfo* blendInfo) const;
egdaniel95131432014-12-09 11:15:43 -0800176
egdaniel95131432014-12-09 11:15:43 -0800177 bool willReadDstColor() const { return fWillReadDstColor; }
178
bsalomon50785a32015-02-06 07:02:37 -0800179 /**
180 * Returns the texture to be used as the destination when reading the dst in the fragment
181 * shader. If the returned texture is NULL then the XP is either not reading the dst or we have
182 * extentions that support framebuffer fetching and thus don't need a copy of the dst texture.
183 */
bsalomon6a44c6a2015-05-26 09:49:05 -0700184 const GrTexture* getDstTexture() const { return fDstTexture.getTexture(); }
bsalomon50785a32015-02-06 07:02:37 -0800185
186 /**
bsalomon6a44c6a2015-05-26 09:49:05 -0700187 * Returns the offset in device coords to use when accessing the dst texture to get the dst
188 * pixel color in the shader. This value is only valid if getDstTexture() != NULL.
bsalomon50785a32015-02-06 07:02:37 -0800189 */
bsalomon6a44c6a2015-05-26 09:49:05 -0700190 const SkIPoint& dstTextureOffset() const {
191 SkASSERT(this->getDstTexture());
192 return fDstTextureOffset;
bsalomon50785a32015-02-06 07:02:37 -0800193 }
194
egdanielc19cdc22015-05-10 08:45:18 -0700195 /**
cdalton86ae0a92015-06-08 15:11:04 -0700196 * If we are performing a dst read, returns whether the base class will use mixed samples to
197 * antialias the shader's final output. If not doing a dst read, the subclass is responsible
198 * for antialiasing and this returns false.
199 */
200 bool dstReadUsesMixedSamples() const { return fDstReadUsesMixedSamples; }
201
202 /**
egdanielc19cdc22015-05-10 08:45:18 -0700203 * Returns whether or not the XP will look at coverage when doing its blending.
204 */
205 bool readsCoverage() const { return fReadsCoverage; }
206
cdaltonedbb31f2015-06-08 12:14:44 -0700207 /**
egdanielc2304142014-12-11 13:15:13 -0800208 * Returns whether or not this xferProcossor will set a secondary output to be used with dual
209 * source blending.
210 */
cdaltonedbb31f2015-06-08 12:14:44 -0700211 bool hasSecondaryOutput() const;
egdanielc2304142014-12-11 13:15:13 -0800212
213 /** Returns true if this and other processor conservatively draw identically. It can only return
214 true when the two processor are of the same subclass (i.e. they return the same object from
215 from getFactory()).
216
217 A return value of true from isEqual() should not be used to test whether the processor would
218 generate the same shader code. To test for identical code generation use getGLProcessorKey*/
219
220 bool isEqual(const GrXferProcessor& that) const {
221 if (this->classID() != that.classID()) {
222 return false;
223 }
bsalomon50785a32015-02-06 07:02:37 -0800224 if (this->fWillReadDstColor != that.fWillReadDstColor) {
225 return false;
226 }
egdanielc19cdc22015-05-10 08:45:18 -0700227 if (this->fReadsCoverage != that.fReadsCoverage) {
228 return false;
229 }
bsalomon6a44c6a2015-05-26 09:49:05 -0700230 if (this->fDstTexture.getTexture() != that.fDstTexture.getTexture()) {
bsalomon50785a32015-02-06 07:02:37 -0800231 return false;
232 }
bsalomon6a44c6a2015-05-26 09:49:05 -0700233 if (this->fDstTextureOffset != that.fDstTextureOffset) {
bsalomon50785a32015-02-06 07:02:37 -0800234 return false;
235 }
cdalton86ae0a92015-06-08 15:11:04 -0700236 if (this->fDstReadUsesMixedSamples != that.fDstReadUsesMixedSamples) {
237 return false;
238 }
egdanielc2304142014-12-11 13:15:13 -0800239 return this->onIsEqual(that);
240 }
241
egdaniel95131432014-12-09 11:15:43 -0800242protected:
bsalomon50785a32015-02-06 07:02:37 -0800243 GrXferProcessor();
cdalton86ae0a92015-06-08 15:11:04 -0700244 GrXferProcessor(const DstTexture*, bool willReadDstColor, bool hasMixedSamples);
egdaniel95131432014-12-09 11:15:43 -0800245
egdaniel378092f2014-12-03 10:40:13 -0800246private:
egdanielc19cdc22015-05-10 08:45:18 -0700247 virtual OptFlags onGetOptimizations(const GrProcOptInfo& colorPOI,
248 const GrProcOptInfo& coveragePOI,
249 bool doesStencilWrite,
250 GrColor* overrideColor,
bsalomon4b91f762015-05-19 09:29:46 -0700251 const GrCaps& caps) = 0;
egdanielc19cdc22015-05-10 08:45:18 -0700252
bsalomon50785a32015-02-06 07:02:37 -0800253 /**
254 * Sets a unique key on the GrProcessorKeyBuilder that is directly associated with this xfer
255 * processor's GL backend implementation.
256 */
jvanverthcfc18862015-04-28 08:48:20 -0700257 virtual void onGetGLProcessorKey(const GrGLSLCaps& caps,
bsalomon50785a32015-02-06 07:02:37 -0800258 GrProcessorKeyBuilder* b) const = 0;
259
cdaltonf4f2b442015-04-23 09:40:23 -0700260 /**
cdalton8917d622015-05-06 13:40:21 -0700261 * If not using a texture barrier, retrieves whether the subclass will require a different type
262 * of barrier.
263 */
264 virtual bool onWillNeedXferBarrier(const GrRenderTarget*,
bsalomon4b91f762015-05-19 09:29:46 -0700265 const GrCaps&,
cdalton8917d622015-05-06 13:40:21 -0700266 GrXferBarrierType* outBarrierType SK_UNUSED) const {
267 return false;
268 }
269
270 /**
cdaltonedbb31f2015-06-08 12:14:44 -0700271 * If we are not performing a dst read, returns whether the subclass will set a secondary
cdalton86ae0a92015-06-08 15:11:04 -0700272 * output. When using dst reads, the base class controls the secondary output and this method
cdaltonedbb31f2015-06-08 12:14:44 -0700273 * will not be called.
274 */
275 virtual bool onHasSecondaryOutput() const { return false; }
276
277 /**
278 * If we are not performing a dst read, retrieves the fixed-function blend state required by the
cdalton86ae0a92015-06-08 15:11:04 -0700279 * subclass. When using dst reads, the base class controls the fixed-function blend state and
280 * this method will not be called. The BlendInfo struct comes initialized to "no blending".
cdaltonf4f2b442015-04-23 09:40:23 -0700281 */
282 virtual void onGetBlendInfo(BlendInfo*) const {}
283
egdanielc2304142014-12-11 13:15:13 -0800284 virtual bool onIsEqual(const GrXferProcessor&) const = 0;
egdaniel378092f2014-12-03 10:40:13 -0800285
bsalomon50785a32015-02-06 07:02:37 -0800286 bool fWillReadDstColor;
cdalton86ae0a92015-06-08 15:11:04 -0700287 bool fDstReadUsesMixedSamples;
egdanielc19cdc22015-05-10 08:45:18 -0700288 bool fReadsCoverage;
bsalomon6a44c6a2015-05-26 09:49:05 -0700289 SkIPoint fDstTextureOffset;
290 GrTextureAccess fDstTexture;
egdaniel95131432014-12-09 11:15:43 -0800291
egdaniel378092f2014-12-03 10:40:13 -0800292 typedef GrFragmentProcessor INHERITED;
293};
294
egdaniel95131432014-12-09 11:15:43 -0800295GR_MAKE_BITFIELD_OPS(GrXferProcessor::OptFlags);
296
bsalomon50785a32015-02-06 07:02:37 -0800297///////////////////////////////////////////////////////////////////////////////
298
egdaniel378092f2014-12-03 10:40:13 -0800299/**
300 * We install a GrXPFactory (XPF) early on in the pipeline before all the final draw information is
301 * known (e.g. whether there is fractional pixel coverage, will coverage be 1 or 4 channel, is the
302 * draw opaque, etc.). Once the state of the draw is finalized, we use the XPF along with all the
303 * draw information to create a GrXferProcessor (XP) which can implement the desired blending for
304 * the draw.
305 *
306 * Before the XP is created, the XPF is able to answer queries about what functionality the XPs it
307 * creates will have. For example, can it create an XP that supports RGB coverage or will the XP
308 * blend with the destination color.
309 */
egdanielc016fb82014-12-03 11:41:54 -0800310class GrXPFactory : public SkRefCnt {
egdaniel378092f2014-12-03 10:40:13 -0800311public:
bsalomon6a44c6a2015-05-26 09:49:05 -0700312 typedef GrXferProcessor::DstTexture DstTexture;
bsalomon50785a32015-02-06 07:02:37 -0800313 GrXferProcessor* createXferProcessor(const GrProcOptInfo& colorPOI,
314 const GrProcOptInfo& coveragePOI,
cdalton86ae0a92015-06-08 15:11:04 -0700315 bool hasMixedSamples,
bsalomon6a44c6a2015-05-26 09:49:05 -0700316 const DstTexture*,
bsalomon4b91f762015-05-19 09:29:46 -0700317 const GrCaps& caps) const;
egdaniel378092f2014-12-03 10:40:13 -0800318
319 /**
320 * This function returns true if the GrXferProcessor generated from this factory will be able to
321 * correctly blend when using RGB coverage. The knownColor and knownColorFlags represent the
322 * final computed color from the color stages.
323 */
324 virtual bool supportsRGBCoverage(GrColor knownColor, uint32_t knownColorFlags) const = 0;
325
cdalton1fa45722015-06-02 10:43:39 -0700326 /**
327 * Known color information after blending, but before accounting for any coverage.
328 */
329 struct InvariantBlendedColor {
330 bool fWillBlendWithDst;
331 GrColor fKnownColor;
332 GrColorComponentFlags fKnownColorFlags;
egdaniel9e4ecdc2014-12-18 12:44:55 -0800333 };
334
335 /**
cdalton1fa45722015-06-02 10:43:39 -0700336 * Returns information about the output color, produced by XPs from this factory, that will be
337 * known after blending. Note that we can conflate coverage and color, so the actual values
338 * written to pixels with partial coverage may not always seem consistent with the invariant
339 * information returned by this function.
egdaniel95131432014-12-09 11:15:43 -0800340 */
cdalton1fa45722015-06-02 10:43:39 -0700341 virtual void getInvariantBlendedColor(const GrProcOptInfo& colorPOI,
342 InvariantBlendedColor*) const = 0;
egdaniel95131432014-12-09 11:15:43 -0800343
bsalomon6a44c6a2015-05-26 09:49:05 -0700344 bool willNeedDstTexture(const GrCaps& caps, const GrProcOptInfo& colorPOI,
cdalton86ae0a92015-06-08 15:11:04 -0700345 const GrProcOptInfo& coveragePOI, bool hasMixedSamples) const;
egdaniel080e6732014-12-22 07:35:52 -0800346
egdaniel915187b2014-12-05 12:58:28 -0800347 bool isEqual(const GrXPFactory& that) const {
348 if (this->classID() != that.classID()) {
349 return false;
350 }
351 return this->onIsEqual(that);
352 }
353
354 /**
355 * Helper for down-casting to a GrXPFactory subclass
356 */
357 template <typename T> const T& cast() const { return *static_cast<const T*>(this); }
358
359 uint32_t classID() const { SkASSERT(kIllegalXPFClassID != fClassID); return fClassID; }
360
361protected:
362 GrXPFactory() : fClassID(kIllegalXPFClassID) {}
363
364 template <typename XPF_SUBCLASS> void initClassID() {
365 static uint32_t kClassID = GenClassID();
366 fClassID = kClassID;
367 }
368
369 uint32_t fClassID;
370
egdaniel378092f2014-12-03 10:40:13 -0800371private:
bsalomon4b91f762015-05-19 09:29:46 -0700372 virtual GrXferProcessor* onCreateXferProcessor(const GrCaps& caps,
egdaniel3ad65702015-02-17 11:15:47 -0800373 const GrProcOptInfo& colorPOI,
bsalomon50785a32015-02-06 07:02:37 -0800374 const GrProcOptInfo& coveragePOI,
cdalton86ae0a92015-06-08 15:11:04 -0700375 bool hasMixedSamples,
bsalomon6a44c6a2015-05-26 09:49:05 -0700376 const DstTexture*) const = 0;
bsalomon50785a32015-02-06 07:02:37 -0800377 /**
378 * Returns true if the XP generated by this factory will explicitly read dst in the fragment
379 * shader.
380 */
bsalomon4b91f762015-05-19 09:29:46 -0700381 virtual bool willReadDstColor(const GrCaps& caps,
egdaniel3ad65702015-02-17 11:15:47 -0800382 const GrProcOptInfo& colorPOI,
cdalton86ae0a92015-06-08 15:11:04 -0700383 const GrProcOptInfo& coveragePOI,
384 bool hasMixedSamples) const = 0;
bsalomon50785a32015-02-06 07:02:37 -0800385
egdaniel915187b2014-12-05 12:58:28 -0800386 virtual bool onIsEqual(const GrXPFactory&) const = 0;
387
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
egdaniel378092f2014-12-03 10:40:13 -0800405 typedef GrProgramElement INHERITED;
406};
407
408#endif
409