OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2016 Google Inc. | 2 * Copyright 2016 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "SkRRectsGaussianEdgeShader.h" | 8 #include "SkRRectsGaussianEdgeShader.h" |
9 #include "SkReadBuffer.h" | 9 #include "SkReadBuffer.h" |
10 #include "SkWriteBuffer.h" | 10 #include "SkWriteBuffer.h" |
11 | 11 |
12 /** \class SkRRectsGaussianEdgeShaderImpl | 12 /** \class SkRRectsGaussianEdgeShaderImpl |
13 * This shader applies a gaussian edge to the intersection of two round rects. | 13 * This shader applies a gaussian edge to the intersection of two round rects. |
14 * The round rects must have the same radii at each corner and the x&y radii | 14 * The round rects must have the same radii at each corner and the x&y radii |
15 * must also be equal. | 15 * must also be equal. |
16 */ | 16 */ |
17 class SkRRectsGaussianEdgeShaderImpl : public SkShader { | 17 class SkRRectsGaussianEdgeShaderImpl : public SkShader { |
18 public: | 18 public: |
19 SkRRectsGaussianEdgeShaderImpl(const SkRRect& first, const SkRRect& second, | 19 SkRRectsGaussianEdgeShaderImpl(const SkRRect& first, const SkRRect& second,
SkScalar radius) |
20 SkScalar radius, SkScalar pad) | |
21 : fFirst(first) | 20 : fFirst(first) |
22 , fSecond(second) | 21 , fSecond(second) |
23 , fRadius(radius) | 22 , fRadius(radius) { |
24 , fPad(pad) { | |
25 } | 23 } |
26 | 24 |
27 bool isOpaque() const override { return false; } | 25 bool isOpaque() const override { return false; } |
28 | 26 |
29 #if SK_SUPPORT_GPU | 27 #if SK_SUPPORT_GPU |
30 sk_sp<GrFragmentProcessor> asFragmentProcessor(const AsFPArgs&) const overri
de; | 28 sk_sp<GrFragmentProcessor> asFragmentProcessor(const AsFPArgs&) const overri
de; |
31 #endif | 29 #endif |
32 | 30 |
33 class GaussianEdgeShaderContext : public SkShader::Context { | 31 class GaussianEdgeShaderContext : public SkShader::Context { |
34 public: | 32 public: |
(...skipping 16 matching lines...) Expand all Loading... |
51 | 49 |
52 protected: | 50 protected: |
53 void flatten(SkWriteBuffer&) const override; | 51 void flatten(SkWriteBuffer&) const override; |
54 size_t onContextSize(const ContextRec&) const override; | 52 size_t onContextSize(const ContextRec&) const override; |
55 Context* onCreateContext(const ContextRec&, void*) const override; | 53 Context* onCreateContext(const ContextRec&, void*) const override; |
56 | 54 |
57 private: | 55 private: |
58 SkRRect fFirst; | 56 SkRRect fFirst; |
59 SkRRect fSecond; | 57 SkRRect fSecond; |
60 SkScalar fRadius; | 58 SkScalar fRadius; |
61 SkScalar fPad; | |
62 | 59 |
63 friend class SkRRectsGaussianEdgeShader; // for serialization registration s
ystem | 60 friend class SkRRectsGaussianEdgeShader; // for serialization registration s
ystem |
64 | 61 |
65 typedef SkShader INHERITED; | 62 typedef SkShader INHERITED; |
66 }; | 63 }; |
67 | 64 |
68 //////////////////////////////////////////////////////////////////////////// | 65 //////////////////////////////////////////////////////////////////////////// |
69 | 66 |
70 #if SK_SUPPORT_GPU | 67 #if SK_SUPPORT_GPU |
71 | 68 |
72 #include "GrCoordTransform.h" | 69 #include "GrCoordTransform.h" |
73 #include "GrFragmentProcessor.h" | 70 #include "GrFragmentProcessor.h" |
74 #include "GrInvariantOutput.h" | 71 #include "GrInvariantOutput.h" |
75 #include "glsl/GrGLSLFragmentProcessor.h" | 72 #include "glsl/GrGLSLFragmentProcessor.h" |
76 #include "glsl/GrGLSLFragmentShaderBuilder.h" | 73 #include "glsl/GrGLSLFragmentShaderBuilder.h" |
77 #include "glsl/GrGLSLProgramDataManager.h" | 74 #include "glsl/GrGLSLProgramDataManager.h" |
78 #include "glsl/GrGLSLUniformHandler.h" | 75 #include "glsl/GrGLSLUniformHandler.h" |
79 #include "SkGr.h" | 76 #include "SkGr.h" |
80 #include "SkGrPriv.h" | 77 #include "SkGrPriv.h" |
81 | 78 |
82 class RRectsGaussianEdgeFP : public GrFragmentProcessor { | 79 class RRectsGaussianEdgeFP : public GrFragmentProcessor { |
83 public: | 80 public: |
84 enum Mode { | 81 enum Mode { |
85 kCircle_Mode, | 82 kCircle_Mode, |
86 kRect_Mode, | 83 kRect_Mode, |
87 kSimpleCircular_Mode, | 84 kSimpleCircular_Mode, |
88 }; | 85 }; |
89 | 86 |
90 RRectsGaussianEdgeFP(const SkRRect& first, const SkRRect& second, | 87 RRectsGaussianEdgeFP(const SkRRect& first, const SkRRect& second, SkScalar r
adius) |
91 SkScalar radius, SkScalar pad) | |
92 : fFirst(first) | 88 : fFirst(first) |
93 , fSecond(second) | 89 , fSecond(second) |
94 , fRadius(radius) | 90 , fRadius(radius) { |
95 , fPad(pad) { | |
96 this->initClassID<RRectsGaussianEdgeFP>(); | 91 this->initClassID<RRectsGaussianEdgeFP>(); |
97 this->setWillReadFragmentPosition(); | 92 this->setWillReadFragmentPosition(); |
98 | 93 |
99 fFirstMode = ComputeMode(fFirst); | 94 fFirstMode = ComputeMode(fFirst); |
100 fSecondMode = ComputeMode(fSecond); | 95 fSecondMode = ComputeMode(fSecond); |
101 } | 96 } |
102 | 97 |
103 class GLSLRRectsGaussianEdgeFP : public GrGLSLFragmentProcessor { | 98 class GLSLRRectsGaussianEdgeFP : public GrGLSLFragmentProcessor { |
104 public: | 99 public: |
105 GLSLRRectsGaussianEdgeFP() { } | 100 GLSLRRectsGaussianEdgeFP() { } |
106 | 101 |
107 // This method emits code so that, for each shape, the distance from the
edge is returned | 102 // This method emits code so that, for each shape, the distance from the
edge is returned |
108 // in 'outputName' clamped to 0..1 with positive distance being towards
the center of the | 103 // in 'outputName' clamped to 0..1 with positive distance being towards
the center of the |
109 // shape. The distance will have been normalized by the radius. | 104 // shape. The distance will have been normalized by the radius. |
110 void emitModeCode(Mode mode, | 105 void emitModeCode(Mode mode, |
111 GrGLSLFPFragmentBuilder* fragBuilder, | 106 GrGLSLFPFragmentBuilder* fragBuilder, |
112 const char* posName, | 107 const char* posName, |
113 const char* sizesName, | 108 const char* sizesName, |
114 const char* radiiName, | 109 const char* radiiName, |
115 const char* padRadName, | 110 const char* radName, |
116 const char* outputName, | 111 const char* outputName, |
117 const char indices[2]) { // how to access the params
for the 2 rrects | 112 const char indices[2]) { // how to access the params
for the 2 rrects |
118 | 113 |
119 // positive distance is towards the center of the circle | 114 // positive distance is towards the center of the circle |
120 fragBuilder->codeAppendf("vec2 delta = %s.xy - %s.%s;", | 115 fragBuilder->codeAppendf("vec2 delta = %s.xy - %s.%s;", |
121 fragBuilder->fragmentPosition(), posName, i
ndices); | 116 fragBuilder->fragmentPosition(), posName, i
ndices); |
122 | 117 |
123 switch (mode) { | 118 switch (mode) { |
124 case kCircle_Mode: | 119 case kCircle_Mode: |
125 fragBuilder->codeAppendf("%s = clamp((%s.%c - length(delta))/%s.
y, 0.0, 1.0);", | 120 fragBuilder->codeAppendf("%s = clamp((%s.%c - length(delta))/%s,
0.0, 1.0);", |
126 outputName, sizesName, indices[0], padR
adName); | 121 outputName, sizesName, indices[0], radN
ame); |
127 break; | 122 break; |
128 case kRect_Mode: | 123 case kRect_Mode: |
129 fragBuilder->codeAppendf( | 124 fragBuilder->codeAppendf( |
130 "vec2 rectDist = vec2(1.0 - clamp((%s.%c - abs(delta.x))/%s.
y, 0.0, 1.0)," | 125 "vec2 rectDist = vec2(1.0 - clamp((%s.%c - abs(delta.x))/%s,
0.0, 1.0)," |
131 "1.0 - clamp((%s.%c - abs(delta.y))/%s.
y, 0.0, 1.0));", | 126 "1.0 - clamp((%s.%c - abs(delta.y))/%s,
0.0, 1.0));", |
132 sizesName, indices[0], padRadName, | 127 sizesName, indices[0], radName, |
133 sizesName, indices[1], padRadName); | 128 sizesName, indices[1], radName); |
134 fragBuilder->codeAppendf("%s = 1.0 - length(rectDist);", outputN
ame); | 129 fragBuilder->codeAppendf("%s = 1.0 - length(rectDist);", outputN
ame); |
135 break; | 130 break; |
136 case kSimpleCircular_Mode: | 131 case kSimpleCircular_Mode: |
137 // For the circular round rect we first compute the distance | 132 // For the circular round rect we first compute the distance |
138 // to the rect. Then we compute a multiplier that is 1 if the | 133 // to the rect. Then we compute a multiplier that is 1 if the |
139 // point is in one of the circular corners. We then compute the | 134 // point is in one of the circular corners. We then compute the |
140 // distance from the corner and then use the multiplier to mask | 135 // distance from the corner and then use the multiplier to mask |
141 // between the two distances. | 136 // between the two distances. |
142 fragBuilder->codeAppendf("float xDist = clamp((%s.%c - abs(delta
.x))/%s.y," | 137 fragBuilder->codeAppendf("float xDist = clamp((%s.%c - abs(delta
.x))/%s," |
143 " 0.0, 1.0);", | 138 " 0.0, 1.0);", |
144 sizesName, indices[0], padRadName); | 139 sizesName, indices[0], radName); |
145 fragBuilder->codeAppendf("float yDist = clamp((%s.%c - abs(delta
.y))/%s.y," | 140 fragBuilder->codeAppendf("float yDist = clamp((%s.%c - abs(delta
.y))/%s," |
146 "0.0, 1.0);", | 141 "0.0, 1.0);", |
147 sizesName, indices[1], padRadName); | 142 sizesName, indices[1], radName); |
148 fragBuilder->codeAppend("float rectDist = min(xDist, yDist);"); | 143 fragBuilder->codeAppend("float rectDist = min(xDist, yDist);"); |
149 | 144 |
150 fragBuilder->codeAppendf("vec2 cornerCenter = %s.%s - %s.%s;", | 145 fragBuilder->codeAppendf("vec2 cornerCenter = %s.%s - %s.%s;", |
151 sizesName, indices, radiiName, indices)
; | 146 sizesName, indices, radiiName, indices)
; |
152 fragBuilder->codeAppend("delta = vec2(abs(delta.x) - cornerCente
r.x," | 147 fragBuilder->codeAppend("delta = vec2(abs(delta.x) - cornerCente
r.x," |
153 "abs(delta.y) - cornerCente
r.y);"); | 148 "abs(delta.y) - cornerCente
r.y);"); |
154 fragBuilder->codeAppendf("xDist = %s.%c - abs(delta.x);", radiiN
ame, indices[0]); | 149 fragBuilder->codeAppendf("xDist = %s.%c - abs(delta.x);", radiiN
ame, indices[0]); |
155 fragBuilder->codeAppendf("yDist = %s.%c - abs(delta.y);", radiiN
ame, indices[1]); | 150 fragBuilder->codeAppendf("yDist = %s.%c - abs(delta.y);", radiiN
ame, indices[1]); |
156 fragBuilder->codeAppend("float cornerDist = min(xDist, yDist);")
; | 151 fragBuilder->codeAppend("float cornerDist = min(xDist, yDist);")
; |
157 fragBuilder->codeAppend("float multiplier = step(0.0, cornerDist
);"); | 152 fragBuilder->codeAppend("float multiplier = step(0.0, cornerDist
);"); |
158 | 153 |
159 fragBuilder->codeAppendf("delta += %s.%s;", radiiName, indices); | 154 fragBuilder->codeAppendf("delta += %s.%s;", radiiName, indices); |
160 | 155 |
161 fragBuilder->codeAppendf("cornerDist = clamp((2.0 * %s.%c - leng
th(delta))/%s.y," | 156 fragBuilder->codeAppendf("cornerDist = clamp((2.0 * %s.%c - leng
th(delta))/%s," |
162 "0.0, 1.0);", | 157 "0.0, 1.0);", |
163 radiiName, indices[0], padRadName); | 158 radiiName, indices[0], radName); |
164 | 159 |
165 fragBuilder->codeAppendf("%s = (multiplier * cornerDist) +" | 160 fragBuilder->codeAppendf("%s = (multiplier * cornerDist) +" |
166 "((1.0-multiplier) * rectDist);", | 161 "((1.0-multiplier) * rectDist);", |
167 outputName); | 162 outputName); |
168 break; | 163 break; |
169 } | 164 } |
170 } | 165 } |
171 | 166 |
172 void emitCode(EmitArgs& args) override { | 167 void emitCode(EmitArgs& args) override { |
173 const RRectsGaussianEdgeFP& fp = args.fFp.cast<RRectsGaussianEdgeFP>
(); | 168 const RRectsGaussianEdgeFP& fp = args.fFp.cast<RRectsGaussianEdgeFP>
(); |
174 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; | 169 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; |
175 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler; | 170 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler; |
176 | 171 |
177 const char* positionsUniName = nullptr; | 172 const char* positionsUniName = nullptr; |
178 fPositionsUni = uniformHandler->addUniform(kFragment_GrShaderFlag, | 173 fPositionsUni = uniformHandler->addUniform(kFragment_GrShaderFlag, |
179 kVec4f_GrSLType, kDefault
_GrSLPrecision, | 174 kVec4f_GrSLType, kDefault
_GrSLPrecision, |
180 "Positions", &positionsUn
iName); | 175 "Positions", &positionsUn
iName); |
181 const char* sizesUniName = nullptr; | 176 const char* sizesUniName = nullptr; |
182 fSizesUni = uniformHandler->addUniform(kFragment_GrShaderFlag, | 177 fSizesUni = uniformHandler->addUniform(kFragment_GrShaderFlag, |
183 kVec4f_GrSLType, kDefault_GrS
LPrecision, | 178 kVec4f_GrSLType, kDefault_GrS
LPrecision, |
184 "Sizes", &sizesUniName); | 179 "Sizes", &sizesUniName); |
185 const char* radiiUniName = nullptr; | 180 const char* radiiUniName = nullptr; |
186 if (fp.fFirstMode == kSimpleCircular_Mode || fp.fSecondMode == kSimp
leCircular_Mode) { | 181 if (fp.fFirstMode == kSimpleCircular_Mode || fp.fSecondMode == kSimp
leCircular_Mode) { |
187 fRadiiUni = uniformHandler->addUniform(kFragment_GrShaderFlag, | 182 fRadiiUni = uniformHandler->addUniform(kFragment_GrShaderFlag, |
188 kVec4f_GrSLType, kDefault
_GrSLPrecision, | 183 kVec4f_GrSLType, kDefault
_GrSLPrecision, |
189 "Radii", &radiiUniName); | 184 "Radii", &radiiUniName); |
190 } | 185 } |
191 const char* padRadUniName = nullptr; | 186 const char* radUniName = nullptr; |
192 fPadRadUni = uniformHandler->addUniform(kFragment_GrShaderFlag, | 187 fRadiusUni = uniformHandler->addUniform(kFragment_GrShaderFlag, |
193 kVec2f_GrSLType, kDefault_Gr
SLPrecision, | 188 kFloat_GrSLType, kDefault_Gr
SLPrecision, |
194 "PadRad", &padRadUniName); | 189 "Radius", &radUniName); |
195 | 190 |
196 fragBuilder->codeAppend("float firstDist;"); | 191 fragBuilder->codeAppend("float firstDist;"); |
197 fragBuilder->codeAppend("{"); | 192 fragBuilder->codeAppend("{"); |
198 this->emitModeCode(fp.firstMode(), fragBuilder, | 193 this->emitModeCode(fp.firstMode(), fragBuilder, |
199 positionsUniName, sizesUniName, radiiUniName, | 194 positionsUniName, sizesUniName, radiiUniName, |
200 padRadUniName, "firstDist", "xy"); | 195 radUniName, "firstDist", "xy"); |
201 fragBuilder->codeAppend("}"); | 196 fragBuilder->codeAppend("}"); |
202 | 197 |
203 fragBuilder->codeAppend("float secondDist;"); | 198 fragBuilder->codeAppend("float secondDist;"); |
204 fragBuilder->codeAppend("{"); | 199 fragBuilder->codeAppend("{"); |
205 this->emitModeCode(fp.secondMode(), fragBuilder, | 200 this->emitModeCode(fp.secondMode(), fragBuilder, |
206 positionsUniName, sizesUniName, radiiUniName, | 201 positionsUniName, sizesUniName, radiiUniName, |
207 padRadUniName, "secondDist", "zw"); | 202 radUniName, "secondDist", "zw"); |
208 fragBuilder->codeAppend("}"); | 203 fragBuilder->codeAppend("}"); |
209 | 204 |
210 fragBuilder->codeAppendf("float dist = %s.y * firstDist * secondDist
;", | 205 fragBuilder->codeAppendf("float dist = %s * firstDist * secondDist;"
, radUniName); |
211 padRadUniName); | |
212 | 206 |
213 // Finally use the distance to apply the Gaussian edge | 207 // Finally use the distance to apply the Gaussian edge |
214 // TODO: we undo the multiply by the radius here - we should just sk
ip both | 208 // TODO: we undo the multiply by the radius here - we should just sk
ip both |
215 fragBuilder->codeAppendf("float factor = 1.0 - clamp((dist - %s.x)/%
s.y, 0.0, 1.0);", | 209 fragBuilder->codeAppendf("float factor = 1.0 - clamp(dist/%s, 0.0, 1
.0);", radUniName); |
216 padRadUniName, padRadUniName); | |
217 fragBuilder->codeAppend("factor = exp(-factor * factor * 4.0) - 0.01
8;"); | 210 fragBuilder->codeAppend("factor = exp(-factor * factor * 4.0) - 0.01
8;"); |
218 fragBuilder->codeAppendf("%s = vec4(%s.rgb, factor);", | 211 fragBuilder->codeAppendf("%s = factor*%s;", |
219 args.fOutputColor, args.fInputColor); | 212 args.fOutputColor, args.fInputColor); |
220 } | 213 } |
221 | 214 |
222 static void GenKey(const GrProcessor& proc, const GrGLSLCaps&, | 215 static void GenKey(const GrProcessor& proc, const GrGLSLCaps&, |
223 GrProcessorKeyBuilder* b) { | 216 GrProcessorKeyBuilder* b) { |
224 const RRectsGaussianEdgeFP& fp = proc.cast<RRectsGaussianEdgeFP>(); | 217 const RRectsGaussianEdgeFP& fp = proc.cast<RRectsGaussianEdgeFP>(); |
225 | 218 |
226 b->add32(fp.firstMode() | (fp.secondMode() << 4)); | 219 b->add32(fp.firstMode() | (fp.secondMode() << 4)); |
227 } | 220 } |
228 | 221 |
(...skipping 20 matching lines...) Expand all Loading... |
249 edgeFP.secondMode() == kSimpleCircular_Mode) { | 242 edgeFP.secondMode() == kSimpleCircular_Mode) { |
250 // This is a bit of overkill since fX should equal fY for both r
ound rects but it | 243 // This is a bit of overkill since fX should equal fY for both r
ound rects but it |
251 // makes the shader code simpler. | 244 // makes the shader code simpler. |
252 pdman.set4f(fRadiiUni, | 245 pdman.set4f(fRadiiUni, |
253 0.5f * first.getSimpleRadii().fX, | 246 0.5f * first.getSimpleRadii().fX, |
254 0.5f * first.getSimpleRadii().fY, | 247 0.5f * first.getSimpleRadii().fY, |
255 0.5f * second.getSimpleRadii().fX, | 248 0.5f * second.getSimpleRadii().fX, |
256 0.5f * second.getSimpleRadii().fY); | 249 0.5f * second.getSimpleRadii().fY); |
257 } | 250 } |
258 | 251 |
259 pdman.set2f(fPadRadUni, edgeFP.pad(), edgeFP.radius()); | 252 pdman.set1f(fRadiusUni, edgeFP.radius()); |
260 } | 253 } |
261 | 254 |
262 private: | 255 private: |
263 // The centers of the two round rects (x1, y1, x2, y2) | 256 // The centers of the two round rects (x1, y1, x2, y2) |
264 GrGLSLProgramDataManager::UniformHandle fPositionsUni; | 257 GrGLSLProgramDataManager::UniformHandle fPositionsUni; |
265 | 258 |
266 // The half widths and half heights of the two round rects (w1/2, h1/2,
w2/2, h2/2) | 259 // The half widths and half heights of the two round rects (w1/2, h1/2,
w2/2, h2/2) |
267 // For circles we still upload both width & height to simplify things | 260 // For circles we still upload both width & height to simplify things |
268 GrGLSLProgramDataManager::UniformHandle fSizesUni; | 261 GrGLSLProgramDataManager::UniformHandle fSizesUni; |
269 | 262 |
270 // The half corner radii of the two round rects (rx1/2, ry1/2, rx2/2, ry
2/2) | 263 // The half corner radii of the two round rects (rx1/2, ry1/2, rx2/2, ry
2/2) |
271 // We upload both the x&y radii (although they are currently always the
same) to make | 264 // We upload both the x&y radii (although they are currently always the
same) to make |
272 // the indexing in the shader code simpler. In some future world we coul
d also support | 265 // the indexing in the shader code simpler. In some future world we coul
d also support |
273 // non-circular corner round rects & ellipses. | 266 // non-circular corner round rects & ellipses. |
274 GrGLSLProgramDataManager::UniformHandle fRadiiUni; | 267 GrGLSLProgramDataManager::UniformHandle fRadiiUni; |
275 | 268 |
276 // The pad and radius parameters (padding, radius) | 269 // The radius parameters (radius) |
277 GrGLSLProgramDataManager::UniformHandle fPadRadUni; | 270 GrGLSLProgramDataManager::UniformHandle fRadiusUni; |
278 | 271 |
279 typedef GrGLSLFragmentProcessor INHERITED; | 272 typedef GrGLSLFragmentProcessor INHERITED; |
280 }; | 273 }; |
281 | 274 |
282 void onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b)
const override { | 275 void onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b)
const override { |
283 GLSLRRectsGaussianEdgeFP::GenKey(*this, caps, b); | 276 GLSLRRectsGaussianEdgeFP::GenKey(*this, caps, b); |
284 } | 277 } |
285 | 278 |
286 const char* name() const override { return "RRectsGaussianEdgeFP"; } | 279 const char* name() const override { return "RRectsGaussianEdgeFP"; } |
287 | 280 |
288 void onComputeInvariantOutput(GrInvariantOutput* inout) const override { | 281 void onComputeInvariantOutput(GrInvariantOutput* inout) const override { |
289 inout->setToUnknown(GrInvariantOutput::kWill_ReadInput); | 282 inout->setToUnknown(GrInvariantOutput::kWill_ReadInput); |
290 } | 283 } |
291 | 284 |
292 const SkRRect& first() const { return fFirst; } | 285 const SkRRect& first() const { return fFirst; } |
293 Mode firstMode() const { return fFirstMode; } | 286 Mode firstMode() const { return fFirstMode; } |
294 const SkRRect& second() const { return fSecond; } | 287 const SkRRect& second() const { return fSecond; } |
295 Mode secondMode() const { return fSecondMode; } | 288 Mode secondMode() const { return fSecondMode; } |
296 SkScalar radius() const { return fRadius; } | 289 SkScalar radius() const { return fRadius; } |
297 SkScalar pad() const { return fPad; } | |
298 | 290 |
299 private: | 291 private: |
300 static Mode ComputeMode(const SkRRect& rr) { | 292 static Mode ComputeMode(const SkRRect& rr) { |
301 if (rr.isCircle()) { | 293 if (rr.isCircle()) { |
302 return kCircle_Mode; | 294 return kCircle_Mode; |
303 } else if (rr.isRect()) { | 295 } else if (rr.isRect()) { |
304 return kRect_Mode; | 296 return kRect_Mode; |
305 } else { | 297 } else { |
306 SkASSERT(rr.isSimpleCircular()); | 298 SkASSERT(rr.isSimpleCircular()); |
307 return kSimpleCircular_Mode; | 299 return kSimpleCircular_Mode; |
308 } | 300 } |
309 } | 301 } |
310 | 302 |
311 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override { | 303 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override { |
312 return new GLSLRRectsGaussianEdgeFP; | 304 return new GLSLRRectsGaussianEdgeFP; |
313 } | 305 } |
314 | 306 |
315 bool onIsEqual(const GrFragmentProcessor& proc) const override { | 307 bool onIsEqual(const GrFragmentProcessor& proc) const override { |
316 const RRectsGaussianEdgeFP& edgeFP = proc.cast<RRectsGaussianEdgeFP>(); | 308 const RRectsGaussianEdgeFP& edgeFP = proc.cast<RRectsGaussianEdgeFP>(); |
317 return fFirst == edgeFP.fFirst && fSecond == edgeFP.fSecond && | 309 return fFirst == edgeFP.fFirst && |
318 fRadius == edgeFP.fRadius && fPad == edgeFP.fPad; | 310 fSecond == edgeFP.fSecond && |
| 311 fRadius == edgeFP.fRadius; |
319 } | 312 } |
320 | 313 |
321 SkRRect fFirst; | 314 SkRRect fFirst; |
322 Mode fFirstMode; | 315 Mode fFirstMode; |
323 SkRRect fSecond; | 316 SkRRect fSecond; |
324 Mode fSecondMode; | 317 Mode fSecondMode; |
325 SkScalar fRadius; | 318 SkScalar fRadius; |
326 SkScalar fPad; | |
327 | 319 |
328 typedef GrFragmentProcessor INHERITED; | 320 typedef GrFragmentProcessor INHERITED; |
329 }; | 321 }; |
330 | 322 |
331 //////////////////////////////////////////////////////////////////////////// | 323 //////////////////////////////////////////////////////////////////////////// |
332 | 324 |
333 sk_sp<GrFragmentProcessor> SkRRectsGaussianEdgeShaderImpl::asFragmentProcessor( | 325 sk_sp<GrFragmentProcessor> SkRRectsGaussianEdgeShaderImpl::asFragmentProcessor( |
334 const AsFPAr
gs& args) const { | 326 const AsFPAr
gs& args) const { |
335 return sk_make_sp<RRectsGaussianEdgeFP>(fFirst, fSecond, fRadius, fPad); | 327 return sk_make_sp<RRectsGaussianEdgeFP>(fFirst, fSecond, fRadius); |
336 } | 328 } |
337 | 329 |
338 #endif | 330 #endif |
339 | 331 |
340 //////////////////////////////////////////////////////////////////////////// | 332 //////////////////////////////////////////////////////////////////////////// |
341 | 333 |
342 SkRRectsGaussianEdgeShaderImpl::GaussianEdgeShaderContext::GaussianEdgeShaderCon
text( | 334 SkRRectsGaussianEdgeShaderImpl::GaussianEdgeShaderContext::GaussianEdgeShaderCon
text( |
343 const SkRRectsGaussianEdgeSh
aderImpl& shader, | 335 const SkRRectsGaussianEdgeSh
aderImpl& shader, |
344 const ContextRec& rec) | 336 const ContextRec& rec) |
345 : INHERITED(shader, rec) { | 337 : INHERITED(shader, rec) { |
(...skipping 27 matching lines...) Expand all Loading... |
373 | 365 |
374 buf.readRect(&rect1); | 366 buf.readRect(&rect1); |
375 SkScalar xRad1 = buf.readScalar(); | 367 SkScalar xRad1 = buf.readScalar(); |
376 SkScalar yRad1 = buf.readScalar(); | 368 SkScalar yRad1 = buf.readScalar(); |
377 | 369 |
378 buf.readRect(&rect2); | 370 buf.readRect(&rect2); |
379 SkScalar xRad2 = buf.readScalar(); | 371 SkScalar xRad2 = buf.readScalar(); |
380 SkScalar yRad2 = buf.readScalar(); | 372 SkScalar yRad2 = buf.readScalar(); |
381 | 373 |
382 SkScalar radius = buf.readScalar(); | 374 SkScalar radius = buf.readScalar(); |
383 SkScalar pad = buf.readScalar(); | |
384 | 375 |
385 return sk_make_sp<SkRRectsGaussianEdgeShaderImpl>(SkRRect::MakeRectXY(rect1,
xRad1, yRad1), | 376 return sk_make_sp<SkRRectsGaussianEdgeShaderImpl>(SkRRect::MakeRectXY(rect1,
xRad1, yRad1), |
386 SkRRect::MakeRectXY(rect2,
xRad2, yRad2), | 377 SkRRect::MakeRectXY(rect2,
xRad2, yRad2), |
387 radius, pad); | 378 radius); |
388 } | 379 } |
389 | 380 |
390 void SkRRectsGaussianEdgeShaderImpl::flatten(SkWriteBuffer& buf) const { | 381 void SkRRectsGaussianEdgeShaderImpl::flatten(SkWriteBuffer& buf) const { |
391 INHERITED::flatten(buf); | 382 INHERITED::flatten(buf); |
392 | 383 |
393 SkASSERT(fFirst.isRect() || fFirst.isCircle() || fFirst.isSimpleCircular()); | 384 SkASSERT(fFirst.isRect() || fFirst.isCircle() || fFirst.isSimpleCircular()); |
394 buf.writeRect(fFirst.rect()); | 385 buf.writeRect(fFirst.rect()); |
395 const SkVector& radii1 = fFirst.getSimpleRadii(); | 386 const SkVector& radii1 = fFirst.getSimpleRadii(); |
396 buf.writeScalar(radii1.fX); | 387 buf.writeScalar(radii1.fX); |
397 buf.writeScalar(radii1.fY); | 388 buf.writeScalar(radii1.fY); |
398 | 389 |
399 SkASSERT(fSecond.isRect() || fSecond.isCircle() || fSecond.isSimpleCircular(
)); | 390 SkASSERT(fSecond.isRect() || fSecond.isCircle() || fSecond.isSimpleCircular(
)); |
400 buf.writeRect(fSecond.rect()); | 391 buf.writeRect(fSecond.rect()); |
401 const SkVector& radii2 = fSecond.getSimpleRadii(); | 392 const SkVector& radii2 = fSecond.getSimpleRadii(); |
402 buf.writeScalar(radii2.fX); | 393 buf.writeScalar(radii2.fX); |
403 buf.writeScalar(radii2.fY); | 394 buf.writeScalar(radii2.fY); |
404 | 395 |
405 buf.writeScalar(fRadius); | 396 buf.writeScalar(fRadius); |
406 buf.writeScalar(fPad); | |
407 } | 397 } |
408 | 398 |
409 size_t SkRRectsGaussianEdgeShaderImpl::onContextSize(const ContextRec& rec) cons
t { | 399 size_t SkRRectsGaussianEdgeShaderImpl::onContextSize(const ContextRec& rec) cons
t { |
410 return sizeof(GaussianEdgeShaderContext); | 400 return sizeof(GaussianEdgeShaderContext); |
411 } | 401 } |
412 | 402 |
413 SkShader::Context* SkRRectsGaussianEdgeShaderImpl::onCreateContext(const Context
Rec& rec, | 403 SkShader::Context* SkRRectsGaussianEdgeShaderImpl::onCreateContext(const Context
Rec& rec, |
414 void* storage
) const { | 404 void* storage
) const { |
415 return new (storage) GaussianEdgeShaderContext(*this, rec); | 405 return new (storage) GaussianEdgeShaderContext(*this, rec); |
416 } | 406 } |
417 | 407 |
418 /////////////////////////////////////////////////////////////////////////////// | 408 /////////////////////////////////////////////////////////////////////////////// |
419 | 409 |
420 sk_sp<SkShader> SkRRectsGaussianEdgeShader::Make(const SkRRect& first, | 410 sk_sp<SkShader> SkRRectsGaussianEdgeShader::Make(const SkRRect& first, |
421 const SkRRect& second, | 411 const SkRRect& second, |
422 SkScalar radius, | 412 SkScalar radius) { |
423 SkScalar pad) { | |
424 if ((!first.isRect() && !first.isCircle() && !first.isSimpleCircular()) ||
| 413 if ((!first.isRect() && !first.isCircle() && !first.isSimpleCircular()) ||
|
425 (!second.isRect() && !second.isCircle() && !second.isSimpleCircular()))
{ | 414 (!second.isRect() && !second.isCircle() && !second.isSimpleCircular()))
{ |
426 // we only deal with the shapes where the x & y radii are equal | 415 // we only deal with the shapes where the x & y radii are equal |
427 // and the same for all four corners | 416 // and the same for all four corners |
428 return nullptr; | 417 return nullptr; |
429 } | 418 } |
430 | 419 |
431 return sk_make_sp<SkRRectsGaussianEdgeShaderImpl>(first, second, radius, pad
); | 420 return sk_make_sp<SkRRectsGaussianEdgeShaderImpl>(first, second, radius); |
432 } | 421 } |
433 | 422 |
434 /////////////////////////////////////////////////////////////////////////////// | 423 /////////////////////////////////////////////////////////////////////////////// |
435 | 424 |
436 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkRRectsGaussianEdgeShader) | 425 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkRRectsGaussianEdgeShader) |
437 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkRRectsGaussianEdgeShaderImpl) | 426 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkRRectsGaussianEdgeShaderImpl) |
438 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END | 427 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END |
439 | 428 |
440 /////////////////////////////////////////////////////////////////////////////// | 429 /////////////////////////////////////////////////////////////////////////////// |
OLD | NEW |