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

Side by Side Diff: src/gpu/effects/GrRRectEffect.cpp

Issue 1517483002: Prevent overflow in length() in GLCircularRRectEffect (Closed) Base URL: https://skia.googlesource.com/skia.git@gm
Patch Set: Remove \n's Created 5 years 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 | « no previous file | 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 2014 Google Inc. 2 * Copyright 2014 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 "GrRRectEffect.h" 8 #include "GrRRectEffect.h"
9 9
10 #include "GrConvexPolyEffect.h" 10 #include "GrConvexPolyEffect.h"
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after
155 const char *rectName; 155 const char *rectName;
156 const char *radiusPlusHalfName; 156 const char *radiusPlusHalfName;
157 // The inner rect is the rrect bounds inset by the radius. Its left, top, ri ght, and bottom 157 // The inner rect is the rrect bounds inset by the radius. Its left, top, ri ght, and bottom
158 // edges correspond to components x, y, z, and w, respectively. When a side of the rrect has 158 // edges correspond to components x, y, z, and w, respectively. When a side of the rrect has
159 // only rectangular corners, that side's value corresponds to the rect edge' s value outset by 159 // only rectangular corners, that side's value corresponds to the rect edge' s value outset by
160 // half a pixel. 160 // half a pixel.
161 fInnerRectUniform = uniformHandler->addUniform(GrGLSLUniformHandler::kFragme nt_Visibility, 161 fInnerRectUniform = uniformHandler->addUniform(GrGLSLUniformHandler::kFragme nt_Visibility,
162 kVec4f_GrSLType, kDefault_GrS LPrecision, 162 kVec4f_GrSLType, kDefault_GrS LPrecision,
163 "innerRect", 163 "innerRect",
164 &rectName); 164 &rectName);
165 // x is (r + .5) and y is 1/(r + .5)
165 fRadiusPlusHalfUniform = uniformHandler->addUniform(GrGLSLUniformHandler::kF ragment_Visibility, 166 fRadiusPlusHalfUniform = uniformHandler->addUniform(GrGLSLUniformHandler::kF ragment_Visibility,
166 kFloat_GrSLType, kDefaul t_GrSLPrecision, 167 kVec2f_GrSLType, kDefaul t_GrSLPrecision,
167 "radiusPlusHalf", 168 "radiusPlusHalf",
168 &radiusPlusHalfName); 169 &radiusPlusHalfName);
169 170
171 // If we're on a device with a "real" mediump then the length calculation co uld overflow.
172 SkString clampedCircleDistance;
173 if (args.fGLSLCaps->floatPrecisionVaries()) {
174 clampedCircleDistance.printf("clamp(%s.x * (1.0 - length(dxy * %s.y)), 0 .0, 1.0);",
175 radiusPlusHalfName, radiusPlusHalfName);
176 } else {
177 clampedCircleDistance.printf("clamp(%s.x - length(dxy), 0.0, 1.0);", rad iusPlusHalfName);
178 }
179
170 GrGLSLFragmentBuilder* fragBuilder = args.fFragBuilder; 180 GrGLSLFragmentBuilder* fragBuilder = args.fFragBuilder;
171 const char* fragmentPos = fragBuilder->fragmentPosition(); 181 const char* fragmentPos = fragBuilder->fragmentPosition();
172 // At each quarter-circle corner we compute a vector that is the offset of t he fragment position 182 // At each quarter-circle corner we compute a vector that is the offset of t he fragment position
173 // from the circle center. The vector is pinned in x and y to be in the quar ter-plane relevant 183 // from the circle center. The vector is pinned in x and y to be in the quar ter-plane relevant
174 // to that corner. This means that points near the interior near the rrect t op edge will have 184 // to that corner. This means that points near the interior near the rrect t op edge will have
175 // a vector that points straight up for both the TL left and TR corners. Com puting an 185 // a vector that points straight up for both the TL left and TR corners. Com puting an
176 // alpha from this vector at either the TR or TL corner will give the correc t result. Similarly, 186 // alpha from this vector at either the TR or TL corner will give the correc t result. Similarly,
177 // fragments near the other three edges will get the correct AA. Fragments i n the interior of 187 // fragments near the other three edges will get the correct AA. Fragments i n the interior of
178 // the rrect will have a (0,0) vector at all four corners. So long as the ra dius > 0.5 they will 188 // the rrect will have a (0,0) vector at all four corners. So long as the ra dius > 0.5 they will
179 // correctly produce an alpha value of 1 at all four corners. We take the mi n of all the alphas. 189 // correctly produce an alpha value of 1 at all four corners. We take the mi n of all the alphas.
180 // The code below is a simplified version of the above that performs maxs on the vector 190 // The code below is a simplified version of the above that performs maxs on the vector
181 // components before computing distances and alpha values so that only one d istance computation 191 // components before computing distances and alpha values so that only one d istance computation
182 // need be computed to determine the min alpha. 192 // need be computed to determine the min alpha.
183 // 193 //
184 // For the cases where one half of the rrect is rectangular we drop one of t he x or y 194 // For the cases where one half of the rrect is rectangular we drop one of t he x or y
185 // computations, compute a separate rect edge alpha for the rect side, and m ul the two computed 195 // computations, compute a separate rect edge alpha for the rect side, and m ul the two computed
186 // alphas together. 196 // alphas together.
187 switch (crre.getCircularCornerFlags()) { 197 switch (crre.getCircularCornerFlags()) {
188 case CircularRRectEffect::kAll_CornerFlags: 198 case CircularRRectEffect::kAll_CornerFlags:
189 fragBuilder->codeAppendf("\t\tvec2 dxy0 = %s.xy - %s.xy;\n", rectNam e, fragmentPos); 199 fragBuilder->codeAppendf("vec2 dxy0 = %s.xy - %s.xy;", rectName, fra gmentPos);
190 fragBuilder->codeAppendf("\t\tvec2 dxy1 = %s.xy - %s.zw;\n", fragmen tPos, rectName); 200 fragBuilder->codeAppendf("vec2 dxy1 = %s.xy - %s.zw;", fragmentPos, rectName);
191 fragBuilder->codeAppend("\t\tvec2 dxy = max(max(dxy0, dxy1), 0.0);\n "); 201 fragBuilder->codeAppend("vec2 dxy = max(max(dxy0, dxy1), 0.0);");
192 fragBuilder->codeAppendf("\t\tfloat alpha = clamp(%s - length(dxy), 0.0, 1.0);\n", 202 fragBuilder->codeAppendf("float alpha = %s;", clampedCircleDistance. c_str());
193 radiusPlusHalfName);
194 break; 203 break;
195 case CircularRRectEffect::kTopLeft_CornerFlag: 204 case CircularRRectEffect::kTopLeft_CornerFlag:
196 fragBuilder->codeAppendf("\t\tvec2 dxy = max(%s.xy - %s.xy, 0.0);\n" , 205 fragBuilder->codeAppendf("vec2 dxy = max(%s.xy - %s.xy, 0.0);",
197 rectName, fragmentPos); 206 rectName, fragmentPos);
198 fragBuilder->codeAppendf("\t\tfloat rightAlpha = clamp(%s.z - %s.x, 0.0, 1.0);\n", 207 fragBuilder->codeAppendf("float rightAlpha = clamp(%s.z - %s.x, 0.0, 1.0);",
199 rectName, fragmentPos); 208 rectName, fragmentPos);
200 fragBuilder->codeAppendf("\t\tfloat bottomAlpha = clamp(%s.w - %s.y, 0.0, 1.0);\n", 209 fragBuilder->codeAppendf("float bottomAlpha = clamp(%s.w - %s.y, 0.0 , 1.0);",
201 rectName, fragmentPos); 210 rectName, fragmentPos);
202 fragBuilder->codeAppendf( 211 fragBuilder->codeAppendf("float alpha = bottomAlpha * rightAlpha * % s;",
203 "\t\tfloat alpha = bottomAlpha * rightAlpha * clamp(%s - length( dxy), 0.0, 1.0);\n", 212 clampedCircleDistance.c_str());
204 radiusPlusHalfName);
205 break; 213 break;
206 case CircularRRectEffect::kTopRight_CornerFlag: 214 case CircularRRectEffect::kTopRight_CornerFlag:
207 fragBuilder->codeAppendf("\t\tvec2 dxy = max(vec2(%s.x - %s.z, %s.y - %s.y), 0.0);\n", 215 fragBuilder->codeAppendf("vec2 dxy = max(vec2(%s.x - %s.z, %s.y - %s .y), 0.0);",
208 fragmentPos, rectName, rectName, fragmentPo s); 216 fragmentPos, rectName, rectName, fragmentPo s);
209 fragBuilder->codeAppendf("\t\tfloat leftAlpha = clamp(%s.x - %s.x, 0 .0, 1.0);\n", 217 fragBuilder->codeAppendf("float leftAlpha = clamp(%s.x - %s.x, 0.0, 1.0);",
210 fragmentPos, rectName); 218 fragmentPos, rectName);
211 fragBuilder->codeAppendf("\t\tfloat bottomAlpha = clamp(%s.w - %s.y, 0.0, 1.0);\n", 219 fragBuilder->codeAppendf("float bottomAlpha = clamp(%s.w - %s.y, 0.0 , 1.0);",
212 rectName, fragmentPos); 220 rectName, fragmentPos);
213 fragBuilder->codeAppendf( 221 fragBuilder->codeAppendf("float alpha = bottomAlpha * leftAlpha * %s ;",
214 "\t\tfloat alpha = bottomAlpha * leftAlpha * clamp(%s - length(d xy), 0.0, 1.0);\n", 222 clampedCircleDistance.c_str());
215 radiusPlusHalfName);
216 break; 223 break;
217 case CircularRRectEffect::kBottomRight_CornerFlag: 224 case CircularRRectEffect::kBottomRight_CornerFlag:
218 fragBuilder->codeAppendf("\t\tvec2 dxy = max(%s.xy - %s.zw, 0.0);\n" , 225 fragBuilder->codeAppendf("vec2 dxy = max(%s.xy - %s.zw, 0.0);",
219 fragmentPos, rectName); 226 fragmentPos, rectName);
220 fragBuilder->codeAppendf("\t\tfloat leftAlpha = clamp(%s.x - %s.x, 0 .0, 1.0);\n", 227 fragBuilder->codeAppendf("float leftAlpha = clamp(%s.x - %s.x, 0.0, 1.0);",
221 fragmentPos, rectName); 228 fragmentPos, rectName);
222 fragBuilder->codeAppendf("\t\tfloat topAlpha = clamp(%s.y - %s.y, 0. 0, 1.0);\n", 229 fragBuilder->codeAppendf("float topAlpha = clamp(%s.y - %s.y, 0.0, 1 .0);",
223 fragmentPos, rectName); 230 fragmentPos, rectName);
224 fragBuilder->codeAppendf( 231 fragBuilder->codeAppendf("float alpha = topAlpha * leftAlpha * %s;",
225 "\t\tfloat alpha = topAlpha * leftAlpha * clamp(%s - length(dxy) , 0.0, 1.0);\n", 232 clampedCircleDistance.c_str());
226 radiusPlusHalfName);
227 break; 233 break;
228 case CircularRRectEffect::kBottomLeft_CornerFlag: 234 case CircularRRectEffect::kBottomLeft_CornerFlag:
229 fragBuilder->codeAppendf("\t\tvec2 dxy = max(vec2(%s.x - %s.x, %s.y - %s.w), 0.0);\n", 235 fragBuilder->codeAppendf("vec2 dxy = max(vec2(%s.x - %s.x, %s.y - %s .w), 0.0);",
230 rectName, fragmentPos, fragmentPos, rectNam e); 236 rectName, fragmentPos, fragmentPos, rectNam e);
231 fragBuilder->codeAppendf("\t\tfloat rightAlpha = clamp(%s.z - %s.x, 0.0, 1.0);\n", 237 fragBuilder->codeAppendf("float rightAlpha = clamp(%s.z - %s.x, 0.0, 1.0);",
232 rectName, fragmentPos); 238 rectName, fragmentPos);
233 fragBuilder->codeAppendf("\t\tfloat topAlpha = clamp(%s.y - %s.y, 0. 0, 1.0);\n", 239 fragBuilder->codeAppendf("float topAlpha = clamp(%s.y - %s.y, 0.0, 1 .0);",
234 fragmentPos, rectName); 240 fragmentPos, rectName);
235 fragBuilder->codeAppendf( 241 fragBuilder->codeAppendf("float alpha = topAlpha * rightAlpha * %s;" ,
236 "\t\tfloat alpha = topAlpha * rightAlpha * clamp(%s - length(dxy ), 0.0, 1.0);\n", 242 clampedCircleDistance.c_str());
237 radiusPlusHalfName);
238 break; 243 break;
239 case CircularRRectEffect::kLeft_CornerFlags: 244 case CircularRRectEffect::kLeft_CornerFlags:
240 fragBuilder->codeAppendf("\t\tvec2 dxy0 = %s.xy - %s.xy;\n", rectNam e, fragmentPos); 245 fragBuilder->codeAppendf("vec2 dxy0 = %s.xy - %s.xy;", rectName, fra gmentPos);
241 fragBuilder->codeAppendf("\t\tfloat dy1 = %s.y - %s.w;\n", fragmentP os, rectName); 246 fragBuilder->codeAppendf("float dy1 = %s.y - %s.w;", fragmentPos, re ctName);
242 fragBuilder->codeAppend("\t\tvec2 dxy = max(vec2(dxy0.x, max(dxy0.y, dy1)), 0.0);\n"); 247 fragBuilder->codeAppend("vec2 dxy = max(vec2(dxy0.x, max(dxy0.y, dy1 )), 0.0);");
243 fragBuilder->codeAppendf("\t\tfloat rightAlpha = clamp(%s.z - %s.x, 0.0, 1.0);\n", 248 fragBuilder->codeAppendf("float rightAlpha = clamp(%s.z - %s.x, 0.0, 1.0);",
244 rectName, fragmentPos); 249 rectName, fragmentPos);
245 fragBuilder->codeAppendf( 250 fragBuilder->codeAppendf("float alpha = rightAlpha * %s;",
246 "\t\tfloat alpha = rightAlpha * clamp(%s - length(dxy), 0.0, 1.0 );\n", 251 clampedCircleDistance.c_str());
247 radiusPlusHalfName);
248 break; 252 break;
249 case CircularRRectEffect::kTop_CornerFlags: 253 case CircularRRectEffect::kTop_CornerFlags:
250 fragBuilder->codeAppendf("\t\tvec2 dxy0 = %s.xy - %s.xy;\n", rectNam e, fragmentPos); 254 fragBuilder->codeAppendf("vec2 dxy0 = %s.xy - %s.xy;", rectName, fra gmentPos);
251 fragBuilder->codeAppendf("\t\tfloat dx1 = %s.x - %s.z;\n", fragmentP os, rectName); 255 fragBuilder->codeAppendf("float dx1 = %s.x - %s.z;", fragmentPos, re ctName);
252 fragBuilder->codeAppend("\t\tvec2 dxy = max(vec2(max(dxy0.x, dx1), d xy0.y), 0.0);\n"); 256 fragBuilder->codeAppend("vec2 dxy = max(vec2(max(dxy0.x, dx1), dxy0. y), 0.0);");
253 fragBuilder->codeAppendf("\t\tfloat bottomAlpha = clamp(%s.w - %s.y, 0.0, 1.0);\n", 257 fragBuilder->codeAppendf("float bottomAlpha = clamp(%s.w - %s.y, 0.0 , 1.0);",
254 rectName, fragmentPos); 258 rectName, fragmentPos);
255 fragBuilder->codeAppendf( 259 fragBuilder->codeAppendf("float alpha = bottomAlpha * %s;",
256 "\t\tfloat alpha = bottomAlpha * clamp(%s - length(dxy), 0.0, 1. 0);\n", 260 clampedCircleDistance.c_str());
257 radiusPlusHalfName);
258 break; 261 break;
259 case CircularRRectEffect::kRight_CornerFlags: 262 case CircularRRectEffect::kRight_CornerFlags:
260 fragBuilder->codeAppendf("\t\tfloat dy0 = %s.y - %s.y;\n", rectName, fragmentPos); 263 fragBuilder->codeAppendf("float dy0 = %s.y - %s.y;", rectName, fragm entPos);
261 fragBuilder->codeAppendf("\t\tvec2 dxy1 = %s.xy - %s.zw;\n", fragmen tPos, rectName); 264 fragBuilder->codeAppendf("vec2 dxy1 = %s.xy - %s.zw;", fragmentPos, rectName);
262 fragBuilder->codeAppend("\t\tvec2 dxy = max(vec2(dxy1.x, max(dy0, dx y1.y)), 0.0);\n"); 265 fragBuilder->codeAppend("vec2 dxy = max(vec2(dxy1.x, max(dy0, dxy1.y )), 0.0);");
263 fragBuilder->codeAppendf("\t\tfloat leftAlpha = clamp(%s.x - %s.x, 0 .0, 1.0);\n", 266 fragBuilder->codeAppendf("float leftAlpha = clamp(%s.x - %s.x, 0.0, 1.0);",
264 fragmentPos, rectName); 267 fragmentPos, rectName);
265 fragBuilder->codeAppendf( 268 fragBuilder->codeAppendf("float alpha = leftAlpha * %s;",
266 "\t\tfloat alpha = leftAlpha * clamp(%s - length(dxy), 0.0, 1.0) ;\n", 269 clampedCircleDistance.c_str());
267 radiusPlusHalfName);
268 break; 270 break;
269 case CircularRRectEffect::kBottom_CornerFlags: 271 case CircularRRectEffect::kBottom_CornerFlags:
270 fragBuilder->codeAppendf("\t\tfloat dx0 = %s.x - %s.x;\n", rectName, fragmentPos); 272 fragBuilder->codeAppendf("float dx0 = %s.x - %s.x;", rectName, fragm entPos);
271 fragBuilder->codeAppendf("\t\tvec2 dxy1 = %s.xy - %s.zw;\n", fragmen tPos, rectName); 273 fragBuilder->codeAppendf("vec2 dxy1 = %s.xy - %s.zw;", fragmentPos, rectName);
272 fragBuilder->codeAppend("\t\tvec2 dxy = max(vec2(max(dx0, dxy1.x), d xy1.y), 0.0);\n"); 274 fragBuilder->codeAppend("vec2 dxy = max(vec2(max(dx0, dxy1.x), dxy1. y), 0.0);");
273 fragBuilder->codeAppendf("\t\tfloat topAlpha = clamp(%s.y - %s.y, 0. 0, 1.0);\n", 275 fragBuilder->codeAppendf("float topAlpha = clamp(%s.y - %s.y, 0.0, 1 .0);",
274 fragmentPos, rectName); 276 fragmentPos, rectName);
275 fragBuilder->codeAppendf( 277 fragBuilder->codeAppendf("float alpha = topAlpha * %s;",
276 "\t\tfloat alpha = topAlpha * clamp(%s - length(dxy), 0.0, 1.0); \n", 278 clampedCircleDistance.c_str());
277 radiusPlusHalfName);
278 break; 279 break;
279 } 280 }
280 281
281 if (kInverseFillAA_GrProcessorEdgeType == crre.getEdgeType()) { 282 if (kInverseFillAA_GrProcessorEdgeType == crre.getEdgeType()) {
282 fragBuilder->codeAppend("\t\talpha = 1.0 - alpha;\n"); 283 fragBuilder->codeAppend("alpha = 1.0 - alpha;");
283 } 284 }
284 285
285 fragBuilder->codeAppendf("\t\t%s = %s;\n", args.fOutputColor, 286 fragBuilder->codeAppendf("%s = %s;", args.fOutputColor,
286 (GrGLSLExpr4(args.fInputColor) * GrGLSLExpr1("alpha ")).c_str()); 287 (GrGLSLExpr4(args.fInputColor) * GrGLSLExpr1("alpha ")).c_str());
287 } 288 }
288 289
289 void GLCircularRRectEffect::GenKey(const GrProcessor& processor, const GrGLSLCap s&, 290 void GLCircularRRectEffect::GenKey(const GrProcessor& processor, const GrGLSLCap s&,
290 GrProcessorKeyBuilder* b) { 291 GrProcessorKeyBuilder* b) {
291 const CircularRRectEffect& crre = processor.cast<CircularRRectEffect>(); 292 const CircularRRectEffect& crre = processor.cast<CircularRRectEffect>();
292 GR_STATIC_ASSERT(kGrProcessorEdgeTypeCnt <= 8); 293 GR_STATIC_ASSERT(kGrProcessorEdgeTypeCnt <= 8);
293 b->add32((crre.getCircularCornerFlags() << 3) | crre.getEdgeType()); 294 b->add32((crre.getCircularCornerFlags() << 3) | crre.getEdgeType());
294 } 295 }
295 296
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
360 radius = rrect.radii(SkRRect::kLowerLeft_Corner).fX; 361 radius = rrect.radii(SkRRect::kLowerLeft_Corner).fX;
361 rect.fLeft += radius; 362 rect.fLeft += radius;
362 rect.fTop -= 0.5f; 363 rect.fTop -= 0.5f;
363 rect.fRight -= radius; 364 rect.fRight -= radius;
364 rect.fBottom -= radius; 365 rect.fBottom -= radius;
365 break; 366 break;
366 default: 367 default:
367 SkFAIL("Should have been one of the above cases."); 368 SkFAIL("Should have been one of the above cases.");
368 } 369 }
369 pdman.set4f(fInnerRectUniform, rect.fLeft, rect.fTop, rect.fRight, rect. fBottom); 370 pdman.set4f(fInnerRectUniform, rect.fLeft, rect.fTop, rect.fRight, rect. fBottom);
370 pdman.set1f(fRadiusPlusHalfUniform, radius + 0.5f); 371 radius += 0.5f;
372 pdman.set2f(fRadiusPlusHalfUniform, radius, 1.f / radius);
371 fPrevRRect = rrect; 373 fPrevRRect = rrect;
372 } 374 }
373 } 375 }
374 376
375 //////////////////////////////////////////////////////////////////////////////// //////////////////// 377 //////////////////////////////////////////////////////////////////////////////// ////////////////////
376 378
377 void CircularRRectEffect::onGetGLSLProcessorKey(const GrGLSLCaps& caps, 379 void CircularRRectEffect::onGetGLSLProcessorKey(const GrGLSLCaps& caps,
378 GrProcessorKeyBuilder* b) const { 380 GrProcessorKeyBuilder* b) const {
379 GLCircularRRectEffect::GenKey(*this, caps, b); 381 GLCircularRRectEffect::GenKey(*this, caps, b);
380 } 382 }
(...skipping 345 matching lines...) Expand 10 before | Expand all | Expand 10 after
726 if (rrect.isNinePatch()) { 728 if (rrect.isNinePatch()) {
727 return EllipticalRRectEffect::Create(edgeType, rrect); 729 return EllipticalRRectEffect::Create(edgeType, rrect);
728 } 730 }
729 return nullptr; 731 return nullptr;
730 } 732 }
731 } 733 }
732 } 734 }
733 735
734 return nullptr; 736 return nullptr;
735 } 737 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698