Index: src/effects/GrCircleBlurFragmentProcessor.cpp |
diff --git a/src/effects/GrCircleBlurFragmentProcessor.cpp b/src/effects/GrCircleBlurFragmentProcessor.cpp |
index ff6985f7c3d56b5ea13b836c786acd9a4dd5a73e..61f755d94f155b19009130a794f73e5bf131507f 100644 |
--- a/src/effects/GrCircleBlurFragmentProcessor.cpp |
+++ b/src/effects/GrCircleBlurFragmentProcessor.cpp |
@@ -137,47 +137,52 @@ static void make_half_kernel_and_summed_table(float* halfKernel, float* summedHa |
} |
} |
robertphillips
2016/05/20 14:44:18
at a points ?
Maybe something more like:
Create
bsalomon
2016/05/20 15:17:14
Done.
|
-// Applies the 1D half kernel vertically at a point (x, 0) to a circle centered at the origin with |
+// Applies the 1D half kernel vertically at a points (x, 0) to a circle centered at the origin with |
// radius circleR. |
-static float eval_vertically(float x, float circleR, const float* summedHalfKernelTable, |
- int halfKernelSize) { |
- // Given x find the positive y that is on the edge of the circle. |
- float y = sqrtf(fabs(circleR * circleR - x * x)); |
- // In the column at x we exit the circle at +y and -y |
- // table entry j is actually the kernel evaluated at j + 0.5. |
- y -= 0.5f; |
- int yInt = SkScalarFloorToInt(y); |
- SkASSERT(yInt >= -1); |
- if (y < 0) { |
- return (y + 0.5f) * summedHalfKernelTable[0]; |
- } else if (yInt >= halfKernelSize - 1) { |
- return 0.5f; |
- } else { |
- float yFrac = y - yInt; |
- return (1.f - yFrac) * summedHalfKernelTable[yInt] + |
- yFrac * summedHalfKernelTable[yInt + 1]; |
+void apply_kernel_in_y(float* results, int numSteps, float firstX, float circleR, |
+ int halfKernelSize, const float* summedHalfKernelTable) { |
+ float x = firstX; |
+ for (int i = 0; i < numSteps; ++i, x += 1.f) { |
+ if (x < -circleR || x > circleR) { |
bsalomon
2016/05/20 00:24:45
I tried breaking this loop up into five parts:
1)
|
+ results[i] = 0; |
+ continue; |
+ } |
+ float y = sqrtf(circleR * circleR - x * x); |
+ // In the column at x we exit the circle at +y and -y |
+ // The summed table entry j is actually reflects an offset of j + 0.5. |
+ y -= 0.5f; |
+ int yInt = SkScalarFloorToInt(y); |
+ SkASSERT(yInt >= -1); |
+ if (y < 0) { |
+ results[i] = (y + 0.5f) * summedHalfKernelTable[0]; |
+ } else if (yInt >= halfKernelSize - 1) { |
+ results[i] = 0.5f; |
+ } else { |
+ float yFrac = y - yInt; |
+ results[i] = (1.f - yFrac) * summedHalfKernelTable[yInt] + |
+ yFrac * summedHalfKernelTable[yInt + 1]; |
+ } |
} |
} |
robertphillips
2016/05/20 14:44:19
// Conceptually combine the 2D Gaussian kernel pos
bsalomon
2016/05/20 15:17:14
Done.
|
-// Apply the kernel at point (t, 0) to a circle centered at the origin with radius circleR. |
-static uint8_t eval_at(float t, float circleR, const float* halfKernel, |
- const float* summedHalfKernelTable, int halfKernelSize) { |
+// Apply the kernel at point (evalX, 0) to a circle centered at the origin with radius circleR. |
+static uint8_t eval_at(float evalX, float circleR, const float* halfKernel, int halfKernelSize, |
+ const float* yKernelEvaluations) { |
float acc = 0; |
- for (int i = 0; i < halfKernelSize; ++i) { |
- float x = t - i - 0.5f; |
+ float x = evalX - halfKernelSize; |
+ for (int i = 0; i < halfKernelSize; ++i, x += 1.f) { |
if (x < -circleR || x > circleR) { |
continue; |
} |
- float verticalEval = eval_vertically(x, circleR, summedHalfKernelTable, halfKernelSize); |
- acc += verticalEval * halfKernel[i]; |
+ float verticalEval = yKernelEvaluations[i]; |
+ acc += verticalEval * halfKernel[halfKernelSize - i - 1]; |
} |
- for (int i = 0; i < halfKernelSize; ++i) { |
- float x = t + i + 0.5f; |
+ for (int i = 0; i < halfKernelSize; ++i, x += 1.f) { |
if (x < -circleR || x > circleR) { |
continue; |
} |
- float verticalEval = eval_vertically(x, circleR, summedHalfKernelTable, halfKernelSize); |
+ float verticalEval = yKernelEvaluations[i + halfKernelSize]; |
acc += verticalEval * halfKernel[i]; |
} |
// Since we applied a half kernel in y we multiply acc by 2 (the circle is symmetric about the |
@@ -217,13 +222,22 @@ static uint8_t* create_profile(float circleR, float sigma) { |
int halfKernelSize = SkScalarCeilToInt(6.0f*sigma); |
// round up to next multiple of 2 and then divide by 2 |
halfKernelSize = ((halfKernelSize + 1) & ~1) >> 1; |
- SkAutoTArray<float> halfKernel(halfKernelSize); |
- SkAutoTArray<float> summedKernel(halfKernelSize); |
- make_half_kernel_and_summed_table(halfKernel.get(), summedKernel.get(), halfKernelSize, |
- sigma); |
+ |
+ // Number of x steps at which to apply kernel in y to cover all the profile samples in x. |
+ int numYSteps = numSteps + 2 * halfKernelSize; |
+ |
+ SkAutoTArray<float> bulkAlloc(halfKernelSize + halfKernelSize + numYSteps); |
+ float* halfKernel = bulkAlloc.get(); |
+ float* summedKernel = bulkAlloc.get() + halfKernelSize; |
+ float* yEvals = bulkAlloc.get() + 2 * halfKernelSize; |
+ make_half_kernel_and_summed_table(halfKernel, summedKernel, halfKernelSize, sigma); |
+ |
+ float firstX = offset - halfKernelSize + 0.5; |
+ apply_kernel_in_y(yEvals, numYSteps, firstX, circleR, halfKernelSize, summedKernel); |
+ |
for (int i = 0; i < numSteps - 1; ++i) { |
- weights[i] = eval_at(offset+i, circleR, halfKernel.get(), summedKernel.get(), |
- halfKernelSize); |
+ float evalX = offset + i + 0.5f; |
+ weights[i] = eval_at(evalX, circleR, halfKernel, halfKernelSize, yEvals + i); |
} |
// Ensure the tail of the Gaussian goes to zero. |
weights[numSteps - 1] = 0; |