• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "include/gpu/GrTypes.h"
12 #include "src/gpu/GrBlend.h"
13 #include "src/gpu/GrNonAtomicRef.h"
14 #include "src/gpu/GrProcessor.h"
15 #include "src/gpu/GrProcessorAnalysis.h"
16 #include "src/gpu/GrSurfaceProxyView.h"
17 #include "src/gpu/glsl/GrGLSLUniformHandler.h"
18 
19 class GrGLSLXPFragmentBuilder;
20 class GrGLSLProgramDataManager;
21 class GrShaderCaps;
22 
23 /**
24  * 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  */
27 enum GrXferBarrierType {
28     kNone_GrXferBarrierType = 0, //<! No barrier is required
29     kTexture_GrXferBarrierType,  //<! Required when a shader reads and renders to the same texture.
30     kBlend_GrXferBarrierType,    //<! Required by certain blend extensions.
31 };
32 /** Should be able to treat kNone as false in boolean expressions */
33 static_assert(SkToBool(kNone_GrXferBarrierType) == false);
34 
35 // Flag version of the above enum.
36 enum class GrXferBarrierFlags {
37     kNone    = 0,
38     kTexture = 1 << 0,
39     kBlend   = 1 << 1,
40 };
41 
GR_MAKE_BITFIELD_CLASS_OPS(GrXferBarrierFlags)42 GR_MAKE_BITFIELD_CLASS_OPS(GrXferBarrierFlags)
43 
44 /**
45  * GrXferProcessor is responsible for implementing the xfer mode that blends the src color and dst
46  * color, and for applying any coverage. It does this by emitting fragment shader code and
47  * controlling the fixed-function blend state. When dual-source blending is available, it may also
48  * write a seconday fragment shader output color. GrXferProcessor has two modes of operation:
49  *
50  * Dst read: When allowed by the backend API, or when supplied a texture of the destination, the
51  * GrXferProcessor may read the destination color. While operating in this mode, the subclass only
52  * provides shader code that blends the src and dst colors, and the base class applies coverage.
53  *
54  * No dst read: When not performing a dst read, the subclass is given full control of the fixed-
55  * function blend state and/or secondary output, and is responsible to apply coverage on its own.
56  *
57  * A GrXferProcessor is never installed directly into our draw state, but instead is created from a
58  * GrXPFactory once we have finalized the state of our draw.
59  */
60 class GrXferProcessor : public GrProcessor, public GrNonAtomicRef<GrXferProcessor> {
61 public:
62     /**
63      * Every GrXferProcessor must be capable of creating a subclass of ProgramImpl. The ProgramImpl
64      * emits the shader code combines determines the fragment shader output(s) from the color and
65      * coverage FP outputs, is attached to the generated backend API pipeline/program, and used to
66      * extract uniform data from GrXferProcessor instances.
67      */
68     class ProgramImpl;
69 
70     /**
71      * Adds a key on the GrProcessorKeyBuilder calls onAddToKey(...) to get the specific subclass's
72      * key.
73      */
74     void addToKey(const GrShaderCaps&,
75                   GrProcessorKeyBuilder*,
76                   const GrSurfaceOrigin* originIfDstTexture,
77                   bool usesInputAttachmentForDstRead) const;
78 
79     /** Returns a new instance of the appropriate *GL* implementation class
80         for the given GrXferProcessor; caller is responsible for deleting
81         the object. */
82     virtual std::unique_ptr<ProgramImpl> makeProgramImpl() const = 0;
83 
84     /**
85      * Returns the barrier type, if any, that this XP will require. Note that the possibility
86      * that a kTexture type barrier is required is handled by the GrPipeline and need not be
87      * considered by subclass overrides of this function.
88      */
89     virtual GrXferBarrierType xferBarrierType(const GrCaps& caps) const {
90         return kNone_GrXferBarrierType;
91     }
92 
93     struct BlendInfo {
94         SkDEBUGCODE(SkString dump() const;)
95 
96         GrBlendEquation fEquation = kAdd_GrBlendEquation;
97         GrBlendCoeff    fSrcBlend = kOne_GrBlendCoeff;
98         GrBlendCoeff    fDstBlend = kZero_GrBlendCoeff;
99         SkPMColor4f     fBlendConstant = SK_PMColor4fTRANSPARENT;
100         bool            fWriteColor = true;
101     };
102 
103     inline BlendInfo getBlendInfo() const {
104         BlendInfo blendInfo;
105         if (!this->willReadDstColor()) {
106             this->onGetBlendInfo(&blendInfo);
107         }
108         return blendInfo;
109     }
110 
111     bool willReadDstColor() const { return fWillReadDstColor; }
112 
113     /**
114      * Returns whether or not this xferProcossor will set a secondary output to be used with dual
115      * source blending.
116      */
117     bool hasSecondaryOutput() const;
118 
119     bool isLCD() const { return fIsLCD; }
120 
121     /** Returns true if this and other processor conservatively draw identically. It can only return
122         true when the two processor are of the same subclass (i.e. they return the same object from
123         from getFactory()).
124 
125         A return value of true from isEqual() should not be used to test whether the processor would
126         generate the same shader code. To test for identical code generation use addToKey.
127       */
128 
129     bool isEqual(const GrXferProcessor& that) const {
130         if (this->classID() != that.classID()) {
131             return false;
132         }
133         if (this->fWillReadDstColor != that.fWillReadDstColor) {
134             return false;
135         }
136         if (fIsLCD != that.fIsLCD) {
137             return false;
138         }
139         return this->onIsEqual(that);
140     }
141 
142 protected:
143     GrXferProcessor(ClassID classID);
144     GrXferProcessor(ClassID classID, bool willReadDstColor, GrProcessorAnalysisCoverage);
145 
146 private:
147     /**
148      * Adds a key on the GrProcessorKeyBuilder that reflects any variety in the code that may be
149      * emitted by the xfer processor subclass.
150      */
151     virtual void onAddToKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const = 0;
152 
153     /**
154      * If we are not performing a dst read, returns whether the subclass will set a secondary
155      * output. When using dst reads, the base class controls the secondary output and this method
156      * will not be called.
157      */
158     virtual bool onHasSecondaryOutput() const { return false; }
159 
160     /**
161      * If we are not performing a dst read, retrieves the fixed-function blend state required by the
162      * subclass. When using dst reads, the base class controls the fixed-function blend state and
163      * this method will not be called. The BlendInfo struct comes initialized to "no blending".
164      */
165     virtual void onGetBlendInfo(BlendInfo*) const {}
166 
167     virtual bool onIsEqual(const GrXferProcessor&) const = 0;
168 
169     bool fWillReadDstColor;
170     bool fIsLCD;
171 
172     using INHERITED = GrProcessor;
173 };
174 
175 /**
176  * We install a GrXPFactory (XPF) early on in the pipeline before all the final draw information is
177  * known (e.g. whether there is fractional pixel coverage, will coverage be 1 or 4 channel, is the
178  * draw opaque, etc.). Once the state of the draw is finalized, we use the XPF along with all the
179  * draw information to create a GrXferProcessor (XP) which can implement the desired blending for
180  * the draw.
181  *
182  * Before the XP is created, the XPF is able to answer queries about what functionality the XPs it
183  * creates will have. For example, can it create an XP that supports RGB coverage or will the XP
184  * blend with the destination color.
185  *
186  * GrXPFactories are intended to be static immutable objects. We pass them around as raw pointers
187  * and expect the pointers to always be valid and for the factories to be reusable and thread safe.
188  * Equality is tested for using pointer comparison. GrXPFactory destructors must be no-ops.
189  */
190 
191 // In order to construct GrXPFactory subclass instances as constexpr the subclass, and therefore
192 // GrXPFactory, must be a literal type. One requirement is having a trivial destructor. This is ok
193 // since these objects have no need for destructors. However, GCC and clang throw a warning when a
194 // class has virtual functions and a non-virtual destructor. We suppress that warning here and
195 // for the subclasses.
196 #if defined(__GNUC__)
197 #pragma GCC diagnostic push
198 #pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
199 #endif
200 #if defined(__clang__)
201 #pragma clang diagnostic push
202 #pragma clang diagnostic ignored "-Wnon-virtual-dtor"
203 #endif
204 class GrXPFactory {
205 public:
206     enum class AnalysisProperties : unsigned {
207         kNone = 0x0,
208         /**
209          * The fragment shader will require the destination color.
210          */
211         kReadsDstInShader = 0x1,
212         /**
213          * The op may apply coverage as alpha and still blend correctly.
214          */
215         kCompatibleWithCoverageAsAlpha = 0x2,
216         /**
217          * The color input to the GrXferProcessor will be ignored.
218          */
219         kIgnoresInputColor = 0x4,
220         /**
221          * The destination color will be provided to the fragment processor using a texture. This is
222          * additional information about the implementation of kReadsDstInShader.
223          */
224         kRequiresDstTexture = 0x10,
225         /**
226          * If set, each pixel can only be touched once during a draw (e.g., because we have a dst
227          * texture or because we need an xfer barrier).
228          */
229         kRequiresNonOverlappingDraws = 0x20,
230         /**
231          * If set the draw will use fixed function non coherent advanced blends.
232          */
233         kUsesNonCoherentHWBlending = 0x40,
234         /**
235          * If set, the existing dst value has no effect on the final output.
236          */
237         kUnaffectedByDstValue = 0x80,
238     };
239     GR_DECL_BITFIELD_CLASS_OPS_FRIENDS(AnalysisProperties);
240 
241     static sk_sp<const GrXferProcessor> MakeXferProcessor(const GrXPFactory*,
242                                                           const GrProcessorAnalysisColor&,
243                                                           GrProcessorAnalysisCoverage,
244                                                           const GrCaps& caps,
245                                                           GrClampType);
246 
247     static AnalysisProperties GetAnalysisProperties(const GrXPFactory*,
248                                                     const GrProcessorAnalysisColor&,
249                                                     const GrProcessorAnalysisCoverage&,
250                                                     const GrCaps&,
251                                                     GrClampType);
252 
253 protected:
GrXPFactory()254     constexpr GrXPFactory() {}
255 
256 private:
257     virtual sk_sp<const GrXferProcessor> makeXferProcessor(const GrProcessorAnalysisColor&,
258                                                            GrProcessorAnalysisCoverage,
259                                                            const GrCaps&,
260                                                            GrClampType) const = 0;
261 
262     /**
263      * Subclass analysis implementation. This should not return kNeedsDstInTexture as that will be
264      * inferred by the base class based on kReadsDstInShader and the caps.
265      */
266     virtual AnalysisProperties analysisProperties(const GrProcessorAnalysisColor&,
267                                                   const GrProcessorAnalysisCoverage&,
268                                                   const GrCaps&,
269                                                   GrClampType) const = 0;
270 };
271 #if defined(__GNUC__)
272 #pragma GCC diagnostic pop
273 #endif
274 #if defined(__clang__)
275 #pragma clang diagnostic pop
276 #endif
277 
GR_MAKE_BITFIELD_CLASS_OPS(GrXPFactory::AnalysisProperties)278 GR_MAKE_BITFIELD_CLASS_OPS(GrXPFactory::AnalysisProperties)
279 
280 //////////////////////////////////////////////////////////////////////////////
281 
282 class GrXferProcessor::ProgramImpl {
283 public:
284     virtual ~ProgramImpl() = default;
285 
286     using SamplerHandle = GrGLSLUniformHandler::SamplerHandle;
287 
288     struct EmitArgs {
289         EmitArgs(GrGLSLXPFragmentBuilder* fragBuilder,
290                  GrGLSLUniformHandler* uniformHandler,
291                  const GrShaderCaps* caps,
292                  const GrXferProcessor& xp,
293                  const char* inputColor,
294                  const char* inputCoverage,
295                  const char* outputPrimary,
296                  const char* outputSecondary,
297                  const SamplerHandle dstTextureSamplerHandle,
298                  GrSurfaceOrigin dstTextureOrigin,
299                  const GrSwizzle& writeSwizzle)
300                 : fXPFragBuilder(fragBuilder)
301                 , fUniformHandler(uniformHandler)
302                 , fShaderCaps(caps)
303                 , fXP(xp)
304                 , fInputColor(inputColor ? inputColor : "half4(1.0)")
305                 , fInputCoverage(inputCoverage)
306                 , fOutputPrimary(outputPrimary)
307                 , fOutputSecondary(outputSecondary)
308                 , fDstTextureSamplerHandle(dstTextureSamplerHandle)
309                 , fDstTextureOrigin(dstTextureOrigin)
310                 , fWriteSwizzle(writeSwizzle) {}
311         GrGLSLXPFragmentBuilder* fXPFragBuilder;
312         GrGLSLUniformHandler* fUniformHandler;
313         const GrShaderCaps* fShaderCaps;
314         const GrXferProcessor& fXP;
315         const char* fInputColor;
316         const char* fInputCoverage;
317         const char* fOutputPrimary;
318         const char* fOutputSecondary;
319         const SamplerHandle fDstTextureSamplerHandle;
320         GrSurfaceOrigin fDstTextureOrigin;
321         GrSwizzle fWriteSwizzle;
322     };
323     /**
324      * This is similar to emitCode() in the base class, except it takes a full shader builder.
325      * This allows the effect subclass to emit vertex code.
326      */
327     void emitCode(const EmitArgs&);
328 
329     /** A ProgramImpl instance can be reused with any GrXferProcessor that produces the same key.
330         This function reads data from a GrXferProcessor and uploads any uniform variables required
331         by the shaders created in emitCode(). The GrXferProcessor parameter is guaranteed to be of
332         the same type that created this ProgramImpl and to have an identical processor key as the
333         one that created this ProgramImpl. This function calls onSetData on the subclass of
334         ProgramImpl.
335      */
336     void setData(const GrGLSLProgramDataManager& pdm, const GrXferProcessor& xp);
337 
338 protected:
339     ProgramImpl() = default;
340 
341     static void DefaultCoverageModulation(GrGLSLXPFragmentBuilder* fragBuilder,
342                                           const char* srcCoverage,
343                                           const char* dstColor,
344                                           const char* outColor,
345                                           const char* outColorSecondary,
346                                           const GrXferProcessor& proc);
347 
348 private:
349     /**
350      * Called by emitCode() when the XP will not be performing a dst read. This method is
351      * responsible for both blending and coverage. A subclass only needs to implement this method if
352      * it can construct a GrXferProcessor that will not read the dst color.
353      */
354     virtual void emitOutputsForBlendState(const EmitArgs&) {
355         SK_ABORT("emitOutputsForBlendState not implemented.");
356     }
357 
358     /**
359      * Called by emitCode() when the XP will perform a dst read. This method only needs to supply
360      * the blending logic. The base class applies coverage. A subclass only needs to implement this
361      * method if it can construct a GrXferProcessor that reads the dst color.
362      */
363     virtual void emitBlendCodeForDstRead(GrGLSLXPFragmentBuilder*,
364                                          GrGLSLUniformHandler*,
365                                          const char* srcColor,
366                                          const char* srcCoverage,
367                                          const char* dstColor,
368                                          const char* outColor,
369                                          const char* outColorSecondary,
370                                          const GrXferProcessor&) {
371         SK_ABORT("emitBlendCodeForDstRead not implemented.");
372     }
373 
374     virtual void emitWriteSwizzle(GrGLSLXPFragmentBuilder*,
375                                   const GrSwizzle&,
376                                   const char* outColor,
377                                   const char* outColorSecondary) const;
378 
379     virtual void onSetData(const GrGLSLProgramDataManager&, const GrXferProcessor&) {}
380 };
381 
382 #endif
383