Simplify SkComputeBlurredRRectParams

Although cool, I don't know if this is worth the increased complexity
for an unused feature.

Change-Id: Id229beab176cebf5b7810fd1e44a5d1e25abcabc
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/312848
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Robert Phillips <robertphillips@google.com>
This commit is contained in:
Robert Phillips 2020-08-24 17:11:10 -04:00 committed by Skia Commit-Bot
parent 5c4880c251
commit 8025507f74
5 changed files with 17 additions and 172 deletions

View File

@ -115,67 +115,14 @@ private:
const SkScalar SkBlurMaskFilterImpl::kMAX_BLUR_SIGMA = SkIntToScalar(128); const SkScalar SkBlurMaskFilterImpl::kMAX_BLUR_SIGMA = SkIntToScalar(128);
// linearly interpolate between y1 & y3 to match x2's position between x1 & x3
static SkScalar interp(SkScalar x1, SkScalar x2, SkScalar x3, SkScalar y1, SkScalar y3) {
SkASSERT(x1 <= x2 && x2 <= x3);
SkASSERT(y1 <= y3);
SkScalar t = (x2 - x1) / (x3 - x1);
return y1 + t * (y3 - y1);
}
// Insert 'lower' and 'higher' into 'array1' and insert a new value at each matching insertion
// point in 'array2' that linearly interpolates between the existing values.
// Return a bit mask which contains a copy of 'inputMask' for all the cells between the two
// insertion points.
static uint32_t insert_into_arrays(SkScalar* array1, SkScalar* array2,
SkScalar lower, SkScalar higher,
int* num, uint32_t inputMask, int maskSize) {
SkASSERT(lower < higher);
SkASSERT(lower >= array1[0] && higher <= array1[*num-1]);
int32_t skipMask = 0x0;
int i;
for (i = 0; i < *num; ++i) {
if (lower >= array1[i] && lower < array1[i+1]) {
if (!SkScalarNearlyEqual(lower, array1[i])) {
memmove(&array1[i+2], &array1[i+1], (*num-i-1)*sizeof(SkScalar));
array1[i+1] = lower;
memmove(&array2[i+2], &array2[i+1], (*num-i-1)*sizeof(SkScalar));
array2[i+1] = interp(array1[i], lower, array1[i+2], array2[i], array2[i+2]);
i++;
(*num)++;
}
break;
}
}
for ( ; i < *num; ++i) {
skipMask |= inputMask << (i*maskSize);
if (higher > array1[i] && higher <= array1[i+1]) {
if (!SkScalarNearlyEqual(higher, array1[i+1])) {
memmove(&array1[i+2], &array1[i+1], (*num-i-1)*sizeof(SkScalar));
array1[i+1] = higher;
memmove(&array2[i+2], &array2[i+1], (*num-i-1)*sizeof(SkScalar));
array2[i+1] = interp(array1[i], higher, array1[i+2], array2[i], array2[i+2]);
(*num)++;
}
break;
}
}
return skipMask;
}
bool SkComputeBlurredRRectParams(const SkRRect& srcRRect, const SkRRect& devRRect, bool SkComputeBlurredRRectParams(const SkRRect& srcRRect, const SkRRect& devRRect,
const SkRect& occluder,
SkScalar sigma, SkScalar xformedSigma, SkScalar sigma, SkScalar xformedSigma,
SkRRect* rrectToDraw, SkRRect* rrectToDraw,
SkISize* widthHeight, SkISize* widthHeight,
SkScalar rectXs[kSkBlurRRectMaxDivisions], SkScalar rectXs[kSkBlurRRectMaxDivisions],
SkScalar rectYs[kSkBlurRRectMaxDivisions], SkScalar rectYs[kSkBlurRRectMaxDivisions],
SkScalar texXs[kSkBlurRRectMaxDivisions], SkScalar texXs[kSkBlurRRectMaxDivisions],
SkScalar texYs[kSkBlurRRectMaxDivisions], SkScalar texYs[kSkBlurRRectMaxDivisions]) {
int* numXs, int* numYs, uint32_t* skipMask) {
unsigned int devBlurRadius = 3*SkScalarCeilToInt(xformedSigma-1/6.0f); unsigned int devBlurRadius = 3*SkScalarCeilToInt(xformedSigma-1/6.0f);
SkScalar srcBlurRadius = 3.0f * sigma; SkScalar srcBlurRadius = 3.0f * sigma;
@ -233,17 +180,6 @@ bool SkComputeBlurredRRectParams(const SkRRect& srcRRect, const SkRRect& devRRec
texYs[2] = 2.0f*devBlurRadius + devTop + 1; texYs[2] = 2.0f*devBlurRadius + devTop + 1;
texYs[3] = SkIntToScalar(widthHeight->fHeight); texYs[3] = SkIntToScalar(widthHeight->fHeight);
SkRect temp = occluder;
*numXs = 4;
*numYs = 4;
*skipMask = 0;
if (!temp.isEmpty() && (srcProxyRect.contains(temp) || temp.intersect(srcProxyRect))) {
*skipMask = insert_into_arrays(rectXs, texXs, temp.fLeft, temp.fRight, numXs, 0x1, 1);
*skipMask = insert_into_arrays(rectYs, texYs, temp.fTop, temp.fBottom,
numYs, *skipMask, *numXs-1);
}
const SkRect newRect = SkRect::MakeXYWH(SkIntToScalar(devBlurRadius), const SkRect newRect = SkRect::MakeXYWH(SkIntToScalar(devBlurRadius),
SkIntToScalar(devBlurRadius), SkIntToScalar(devBlurRadius),
SkIntToScalar(newRRWidth), SkIntToScalar(newRRWidth),

View File

@ -19,19 +19,15 @@ static const int kSkBlurRRectMaxDivisions = 6;
// widthHeight - how large to make the mask (rrectToDraw will be centered in this coord sys) // widthHeight - how large to make the mask (rrectToDraw will be centered in this coord sys)
// rectXs, rectYs - the x & y coordinates of the covering geometry lattice // rectXs, rectYs - the x & y coordinates of the covering geometry lattice
// texXs, texYs - the texture coordinate at each point in rectXs & rectYs // texXs, texYs - the texture coordinate at each point in rectXs & rectYs
// numXs, numYs - number of coordinates in the x & y directions
// skipMask - bit mask that contains a 1-bit whenever one of the cells is occluded
// It returns true if 'devRRect' is nine-patchable // It returns true if 'devRRect' is nine-patchable
bool SkComputeBlurredRRectParams(const SkRRect& srcRRect, const SkRRect& devRRect, bool SkComputeBlurredRRectParams(const SkRRect& srcRRect, const SkRRect& devRRect,
const SkRect& occluder,
SkScalar sigma, SkScalar xformedSigma, SkScalar sigma, SkScalar xformedSigma,
SkRRect* rrectToDraw, SkRRect* rrectToDraw,
SkISize* widthHeight, SkISize* widthHeight,
SkScalar rectXs[kSkBlurRRectMaxDivisions], SkScalar rectXs[kSkBlurRRectMaxDivisions],
SkScalar rectYs[kSkBlurRRectMaxDivisions], SkScalar rectYs[kSkBlurRRectMaxDivisions],
SkScalar texXs[kSkBlurRRectMaxDivisions], SkScalar texXs[kSkBlurRRectMaxDivisions],
SkScalar texYs[kSkBlurRRectMaxDivisions], SkScalar texYs[kSkBlurRRectMaxDivisions]);
int* numXs, int* numYs, uint32_t* skipMask);
extern void sk_register_blur_maskfilter_createproc(); extern void sk_register_blur_maskfilter_createproc();

View File

@ -144,17 +144,12 @@ uniform half blurRadius;
SkRRect rrectToDraw; SkRRect rrectToDraw;
SkISize dimensions; SkISize dimensions;
SkScalar ignored[kSkBlurRRectMaxDivisions]; SkScalar ignored[kSkBlurRRectMaxDivisions];
int ignoredSize;
uint32_t ignored32;
bool ninePatchable = SkComputeBlurredRRectParams(srcRRect, devRRect, bool ninePatchable = SkComputeBlurredRRectParams(srcRRect, devRRect,
SkRect::MakeEmpty(),
sigma, xformedSigma, sigma, xformedSigma,
&rrectToDraw, &dimensions, &rrectToDraw, &dimensions,
ignored, ignored, ignored, ignored,
ignored, ignored, ignored, ignored);
&ignoredSize, &ignoredSize,
&ignored32);
if (!ninePatchable) { if (!ninePatchable) {
return nullptr; return nullptr;
} }

View File

@ -120,12 +120,10 @@ std::unique_ptr<GrFragmentProcessor> GrRRectBlurEffect::Make(
SkRRect rrectToDraw; SkRRect rrectToDraw;
SkISize dimensions; SkISize dimensions;
SkScalar ignored[kSkBlurRRectMaxDivisions]; SkScalar ignored[kSkBlurRRectMaxDivisions];
int ignoredSize;
uint32_t ignored32;
bool ninePatchable = SkComputeBlurredRRectParams( bool ninePatchable =
srcRRect, devRRect, SkRect::MakeEmpty(), sigma, xformedSigma, &rrectToDraw, &dimensions, SkComputeBlurredRRectParams(srcRRect, devRRect, sigma, xformedSigma, &rrectToDraw,
ignored, ignored, ignored, ignored, &ignoredSize, &ignoredSize, &ignored32); &dimensions, ignored, ignored, ignored, ignored);
if (!ninePatchable) { if (!ninePatchable) {
return nullptr; return nullptr;
} }
@ -184,18 +182,18 @@ half2 texCoord = translatedFragPos / proxyDims;)SkSL",
args.fUniformHandler->getUniformCStr(proxyRectVar), args.fUniformHandler->getUniformCStr(proxyRectVar),
args.fUniformHandler->getUniformCStr(blurRadiusVar), args.fUniformHandler->getUniformCStr(blurRadiusVar),
args.fUniformHandler->getUniformCStr(cornerRadiusVar)); args.fUniformHandler->getUniformCStr(cornerRadiusVar));
SkString _sample9630 = this->invokeChild(0, args); SkString _sample9345 = this->invokeChild(0, args);
fragBuilder->codeAppendf( fragBuilder->codeAppendf(
R"SkSL( R"SkSL(
half4 inputColor = %s;)SkSL", half4 inputColor = %s;)SkSL",
_sample9630.c_str()); _sample9345.c_str());
SkString _coords9678("float2(texCoord)"); SkString _coords9393("float2(texCoord)");
SkString _sample9678 = this->invokeChild(1, args, _coords9678.c_str()); SkString _sample9393 = this->invokeChild(1, args, _coords9393.c_str());
fragBuilder->codeAppendf( fragBuilder->codeAppendf(
R"SkSL( R"SkSL(
%s = inputColor * %s; %s = inputColor * %s;
)SkSL", )SkSL",
args.fOutputColor, _sample9678.c_str()); args.fOutputColor, _sample9393.c_str());
} }
private: private:

View File

@ -526,8 +526,6 @@ DEF_TEST(BlurredRRectNinePatchComputation, reporter) {
rectYs[kSkBlurRRectMaxDivisions]; rectYs[kSkBlurRRectMaxDivisions];
SkScalar texXs[kSkBlurRRectMaxDivisions], SkScalar texXs[kSkBlurRRectMaxDivisions],
texYs[kSkBlurRRectMaxDivisions]; texYs[kSkBlurRRectMaxDivisions];
int numX, numY;
uint32_t skipMask;
// not nine-patchable // not nine-patchable
{ {
@ -536,11 +534,9 @@ DEF_TEST(BlurredRRectNinePatchComputation, reporter) {
SkRRect rr; SkRRect rr;
rr.setRectRadii(r, radii); rr.setRectRadii(r, radii);
ninePatchable = SkComputeBlurredRRectParams(rr, rr, SkRect::MakeEmpty(), ninePatchable = SkComputeBlurredRRectParams(rr, rr, kBlurRad, kBlurRad,
kBlurRad, kBlurRad,
&rrectToDraw, &size, &rrectToDraw, &size,
rectXs, rectYs, texXs, texYs, rectXs, rectYs, texXs, texYs);
&numX, &numY, &skipMask);
REPORTER_ASSERT(reporter, !ninePatchable); REPORTER_ASSERT(reporter, !ninePatchable);
} }
@ -550,18 +546,14 @@ DEF_TEST(BlurredRRectNinePatchComputation, reporter) {
SkRRect rr; SkRRect rr;
rr.setRectXY(r, kCornerRad, kCornerRad); rr.setRectXY(r, kCornerRad, kCornerRad);
ninePatchable = SkComputeBlurredRRectParams(rr, rr, SkRect::MakeEmpty(), ninePatchable = SkComputeBlurredRRectParams(rr, rr, kBlurRad, kBlurRad,
kBlurRad, kBlurRad,
&rrectToDraw, &size, &rrectToDraw, &size,
rectXs, rectYs, texXs, texYs, rectXs, rectYs, texXs, texYs);
&numX, &numY, &skipMask);
static const SkScalar kAns = 12.0f * kBlurRad + 2.0f * kCornerRad + 1.0f; static const SkScalar kAns = 12.0f * kBlurRad + 2.0f * kCornerRad + 1.0f;
REPORTER_ASSERT(reporter, ninePatchable); REPORTER_ASSERT(reporter, ninePatchable);
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(SkIntToScalar(size.fWidth), kAns)); REPORTER_ASSERT(reporter, SkScalarNearlyEqual(SkIntToScalar(size.fWidth), kAns));
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(SkIntToScalar(size.fHeight), kAns)); REPORTER_ASSERT(reporter, SkScalarNearlyEqual(SkIntToScalar(size.fHeight), kAns));
REPORTER_ASSERT(reporter, 4 == numX && 4 == numY);
REPORTER_ASSERT(reporter, !skipMask);
} }
// simple elliptical // simple elliptical
@ -571,11 +563,9 @@ DEF_TEST(BlurredRRectNinePatchComputation, reporter) {
SkRRect rr; SkRRect rr;
rr.setRectXY(r, kXCornerRad, kYCornerRad); rr.setRectXY(r, kXCornerRad, kYCornerRad);
ninePatchable = SkComputeBlurredRRectParams(rr, rr, SkRect::MakeEmpty(), ninePatchable = SkComputeBlurredRRectParams(rr, rr, kBlurRad, kBlurRad,
kBlurRad, kBlurRad,
&rrectToDraw, &size, &rrectToDraw, &size,
rectXs, rectYs, texXs, texYs, rectXs, rectYs, texXs, texYs);
&numX, &numY, &skipMask);
static const SkScalar kXAns = 12.0f * kBlurRad + 2.0f * kXCornerRad + 1.0f; static const SkScalar kXAns = 12.0f * kBlurRad + 2.0f * kXCornerRad + 1.0f;
static const SkScalar kYAns = 12.0f * kBlurRad + 2.0f * kYCornerRad + 1.0f; static const SkScalar kYAns = 12.0f * kBlurRad + 2.0f * kYCornerRad + 1.0f;
@ -583,77 +573,7 @@ DEF_TEST(BlurredRRectNinePatchComputation, reporter) {
REPORTER_ASSERT(reporter, ninePatchable); REPORTER_ASSERT(reporter, ninePatchable);
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(SkIntToScalar(size.fWidth), kXAns)); REPORTER_ASSERT(reporter, SkScalarNearlyEqual(SkIntToScalar(size.fWidth), kXAns));
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(SkIntToScalar(size.fHeight), kYAns)); REPORTER_ASSERT(reporter, SkScalarNearlyEqual(SkIntToScalar(size.fHeight), kYAns));
REPORTER_ASSERT(reporter, 4 == numX && 4 == numY);
REPORTER_ASSERT(reporter, !skipMask);
} }
// test-out occlusion
{
static const SkScalar kCornerRad = 10.0f;
SkRRect rr;
rr.setRectXY(r, kCornerRad, kCornerRad);
// The rectXs & rectYs should be { 1, 29, 91, 119 }. Add two more points around each.
SkScalar testLocs[] = {
-18.0f, -9.0f,
1.0f,
9.0f, 18.0f,
29.0f,
39.0f, 49.0f,
91.0f,
109.0f, 118.0f,
119.0f,
139.0f, 149.0f
};
for (int minY = 0; minY < (int)SK_ARRAY_COUNT(testLocs); ++minY) {
for (int maxY = minY+1; maxY < (int)SK_ARRAY_COUNT(testLocs); ++maxY) {
for (int minX = 0; minX < (int)SK_ARRAY_COUNT(testLocs); ++minX) {
for (int maxX = minX+1; maxX < (int)SK_ARRAY_COUNT(testLocs); ++maxX) {
SkRect occluder = SkRect::MakeLTRB(testLocs[minX], testLocs[minY],
testLocs[maxX], testLocs[maxY]);
if (occluder.isEmpty()) {
continue;
}
ninePatchable = SkComputeBlurredRRectParams(rr, rr, occluder,
kBlurRad, kBlurRad,
&rrectToDraw, &size,
rectXs, rectYs, texXs, texYs,
&numX, &numY, &skipMask);
static const SkScalar kAns = 12.0f * kBlurRad + 2.0f * kCornerRad + 1.0f;
REPORTER_ASSERT(reporter, ninePatchable);
REPORTER_ASSERT(reporter,
SkScalarNearlyEqual(SkIntToScalar(size.fWidth), kAns));
REPORTER_ASSERT(reporter,
SkScalarNearlyEqual(SkIntToScalar(size.fHeight), kAns));
int checkBit = 0x1;
for (int y = 0; y < numY-1; ++y) {
for (int x = 0; x < numX-1; ++x) {
SkRect cell = SkRect::MakeLTRB(rectXs[x], rectYs[y],
rectXs[x+1], rectYs[y+1]);
REPORTER_ASSERT(reporter,
SkToBool(skipMask & checkBit) ==
(cell.isEmpty() || occluder.contains(cell)));
REPORTER_ASSERT(reporter, texXs[x] >= 0 &&
texXs[x] <= size.fWidth);
REPORTER_ASSERT(reporter, texYs[y] >= 0 &&
texXs[y] <= size.fHeight);
checkBit <<= 1;
}
}
}
}
}
}
}
} }
// https://crbugs.com/787712 // https://crbugs.com/787712