xref: /third_party/skia/src/gpu/GrXferProcessor.h (revision cb93a386)
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
19class GrGLSLXPFragmentBuilder;
20class GrGLSLProgramDataManager;
21class 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 */
27enum 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 */
33static_assert(SkToBool(kNone_GrXferBarrierType) == false);
34
35// Flag version of the above enum.
36enum class GrXferBarrierFlags {
37    kNone    = 0,
38    kTexture = 1 << 0,
39    kBlend   = 1 << 1,
40};
41
42GR_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 */
60class GrXferProcessor : public GrProcessor, public GrNonAtomicRef<GrXferProcessor> {
61public:
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
142protected:
143    GrXferProcessor(ClassID classID);
144    GrXferProcessor(ClassID classID, bool willReadDstColor, GrProcessorAnalysisCoverage);
145
146private:
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
204class GrXPFactory {
205public:
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
253protected:
254    constexpr GrXPFactory() {}
255
256private:
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
278GR_MAKE_BITFIELD_CLASS_OPS(GrXPFactory::AnalysisProperties)
279
280//////////////////////////////////////////////////////////////////////////////
281
282class GrXferProcessor::ProgramImpl {
283public:
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
338protected:
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
348private:
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