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

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

Issue 471473002: Optimize CSS box-shadow performance (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: backed blur mask with a bitmap Created 6 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
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 "SkResourceCache.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
(...skipping 450 matching lines...) Expand 10 before | Expand all | Expand 10 after
472 473
473 /////////////////////////////////////////////////////////////////////////////// 474 ///////////////////////////////////////////////////////////////////////////////
474 475
475 // we use a local function to wrap the class static method to work around 476 // we use a local function to wrap the class static method to work around
476 // a bug in gcc98 477 // a bug in gcc98
477 void SkMask_FreeImage(uint8_t* image); 478 void SkMask_FreeImage(uint8_t* image);
478 void SkMask_FreeImage(uint8_t* image) { 479 void SkMask_FreeImage(uint8_t* image) {
479 SkMask::FreeImage(image); 480 SkMask::FreeImage(image);
480 } 481 }
481 482
483 SkBitmap createBitmap(const SkImageInfo& info, size_t rowBytes) {
484 SkBitmap bitmap;
485 SkBitmap::Allocator* allocator = SkResourceCache::GetAllocator();
486 bitmap.setInfo(info, rowBytes);
487 bitmap.allocPixels(allocator, NULL);
488 return bitmap;
489 }
490
482 bool SkBlurMask::BoxBlur(SkMask* dst, const SkMask& src, 491 bool SkBlurMask::BoxBlur(SkMask* dst, const SkMask& src,
483 SkScalar sigma, SkBlurStyle style, SkBlurQuality qualit y, 492 SkScalar sigma, SkBlurStyle style, SkBlurQuality qualit y,
484 SkIPoint* margin, bool force_quality) { 493 SkIPoint* margin, bool force_quality) {
485 494
486 if (src.fFormat != SkMask::kA8_Format) { 495 if (src.fFormat != SkMask::kA8_Format) {
487 return false; 496 return false;
488 } 497 }
489 498
490 // Force high quality off for small radii (performance) 499 // Force high quality off for small radii (performance)
491 if (!force_quality && sigma <= SkIntToScalar(2)) { 500 if (!force_quality && sigma <= SkIntToScalar(2)) {
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
534 543
535 if (src.fImage) { 544 if (src.fImage) {
536 size_t dstSize = dst->computeImageSize(); 545 size_t dstSize = dst->computeImageSize();
537 if (0 == dstSize) { 546 if (0 == dstSize) {
538 return false; // too big to allocate, abort 547 return false; // too big to allocate, abort
539 } 548 }
540 549
541 int sw = src.fBounds.width(); 550 int sw = src.fBounds.width();
542 int sh = src.fBounds.height(); 551 int sh = src.fBounds.height();
543 const uint8_t* sp = src.fImage; 552 const uint8_t* sp = src.fImage;
544 uint8_t* dp = SkMask::AllocImage(dstSize); 553 SkBitmap bitmap;
545 SkAutoTCallVProc<uint8_t, SkMask_FreeImage> autoCall(dp); 554 bitmap = createBitmap(SkImageInfo::MakeA8(dst->fBounds.width(),dst->fBou nds.height()), dst->fRowBytes);
555 SkAutoLockPixels alp(bitmap);
556 uint8_t* dp = bitmap.getAddr8(0, 0);
546 557
547 // build the blurry destination 558 // build the blurry destination
548 SkAutoTMalloc<uint8_t> tmpBuffer(dstSize); 559 SkAutoTMalloc<uint8_t> tmpBuffer(dstSize);
549 uint8_t* tp = tmpBuffer.get(); 560 uint8_t* tp = tmpBuffer.get();
550 int w = sw, h = sh; 561 int w = sw, h = sh;
551 562
552 if (outerWeight == 255) { 563 if (outerWeight == 255) {
553 int loRadius, hiRadius; 564 int loRadius, hiRadius;
554 get_adjusted_radii(passRadius, &loRadius, &hiRadius); 565 get_adjusted_radii(passRadius, &loRadius, &hiRadius);
555 if (kHigh_SkBlurQuality == quality) { 566 if (kHigh_SkBlurQuality == quality) {
(...skipping 19 matching lines...) Expand all
575 h = boxBlurInterp(tp, h, dp, ry, h, w, false, outerW eight); 586 h = boxBlurInterp(tp, h, dp, ry, h, w, false, outerW eight);
576 h = boxBlurInterp(dp, h, tp, ry, h, w, false, outerW eight); 587 h = boxBlurInterp(dp, h, tp, ry, h, w, false, outerW eight);
577 h = boxBlurInterp(tp, h, dp, ry, h, w, true, outerWe ight); 588 h = boxBlurInterp(tp, h, dp, ry, h, w, true, outerWe ight);
578 } else { 589 } else {
579 w = boxBlurInterp(sp, src.fRowBytes, tp, rx, w, h, true, outerWe ight); 590 w = boxBlurInterp(sp, src.fRowBytes, tp, rx, w, h, true, outerWe ight);
580 h = boxBlurInterp(tp, h, dp, ry, h, w, true, outerWe ight); 591 h = boxBlurInterp(tp, h, dp, ry, h, w, true, outerWe ight);
581 } 592 }
582 } 593 }
583 594
584 dst->fImage = dp; 595 dst->fImage = dp;
596 dst->fBitmap = bitmap;
585 // if need be, alloc the "real" dst (same size as src) and copy/merge 597 // if need be, alloc the "real" dst (same size as src) and copy/merge
586 // the blur into it (applying the src) 598 // the blur into it (applying the src)
587 if (style == kInner_SkBlurStyle) { 599 if (style == kInner_SkBlurStyle) {
588 // now we allocate the "real" dst, mirror the size of src 600 // now we allocate the "real" dst, mirror the size of src
589 size_t srcSize = src.computeImageSize(); 601 size_t srcSize = src.computeImageSize();
590 if (0 == srcSize) { 602 if (0 == srcSize) {
591 return false; // too big to allocate, abort 603 return false; // too big to allocate, abort
592 } 604 }
593 dst->fImage = SkMask::AllocImage(srcSize); 605 dst->fBitmap = createBitmap(SkImageInfo::MakeA8(sw, sh), src.fRowByt es);
606 SkAutoLockPixels alp(dst->fBitmap);
607 dst->fImage = dst->fBitmap.getAddr8(0, 0);
594 merge_src_with_blur(dst->fImage, src.fRowBytes, 608 merge_src_with_blur(dst->fImage, src.fRowBytes,
595 sp, src.fRowBytes, 609 sp, src.fRowBytes,
596 dp + passCount * (rx + ry * dst->fRowBytes), 610 dp + passCount * (rx + ry * dst->fRowBytes),
597 dst->fRowBytes, sw, sh); 611 dst->fRowBytes, sw, sh);
598 SkMask::FreeImage(dp);
599 } else if (style != kNormal_SkBlurStyle) { 612 } else if (style != kNormal_SkBlurStyle) {
600 clamp_with_orig(dp + passCount * (rx + ry * dst->fRowBytes), 613 clamp_with_orig(dp + passCount * (rx + ry * dst->fRowBytes),
601 dst->fRowBytes, sp, src.fRowBytes, sw, sh, style); 614 dst->fRowBytes, sp, src.fRowBytes, sw, sh, style);
602 } 615 }
603 (void)autoCall.detach();
604 } 616 }
605 617
606 if (style == kInner_SkBlurStyle) { 618 if (style == kInner_SkBlurStyle) {
607 dst->fBounds = src.fBounds; // restore trimmed bounds 619 dst->fBounds = src.fBounds; // restore trimmed bounds
608 dst->fRowBytes = src.fRowBytes; 620 dst->fRowBytes = src.fRowBytes;
609 } 621 }
610 622
611 return true; 623 return true;
612 } 624 }
613 625
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after
772 uint8_t *profile = NULL; 784 uint8_t *profile = NULL;
773 785
774 ComputeBlurProfile(sigma, &profile); 786 ComputeBlurProfile(sigma, &profile);
775 SkAutoTDeleteArray<uint8_t> ada(profile); 787 SkAutoTDeleteArray<uint8_t> ada(profile);
776 788
777 size_t dstSize = dst->computeImageSize(); 789 size_t dstSize = dst->computeImageSize();
778 if (0 == dstSize) { 790 if (0 == dstSize) {
779 return false; // too big to allocate, abort 791 return false; // too big to allocate, abort
780 } 792 }
781 793
782 uint8_t* dp = SkMask::AllocImage(dstSize);
783
784 dst->fImage = dp;
785
786 int dstHeight = dst->fBounds.height(); 794 int dstHeight = dst->fBounds.height();
787 int dstWidth = dst->fBounds.width(); 795 int dstWidth = dst->fBounds.width();
788 796
797 SkBitmap bitmap = createBitmap(SkImageInfo::MakeA8(dstWidth, dstHeight), dst ->fRowBytes);
798 SkAutoLockPixels alp(bitmap);
799 uint8_t* dp = bitmap.getAddr8(0, 0);
800 dst->fImage = dp;
801 dst->fBitmap = bitmap;
802
789 uint8_t *outptr = dp; 803 uint8_t *outptr = dp;
790 804
791 SkAutoTMalloc<uint8_t> horizontalScanline(dstWidth); 805 SkAutoTMalloc<uint8_t> horizontalScanline(dstWidth);
792 SkAutoTMalloc<uint8_t> verticalScanline(dstHeight); 806 SkAutoTMalloc<uint8_t> verticalScanline(dstHeight);
793 807
794 ComputeBlurredScanline(horizontalScanline, profile, dstWidth, sigma); 808 ComputeBlurredScanline(horizontalScanline, profile, dstWidth, sigma);
795 ComputeBlurredScanline(verticalScanline, profile, dstHeight, sigma); 809 ComputeBlurredScanline(verticalScanline, profile, dstHeight, sigma);
796 810
797 for (int y = 0 ; y < dstHeight ; ++y) { 811 for (int y = 0 ; y < dstHeight ; ++y) {
798 for (int x = 0 ; x < dstWidth ; x++) { 812 for (int x = 0 ; x < dstWidth ; x++) {
799 unsigned int maskval = SkMulDiv255Round(horizontalScanline[x], verti calScanline[y]); 813 unsigned int maskval = SkMulDiv255Round(horizontalScanline[x], verti calScanline[y]);
800 *(outptr++) = maskval; 814 *(outptr++) = maskval;
801 } 815 }
802 } 816 }
803 817
804 if (style == kInner_SkBlurStyle) { 818 if (style == kInner_SkBlurStyle) {
805 // now we allocate the "real" dst, mirror the size of src 819 // now we allocate the "real" dst, mirror the size of src
806 size_t srcSize = (size_t)(src.width() * src.height()); 820 size_t srcSize = (size_t)(src.width() * src.height());
807 if (0 == srcSize) { 821 if (0 == srcSize) {
808 return false; // too big to allocate, abort 822 return false; // too big to allocate, abort
809 } 823 }
810 dst->fImage = SkMask::AllocImage(srcSize);
811 for (int y = 0 ; y < sh ; y++) {
812 uint8_t *blur_scanline = dp + (y+pad)*dstWidth + pad;
813 uint8_t *inner_scanline = dst->fImage + y*sw;
814 memcpy(inner_scanline, blur_scanline, sw);
815 }
816 SkMask::FreeImage(dp);
817
818 dst->fBounds.set(SkScalarRoundToInt(src.fLeft), 824 dst->fBounds.set(SkScalarRoundToInt(src.fLeft),
819 SkScalarRoundToInt(src.fTop), 825 SkScalarRoundToInt(src.fTop),
820 SkScalarRoundToInt(src.fRight), 826 SkScalarRoundToInt(src.fRight),
821 SkScalarRoundToInt(src.fBottom)); // restore trimmed bo unds 827 SkScalarRoundToInt(src.fBottom)); // restore trimmed bo unds
822 dst->fRowBytes = sw; 828 dst->fRowBytes = sw;
823 829
830 dst->fBitmap = createBitmap(SkImageInfo::MakeA8(dst->fBounds.width(),
831 dst->fBounds.height()), dst->fRowBytes);
832 SkAutoLockPixels alp(dst->fBitmap);
833 dst->fImage = dst->fBitmap.getAddr8(0, 0);
834 for (int y = 0 ; y < sh ; y++) {
835 uint8_t *blur_scanline = dp + (y+pad)*dstWidth + pad;
836 uint8_t *inner_scanline = dst->fImage + y*sw;
837 memcpy(inner_scanline, blur_scanline, sw);
838 }
824 } else if (style == kOuter_SkBlurStyle) { 839 } else if (style == kOuter_SkBlurStyle) {
825 for (int y = pad ; y < dstHeight-pad ; y++) { 840 for (int y = pad ; y < dstHeight-pad ; y++) {
826 uint8_t *dst_scanline = dp + y*dstWidth + pad; 841 uint8_t *dst_scanline = dp + y*dstWidth + pad;
827 memset(dst_scanline, 0, sw); 842 memset(dst_scanline, 0, sw);
828 } 843 }
829 } else if (style == kSolid_SkBlurStyle) { 844 } else if (style == kSolid_SkBlurStyle) {
830 for (int y = pad ; y < dstHeight-pad ; y++) { 845 for (int y = pad ; y < dstHeight-pad ; y++) {
831 uint8_t *dst_scanline = dp + y*dstWidth + pad; 846 uint8_t *dst_scanline = dp + y*dstWidth + pad;
832 memset(dst_scanline, 0xff, sw); 847 memset(dst_scanline, 0xff, sw);
833 } 848 }
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after
987 (void)autoCall.detach(); 1002 (void)autoCall.detach();
988 } 1003 }
989 1004
990 if (style == kInner_SkBlurStyle) { 1005 if (style == kInner_SkBlurStyle) {
991 dst->fBounds = src.fBounds; // restore trimmed bounds 1006 dst->fBounds = src.fBounds; // restore trimmed bounds
992 dst->fRowBytes = src.fRowBytes; 1007 dst->fRowBytes = src.fRowBytes;
993 } 1008 }
994 1009
995 return true; 1010 return true;
996 } 1011 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698