diff options
-rw-r--r-- | src/effects/SkBlurMask.cpp | 30 | ||||
-rw-r--r-- | src/effects/SkBlurMask.h | 13 | ||||
-rw-r--r-- | src/gpu/effects/GrRectBlurEffect.fp | 24 | ||||
-rw-r--r-- | src/gpu/effects/GrRectBlurEffect.h | 24 |
4 files changed, 52 insertions, 39 deletions
diff --git a/src/effects/SkBlurMask.cpp b/src/effects/SkBlurMask.cpp index 59d70205c9..297d15c9d5 100644 --- a/src/effects/SkBlurMask.cpp +++ b/src/effects/SkBlurMask.cpp @@ -209,22 +209,18 @@ static float gaussianIntegral(float x) { return 0.4375f + (-x3 / 6.0f - 3.0f * x2 * 0.25f - 1.125f * x); } -/* ComputeBlurProfile allocates and fills in an array of floating +/* ComputeBlurProfile 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)) all the time, we actually fill in the profile pre-inverted (already done 255-x). - - It's the responsibility of the caller to delete the - memory returned in profile_out. */ -uint8_t* SkBlurMask::ComputeBlurProfile(SkScalar sigma) { - int size = SkScalarCeilToInt(6*sigma); +void SkBlurMask::ComputeBlurProfile(uint8_t* profile, int size, SkScalar sigma) { + SkASSERT(SkScalarCeilToInt(6*sigma) == size); int center = size >> 1; - uint8_t* profile = new uint8_t[size]; float invr = 1.f/(2*sigma); @@ -234,8 +230,6 @@ uint8_t* SkBlurMask::ComputeBlurProfile(SkScalar sigma) { float gi = gaussianIntegral(scaled_x); profile[x] = 255 - (uint8_t) (255.f * gi); } - - return profile; } // TODO MAYBE: Maintain a profile cache to avoid recomputing this for @@ -245,8 +239,10 @@ uint8_t* SkBlurMask::ComputeBlurProfile(SkScalar sigma) { // Implementation adapted from Michael Herf's approach: // http://stereopsis.com/shadowrect/ -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? +uint8_t SkBlurMask::ProfileLookup(const uint8_t *profile, int loc, + int blurredWidth, int sharpWidth) { + // how far are we from the original edge? + int dx = SkAbs32(((loc << 1) + 1) - blurredWidth) - sharpWidth; int ox = dx >> 1; if (ox < 0) { ox = 0; @@ -282,9 +278,9 @@ void SkBlurMask::ComputeBlurredScanline(uint8_t *pixels, const uint8_t *profile, bool SkBlurMask::BlurRect(SkScalar sigma, SkMask *dst, const SkRect &src, SkBlurStyle style, SkIPoint *margin, SkMask::CreateMode createMode) { - int profile_size = SkScalarCeilToInt(6*sigma); + int profileSize = SkScalarCeilToInt(6*sigma); - int pad = profile_size/2; + int pad = profileSize/2; if (margin) { margin->set( pad, pad ); } @@ -312,7 +308,9 @@ bool SkBlurMask::BlurRect(SkScalar sigma, SkMask *dst, return true; } - std::unique_ptr<uint8_t[]> profile(ComputeBlurProfile(sigma)); + SkAutoTMalloc<uint8_t> profile(profileSize); + + ComputeBlurProfile(profile, profileSize, sigma); size_t dstSize = dst->computeImageSize(); if (0 == dstSize) { @@ -331,8 +329,8 @@ bool SkBlurMask::BlurRect(SkScalar sigma, SkMask *dst, SkAutoTMalloc<uint8_t> horizontalScanline(dstWidth); SkAutoTMalloc<uint8_t> verticalScanline(dstHeight); - ComputeBlurredScanline(horizontalScanline, profile.get(), dstWidth, sigma); - ComputeBlurredScanline(verticalScanline, profile.get(), dstHeight, sigma); + ComputeBlurredScanline(horizontalScanline, profile, dstWidth, sigma); + ComputeBlurredScanline(verticalScanline, profile, dstHeight, sigma); for (int y = 0 ; y < dstHeight ; ++y) { for (int x = 0 ; x < dstWidth ; x++) { diff --git a/src/effects/SkBlurMask.h b/src/effects/SkBlurMask.h index 9da19fab5a..67009b0bb5 100644 --- a/src/effects/SkBlurMask.h +++ b/src/effects/SkBlurMask.h @@ -54,8 +54,7 @@ public: /* Helper functions for analytic rectangle blurs */ /** Look up the intensity of the (one dimnensional) blurred half-plane. - @param profile The precomputed 1D blur profile; memory allocated by and managed by - ComputeBlurProfile below. + @param profile The precomputed 1D blur profile; initialized by ComputeBlurProfile below. @param loc the location to look up; The lookup will clamp invalid inputs, but meaningful data are available between 0 and blurred_width @param blurred_width The width of the final, blurred rectangle @@ -63,12 +62,12 @@ public: */ static uint8_t ProfileLookup(const uint8_t* profile, int loc, int blurredWidth, int sharpWidth); - /** Allocate memory for and populate the profile of a 1D blurred halfplane. The caller - must free the memory. The amount of memory allocated will be exactly 6*sigma bytes. - @param sigma The standard deviation of the gaussian blur kernel + /** Populate the profile of a 1D blurred halfplane. + @param profile The 1D table to fill in + @param size Should be 6*sigma bytes + @param sigma The standard deviation of the gaussian blur kernel */ - - static uint8_t* ComputeBlurProfile(SkScalar sigma); + static void ComputeBlurProfile(uint8_t* profile, int size, SkScalar sigma); /** Compute an entire scanline of a blurred step function. This is a 1D helper that will produce both the horizontal and vertical profiles of the blurry rectangle. diff --git a/src/gpu/effects/GrRectBlurEffect.fp b/src/gpu/effects/GrRectBlurEffect.fp index 762942aaa4..7057a8e173 100644 --- a/src/gpu/effects/GrRectBlurEffect.fp +++ b/src/gpu/effects/GrRectBlurEffect.fp @@ -52,16 +52,24 @@ uniform half profileSize; sk_sp<GrTextureProxy> blurProfile(proxyProvider->findOrCreateProxyByUniqueKey( key, kTopLeft_GrSurfaceOrigin)); if (!blurProfile) { - GrSurfaceDesc texDesc; - texDesc.fOrigin = kTopLeft_GrSurfaceOrigin; - texDesc.fWidth = profileSize; - texDesc.fHeight = 1; - texDesc.fConfig = kAlpha_8_GrPixelConfig; + SkImageInfo ii = SkImageInfo::MakeA8(profileSize, 1); - std::unique_ptr<uint8_t[]> profile(SkBlurMask::ComputeBlurProfile(sigma)); + SkBitmap bitmap; + if (!bitmap.tryAllocPixels(ii)) { + return nullptr; + } + + SkBlurMask::ComputeBlurProfile(bitmap.getAddr8(0, 0), profileSize, sigma); + bitmap.setImmutable(); + + sk_sp<SkImage> image = SkImage::MakeFromBitmap(bitmap); + if (!image) { + return nullptr; + } - blurProfile = proxyProvider->createTextureProxy(texDesc, SkBudgeted::kYes, - profile.get(), 0); + blurProfile = proxyProvider->createTextureProxy(std::move(image), kNone_GrSurfaceFlags, + kTopLeft_GrSurfaceOrigin, 1, + SkBudgeted::kYes, SkBackingFit::kExact); if (!blurProfile) { return nullptr; } diff --git a/src/gpu/effects/GrRectBlurEffect.h b/src/gpu/effects/GrRectBlurEffect.h index 91177072a1..b6b8a029f1 100644 --- a/src/gpu/effects/GrRectBlurEffect.h +++ b/src/gpu/effects/GrRectBlurEffect.h @@ -32,16 +32,24 @@ public: sk_sp<GrTextureProxy> blurProfile( proxyProvider->findOrCreateProxyByUniqueKey(key, kTopLeft_GrSurfaceOrigin)); if (!blurProfile) { - GrSurfaceDesc texDesc; - texDesc.fOrigin = kTopLeft_GrSurfaceOrigin; - texDesc.fWidth = profileSize; - texDesc.fHeight = 1; - texDesc.fConfig = kAlpha_8_GrPixelConfig; + SkImageInfo ii = SkImageInfo::MakeA8(profileSize, 1); - std::unique_ptr<uint8_t[]> profile(SkBlurMask::ComputeBlurProfile(sigma)); + SkBitmap bitmap; + if (!bitmap.tryAllocPixels(ii)) { + return nullptr; + } + + SkBlurMask::ComputeBlurProfile(bitmap.getAddr8(0, 0), profileSize, sigma); + bitmap.setImmutable(); + + sk_sp<SkImage> image = SkImage::MakeFromBitmap(bitmap); + if (!image) { + return nullptr; + } - blurProfile = - proxyProvider->createTextureProxy(texDesc, SkBudgeted::kYes, profile.get(), 0); + blurProfile = proxyProvider->createTextureProxy(std::move(image), kNone_GrSurfaceFlags, + kTopLeft_GrSurfaceOrigin, 1, + SkBudgeted::kYes, SkBackingFit::kExact); if (!blurProfile) { return nullptr; } |