Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(19)

Side by Side Diff: src/effects/SkRRectsGaussianEdgeShader.cpp

Issue 2335783003: Fixup SkRRectsGaussianEdgeShader's shaders (Closed)
Patch Set: Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « gm/reveal.cpp ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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"
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
97 this->setWillReadFragmentPosition(); 97 this->setWillReadFragmentPosition();
98 98
99 fFirstMode = ComputeMode(fFirst); 99 fFirstMode = ComputeMode(fFirst);
100 fSecondMode = ComputeMode(fSecond); 100 fSecondMode = ComputeMode(fSecond);
101 } 101 }
102 102
103 class GLSLRRectsGaussianEdgeFP : public GrGLSLFragmentProcessor { 103 class GLSLRRectsGaussianEdgeFP : public GrGLSLFragmentProcessor {
104 public: 104 public:
105 GLSLRRectsGaussianEdgeFP() { } 105 GLSLRRectsGaussianEdgeFP() { }
106 106
107 // 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
109 // shape. The distance will have been normalized by the radius.
107 void emitModeCode(Mode mode, 110 void emitModeCode(Mode mode,
108 GrGLSLFPFragmentBuilder* fragBuilder, 111 GrGLSLFPFragmentBuilder* fragBuilder,
109 const char* posName, 112 const char* posName,
110 const char* sizesName, 113 const char* sizesName,
111 const char* radiiName, 114 const char* radiiName,
115 const char* padRadName,
112 const char* outputName, 116 const char* outputName,
113 const char indices[2]) { // how to access the params for the 2 rrects 117 const char indices[2]) { // how to access the params for the 2 rrects
114 118
115 // positive distance is towards the center of the circle 119 // positive distance is towards the center of the circle
116 fragBuilder->codeAppendf("vec2 delta = %s.xy - %s.%s;", 120 fragBuilder->codeAppendf("vec2 delta = %s.xy - %s.%s;",
117 fragBuilder->fragmentPosition(), 121 fragBuilder->fragmentPosition(), posName, i ndices);
118 posName, indices);
119 122
120 switch (mode) { 123 switch (mode) {
121 case kCircle_Mode: 124 case kCircle_Mode:
122 fragBuilder->codeAppendf("%s = %s.%c - length(delta);", 125 fragBuilder->codeAppendf("%s = clamp((%s.%c - length(delta))/%s. y, 0.0, 1.0);",
123 outputName, 126 outputName, sizesName, indices[0], padR adName);
124 sizesName, indices[0]);
125 break; 127 break;
126 case kRect_Mode: 128 case kRect_Mode:
127 fragBuilder->codeAppendf("float xDist = %s.%c - abs(delta.x);", 129 fragBuilder->codeAppendf(
128 sizesName, indices[0]); 130 "vec2 rectDist = vec2(1.0 - clamp((%s.%c - abs(delta.x))/%s. y, 0.0, 1.0),"
129 fragBuilder->codeAppendf("float yDist = %s.%c - abs(delta.y);", 131 "1.0 - clamp((%s.%c - abs(delta.y))/%s. y, 0.0, 1.0));",
130 sizesName, indices[1]); 132 sizesName, indices[0], padRadName,
131 fragBuilder->codeAppendf("%s = min(xDist, yDist);", outputName); 133 sizesName, indices[1], padRadName);
134 fragBuilder->codeAppendf("%s = 1.0 - length(rectDist);", outputN ame);
132 break; 135 break;
133 case kSimpleCircular_Mode: 136 case kSimpleCircular_Mode:
134 // For the circular round rect we first compute the distance 137 // For the circular round rect we first compute the distance
135 // to the rect. Then we compute a multiplier that is 1 if the 138 // to the rect. Then we compute a multiplier that is 1 if the
136 // point is in one of the circular corners. We then compute the 139 // point is in one of the circular corners. We then compute the
137 // distance from the corner and then use the multiplier to mask 140 // distance from the corner and then use the multiplier to mask
138 // between the two distances. 141 // between the two distances.
139 fragBuilder->codeAppendf("float xDist = %s.%c - abs(delta.x);", 142 fragBuilder->codeAppendf("float xDist = clamp((%s.%c - abs(delta .x))/%s.y,"
140 sizesName, indices[0]); 143 " 0.0, 1.0);",
141 fragBuilder->codeAppendf("float yDist = %s.%c - abs(delta.y);", 144 sizesName, indices[0], padRadName);
142 sizesName, indices[1]); 145 fragBuilder->codeAppendf("float yDist = clamp((%s.%c - abs(delta .y))/%s.y,"
146 "0.0, 1.0);",
147 sizesName, indices[1], padRadName);
143 fragBuilder->codeAppend("float rectDist = min(xDist, yDist);"); 148 fragBuilder->codeAppend("float rectDist = min(xDist, yDist);");
144 149
145 fragBuilder->codeAppendf("vec2 cornerCenter = %s.%s - %s.%s;", 150 fragBuilder->codeAppendf("vec2 cornerCenter = %s.%s - %s.%s;",
146 sizesName, indices, 151 sizesName, indices, radiiName, indices) ;
147 radiiName, indices);
148 fragBuilder->codeAppend("delta = vec2(abs(delta.x) - cornerCente r.x," 152 fragBuilder->codeAppend("delta = vec2(abs(delta.x) - cornerCente r.x,"
149 "abs(delta.y) - cornerCente r.y);"); 153 "abs(delta.y) - cornerCente r.y);");
150 fragBuilder->codeAppendf("xDist = %s.%c - abs(delta.x);", 154 fragBuilder->codeAppendf("xDist = %s.%c - abs(delta.x);", radiiN ame, indices[0]);
151 radiiName, indices[0]); 155 fragBuilder->codeAppendf("yDist = %s.%c - abs(delta.y);", radiiN ame, indices[1]);
152 fragBuilder->codeAppendf("yDist = %s.%c - abs(delta.y);",
153 radiiName, indices[1]);
154 fragBuilder->codeAppend("float cornerDist = min(xDist, yDist);") ; 156 fragBuilder->codeAppend("float cornerDist = min(xDist, yDist);") ;
155 fragBuilder->codeAppend("float multiplier = step(0.0, cornerDist );"); 157 fragBuilder->codeAppend("float multiplier = step(0.0, cornerDist );");
156 158
157 fragBuilder->codeAppendf("delta += %s.%s;", radiiName, indices); 159 fragBuilder->codeAppendf("delta += %s.%s;", radiiName, indices);
158 160
159 fragBuilder->codeAppendf("cornerDist = 2.0 * %s.%c - length(delt a);", 161 fragBuilder->codeAppendf("cornerDist = clamp((2.0 * %s.%c - leng th(delta))/%s.y,"
160 radiiName, indices[0]); 162 "0.0, 1.0);",
163 radiiName, indices[0], padRadName);
161 164
162 fragBuilder->codeAppendf("%s = (multiplier * cornerDist) +" 165 fragBuilder->codeAppendf("%s = (multiplier * cornerDist) +"
163 "((1.0-multiplier) * rectDist);", 166 "((1.0-multiplier) * rectDist);",
164 outputName); 167 outputName);
165 break; 168 break;
166 } 169 }
167 } 170 }
168 171
169 void emitCode(EmitArgs& args) override { 172 void emitCode(EmitArgs& args) override {
170 const RRectsGaussianEdgeFP& fp = args.fFp.cast<RRectsGaussianEdgeFP> (); 173 const RRectsGaussianEdgeFP& fp = args.fFp.cast<RRectsGaussianEdgeFP> ();
171 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; 174 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
172 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler; 175 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
173 176
174 const char* positionsUniName = nullptr; 177 const char* positionsUniName = nullptr;
175 fPositionsUni = uniformHandler->addUniform(kFragment_GrShaderFlag, 178 fPositionsUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
176 kVec4f_GrSLType, kDefault _GrSLPrecision, 179 kVec4f_GrSLType, kDefault _GrSLPrecision,
177 "Positions", &positionsUn iName); 180 "Positions", &positionsUn iName);
178 const char* sizesUniName = nullptr; 181 const char* sizesUniName = nullptr;
179 fSizesUni = uniformHandler->addUniform(kFragment_GrShaderFlag, 182 fSizesUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
180 kVec4f_GrSLType, kDefault_GrS LPrecision, 183 kVec4f_GrSLType, kDefault_GrS LPrecision,
181 "Sizes", &sizesUniName); 184 "Sizes", &sizesUniName);
182 const char* radiiUniName = nullptr; 185 const char* radiiUniName = nullptr;
183 fRadiiUni = uniformHandler->addUniform(kFragment_GrShaderFlag, 186 if (fp.fFirstMode == kSimpleCircular_Mode || fp.fSecondMode == kSimp leCircular_Mode) {
184 kVec4f_GrSLType, kDefault_GrS LPrecision, 187 fRadiiUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
185 "Radii", &radiiUniName); 188 kVec4f_GrSLType, kDefault _GrSLPrecision,
189 "Radii", &radiiUniName);
190 }
186 const char* padRadUniName = nullptr; 191 const char* padRadUniName = nullptr;
187 fPadRadUni = uniformHandler->addUniform(kFragment_GrShaderFlag, 192 fPadRadUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
188 kVec2f_GrSLType, kDefault_Gr SLPrecision, 193 kVec2f_GrSLType, kDefault_Gr SLPrecision,
189 "PadRad", &padRadUniName); 194 "PadRad", &padRadUniName);
190 195
191 fragBuilder->codeAppend("float firstDist;"); 196 fragBuilder->codeAppend("float firstDist;");
192 fragBuilder->codeAppend("{"); 197 fragBuilder->codeAppend("{");
193 this->emitModeCode(fp.firstMode(), fragBuilder, 198 this->emitModeCode(fp.firstMode(), fragBuilder,
194 positionsUniName, sizesUniName, radiiUniName, "fi rstDist", "xy"); 199 positionsUniName, sizesUniName, radiiUniName,
200 padRadUniName, "firstDist", "xy");
195 fragBuilder->codeAppend("}"); 201 fragBuilder->codeAppend("}");
196 202
197 fragBuilder->codeAppend("float secondDist;"); 203 fragBuilder->codeAppend("float secondDist;");
198 fragBuilder->codeAppend("{"); 204 fragBuilder->codeAppend("{");
199 this->emitModeCode(fp.secondMode(), fragBuilder, 205 this->emitModeCode(fp.secondMode(), fragBuilder,
200 positionsUniName, sizesUniName, radiiUniName, "se condDist", "zw"); 206 positionsUniName, sizesUniName, radiiUniName,
207 padRadUniName, "secondDist", "zw");
201 fragBuilder->codeAppend("}"); 208 fragBuilder->codeAppend("}");
202 209
203 // Here use the sign of the distance to the two round rects to mask off the different 210 fragBuilder->codeAppendf("float dist = %s.y * firstDist * secondDist ;",
204 // cases. 211 padRadUniName);
205 fragBuilder->codeAppend("float in1 = step(0.0f, firstDist);");
206 fragBuilder->codeAppend("float in2 = step(0.0f, secondDist);");
207 fragBuilder->codeAppend("float dist = "
208 "in1*in2 * min(firstDis t, secondDist);"
209 "in1*(1.0-in2) * firstDist +"
210 "(1.0-in1)*in2 * secondDist;" );
211 212
212 // Finally use the distance to apply the Gaussian edge 213 // 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
213 fragBuilder->codeAppendf("float factor = 1.0 - clamp((dist - %s.x)/% s.y, 0.0, 1.0);", 215 fragBuilder->codeAppendf("float factor = 1.0 - clamp((dist - %s.x)/% s.y, 0.0, 1.0);",
214 padRadUniName, padRadUniName); 216 padRadUniName, padRadUniName);
215 fragBuilder->codeAppend("factor = exp(-factor * factor * 4.0) - 0.01 8;"); 217 fragBuilder->codeAppend("factor = exp(-factor * factor * 4.0) - 0.01 8;");
216 fragBuilder->codeAppendf("%s = vec4(%s.rgb, factor);", 218 fragBuilder->codeAppendf("%s = vec4(%s.rgb, factor);",
217 args.fOutputColor, args.fInputColor); 219 args.fOutputColor, args.fInputColor);
218 } 220 }
219 221
220 static void GenKey(const GrProcessor& proc, const GrGLSLCaps&, 222 static void GenKey(const GrProcessor& proc, const GrGLSLCaps&,
221 GrProcessorKeyBuilder* b) { 223 GrProcessorKeyBuilder* b) {
222 const RRectsGaussianEdgeFP& fp = proc.cast<RRectsGaussianEdgeFP>(); 224 const RRectsGaussianEdgeFP& fp = proc.cast<RRectsGaussianEdgeFP>();
(...skipping 13 matching lines...) Expand all
236 first.getBounds().centerY(), 238 first.getBounds().centerY(),
237 second.getBounds().centerX(), 239 second.getBounds().centerX(),
238 second.getBounds().centerY()); 240 second.getBounds().centerY());
239 241
240 pdman.set4f(fSizesUni, 242 pdman.set4f(fSizesUni,
241 0.5f * first.rect().width(), 243 0.5f * first.rect().width(),
242 0.5f * first.rect().height(), 244 0.5f * first.rect().height(),
243 0.5f * second.rect().width(), 245 0.5f * second.rect().width(),
244 0.5f * second.rect().height()); 246 0.5f * second.rect().height());
245 247
246 // This is a bit of overkill since fX should equal fY for both round rects but it 248 if (edgeFP.firstMode() == kSimpleCircular_Mode ||
247 // makes the shader code simpler. 249 edgeFP.secondMode() == kSimpleCircular_Mode) {
248 pdman.set4f(fRadiiUni, 250 // This is a bit of overkill since fX should equal fY for both r ound rects but it
249 0.5f * first.getSimpleRadii().fX, 251 // makes the shader code simpler.
250 0.5f * first.getSimpleRadii().fY, 252 pdman.set4f(fRadiiUni,
251 0.5f * second.getSimpleRadii().fX, 253 0.5f * first.getSimpleRadii().fX,
252 0.5f * second.getSimpleRadii().fY); 254 0.5f * first.getSimpleRadii().fY,
255 0.5f * second.getSimpleRadii().fX,
256 0.5f * second.getSimpleRadii().fY);
257 }
253 258
254 pdman.set2f(fPadRadUni, edgeFP.pad(), edgeFP.radius()); 259 pdman.set2f(fPadRadUni, edgeFP.pad(), edgeFP.radius());
255 } 260 }
256 261
257 private: 262 private:
258 // The centers of the two round rects (x1, y1, x2, y2) 263 // The centers of the two round rects (x1, y1, x2, y2)
259 GrGLSLProgramDataManager::UniformHandle fPositionsUni; 264 GrGLSLProgramDataManager::UniformHandle fPositionsUni;
260 265
261 // The half widths and half heights of the two round rects (w1/2, h1/2, w2/2, h2/2) 266 // The half widths and half heights of the two round rects (w1/2, h1/2, w2/2, h2/2)
262 // For circles we still upload both width & height to simplify things 267 // For circles we still upload both width & height to simplify things
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after
426 return sk_make_sp<SkRRectsGaussianEdgeShaderImpl>(first, second, radius, pad ); 431 return sk_make_sp<SkRRectsGaussianEdgeShaderImpl>(first, second, radius, pad );
427 } 432 }
428 433
429 /////////////////////////////////////////////////////////////////////////////// 434 ///////////////////////////////////////////////////////////////////////////////
430 435
431 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkRRectsGaussianEdgeShader) 436 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkRRectsGaussianEdgeShader)
432 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkRRectsGaussianEdgeShaderImpl) 437 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkRRectsGaussianEdgeShaderImpl)
433 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END 438 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END
434 439
435 /////////////////////////////////////////////////////////////////////////////// 440 ///////////////////////////////////////////////////////////////////////////////
OLDNEW
« no previous file with comments | « gm/reveal.cpp ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698