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:
parent
9b009bb069
commit
cb25659eb1
@ -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++) {
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user