DDL-ify GrRectBlurEffect

This allows the upload of the blur profile to be delayed until the draw is actually executed.

Change-Id: I10a7e8fb0edc90ef509c418552740a867f1f3df2
Reviewed-on: https://skia-review.googlesource.com/107354
Commit-Queue: Robert Phillips <robertphillips@google.com>
Reviewed-by: Greg Daniel <egdaniel@google.com>
This commit is contained in:
Robert Phillips 2018-02-14 15:20:41 -05:00 committed by Skia Commit-Bot
parent 9b009bb069
commit cb25659eb1
4 changed files with 52 additions and 39 deletions

View File

@ -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++) {

View File

@ -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.

View File

@ -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;
}
blurProfile = proxyProvider->createTextureProxy(texDesc, SkBudgeted::kYes,
profile.get(), 0);
SkBlurMask::ComputeBlurProfile(bitmap.getAddr8(0, 0), profileSize, sigma);
bitmap.setImmutable();
sk_sp<SkImage> image = SkImage::MakeFromBitmap(bitmap);
if (!image) {
return nullptr;
}
blurProfile = proxyProvider->createTextureProxy(std::move(image), kNone_GrSurfaceFlags,
kTopLeft_GrSurfaceOrigin, 1,
SkBudgeted::kYes, SkBackingFit::kExact);
if (!blurProfile) {
return nullptr;
}

View File

@ -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;
}
blurProfile =
proxyProvider->createTextureProxy(texDesc, SkBudgeted::kYes, profile.get(), 0);
SkBlurMask::ComputeBlurProfile(bitmap.getAddr8(0, 0), profileSize, sigma);
bitmap.setImmutable();
sk_sp<SkImage> image = SkImage::MakeFromBitmap(bitmap);
if (!image) {
return nullptr;
}
blurProfile = proxyProvider->createTextureProxy(std::move(image), kNone_GrSurfaceFlags,
kTopLeft_GrSurfaceOrigin, 1,
SkBudgeted::kYes, SkBackingFit::kExact);
if (!blurProfile) {
return nullptr;
}