blob: 1d4717e1569dd4f1799582242b859bf9d6e39fba [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;
egdanielfa4cc8b2015-11-13 08:34:52 -080020class GrGLSLXferProcessor;
egdaniel95131432014-12-09 11:15:43 -080021class GrProcOptInfo;
ethannicholasde4166a2015-11-30 08:57:38 -080022struct GrPipelineOptimizations;
egdaniel95131432014-12-09 11:15:43 -080023
egdaniel378092f2014-12-03 10:40:13 -080024/**
cdalton9954bc32015-04-29 14:17:00 -070025 * Barriers for blending. When a shader reads the dst directly, an Xfer barrier is sometimes
26 * required after a pixel has been written, before it can be safely read again.
27 */
28enum GrXferBarrierType {
bsalomoncb02b382015-08-12 11:14:50 -070029 kNone_GrXferBarrierType = 0, //<! No barrier is required
30 kTexture_GrXferBarrierType, //<! Required when a shader reads and renders to the same texture.
31 kBlend_GrXferBarrierType, //<! Required by certain blend extensions.
cdalton9954bc32015-04-29 14:17:00 -070032};
bsalomoncb02b382015-08-12 11:14:50 -070033/** Should be able to treat kNone as false in boolean expressions */
34GR_STATIC_ASSERT(SkToBool(kNone_GrXferBarrierType) == false);
cdalton9954bc32015-04-29 14:17:00 -070035
36/**
egdaniel378092f2014-12-03 10:40:13 -080037 * GrXferProcessor is responsible for implementing the xfer mode that blends the src color and dst
cdaltonedbb31f2015-06-08 12:14:44 -070038 * color, and for applying any coverage. It does this by emitting fragment shader code and
39 * controlling the fixed-function blend state. When dual-source blending is available, it may also
40 * write a seconday fragment shader output color. GrXferProcessor has two modes of operation:
41 *
42 * Dst read: When allowed by the backend API, or when supplied a texture of the destination, the
43 * GrXferProcessor may read the destination color. While operating in this mode, the subclass only
44 * provides shader code that blends the src and dst colors, and the base class applies coverage.
45 *
46 * No dst read: When not performing a dst read, the subclass is given full control of the fixed-
47 * function blend state and/or secondary output, and is responsible to apply coverage on its own.
egdaniel378092f2014-12-03 10:40:13 -080048 *
49 * A GrXferProcessor is never installed directly into our draw state, but instead is created from a
50 * GrXPFactory once we have finalized the state of our draw.
51 */
egdanielc2304142014-12-11 13:15:13 -080052class GrXferProcessor : public GrProcessor {
egdaniel95131432014-12-09 11:15:43 -080053public:
54 /**
bsalomon6a44c6a2015-05-26 09:49:05 -070055 * A texture that contains the dst pixel values and an integer coord offset from device space
56 * to the space of the texture. Depending on GPU capabilities a DstTexture may be used by a
57 * GrXferProcessor for blending in the fragment shader.
58 */
59 class DstTexture {
60 public:
61 DstTexture() { fOffset.set(0, 0); }
62
63 DstTexture(const DstTexture& other) {
64 *this = other;
65 }
66
67 DstTexture(GrTexture* texture, const SkIPoint& offset)
68 : fTexture(SkSafeRef(texture))
69 , fOffset(offset) {
70 }
71
72 DstTexture& operator=(const DstTexture& other) {
73 fTexture.reset(SkSafeRef(other.fTexture.get()));
74 fOffset = other.fOffset;
75 return *this;
76 }
77
78 const SkIPoint& offset() const { return fOffset; }
79
80 void setOffset(const SkIPoint& offset) { fOffset = offset; }
81 void setOffset(int ox, int oy) { fOffset.set(ox, oy); }
82
83 GrTexture* texture() const { return fTexture.get(); }
84
85 GrTexture* setTexture(GrTexture* texture) {
86 fTexture.reset(SkSafeRef(texture));
87 return texture;
88 }
89
90 private:
91 SkAutoTUnref<GrTexture> fTexture;
92 SkIPoint fOffset;
93 };
94
95 /**
egdaniel57d3b032015-11-13 11:57:27 -080096 * Sets a unique key on the GrProcessorKeyBuilder calls onGetGLSLProcessorKey(...) to get the
bsalomon50785a32015-02-06 07:02:37 -080097 * specific subclass's key.
98 */
egdaniel57d3b032015-11-13 11:57:27 -080099 void getGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const;
egdanielc2304142014-12-11 13:15:13 -0800100
101 /** Returns a new instance of the appropriate *GL* implementation class
102 for the given GrXferProcessor; caller is responsible for deleting
103 the object. */
egdaniel57d3b032015-11-13 11:57:27 -0800104 virtual GrGLSLXferProcessor* createGLSLInstance() const = 0;
egdanielc2304142014-12-11 13:15:13 -0800105
106 /**
egdaniel95131432014-12-09 11:15:43 -0800107 * Optimizations for blending / coverage that an OptDrawState should apply to itself.
108 */
109 enum OptFlags {
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
bsalomon7765a472015-07-08 11:26:37 -0700132 static const OptFlags kNone_OptFlags = (OptFlags)0;
133
egdaniel95131432014-12-09 11:15:43 -0800134 GR_DECL_BITFIELD_OPS_FRIENDS(OptFlags);
135
136 /**
137 * Determines which optimizations (as described by the ptFlags above) can be performed by
138 * the draw with this xfer processor. If this function is called, the xfer processor may change
egdaniel54160f32014-12-15 12:38:53 -0800139 * its state to reflected the given blend optimizations. If the XP needs to see a specific input
140 * color to blend correctly, it will set the OverrideColor flag and the output parameter
141 * overrideColor will be the required value that should be passed into the XP.
egdaniel95131432014-12-09 11:15:43 -0800142 * A caller who calls this function on a XP is required to honor the returned OptFlags
egdaniel54160f32014-12-15 12:38:53 -0800143 * and color values for its draw.
egdaniel95131432014-12-09 11:15:43 -0800144 */
ethannicholasde4166a2015-11-30 08:57:38 -0800145 OptFlags getOptimizations(const GrPipelineOptimizations& optimizations,
egdanielc19cdc22015-05-10 08:45:18 -0700146 bool doesStencilWrite,
147 GrColor* overrideColor,
egdaniel56cf6dc2015-11-30 10:15:58 -0800148 const GrCaps& caps) const;
egdaniel95131432014-12-09 11:15:43 -0800149
cdalton9954bc32015-04-29 14:17:00 -0700150 /**
151 * Returns whether this XP will require an Xfer barrier on the given rt. If true, outBarrierType
152 * is updated to contain the type of barrier needed.
153 */
bsalomoncb02b382015-08-12 11:14:50 -0700154 GrXferBarrierType xferBarrierType(const GrRenderTarget* rt, const GrCaps& caps) const;
cdalton9954bc32015-04-29 14:17:00 -0700155
egdaniel95131432014-12-09 11:15:43 -0800156 struct BlendInfo {
cdaltonf4f2b442015-04-23 09:40:23 -0700157 void reset() {
cdalton8917d622015-05-06 13:40:21 -0700158 fEquation = kAdd_GrBlendEquation;
cdaltonf4f2b442015-04-23 09:40:23 -0700159 fSrcBlend = kOne_GrBlendCoeff;
160 fDstBlend = kZero_GrBlendCoeff;
161 fBlendConstant = 0;
162 fWriteColor = true;
163 }
egdaniel080e6732014-12-22 07:35:52 -0800164
bsalomonf7cc8772015-05-11 11:21:14 -0700165 SkDEBUGCODE(SkString dump() const;)
166
cdalton8917d622015-05-06 13:40:21 -0700167 GrBlendEquation fEquation;
168 GrBlendCoeff fSrcBlend;
169 GrBlendCoeff fDstBlend;
170 GrColor fBlendConstant;
171 bool fWriteColor;
egdaniel95131432014-12-09 11:15:43 -0800172 };
173
cdaltonedbb31f2015-06-08 12:14:44 -0700174 void getBlendInfo(BlendInfo* blendInfo) const;
egdaniel95131432014-12-09 11:15:43 -0800175
egdaniel95131432014-12-09 11:15:43 -0800176 bool willReadDstColor() const { return fWillReadDstColor; }
177
bsalomon50785a32015-02-06 07:02:37 -0800178 /**
179 * Returns the texture to be used as the destination when reading the dst in the fragment
180 * shader. If the returned texture is NULL then the XP is either not reading the dst or we have
181 * extentions that support framebuffer fetching and thus don't need a copy of the dst texture.
182 */
bsalomon6a44c6a2015-05-26 09:49:05 -0700183 const GrTexture* getDstTexture() const { return fDstTexture.getTexture(); }
bsalomon50785a32015-02-06 07:02:37 -0800184
185 /**
bsalomon6a44c6a2015-05-26 09:49:05 -0700186 * Returns the offset in device coords to use when accessing the dst texture to get the dst
187 * pixel color in the shader. This value is only valid if getDstTexture() != NULL.
bsalomon50785a32015-02-06 07:02:37 -0800188 */
bsalomon6a44c6a2015-05-26 09:49:05 -0700189 const SkIPoint& dstTextureOffset() const {
190 SkASSERT(this->getDstTexture());
191 return fDstTextureOffset;
bsalomon50785a32015-02-06 07:02:37 -0800192 }
193
egdanielc19cdc22015-05-10 08:45:18 -0700194 /**
cdalton86ae0a92015-06-08 15:11:04 -0700195 * If we are performing a dst read, returns whether the base class will use mixed samples to
196 * antialias the shader's final output. If not doing a dst read, the subclass is responsible
197 * for antialiasing and this returns false.
198 */
199 bool dstReadUsesMixedSamples() const { return fDstReadUsesMixedSamples; }
200
201 /**
egdanielc2304142014-12-11 13:15:13 -0800202 * Returns whether or not this xferProcossor will set a secondary output to be used with dual
203 * source blending.
204 */
cdaltonedbb31f2015-06-08 12:14:44 -0700205 bool hasSecondaryOutput() const;
egdanielc2304142014-12-11 13:15:13 -0800206
207 /** Returns true if this and other processor conservatively draw identically. It can only return
208 true when the two processor are of the same subclass (i.e. they return the same object from
209 from getFactory()).
210
211 A return value of true from isEqual() should not be used to test whether the processor would
egdaniel57d3b032015-11-13 11:57:27 -0800212 generate the same shader code. To test for identical code generation use getGLSLProcessorKey
213 */
egdanielc2304142014-12-11 13:15:13 -0800214
215 bool isEqual(const GrXferProcessor& that) const {
216 if (this->classID() != that.classID()) {
217 return false;
218 }
bsalomon50785a32015-02-06 07:02:37 -0800219 if (this->fWillReadDstColor != that.fWillReadDstColor) {
220 return false;
221 }
bsalomon6a44c6a2015-05-26 09:49:05 -0700222 if (this->fDstTexture.getTexture() != that.fDstTexture.getTexture()) {
bsalomon50785a32015-02-06 07:02:37 -0800223 return false;
224 }
bsalomon6a44c6a2015-05-26 09:49:05 -0700225 if (this->fDstTextureOffset != that.fDstTextureOffset) {
bsalomon50785a32015-02-06 07:02:37 -0800226 return false;
227 }
cdalton86ae0a92015-06-08 15:11:04 -0700228 if (this->fDstReadUsesMixedSamples != that.fDstReadUsesMixedSamples) {
229 return false;
230 }
egdanielc2304142014-12-11 13:15:13 -0800231 return this->onIsEqual(that);
232 }
233
egdaniel95131432014-12-09 11:15:43 -0800234protected:
bsalomon50785a32015-02-06 07:02:37 -0800235 GrXferProcessor();
cdalton86ae0a92015-06-08 15:11:04 -0700236 GrXferProcessor(const DstTexture*, bool willReadDstColor, bool hasMixedSamples);
egdaniel95131432014-12-09 11:15:43 -0800237
egdaniel378092f2014-12-03 10:40:13 -0800238private:
bsalomon42048002015-08-27 16:43:48 -0700239 void notifyRefCntIsZero() const final {}
240
ethannicholasde4166a2015-11-30 08:57:38 -0800241 virtual OptFlags onGetOptimizations(const GrPipelineOptimizations& optimizations,
egdanielc19cdc22015-05-10 08:45:18 -0700242 bool doesStencilWrite,
243 GrColor* overrideColor,
egdaniel56cf6dc2015-11-30 10:15:58 -0800244 const GrCaps& caps) const = 0;
egdanielc19cdc22015-05-10 08:45:18 -0700245
bsalomon50785a32015-02-06 07:02:37 -0800246 /**
247 * Sets a unique key on the GrProcessorKeyBuilder that is directly associated with this xfer
248 * processor's GL backend implementation.
249 */
egdaniel57d3b032015-11-13 11:57:27 -0800250 virtual void onGetGLSLProcessorKey(const GrGLSLCaps& caps,
251 GrProcessorKeyBuilder* b) const = 0;
bsalomon50785a32015-02-06 07:02:37 -0800252
cdaltonf4f2b442015-04-23 09:40:23 -0700253 /**
bsalomoncb02b382015-08-12 11:14:50 -0700254 * Determines the type of barrier (if any) required by the subclass. Note that the possibility
255 * that a kTexture type barrier is required is handled by the base class and need not be
256 * considered by subclass overrides of this function.
cdalton8917d622015-05-06 13:40:21 -0700257 */
bsalomoncb02b382015-08-12 11:14:50 -0700258 virtual GrXferBarrierType onXferBarrier(const GrRenderTarget*, const GrCaps&) const {
259 return kNone_GrXferBarrierType;
cdalton8917d622015-05-06 13:40:21 -0700260 }
261
262 /**
cdaltonedbb31f2015-06-08 12:14:44 -0700263 * If we are not performing a dst read, returns whether the subclass will set a secondary
cdalton86ae0a92015-06-08 15:11:04 -0700264 * output. When using dst reads, the base class controls the secondary output and this method
cdaltonedbb31f2015-06-08 12:14:44 -0700265 * will not be called.
266 */
267 virtual bool onHasSecondaryOutput() const { return false; }
268
269 /**
270 * If we are not performing a dst read, retrieves the fixed-function blend state required by the
cdalton86ae0a92015-06-08 15:11:04 -0700271 * subclass. When using dst reads, the base class controls the fixed-function blend state and
272 * this method will not be called. The BlendInfo struct comes initialized to "no blending".
cdaltonf4f2b442015-04-23 09:40:23 -0700273 */
274 virtual void onGetBlendInfo(BlendInfo*) const {}
275
egdanielc2304142014-12-11 13:15:13 -0800276 virtual bool onIsEqual(const GrXferProcessor&) const = 0;
egdaniel378092f2014-12-03 10:40:13 -0800277
bsalomon50785a32015-02-06 07:02:37 -0800278 bool fWillReadDstColor;
cdalton86ae0a92015-06-08 15:11:04 -0700279 bool fDstReadUsesMixedSamples;
bsalomon6a44c6a2015-05-26 09:49:05 -0700280 SkIPoint fDstTextureOffset;
281 GrTextureAccess fDstTexture;
egdaniel95131432014-12-09 11:15:43 -0800282
egdaniel378092f2014-12-03 10:40:13 -0800283 typedef GrFragmentProcessor INHERITED;
284};
285
egdaniel95131432014-12-09 11:15:43 -0800286GR_MAKE_BITFIELD_OPS(GrXferProcessor::OptFlags);
287
bsalomon50785a32015-02-06 07:02:37 -0800288///////////////////////////////////////////////////////////////////////////////
289
egdaniel378092f2014-12-03 10:40:13 -0800290/**
291 * We install a GrXPFactory (XPF) early on in the pipeline before all the final draw information is
292 * known (e.g. whether there is fractional pixel coverage, will coverage be 1 or 4 channel, is the
293 * draw opaque, etc.). Once the state of the draw is finalized, we use the XPF along with all the
294 * draw information to create a GrXferProcessor (XP) which can implement the desired blending for
295 * the draw.
296 *
297 * Before the XP is created, the XPF is able to answer queries about what functionality the XPs it
298 * creates will have. For example, can it create an XP that supports RGB coverage or will the XP
299 * blend with the destination color.
300 */
egdanielc016fb82014-12-03 11:41:54 -0800301class GrXPFactory : public SkRefCnt {
egdaniel378092f2014-12-03 10:40:13 -0800302public:
bsalomon6a44c6a2015-05-26 09:49:05 -0700303 typedef GrXferProcessor::DstTexture DstTexture;
ethannicholasde4166a2015-11-30 08:57:38 -0800304 GrXferProcessor* createXferProcessor(const GrPipelineOptimizations& optimizations,
cdalton86ae0a92015-06-08 15:11:04 -0700305 bool hasMixedSamples,
bsalomon6a44c6a2015-05-26 09:49:05 -0700306 const DstTexture*,
bsalomon4b91f762015-05-19 09:29:46 -0700307 const GrCaps& caps) const;
cdalton1fa45722015-06-02 10:43:39 -0700308 /**
309 * Known color information after blending, but before accounting for any coverage.
310 */
311 struct InvariantBlendedColor {
312 bool fWillBlendWithDst;
313 GrColor fKnownColor;
314 GrColorComponentFlags fKnownColorFlags;
egdaniel9e4ecdc2014-12-18 12:44:55 -0800315 };
316
317 /**
cdalton1fa45722015-06-02 10:43:39 -0700318 * Returns information about the output color, produced by XPs from this factory, that will be
319 * known after blending. Note that we can conflate coverage and color, so the actual values
320 * written to pixels with partial coverage may not always seem consistent with the invariant
321 * information returned by this function.
egdaniel95131432014-12-09 11:15:43 -0800322 */
cdalton1fa45722015-06-02 10:43:39 -0700323 virtual void getInvariantBlendedColor(const GrProcOptInfo& colorPOI,
324 InvariantBlendedColor*) const = 0;
egdaniel95131432014-12-09 11:15:43 -0800325
cdalton3ccf2e72016-05-06 09:41:16 -0700326 bool willNeedDstTexture(const GrCaps& caps, const GrPipelineOptimizations& optimizations) const;
egdaniel080e6732014-12-22 07:35:52 -0800327
egdaniel915187b2014-12-05 12:58:28 -0800328 bool isEqual(const GrXPFactory& that) const {
329 if (this->classID() != that.classID()) {
330 return false;
331 }
332 return this->onIsEqual(that);
333 }
334
335 /**
336 * Helper for down-casting to a GrXPFactory subclass
337 */
338 template <typename T> const T& cast() const { return *static_cast<const T*>(this); }
339
340 uint32_t classID() const { SkASSERT(kIllegalXPFClassID != fClassID); return fClassID; }
341
342protected:
343 GrXPFactory() : fClassID(kIllegalXPFClassID) {}
344
345 template <typename XPF_SUBCLASS> void initClassID() {
346 static uint32_t kClassID = GenClassID();
347 fClassID = kClassID;
348 }
349
350 uint32_t fClassID;
351
egdaniel378092f2014-12-03 10:40:13 -0800352private:
bsalomon4b91f762015-05-19 09:29:46 -0700353 virtual GrXferProcessor* onCreateXferProcessor(const GrCaps& caps,
ethannicholasde4166a2015-11-30 08:57:38 -0800354 const GrPipelineOptimizations& optimizations,
cdalton86ae0a92015-06-08 15:11:04 -0700355 bool hasMixedSamples,
bsalomon6a44c6a2015-05-26 09:49:05 -0700356 const DstTexture*) const = 0;
ethannicholas22793252016-01-30 09:59:10 -0800357
358 virtual bool onIsEqual(const GrXPFactory&) const = 0;
359
cdalton3ccf2e72016-05-06 09:41:16 -0700360 bool willReadDstColor(const GrCaps&, const GrPipelineOptimizations&) const;
bsalomon50785a32015-02-06 07:02:37 -0800361 /**
362 * Returns true if the XP generated by this factory will explicitly read dst in the fragment
363 * shader.
364 */
cdalton3ccf2e72016-05-06 09:41:16 -0700365 virtual bool onWillReadDstColor(const GrCaps&, const GrPipelineOptimizations&) const = 0;
egdaniel915187b2014-12-05 12:58:28 -0800366
367 static uint32_t GenClassID() {
368 // fCurrXPFactoryID has been initialized to kIllegalXPFactoryID. The
369 // atomic inc returns the old value not the incremented value. So we add
370 // 1 to the returned value.
371 uint32_t id = static_cast<uint32_t>(sk_atomic_inc(&gCurrXPFClassID)) + 1;
372 if (!id) {
373 SkFAIL("This should never wrap as it should only be called once for each GrXPFactory "
374 "subclass.");
375 }
376 return id;
377 }
378
379 enum {
380 kIllegalXPFClassID = 0,
381 };
382 static int32_t gCurrXPFClassID;
383
egdaniel378092f2014-12-03 10:40:13 -0800384 typedef GrProgramElement INHERITED;
385};
386
387#endif
388