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

Side by Side Diff: src/effects/gradients/SkRadialGradient.cpp

Issue 1109883003: Revert of Mike's radial gradient CL with better float -> int. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Created 5 years, 7 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 | « src/core/SkNx.h ('k') | src/opts/SkNx_neon.h » ('j') | 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 /* 2 /*
3 * Copyright 2012 Google Inc. 3 * Copyright 2012 Google Inc.
4 * 4 *
5 * Use of this source code is governed by a BSD-style license that can be 5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file. 6 * found in the LICENSE file.
7 */ 7 */
8 8
9 #include "SkRadialGradient.h" 9 #include "SkRadialGradient.h"
10 #include "SkRadialGradient_Table.h" 10 #include "SkRadialGradient_Table.h"
11 #include "SkNx.h"
12 11
13 #define kSQRT_TABLE_BITS 11 12 #define kSQRT_TABLE_BITS 11
14 #define kSQRT_TABLE_SIZE (1 << kSQRT_TABLE_BITS) 13 #define kSQRT_TABLE_SIZE (1 << kSQRT_TABLE_BITS)
15 14
16 SK_COMPILE_ASSERT(sizeof(gSqrt8Table) == kSQRT_TABLE_SIZE, SqrtTableSizesMatch); 15 SK_COMPILE_ASSERT(sizeof(gSqrt8Table) == kSQRT_TABLE_SIZE, SqrtTableSizesMatch);
17 16
18 #if 0 17 #if 0
19 18
20 #include <stdio.h> 19 #include <stdio.h>
21 20
(...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after
264 263
265 void SkRadialGradient::flatten(SkWriteBuffer& buffer) const { 264 void SkRadialGradient::flatten(SkWriteBuffer& buffer) const {
266 this->INHERITED::flatten(buffer); 265 this->INHERITED::flatten(buffer);
267 buffer.writePoint(fCenter); 266 buffer.writePoint(fCenter);
268 buffer.writeScalar(fRadius); 267 buffer.writeScalar(fRadius);
269 } 268 }
270 269
271 namespace { 270 namespace {
272 271
273 inline bool radial_completely_pinned(int fx, int dx, int fy, int dy) { 272 inline bool radial_completely_pinned(int fx, int dx, int fy, int dy) {
274 // fast, overly-conservative test: checks unit square instead of unit circle 273 // fast, overly-conservative test: checks unit square instead
275 bool xClamped = (fx >= SK_FixedHalf && dx >= 0) || (fx <= -SK_FixedHalf && d x <= 0); 274 // of unit circle
276 bool yClamped = (fy >= SK_FixedHalf && dy >= 0) || (fy <= -SK_FixedHalf && d y <= 0); 275 bool xClamped = (fx >= SK_FixedHalf && dx >= 0) ||
276 (fx <= -SK_FixedHalf && dx <= 0);
277 bool yClamped = (fy >= SK_FixedHalf && dy >= 0) ||
278 (fy <= -SK_FixedHalf && dy <= 0);
279
277 return xClamped || yClamped; 280 return xClamped || yClamped;
278 } 281 }
279 282
280 inline bool radial_completely_pinned(SkScalar fx, SkScalar dx, SkScalar fy, SkSc alar dy) {
281 // fast, overly-conservative test: checks unit square instead of unit circle
282 bool xClamped = (fx >= 1 && dx >= 0) || (fx <= -1 && dx <= 0);
283 bool yClamped = (fy >= 1 && dy >= 0) || (fy <= -1 && dy <= 0);
284 return xClamped || yClamped;
285 }
286
287 // Return true if (fx * fy) is always inside the unit circle 283 // Return true if (fx * fy) is always inside the unit circle
288 // SkPin32 is expensive, but so are all the SkFixedMul in this test, 284 // SkPin32 is expensive, but so are all the SkFixedMul in this test,
289 // so it shouldn't be run if count is small. 285 // so it shouldn't be run if count is small.
290 inline bool no_need_for_radial_pin(int fx, int dx, 286 inline bool no_need_for_radial_pin(int fx, int dx,
291 int fy, int dy, int count) { 287 int fy, int dy, int count) {
292 SkASSERT(count > 0); 288 SkASSERT(count > 0);
293 if (SkAbs32(fx) > 0x7FFF || SkAbs32(fy) > 0x7FFF) { 289 if (SkAbs32(fx) > 0x7FFF || SkAbs32(fy) > 0x7FFF) {
294 return false; 290 return false;
295 } 291 }
296 if (fx*fx + fy*fy > 0x7FFF*0x7FFF) { 292 if (fx*fx + fy*fy > 0x7FFF*0x7FFF) {
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
370 *dstC++ = cache[toggle + (sqrt_table[fi] >> 366 *dstC++ = cache[toggle + (sqrt_table[fi] >>
371 SkGradientShaderBase::kSqrt32Shift)]; 367 SkGradientShaderBase::kSqrt32Shift)];
372 toggle = next_dither_toggle(toggle); 368 toggle = next_dither_toggle(toggle);
373 fx += dx; 369 fx += dx;
374 fy += dy; 370 fy += dy;
375 } while (--count != 0); 371 } while (--count != 0);
376 } 372 }
377 } 373 }
378 } 374 }
379 375
380 // TODO: can we get away with 0th approximatino of inverse-sqrt (i.e. faster tha n rsqrt)?
381 // seems like ~10bits is more than enough for our use, since we want a byt e-index
382 static inline Sk4f fast_sqrt(const Sk4f& R) {
383 return R * R.rsqrt();
384 }
385
386 static inline Sk4f sum_squares(const Sk4f& a, const Sk4f& b) {
387 return a * a + b * b;
388 }
389
390 void shadeSpan_radial_clamp2(SkScalar sfx, SkScalar sdx, SkScalar sfy, SkScalar sdy,
391 SkPMColor* SK_RESTRICT dstC, const SkPMColor* SK_RE STRICT cache,
392 int count, int toggle) {
393 if (radial_completely_pinned(sfx, sdx, sfy, sdy)) {
394 unsigned fi = SkGradientShaderBase::kCache32Count - 1;
395 sk_memset32_dither(dstC,
396 cache[toggle + fi],
397 cache[next_dither_toggle(toggle) + fi],
398 count);
399 } else {
400 const Sk4f max(255);
401 const float scale = 255;
402 sfx *= scale;
403 sfy *= scale;
404 sdx *= scale;
405 sdy *= scale;
406 const Sk4f fx4(sfx, sfx + sdx, sfx + 2*sdx, sfx + 3*sdx);
407 const Sk4f fy4(sfy, sfy + sdy, sfy + 2*sdy, sfy + 3*sdy);
408 const Sk4f dx4(sdx * 4);
409 const Sk4f dy4(sdy * 4);
410
411 Sk4f tmpxy = fx4 * dx4 + fy4 * dy4;
412 Sk4f tmpdxdy = sum_squares(dx4, dy4);
413 Sk4f R = sum_squares(fx4, fy4);
414 Sk4f dR = tmpxy + tmpxy + tmpdxdy;
415 const Sk4f ddR = tmpdxdy + tmpdxdy;
416
417 for (int i = 0; i < (count >> 2); ++i) {
418 Sk4f dist = Sk4f::Min(fast_sqrt(R), max);
419 R += dR;
420 dR += ddR;
421
422 int fi[4];
423 dist.castTrunc().store(fi);
424
425 for (int i = 0; i < 4; i++) {
426 *dstC++ = cache[toggle + fi[i]];
427 toggle = next_dither_toggle(toggle);
428 }
429 }
430 count &= 3;
431 if (count) {
432 Sk4f dist = Sk4f::Min(fast_sqrt(R), max);
433
434 int fi[4];
435 dist.castTrunc().store(fi);
436 for (int i = 0; i < count; i++) {
437 *dstC++ = cache[toggle + fi[i]];
438 toggle = next_dither_toggle(toggle);
439 }
440 }
441 }
442 }
443
444 // Unrolling this loop doesn't seem to help (when float); we're stalling to 376 // Unrolling this loop doesn't seem to help (when float); we're stalling to
445 // get the results of the sqrt (?), and don't have enough extra registers to 377 // get the results of the sqrt (?), and don't have enough extra registers to
446 // have many in flight. 378 // have many in flight.
447 template <SkFixed (*TileProc)(SkFixed)> 379 template <SkFixed (*TileProc)(SkFixed)>
448 void shadeSpan_radial(SkScalar fx, SkScalar dx, SkScalar fy, SkScalar dy, 380 void shadeSpan_radial(SkScalar fx, SkScalar dx, SkScalar fy, SkScalar dy,
449 SkPMColor* SK_RESTRICT dstC, const SkPMColor* SK_RESTRICT cache, 381 SkPMColor* SK_RESTRICT dstC, const SkPMColor* SK_RESTRICT cache,
450 int count, int toggle) { 382 int count, int toggle) {
451 do { 383 do {
452 const SkFixed dist = SkFloatToFixed(sk_float_sqrt(fx*fx + fy*fy)); 384 const SkFixed dist = SkFloatToFixed(sk_float_sqrt(fx*fx + fy*fy));
453 const unsigned fi = TileProc(dist); 385 const unsigned fi = TileProc(dist);
(...skipping 14 matching lines...) Expand all
468 void shadeSpan_radial_repeat(SkScalar fx, SkScalar dx, SkScalar fy, SkScalar dy, 400 void shadeSpan_radial_repeat(SkScalar fx, SkScalar dx, SkScalar fy, SkScalar dy,
469 SkPMColor* SK_RESTRICT dstC, const SkPMColor* SK_RE STRICT cache, 401 SkPMColor* SK_RESTRICT dstC, const SkPMColor* SK_RE STRICT cache,
470 int count, int toggle) { 402 int count, int toggle) {
471 shadeSpan_radial<repeat_tileproc_nonstatic>(fx, dx, fy, dy, dstC, cache, cou nt, toggle); 403 shadeSpan_radial<repeat_tileproc_nonstatic>(fx, dx, fy, dy, dstC, cache, cou nt, toggle);
472 } 404 }
473 405
474 } // namespace 406 } // namespace
475 407
476 void SkRadialGradient::RadialGradientContext::shadeSpan(int x, int y, 408 void SkRadialGradient::RadialGradientContext::shadeSpan(int x, int y,
477 SkPMColor* SK_RESTRICT d stC, int count) { 409 SkPMColor* SK_RESTRICT d stC, int count) {
478 #ifdef SK_SUPPORT_LEGACY_RADIAL_GRADIENT_SQRT
479 const bool use_new_proc = false;
480 #else
481 const bool use_new_proc = true;
482 #endif
483 SkASSERT(count > 0); 410 SkASSERT(count > 0);
484 411
485 const SkRadialGradient& radialGradient = static_cast<const SkRadialGradient& >(fShader); 412 const SkRadialGradient& radialGradient = static_cast<const SkRadialGradient& >(fShader);
486 413
487 SkPoint srcPt; 414 SkPoint srcPt;
488 SkMatrix::MapXYProc dstProc = fDstToIndexProc; 415 SkMatrix::MapXYProc dstProc = fDstToIndexProc;
489 TileProc proc = radialGradient.fTileProc; 416 TileProc proc = radialGradient.fTileProc;
490 const SkPMColor* SK_RESTRICT cache = fCache->getCache32(); 417 const SkPMColor* SK_RESTRICT cache = fCache->getCache32();
491 int toggle = init_dither_toggle(x, y); 418 int toggle = init_dither_toggle(x, y);
492 419
493 if (fDstToIndexClass != kPerspective_MatrixClass) { 420 if (fDstToIndexClass != kPerspective_MatrixClass) {
494 dstProc(fDstToIndex, SkIntToScalar(x) + SK_ScalarHalf, 421 dstProc(fDstToIndex, SkIntToScalar(x) + SK_ScalarHalf,
495 SkIntToScalar(y) + SK_ScalarHalf, &srcPt); 422 SkIntToScalar(y) + SK_ScalarHalf, &srcPt);
496 SkScalar sdx = fDstToIndex.getScaleX(); 423 SkScalar sdx = fDstToIndex.getScaleX();
497 SkScalar sdy = fDstToIndex.getSkewY(); 424 SkScalar sdy = fDstToIndex.getSkewY();
498 425
499 if (fDstToIndexClass == kFixedStepInX_MatrixClass) { 426 if (fDstToIndexClass == kFixedStepInX_MatrixClass) {
500 SkFixed storage[2]; 427 SkFixed storage[2];
501 (void)fDstToIndex.fixedStepInX(SkIntToScalar(y), 428 (void)fDstToIndex.fixedStepInX(SkIntToScalar(y),
502 &storage[0], &storage[1]); 429 &storage[0], &storage[1]);
503 sdx = SkFixedToScalar(storage[0]); 430 sdx = SkFixedToScalar(storage[0]);
504 sdy = SkFixedToScalar(storage[1]); 431 sdy = SkFixedToScalar(storage[1]);
505 } else { 432 } else {
506 SkASSERT(fDstToIndexClass == kLinear_MatrixClass); 433 SkASSERT(fDstToIndexClass == kLinear_MatrixClass);
507 } 434 }
508 435
509 RadialShadeProc shadeProc = shadeSpan_radial_repeat; 436 RadialShadeProc shadeProc = shadeSpan_radial_repeat;
510 if (SkShader::kClamp_TileMode == radialGradient.fTileMode) { 437 if (SkShader::kClamp_TileMode == radialGradient.fTileMode) {
511 shadeProc = use_new_proc ? shadeSpan_radial_clamp2 : shadeSpan_radia l_clamp; 438 shadeProc = shadeSpan_radial_clamp;
512 } else if (SkShader::kMirror_TileMode == radialGradient.fTileMode) { 439 } else if (SkShader::kMirror_TileMode == radialGradient.fTileMode) {
513 shadeProc = shadeSpan_radial_mirror; 440 shadeProc = shadeSpan_radial_mirror;
514 } else { 441 } else {
515 SkASSERT(SkShader::kRepeat_TileMode == radialGradient.fTileMode); 442 SkASSERT(SkShader::kRepeat_TileMode == radialGradient.fTileMode);
516 } 443 }
517 (*shadeProc)(srcPt.fX, sdx, srcPt.fY, sdy, dstC, cache, count, toggle); 444 (*shadeProc)(srcPt.fX, sdx, srcPt.fY, sdy, dstC, cache, count, toggle);
518 } else { // perspective case 445 } else { // perspective case
519 SkScalar dstX = SkIntToScalar(x); 446 SkScalar dstX = SkIntToScalar(x);
520 SkScalar dstY = SkIntToScalar(y); 447 SkScalar dstY = SkIntToScalar(y);
521 do { 448 do {
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after
688 str->appendScalar(fCenter.fY); 615 str->appendScalar(fCenter.fY);
689 str->append(") radius: "); 616 str->append(") radius: ");
690 str->appendScalar(fRadius); 617 str->appendScalar(fRadius);
691 str->append(" "); 618 str->append(" ");
692 619
693 this->INHERITED::toString(str); 620 this->INHERITED::toString(str);
694 621
695 str->append(")"); 622 str->append(")");
696 } 623 }
697 #endif 624 #endif
OLDNEW
« no previous file with comments | « src/core/SkNx.h ('k') | src/opts/SkNx_neon.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698