Chromium Code Reviews| 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; |