1 
2 /*
3  * Copyright 2011 Google Inc.
4  *
5  * Use of this source code is governed by a BSD-style license that can be
6  * found in the LICENSE file.
7  */
8 
9 
10 #ifndef GrPaint_DEFINED
11 #define GrPaint_DEFINED
12 
13 #include "GrColor.h"
14 #include "GrColorSpaceXform.h"
15 #include "GrFragmentProcessor.h"
16 #include "SkBlendMode.h"
17 #include "SkRefCnt.h"
18 #include "SkRegion.h"
19 #include "SkTLazy.h"
20 
21 class GrTextureProxy;
22 class GrXPFactory;
23 
24 /**
25  * The paint describes how color and coverage are computed at each pixel by GrContext draw
26  * functions and the how color is blended with the destination pixel.
27  *
28  * The paint allows installation of custom color and coverage stages. New types of stages are
29  * created by subclassing GrProcessor.
30  *
31  * The primitive color computation starts with the color specified by setColor(). This color is the
32  * input to the first color stage. Each color stage feeds its output to the next color stage.
33  *
34  * Fractional pixel coverage follows a similar flow. The GrGeometryProcessor (specified elsewhere)
35  * provides the initial coverage which is passed to the first coverage fragment processor, which
36  * feeds its output to next coverage fragment processor.
37  *
38  * setXPFactory is used to control blending between the output color and dest. It also implements
39  * the application of fractional coverage from the coverage pipeline.
40  */
41 class GrPaint {
42 public:
43     GrPaint() = default;
44     explicit GrPaint(const GrPaint&) = default;
45     ~GrPaint() = default;
46 
47     /**
48      * The initial color of the drawn primitive. Defaults to solid white.
49      */
setColor4f(const GrColor4f & color)50     void setColor4f(const GrColor4f& color) { fColor = color; }
getColor4f()51     const GrColor4f& getColor4f() const { return fColor; }
52 
53     /**
54      * Legacy getter, until all code handles 4f directly.
55      */
getColor()56     GrColor getColor() const { return fColor.toGrColor(); }
57 
58     /**
59      * Should shader output conversion from linear to sRGB be disabled.
60      * Only relevant if the destination is sRGB. Defaults to false.
61      */
setDisableOutputConversionToSRGB(bool srgb)62     void setDisableOutputConversionToSRGB(bool srgb) { fDisableOutputConversionToSRGB = srgb; }
getDisableOutputConversionToSRGB()63     bool getDisableOutputConversionToSRGB() const { return fDisableOutputConversionToSRGB; }
64 
65     /**
66      * Should sRGB inputs be allowed to perform sRGB to linear conversion. With this flag
67      * set to false, sRGB textures will be treated as linear (including filtering).
68      */
setAllowSRGBInputs(bool allowSRGBInputs)69     void setAllowSRGBInputs(bool allowSRGBInputs) { fAllowSRGBInputs = allowSRGBInputs; }
getAllowSRGBInputs()70     bool getAllowSRGBInputs() const { return fAllowSRGBInputs; }
71 
72     /**
73      * Does one of the fragment processors need a field of distance vectors to the nearest edge?
74      */
usesDistanceVectorField()75     bool usesDistanceVectorField() const { return fUsesDistanceVectorField; }
76 
77     /**
78      * Should rendering be gamma-correct, end-to-end. Causes sRGB render targets to behave
79      * as such (with linear blending), and sRGB inputs to be filtered and decoded correctly.
80      */
setGammaCorrect(bool gammaCorrect)81     void setGammaCorrect(bool gammaCorrect) {
82         setDisableOutputConversionToSRGB(!gammaCorrect);
83         setAllowSRGBInputs(gammaCorrect);
84     }
85 
setXPFactory(const GrXPFactory * xpFactory)86     void setXPFactory(const GrXPFactory* xpFactory) { fXPFactory = xpFactory; }
87 
88     void setPorterDuffXPFactory(SkBlendMode mode);
89 
90     void setCoverageSetOpXPFactory(SkRegion::Op, bool invertCoverage = false);
91 
92     /**
93      * Appends an additional color processor to the color computation.
94      */
addColorFragmentProcessor(sk_sp<GrFragmentProcessor> fp)95     void addColorFragmentProcessor(sk_sp<GrFragmentProcessor> fp) {
96         SkASSERT(fp);
97         fUsesDistanceVectorField |= fp->usesDistanceVectorField();
98         fColorFragmentProcessors.push_back(std::move(fp));
99     }
100 
101     /**
102      * Appends an additional coverage processor to the coverage computation.
103      */
addCoverageFragmentProcessor(sk_sp<GrFragmentProcessor> fp)104     void addCoverageFragmentProcessor(sk_sp<GrFragmentProcessor> fp) {
105         SkASSERT(fp);
106         fUsesDistanceVectorField |= fp->usesDistanceVectorField();
107         fCoverageFragmentProcessors.push_back(std::move(fp));
108     }
109 
110     /**
111      * Helpers for adding color or coverage effects that sample a texture. The matrix is applied
112      * to the src space position to compute texture coordinates.
113      */
114     void addColorTextureProcessor(GrResourceProvider*, sk_sp<GrTextureProxy>,
115                                   sk_sp<GrColorSpaceXform>, const SkMatrix&);
116     void addColorTextureProcessor(GrResourceProvider*, sk_sp<GrTextureProxy>,
117                                   sk_sp<GrColorSpaceXform>, const SkMatrix&,
118                                   const GrSamplerParams&);
119 
120     void addCoverageTextureProcessor(GrResourceProvider*, sk_sp<GrTextureProxy>, const SkMatrix&);
121     void addCoverageTextureProcessor(GrResourceProvider*, sk_sp<GrTextureProxy>,
122                                      const SkMatrix&, const GrSamplerParams&);
123 
numColorFragmentProcessors()124     int numColorFragmentProcessors() const { return fColorFragmentProcessors.count(); }
numCoverageFragmentProcessors()125     int numCoverageFragmentProcessors() const { return fCoverageFragmentProcessors.count(); }
numTotalFragmentProcessors()126     int numTotalFragmentProcessors() const { return this->numColorFragmentProcessors() +
127                                               this->numCoverageFragmentProcessors(); }
128 
getXPFactory()129     const GrXPFactory* getXPFactory() const { return fXPFactory; }
130 
getColorFragmentProcessor(int i)131     GrFragmentProcessor* getColorFragmentProcessor(int i) const {
132         return fColorFragmentProcessors[i].get();
133     }
getCoverageFragmentProcessor(int i)134     GrFragmentProcessor* getCoverageFragmentProcessor(int i) const {
135         return fCoverageFragmentProcessors[i].get();
136     }
137 
138     /**
139      * Returns true if the paint's output color will be constant after blending. If the result is
140      * true, constantColor will be updated to contain the constant color. Note that we can conflate
141      * coverage and color, so the actual values written to pixels with partial coverage may still
142      * not seem constant, even if this function returns true.
143      */
144     bool isConstantBlendedColor(GrColor* constantColor) const;
145 
146 private:
147     template <bool> class MoveOrImpl;
148 
149 public:
150     /**
151      * A temporary instance of this class can be used to select between moving an existing paint or
152      * a temporary copy of an existing paint into a call site. MoveOrClone(paint, false) is a rvalue
153      * reference to paint while MoveOrClone(paint, true) is a rvalue reference to a copy of paint.
154      */
155     using MoveOrClone = MoveOrImpl<true>;
156 
157     /**
158      * A temporary instance of this class can be used to select between moving an existing or a
159      * newly default constructed paint into a call site. MoveOrNew(paint, false) is a rvalue
160      * reference to paint while MoveOrNew(paint, true) is a rvalue reference to a default paint.
161      */
162     using MoveOrNew = MoveOrImpl<false>;
163 
164 private:
165     GrPaint& operator=(const GrPaint&) = delete;
166 
167     friend class GrProcessorSet;
168 
169     const GrXPFactory* fXPFactory = nullptr;
170     SkSTArray<4, sk_sp<GrFragmentProcessor>>  fColorFragmentProcessors;
171     SkSTArray<2, sk_sp<GrFragmentProcessor>>  fCoverageFragmentProcessors;
172     bool fDisableOutputConversionToSRGB = false;
173     bool fAllowSRGBInputs = false;
174     bool fUsesDistanceVectorField = false;
175     GrColor4f fColor = GrColor4f::OpaqueWhite();
176 };
177 
178 /** This is the implementation of MoveOrCopy and MoveOrNew. */
179 template <bool COPY_IF_NEW>
180 class GrPaint::MoveOrImpl {
181 public:
MoveOrImpl(GrPaint & paint,bool newPaint)182     MoveOrImpl(GrPaint& paint, bool newPaint) {
183         if (newPaint) {
184             if (COPY_IF_NEW) {
185                 fStorage.init(paint);
186             } else {
187                 fStorage.init();
188             };
189             fPaint = fStorage.get();
190         } else {
191             fPaint = &paint;
192         }
193     }
194 
195     operator GrPaint&&() && { return std::move(*fPaint); }
paint()196     GrPaint& paint() { return *fPaint; }
197 
198 private:
199     SkTLazy<GrPaint> fStorage;
200     GrPaint* fPaint;
201 };
202 
203 #endif
204