Line data Source code
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 "GrBlend.h"
12 : #include "GrColor.h"
13 : #include "GrNonAtomicRef.h"
14 : #include "GrProcessor.h"
15 : #include "GrProcessorSet.h"
16 : #include "GrTexture.h"
17 : #include "GrTypes.h"
18 :
19 : class GrShaderCaps;
20 : class GrGLSLXferProcessor;
21 :
22 : /**
23 : * Barriers for blending. When a shader reads the dst directly, an Xfer barrier is sometimes
24 : * required after a pixel has been written, before it can be safely read again.
25 : */
26 : enum GrXferBarrierType {
27 : kNone_GrXferBarrierType = 0, //<! No barrier is required
28 : kTexture_GrXferBarrierType, //<! Required when a shader reads and renders to the same texture.
29 : kBlend_GrXferBarrierType, //<! Required by certain blend extensions.
30 : };
31 : /** Should be able to treat kNone as false in boolean expressions */
32 : GR_STATIC_ASSERT(SkToBool(kNone_GrXferBarrierType) == false);
33 :
34 : /**
35 : * GrXferProcessor is responsible for implementing the xfer mode that blends the src color and dst
36 : * color, and for applying any coverage. It does this by emitting fragment shader code and
37 : * controlling the fixed-function blend state. When dual-source blending is available, it may also
38 : * write a seconday fragment shader output color. GrXferProcessor has two modes of operation:
39 : *
40 : * Dst read: When allowed by the backend API, or when supplied a texture of the destination, the
41 : * GrXferProcessor may read the destination color. While operating in this mode, the subclass only
42 : * provides shader code that blends the src and dst colors, and the base class applies coverage.
43 : *
44 : * No dst read: When not performing a dst read, the subclass is given full control of the fixed-
45 : * function blend state and/or secondary output, and is responsible to apply coverage on its own.
46 : *
47 : * A GrXferProcessor is never installed directly into our draw state, but instead is created from a
48 : * GrXPFactory once we have finalized the state of our draw.
49 : */
50 0 : class GrXferProcessor : public GrProcessor, public GrNonAtomicRef<GrXferProcessor> {
51 : public:
52 : /**
53 : * A texture that contains the dst pixel values and an integer coord offset from device space
54 : * to the space of the texture. Depending on GPU capabilities a DstTexture may be used by a
55 : * GrXferProcessor for blending in the fragment shader.
56 : */
57 0 : class DstTexture {
58 : public:
59 0 : DstTexture() { fOffset.set(0, 0); }
60 :
61 0 : DstTexture(const DstTexture& other) {
62 0 : *this = other;
63 0 : }
64 :
65 : DstTexture(GrTexture* texture, const SkIPoint& offset)
66 : : fTexture(SkSafeRef(texture)), fOffset(texture ? offset : SkIPoint{0, 0}) {}
67 :
68 0 : DstTexture& operator=(const DstTexture& other) {
69 0 : fTexture = other.fTexture;
70 0 : fOffset = other.fOffset;
71 0 : return *this;
72 : }
73 :
74 0 : bool operator==(const DstTexture& that) const {
75 0 : return fTexture == that.fTexture && fOffset == that.fOffset;
76 : }
77 0 : bool operator!=(const DstTexture& that) const { return !(*this == that); }
78 :
79 0 : const SkIPoint& offset() const { return fOffset; }
80 :
81 0 : void setOffset(const SkIPoint& offset) { fOffset = offset; }
82 0 : void setOffset(int ox, int oy) { fOffset.set(ox, oy); }
83 :
84 0 : GrTexture* texture() const { return fTexture.get(); }
85 :
86 0 : void setTexture(sk_sp<GrTexture> texture) {
87 0 : fTexture = std::move(texture);
88 0 : if (!fTexture) {
89 0 : fOffset = {0, 0};
90 : }
91 0 : }
92 :
93 : private:
94 : sk_sp<GrTexture> fTexture;
95 : SkIPoint fOffset;
96 : };
97 :
98 : /**
99 : * Sets a unique key on the GrProcessorKeyBuilder calls onGetGLSLProcessorKey(...) to get the
100 : * specific subclass's key.
101 : */
102 : void getGLSLProcessorKey(const GrShaderCaps&,
103 : GrProcessorKeyBuilder*,
104 : const GrSurfaceOrigin* originIfDstTexture) const;
105 :
106 : /** Returns a new instance of the appropriate *GL* implementation class
107 : for the given GrXferProcessor; caller is responsible for deleting
108 : the object. */
109 : virtual GrGLSLXferProcessor* createGLSLInstance() const = 0;
110 :
111 : /**
112 : * Returns the barrier type, if any, that this XP will require. Note that the possibility
113 : * that a kTexture type barrier is required is handled by the GrPipeline and need not be
114 : * considered by subclass overrides of this function.
115 : */
116 0 : virtual GrXferBarrierType xferBarrierType(const GrCaps& caps) const {
117 0 : return kNone_GrXferBarrierType;
118 : }
119 :
120 : struct BlendInfo {
121 0 : void reset() {
122 0 : fEquation = kAdd_GrBlendEquation;
123 0 : fSrcBlend = kOne_GrBlendCoeff;
124 0 : fDstBlend = kZero_GrBlendCoeff;
125 0 : fBlendConstant = 0;
126 0 : fWriteColor = true;
127 0 : }
128 :
129 : SkDEBUGCODE(SkString dump() const;)
130 :
131 : GrBlendEquation fEquation;
132 : GrBlendCoeff fSrcBlend;
133 : GrBlendCoeff fDstBlend;
134 : GrColor fBlendConstant;
135 : bool fWriteColor;
136 : };
137 :
138 : void getBlendInfo(BlendInfo* blendInfo) const;
139 :
140 0 : bool willReadDstColor() const { return fWillReadDstColor; }
141 :
142 : /**
143 : * If we are performing a dst read, returns whether the base class will use mixed samples to
144 : * antialias the shader's final output. If not doing a dst read, the subclass is responsible
145 : * for antialiasing and this returns false.
146 : */
147 0 : bool dstReadUsesMixedSamples() const { return fDstReadUsesMixedSamples; }
148 :
149 : /**
150 : * Returns whether or not this xferProcossor will set a secondary output to be used with dual
151 : * source blending.
152 : */
153 : bool hasSecondaryOutput() const;
154 :
155 : /** Returns true if this and other processor conservatively draw identically. It can only return
156 : true when the two processor are of the same subclass (i.e. they return the same object from
157 : from getFactory()).
158 :
159 : A return value of true from isEqual() should not be used to test whether the processor would
160 : generate the same shader code. To test for identical code generation use getGLSLProcessorKey
161 : */
162 :
163 0 : bool isEqual(const GrXferProcessor& that) const {
164 0 : if (this->classID() != that.classID()) {
165 0 : return false;
166 : }
167 0 : if (this->fWillReadDstColor != that.fWillReadDstColor) {
168 0 : return false;
169 : }
170 0 : if (this->fDstReadUsesMixedSamples != that.fDstReadUsesMixedSamples) {
171 0 : return false;
172 : }
173 0 : return this->onIsEqual(that);
174 : }
175 :
176 : protected:
177 : GrXferProcessor();
178 : GrXferProcessor(bool willReadDstColor, bool hasMixedSamples);
179 :
180 : private:
181 : /**
182 : * Sets a unique key on the GrProcessorKeyBuilder that is directly associated with this xfer
183 : * processor's GL backend implementation.
184 : */
185 : virtual void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const = 0;
186 :
187 : /**
188 : * If we are not performing a dst read, returns whether the subclass will set a secondary
189 : * output. When using dst reads, the base class controls the secondary output and this method
190 : * will not be called.
191 : */
192 0 : virtual bool onHasSecondaryOutput() const { return false; }
193 :
194 : /**
195 : * If we are not performing a dst read, retrieves the fixed-function blend state required by the
196 : * subclass. When using dst reads, the base class controls the fixed-function blend state and
197 : * this method will not be called. The BlendInfo struct comes initialized to "no blending".
198 : */
199 0 : virtual void onGetBlendInfo(BlendInfo*) const {}
200 :
201 : virtual bool onIsEqual(const GrXferProcessor&) const = 0;
202 :
203 : bool fWillReadDstColor;
204 : bool fDstReadUsesMixedSamples;
205 :
206 : typedef GrFragmentProcessor INHERITED;
207 : };
208 :
209 : /**
210 : * We install a GrXPFactory (XPF) early on in the pipeline before all the final draw information is
211 : * known (e.g. whether there is fractional pixel coverage, will coverage be 1 or 4 channel, is the
212 : * draw opaque, etc.). Once the state of the draw is finalized, we use the XPF along with all the
213 : * draw information to create a GrXferProcessor (XP) which can implement the desired blending for
214 : * the draw.
215 : *
216 : * Before the XP is created, the XPF is able to answer queries about what functionality the XPs it
217 : * creates will have. For example, can it create an XP that supports RGB coverage or will the XP
218 : * blend with the destination color.
219 : *
220 : * GrXPFactories are intended to be static immutable objects. We pass them around as raw pointers
221 : * and expect the pointers to always be valid and for the factories to be reusable and thread safe.
222 : * Equality is tested for using pointer comparison. GrXPFactory destructors must be no-ops.
223 : */
224 :
225 : // In order to construct GrXPFactory subclass instances as constexpr the subclass, and therefore
226 : // GrXPFactory, must be a literal type. One requirement is having a trivial destructor. This is ok
227 : // since these objects have no need for destructors. However, GCC and clang throw a warning when a
228 : // class has virtual functions and a non-virtual destructor. We suppress that warning here and
229 : // for the subclasses.
230 : #if defined(__GNUC__) || defined(__clang)
231 : #pragma GCC diagnostic push
232 : #pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
233 : #endif
234 : class GrXPFactory {
235 : public:
236 : typedef GrXferProcessor::DstTexture DstTexture;
237 :
238 : enum class AnalysisProperties : unsigned {
239 : kNone = 0x0,
240 : /**
241 : * The fragment shader will require the destination color.
242 : */
243 : kReadsDstInShader = 0x1,
244 : /**
245 : * The op may apply coverage as alpha and still blend correctly.
246 : */
247 : kCompatibleWithAlphaAsCoverage = 0x2,
248 : /**
249 : * The color input to the GrXferProcessor will be ignored.
250 : */
251 : kIgnoresInputColor = 0x4,
252 : /**
253 : * If set overlapping stencil and cover operations can be replaced by a combined stencil
254 : * followed by a combined cover.
255 : */
256 : kCanCombineOverlappedStencilAndCover = 0x8,
257 : /**
258 : * The destination color will be provided to the fragment processor using a texture. This is
259 : * additional information about the implementation of kReadsDstInShader.
260 : */
261 : kRequiresDstTexture = 0x10,
262 : /**
263 : * If set overlapping draws may not be combined because a barrier must be inserted between
264 : * them.
265 : */
266 : kRequiresBarrierBetweenOverlappingDraws = 0x20,
267 : };
268 : GR_DECL_BITFIELD_CLASS_OPS_FRIENDS(AnalysisProperties);
269 :
270 : static sk_sp<const GrXferProcessor> MakeXferProcessor(const GrXPFactory*,
271 : const GrProcessorAnalysisColor&,
272 : GrProcessorAnalysisCoverage,
273 : bool hasMixedSamples,
274 : const GrCaps& caps);
275 :
276 : static AnalysisProperties GetAnalysisProperties(const GrXPFactory*,
277 : const GrProcessorAnalysisColor&,
278 : const GrProcessorAnalysisCoverage&,
279 : const GrCaps&);
280 :
281 : protected:
282 : constexpr GrXPFactory() {}
283 :
284 : private:
285 : virtual sk_sp<const GrXferProcessor> makeXferProcessor(const GrProcessorAnalysisColor&,
286 : GrProcessorAnalysisCoverage,
287 : bool hasMixedSamples,
288 : const GrCaps&) const = 0;
289 :
290 : /**
291 : * Subclass analysis implementation. This should not return kNeedsDstInTexture as that will be
292 : * inferred by the base class based on kReadsDstInShader and the caps.
293 : */
294 : virtual AnalysisProperties analysisProperties(const GrProcessorAnalysisColor&,
295 : const GrProcessorAnalysisCoverage&,
296 : const GrCaps&) const = 0;
297 : };
298 : #if defined(__GNUC__) || defined(__clang)
299 : #pragma GCC diagnostic pop
300 : #endif
301 :
302 0 : GR_MAKE_BITFIELD_CLASS_OPS(GrXPFactory::AnalysisProperties);
303 :
304 : #endif
|