Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 | 1 |
| 2 /* | 2 /* |
| 3 * Copyright 2006 The Android Open Source Project | 3 * Copyright 2006 The Android Open Source Project |
| 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 | 9 |
| 10 #include "SkBlurMask.h" | 10 #include "SkBlurMask.h" |
| 11 #include "SkMath.h" | 11 #include "SkMath.h" |
| 12 #include "SkScaledImageCache.h" | |
| 12 #include "SkTemplates.h" | 13 #include "SkTemplates.h" |
| 13 #include "SkEndian.h" | 14 #include "SkEndian.h" |
| 14 | 15 |
| 15 | 16 |
| 16 // This constant approximates the scaling done in the software path's | 17 // This constant approximates the scaling done in the software path's |
| 17 // "high quality" mode, in SkBlurMask::Blur() (1 / sqrt(3)). | 18 // "high quality" mode, in SkBlurMask::Blur() (1 / sqrt(3)). |
| 18 // IMHO, it actually should be 1: we blur "less" than we should do | 19 // IMHO, it actually should be 1: we blur "less" than we should do |
| 19 // according to the CSS and canvas specs, simply because Safari does the same. | 20 // according to the CSS and canvas specs, simply because Safari does the same. |
| 20 // Firefox used to do the same too, until 4.0 where they fixed it. So at some | 21 // Firefox used to do the same too, until 4.0 where they fixed it. So at some |
| 21 // point we should probably get rid of these scaling constants and rebaseline | 22 // point we should probably get rid of these scaling constants and rebaseline |
| 22 // all the blur tests. | 23 // all the blur tests. |
| 23 static const SkScalar kBLUR_SIGMA_SCALE = 0.57735f; | 24 static const SkScalar kBLUR_SIGMA_SCALE = 0.57735f; |
| 25 std::map<SkMask*, SkDiscardableMemoryMask*> SkBlurMask::fDiscardableMemoryMaskMa p; | |
| 26 | |
| 27 SK_DECLARE_STATIC_MUTEX(gMapMutex); | |
| 28 | |
| 29 bool SkBlurMask::addDiscardableMemoryMaskToMap(SkMask* mask, SkDiscardableMemory Mask* dmMask) { | |
| 30 SkAutoMutexAcquire am(gMapMutex); | |
| 31 fDiscardableMemoryMaskMap.insert(std::pair<SkMask*, SkDiscardableMemoryMask* >(mask, dmMask)); | |
| 32 return true; | |
| 33 } | |
| 34 | |
| 35 bool SkBlurMask::removeDiscardableMemoryMaskFromMap(SkMask* mask) { | |
| 36 SkAutoMutexAcquire am(gMapMutex); | |
| 37 std::map<SkMask*, SkDiscardableMemoryMask*>::iterator it; | |
| 38 it = fDiscardableMemoryMaskMap.find(mask); | |
| 39 if (it != fDiscardableMemoryMaskMap.end()) | |
| 40 fDiscardableMemoryMaskMap.erase(it); | |
| 41 return true; | |
| 42 } | |
| 43 | |
| 44 SkDiscardableMemoryMask* SkBlurMask::getDiscardableMemoryMaskFromMap(SkMask* mas k) { | |
| 45 SkAutoMutexAcquire am(gMapMutex); | |
| 46 std::map<SkMask*, SkDiscardableMemoryMask*>::iterator it; | |
| 47 it = fDiscardableMemoryMaskMap.find(mask); | |
| 48 if (it != fDiscardableMemoryMaskMap.end()) | |
| 49 return it->second; | |
| 50 return NULL; | |
| 51 } | |
| 24 | 52 |
| 25 SkScalar SkBlurMask::ConvertRadiusToSigma(SkScalar radius) { | 53 SkScalar SkBlurMask::ConvertRadiusToSigma(SkScalar radius) { |
| 26 return radius > 0 ? kBLUR_SIGMA_SCALE * radius + 0.5f : 0.0f; | 54 return radius > 0 ? kBLUR_SIGMA_SCALE * radius + 0.5f : 0.0f; |
| 27 } | 55 } |
| 28 | 56 |
| 29 SkScalar SkBlurMask::ConvertSigmaToRadius(SkScalar sigma) { | 57 SkScalar SkBlurMask::ConvertSigmaToRadius(SkScalar sigma) { |
| 30 return sigma > 0.5f ? (sigma - 0.5f) / kBLUR_SIGMA_SCALE : 0.0f; | 58 return sigma > 0.5f ? (sigma - 0.5f) / kBLUR_SIGMA_SCALE : 0.0f; |
| 31 } | 59 } |
| 32 | 60 |
| 33 #define UNROLL_SEPARABLE_LOOPS | 61 #define UNROLL_SEPARABLE_LOOPS |
| (...skipping 500 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 534 | 562 |
| 535 if (src.fImage) { | 563 if (src.fImage) { |
| 536 size_t dstSize = dst->computeImageSize(); | 564 size_t dstSize = dst->computeImageSize(); |
| 537 if (0 == dstSize) { | 565 if (0 == dstSize) { |
| 538 return false; // too big to allocate, abort | 566 return false; // too big to allocate, abort |
| 539 } | 567 } |
| 540 | 568 |
| 541 int sw = src.fBounds.width(); | 569 int sw = src.fBounds.width(); |
| 542 int sh = src.fBounds.height(); | 570 int sh = src.fBounds.height(); |
| 543 const uint8_t* sp = src.fImage; | 571 const uint8_t* sp = src.fImage; |
| 544 uint8_t* dp = SkMask::AllocImage(dstSize); | 572 uint8_t* dp = NULL; |
| 545 SkAutoTCallVProc<uint8_t, SkMask_FreeImage> autoCall(dp); | 573 SkDiscardableMemoryMask* dm = SkBlurMask::getDiscardableMemoryMaskFromMa p(dst); |
| 574 if (dm) { | |
| 575 SkBitmap bitmap; | |
| 576 SkBitmap::Allocator* allocator = SkScaledImageCache::GetAllocator(); | |
| 577 bitmap.setConfig(SkBitmap::kA8_Config, dst->fBounds.width(), | |
| 578 dst->fBounds.height(), dst->fRowBytes); | |
| 579 bitmap.allocPixels(allocator, NULL); | |
| 580 if (!bitmap.readyToDraw()) { | |
| 581 return false; | |
| 582 } | |
| 583 dm->fPixelGenerationID = bitmap.getGenerationID(); | |
| 584 dm->fCacheId = SkScaledImageCache::AddAndLock(dm->fPixelGenerationID , | |
| 585 bitmap.width(), | |
| 586 bitmap.height(), | |
| 587 bitmap); | |
| 588 SkASSERT(dm->fCacheId != NULL); | |
| 589 dp = static_cast<uint8_t*>(bitmap.getPixels()); | |
| 590 } else | |
| 591 dp = SkMask::AllocImage(dstSize); | |
| 546 | 592 |
| 547 // build the blurry destination | 593 // build the blurry destination |
| 548 SkAutoTMalloc<uint8_t> tmpBuffer(dstSize); | 594 SkAutoTMalloc<uint8_t> tmpBuffer(dstSize); |
| 549 uint8_t* tp = tmpBuffer.get(); | 595 uint8_t* tp = tmpBuffer.get(); |
| 550 int w = sw, h = sh; | 596 int w = sw, h = sh; |
| 551 | 597 |
| 552 if (outerWeight == 255) { | 598 if (outerWeight == 255) { |
| 553 int loRadius, hiRadius; | 599 int loRadius, hiRadius; |
| 554 get_adjusted_radii(passRadius, &loRadius, &hiRadius); | 600 get_adjusted_radii(passRadius, &loRadius, &hiRadius); |
| 555 if (kHigh_SkBlurQuality == quality) { | 601 if (kHigh_SkBlurQuality == quality) { |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 581 } | 627 } |
| 582 } | 628 } |
| 583 | 629 |
| 584 dst->fImage = dp; | 630 dst->fImage = dp; |
| 585 // if need be, alloc the "real" dst (same size as src) and copy/merge | 631 // if need be, alloc the "real" dst (same size as src) and copy/merge |
| 586 // the blur into it (applying the src) | 632 // the blur into it (applying the src) |
| 587 if (style == kInner_SkBlurStyle) { | 633 if (style == kInner_SkBlurStyle) { |
| 588 // now we allocate the "real" dst, mirror the size of src | 634 // now we allocate the "real" dst, mirror the size of src |
| 589 size_t srcSize = src.computeImageSize(); | 635 size_t srcSize = src.computeImageSize(); |
| 590 if (0 == srcSize) { | 636 if (0 == srcSize) { |
| 637 if (dm) { | |
| 638 SkScaledImageCache::Unlock(static_cast<SkScaledImageCache::I D*>(dm->fCacheId)); | |
|
Stephen White
2014/06/09 18:03:57
This 5-line stanza is repeated 3 times. Could we r
| |
| 639 } else if (dp) { | |
| 640 SkMask::FreeImage(dp); | |
| 641 } | |
| 591 return false; // too big to allocate, abort | 642 return false; // too big to allocate, abort |
| 592 } | 643 } |
| 593 dst->fImage = SkMask::AllocImage(srcSize); | 644 dst->fImage = SkMask::AllocImage(srcSize); |
| 594 merge_src_with_blur(dst->fImage, src.fRowBytes, | 645 merge_src_with_blur(dst->fImage, src.fRowBytes, |
| 595 sp, src.fRowBytes, | 646 sp, src.fRowBytes, |
| 596 dp + passCount * (rx + ry * dst->fRowBytes), | 647 dp + passCount * (rx + ry * dst->fRowBytes), |
| 597 dst->fRowBytes, sw, sh); | 648 dst->fRowBytes, sw, sh); |
| 598 SkMask::FreeImage(dp); | 649 if (dm) { |
| 650 SkScaledImageCache::Unlock(static_cast<SkScaledImageCache::ID*>( dm->fCacheId)); | |
| 651 } else if (dp) { | |
| 652 SkMask::FreeImage(dp); | |
| 653 } | |
| 599 } else if (style != kNormal_SkBlurStyle) { | 654 } else if (style != kNormal_SkBlurStyle) { |
| 600 clamp_with_orig(dp + passCount * (rx + ry * dst->fRowBytes), | 655 clamp_with_orig(dp + passCount * (rx + ry * dst->fRowBytes), |
| 601 dst->fRowBytes, sp, src.fRowBytes, sw, sh, style); | 656 dst->fRowBytes, sp, src.fRowBytes, sw, sh, style); |
| 602 } | 657 } |
| 603 (void)autoCall.detach(); | |
| 604 } | 658 } |
| 605 | 659 |
| 606 if (style == kInner_SkBlurStyle) { | 660 if (style == kInner_SkBlurStyle) { |
| 607 dst->fBounds = src.fBounds; // restore trimmed bounds | 661 dst->fBounds = src.fBounds; // restore trimmed bounds |
| 608 dst->fRowBytes = src.fRowBytes; | 662 dst->fRowBytes = src.fRowBytes; |
| 609 } | 663 } |
| 610 | 664 |
| 611 return true; | 665 return true; |
| 612 } | 666 } |
| 613 | 667 |
| (...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 772 uint8_t *profile = NULL; | 826 uint8_t *profile = NULL; |
| 773 | 827 |
| 774 ComputeBlurProfile(sigma, &profile); | 828 ComputeBlurProfile(sigma, &profile); |
| 775 SkAutoTDeleteArray<uint8_t> ada(profile); | 829 SkAutoTDeleteArray<uint8_t> ada(profile); |
| 776 | 830 |
| 777 size_t dstSize = dst->computeImageSize(); | 831 size_t dstSize = dst->computeImageSize(); |
| 778 if (0 == dstSize) { | 832 if (0 == dstSize) { |
| 779 return false; // too big to allocate, abort | 833 return false; // too big to allocate, abort |
| 780 } | 834 } |
| 781 | 835 |
| 782 uint8_t* dp = SkMask::AllocImage(dstSize); | 836 uint8_t* dp = NULL; |
| 837 SkDiscardableMemoryMask* dm = SkBlurMask::getDiscardableMemoryMaskFromMap(ds t); | |
| 838 if (dm) { | |
| 839 SkBitmap bitmap; | |
| 840 SkBitmap::Allocator* allocator = SkScaledImageCache::GetAllocator(); | |
| 841 bitmap.setConfig(SkBitmap::kA8_Config, dst->fBounds.width(), | |
| 842 dst->fBounds.height(), dst->fRowBytes); | |
| 843 bitmap.allocPixels(allocator, NULL); | |
| 844 if (!bitmap.readyToDraw()) { | |
| 845 return false; | |
| 846 } | |
| 847 dm->fPixelGenerationID = bitmap.getGenerationID(); | |
| 848 dm->fCacheId = SkScaledImageCache::AddAndLock(dm->fPixelGenerationID, | |
| 849 bitmap.width(), | |
| 850 bitmap.height(), | |
| 851 bitmap); | |
| 852 SkASSERT(dm->fCacheId != NULL); | |
| 853 dp = static_cast<uint8_t*>(bitmap.getPixels()); | |
| 854 } else | |
| 855 dp = SkMask::AllocImage(dstSize); | |
| 783 | 856 |
| 784 dst->fImage = dp; | 857 dst->fImage = dp; |
| 785 | 858 |
| 786 int dstHeight = dst->fBounds.height(); | 859 int dstHeight = dst->fBounds.height(); |
| 787 int dstWidth = dst->fBounds.width(); | 860 int dstWidth = dst->fBounds.width(); |
| 788 | 861 |
| 789 uint8_t *outptr = dp; | 862 uint8_t *outptr = dp; |
| 790 | 863 |
| 791 SkAutoTMalloc<uint8_t> horizontalScanline(dstWidth); | 864 SkAutoTMalloc<uint8_t> horizontalScanline(dstWidth); |
| 792 SkAutoTMalloc<uint8_t> verticalScanline(dstHeight); | 865 SkAutoTMalloc<uint8_t> verticalScanline(dstHeight); |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 806 size_t srcSize = (size_t)(src.width() * src.height()); | 879 size_t srcSize = (size_t)(src.width() * src.height()); |
| 807 if (0 == srcSize) { | 880 if (0 == srcSize) { |
| 808 return false; // too big to allocate, abort | 881 return false; // too big to allocate, abort |
| 809 } | 882 } |
| 810 dst->fImage = SkMask::AllocImage(srcSize); | 883 dst->fImage = SkMask::AllocImage(srcSize); |
| 811 for (int y = 0 ; y < sh ; y++) { | 884 for (int y = 0 ; y < sh ; y++) { |
| 812 uint8_t *blur_scanline = dp + (y+pad)*dstWidth + pad; | 885 uint8_t *blur_scanline = dp + (y+pad)*dstWidth + pad; |
| 813 uint8_t *inner_scanline = dst->fImage + y*sw; | 886 uint8_t *inner_scanline = dst->fImage + y*sw; |
| 814 memcpy(inner_scanline, blur_scanline, sw); | 887 memcpy(inner_scanline, blur_scanline, sw); |
| 815 } | 888 } |
| 816 SkMask::FreeImage(dp); | 889 if (dm) { |
| 890 SkScaledImageCache::Unlock(static_cast<SkScaledImageCache::ID*>(dm-> fCacheId)); | |
| 891 } else if (dp) { | |
| 892 SkMask::FreeImage(dp); | |
| 893 } | |
| 817 | 894 |
| 818 dst->fBounds.set(SkScalarRoundToInt(src.fLeft), | 895 dst->fBounds.set(SkScalarRoundToInt(src.fLeft), |
| 819 SkScalarRoundToInt(src.fTop), | 896 SkScalarRoundToInt(src.fTop), |
| 820 SkScalarRoundToInt(src.fRight), | 897 SkScalarRoundToInt(src.fRight), |
| 821 SkScalarRoundToInt(src.fBottom)); // restore trimmed bo unds | 898 SkScalarRoundToInt(src.fBottom)); // restore trimmed bo unds |
| 822 dst->fRowBytes = sw; | 899 dst->fRowBytes = sw; |
| 823 | 900 |
| 824 } else if (style == kOuter_SkBlurStyle) { | 901 } else if (style == kOuter_SkBlurStyle) { |
| 825 for (int y = pad ; y < dstHeight-pad ; y++) { | 902 for (int y = pad ; y < dstHeight-pad ; y++) { |
| 826 uint8_t *dst_scanline = dp + y*dstWidth + pad; | 903 uint8_t *dst_scanline = dp + y*dstWidth + pad; |
| (...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 987 (void)autoCall.detach(); | 1064 (void)autoCall.detach(); |
| 988 } | 1065 } |
| 989 | 1066 |
| 990 if (style == kInner_SkBlurStyle) { | 1067 if (style == kInner_SkBlurStyle) { |
| 991 dst->fBounds = src.fBounds; // restore trimmed bounds | 1068 dst->fBounds = src.fBounds; // restore trimmed bounds |
| 992 dst->fRowBytes = src.fRowBytes; | 1069 dst->fRowBytes = src.fRowBytes; |
| 993 } | 1070 } |
| 994 | 1071 |
| 995 return true; | 1072 return true; |
| 996 } | 1073 } |
| OLD | NEW |