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

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

Issue 286273002: Optimize CSS box-shadow performance by caching the SkMask of the blur effect. (Closed) Base URL: https://skia.googlecode.com/svn/trunk
Patch Set: rebase with latest skia in git instead of svn trunk Created 6 years, 6 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 | Annotate | Revision Log
OLDNEW
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
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
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
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
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698