aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/effects/SkBlurMask.cpp
diff options
context:
space:
mode:
authorGravatar commit-bot@chromium.org <commit-bot@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>2014-01-27 22:41:45 +0000
committerGravatar commit-bot@chromium.org <commit-bot@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>2014-01-27 22:41:45 +0000
commitd1829151a5f5fb69faa50c326ed018376d117b3e (patch)
treee424d35b0b3d4be436b10ca361577e18a68702ef /src/effects/SkBlurMask.cpp
parent01260b2dbcc070006c0b960015e44ef83dcbaa56 (diff)
Perform the same analytic blur calculation on the GPU that we do on the CPU. Results in significant performance gains when using Ganesh to render drop shadows in Chrome.
BUG= R=bsalomon@google.com, reed@google.com Author: humper@google.com Review URL: https://codereview.chromium.org/119343003 git-svn-id: http://skia.googlecode.com/svn/trunk@13210 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'src/effects/SkBlurMask.cpp')
-rw-r--r--src/effects/SkBlurMask.cpp70
1 files changed, 36 insertions, 34 deletions
diff --git a/src/effects/SkBlurMask.cpp b/src/effects/SkBlurMask.cpp
index 32a3d20d31..f61536e65a 100644
--- a/src/effects/SkBlurMask.cpp
+++ b/src/effects/SkBlurMask.cpp
@@ -671,7 +671,7 @@ static float gaussianIntegral(float x) {
return 0.4375f + (-x3 / 6.0f - 3.0f * x2 * 0.25f - 1.125f * x);
}
-/* compute_profile allocates and fills in an array of floating
+/* ComputeBlurProfile allocates and fills in an array of floating
point values between 0 and 255 for the profile signature of
a blurred half-plane with the given blur radius. Since we're
going to be doing screened multiplications (i.e., 1 - (1-x)(1-y))
@@ -682,11 +682,11 @@ static float gaussianIntegral(float x) {
memory returned in profile_out.
*/
-static void compute_profile(SkScalar sigma, unsigned int **profile_out) {
+void SkBlurMask::ComputeBlurProfile(SkScalar sigma, uint8_t **profile_out) {
int size = SkScalarCeilToInt(6*sigma);
int center = size >> 1;
- unsigned int *profile = SkNEW_ARRAY(unsigned int, size);
+ uint8_t *profile = SkNEW_ARRAY(uint8_t, size);
float invr = 1.f/(2*sigma);
@@ -707,7 +707,7 @@ static void compute_profile(SkScalar sigma, unsigned int **profile_out) {
// Implementation adapted from Michael Herf's approach:
// http://stereopsis.com/shadowrect/
-static inline unsigned int profile_lookup( unsigned int *profile, int loc, int blurred_width, int sharp_width ) {
+uint8_t SkBlurMask::ProfileLookup(const uint8_t *profile, int loc, int blurred_width, int sharp_width) {
int dx = SkAbs32(((loc << 1) + 1) - blurred_width) - sharp_width; // how far are we from the original edge?
int ox = dx >> 1;
if (ox < 0) {
@@ -717,6 +717,30 @@ static inline unsigned int profile_lookup( unsigned int *profile, int loc, int b
return profile[ox];
}
+void SkBlurMask::ComputeBlurredScanline(uint8_t *pixels, const uint8_t *profile,
+ unsigned int width, SkScalar sigma) {
+
+ unsigned int profile_size = SkScalarCeilToInt(6*sigma);
+ SkAutoTMalloc<uint8_t> horizontalScanline(width);
+
+ unsigned int sw = width - profile_size;
+ // nearest odd number less than the profile size represents the center
+ // of the (2x scaled) profile
+ int center = ( profile_size & ~1 ) - 1;
+
+ int w = sw - center;
+
+ for (unsigned int x = 0 ; x < width ; ++x) {
+ if (profile_size <= sw) {
+ pixels[x] = ProfileLookup(profile, x, width, w);
+ } else {
+ float span = float(sw)/(2*sigma);
+ float giX = 1.5f - (x+.5f)/(2*sigma);
+ pixels[x] = (uint8_t) (255 * (gaussianIntegral(giX) - gaussianIntegral(giX + span)));
+ }
+ }
+}
+
bool SkBlurMask::BlurRect(SkMask *dst, const SkRect &src,
SkScalar radius, Style style,
SkIPoint *margin, SkMask::CreateMode createMode) {
@@ -757,10 +781,10 @@ bool SkBlurMask::BlurRect(SkScalar sigma, SkMask *dst,
}
return true;
}
- unsigned int *profile = NULL;
+ uint8_t *profile = NULL;
- compute_profile(sigma, &profile);
- SkAutoTDeleteArray<unsigned int> ada(profile);
+ ComputeBlurProfile(sigma, &profile);
+ SkAutoTDeleteArray<uint8_t> ada(profile);
size_t dstSize = dst->computeImageSize();
if (0 == dstSize) {
@@ -774,39 +798,17 @@ bool SkBlurMask::BlurRect(SkScalar sigma, SkMask *dst,
int dstHeight = dst->fBounds.height();
int dstWidth = dst->fBounds.width();
- // nearest odd number less than the profile size represents the center
- // of the (2x scaled) profile
- int center = ( profile_size & ~1 ) - 1;
-
- int w = sw - center;
- int h = sh - center;
-
uint8_t *outptr = dp;
SkAutoTMalloc<uint8_t> horizontalScanline(dstWidth);
-
- for (int x = 0 ; x < dstWidth ; ++x) {
- if (profile_size <= sw) {
- horizontalScanline[x] = profile_lookup(profile, x, dstWidth, w);
- } else {
- float span = float(sw)/(2*sigma);
- float giX = 1.5f - (x+.5f)/(2*sigma);
- horizontalScanline[x] = (uint8_t) (255 * (gaussianIntegral(giX) - gaussianIntegral(giX + span)));
- }
- }
+ SkAutoTMalloc<uint8_t> verticalScanline(dstHeight);
+
+ ComputeBlurredScanline(horizontalScanline, profile, dstWidth, sigma);
+ ComputeBlurredScanline(verticalScanline, profile, dstHeight, sigma);
for (int y = 0 ; y < dstHeight ; ++y) {
- unsigned int profile_y;
- if (profile_size <= sh) {
- profile_y = profile_lookup(profile, y, dstHeight, h);
- } else {
- float span = float(sh)/(2*sigma);
- float giY = 1.5f - (y+.5f)/(2*sigma);
- profile_y = (uint8_t) (255 * (gaussianIntegral(giY) - gaussianIntegral(giY + span)));
- }
-
for (int x = 0 ; x < dstWidth ; x++) {
- unsigned int maskval = SkMulDiv255Round(horizontalScanline[x], profile_y);
+ unsigned int maskval = SkMulDiv255Round(horizontalScanline[x], verticalScanline[y]);
*(outptr++) = maskval;
}
}