Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(147)

Unified Diff: src/core/SkConvolver.cpp

Issue 2500113004: Port convolve functions to SkOpts (Closed)
Patch Set: Fix typo Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/core/SkConvolver.h ('k') | src/core/SkOpts.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/core/SkConvolver.cpp
diff --git a/src/core/SkConvolver.cpp b/src/core/SkConvolver.cpp
index c32cc0347207a0bacc7a1e036f49384719e0e9dd..81fa9ee616841f2f847a84731945524f3ae6a92b 100644
--- a/src/core/SkConvolver.cpp
+++ b/src/core/SkConvolver.cpp
@@ -3,22 +3,10 @@
// found in the LICENSE file.
#include "SkConvolver.h"
+#include "SkOpts.h"
#include "SkTArray.h"
namespace {
-
- // Converts the argument to an 8-bit unsigned value by clamping to the range
- // 0-255.
- inline unsigned char ClampTo8(int a) {
- if (static_cast<unsigned>(a) < 256) {
- return a; // Avoid the extra check in the common case.
- }
- if (a < 0) {
- return 0;
- }
- return 255;
- }
-
// Stores a list of rows in a circular buffer. The usage is you write into it
// by calling AdvanceRow. It will keep track of which row in the buffer it
// should use next, and the total number of rows added.
@@ -108,169 +96,6 @@ namespace {
SkTArray<unsigned char*> fRowAddresses;
};
-// Convolves horizontally along a single row. The row data is given in
-// |srcData| and continues for the numValues() of the filter.
-template<bool hasAlpha>
- void ConvolveHorizontally(const unsigned char* srcData,
- const SkConvolutionFilter1D& filter,
- unsigned char* outRow) {
- // Loop over each pixel on this row in the output image.
- int numValues = filter.numValues();
- for (int outX = 0; outX < numValues; outX++) {
- // Get the filter that determines the current output pixel.
- int filterOffset, filterLength;
- const SkConvolutionFilter1D::ConvolutionFixed* filterValues =
- filter.FilterForValue(outX, &filterOffset, &filterLength);
-
- // Compute the first pixel in this row that the filter affects. It will
- // touch |filterLength| pixels (4 bytes each) after this.
- const unsigned char* rowToFilter = &srcData[filterOffset * 4];
-
- // Apply the filter to the row to get the destination pixel in |accum|.
- int accum[4] = {0};
- for (int filterX = 0; filterX < filterLength; filterX++) {
- SkConvolutionFilter1D::ConvolutionFixed curFilter = filterValues[filterX];
- accum[0] += curFilter * rowToFilter[filterX * 4 + 0];
- accum[1] += curFilter * rowToFilter[filterX * 4 + 1];
- accum[2] += curFilter * rowToFilter[filterX * 4 + 2];
- if (hasAlpha) {
- accum[3] += curFilter * rowToFilter[filterX * 4 + 3];
- }
- }
-
- // Bring this value back in range. All of the filter scaling factors
- // are in fixed point with kShiftBits bits of fractional part.
- accum[0] >>= SkConvolutionFilter1D::kShiftBits;
- accum[1] >>= SkConvolutionFilter1D::kShiftBits;
- accum[2] >>= SkConvolutionFilter1D::kShiftBits;
- if (hasAlpha) {
- accum[3] >>= SkConvolutionFilter1D::kShiftBits;
- }
-
- // Store the new pixel.
- outRow[outX * 4 + 0] = ClampTo8(accum[0]);
- outRow[outX * 4 + 1] = ClampTo8(accum[1]);
- outRow[outX * 4 + 2] = ClampTo8(accum[2]);
- if (hasAlpha) {
- outRow[outX * 4 + 3] = ClampTo8(accum[3]);
- }
- }
- }
-
- // There's a bug somewhere here with GCC autovectorization (-ftree-vectorize). We originally
- // thought this was 32 bit only, but subsequent tests show that some 64 bit gcc compiles
- // suffer here too.
- //
- // Dropping to -O2 disables -ftree-vectorize. GCC 4.6 needs noinline. https://bug.skia.org/2575
- #if SK_HAS_ATTRIBUTE(optimize) && defined(SK_RELEASE)
- #define SK_MAYBE_DISABLE_VECTORIZATION __attribute__((optimize("O2"), noinline))
- #else
- #define SK_MAYBE_DISABLE_VECTORIZATION
- #endif
-
- SK_MAYBE_DISABLE_VECTORIZATION
- static void ConvolveHorizontallyAlpha(const unsigned char* srcData,
- const SkConvolutionFilter1D& filter,
- unsigned char* outRow) {
- return ConvolveHorizontally<true>(srcData, filter, outRow);
- }
-
- SK_MAYBE_DISABLE_VECTORIZATION
- static void ConvolveHorizontallyNoAlpha(const unsigned char* srcData,
- const SkConvolutionFilter1D& filter,
- unsigned char* outRow) {
- return ConvolveHorizontally<false>(srcData, filter, outRow);
- }
-
- #undef SK_MAYBE_DISABLE_VECTORIZATION
-
-
-// Does vertical convolution to produce one output row. The filter values and
-// length are given in the first two parameters. These are applied to each
-// of the rows pointed to in the |sourceDataRows| array, with each row
-// being |pixelWidth| wide.
-//
-// The output must have room for |pixelWidth * 4| bytes.
-template<bool hasAlpha>
- void ConvolveVertically(const SkConvolutionFilter1D::ConvolutionFixed* filterValues,
- int filterLength,
- unsigned char* const* sourceDataRows,
- int pixelWidth,
- unsigned char* outRow) {
- // We go through each column in the output and do a vertical convolution,
- // generating one output pixel each time.
- for (int outX = 0; outX < pixelWidth; outX++) {
- // Compute the number of bytes over in each row that the current column
- // we're convolving starts at. The pixel will cover the next 4 bytes.
- int byteOffset = outX * 4;
-
- // Apply the filter to one column of pixels.
- int accum[4] = {0};
- for (int filterY = 0; filterY < filterLength; filterY++) {
- SkConvolutionFilter1D::ConvolutionFixed curFilter = filterValues[filterY];
- accum[0] += curFilter * sourceDataRows[filterY][byteOffset + 0];
- accum[1] += curFilter * sourceDataRows[filterY][byteOffset + 1];
- accum[2] += curFilter * sourceDataRows[filterY][byteOffset + 2];
- if (hasAlpha) {
- accum[3] += curFilter * sourceDataRows[filterY][byteOffset + 3];
- }
- }
-
- // Bring this value back in range. All of the filter scaling factors
- // are in fixed point with kShiftBits bits of precision.
- accum[0] >>= SkConvolutionFilter1D::kShiftBits;
- accum[1] >>= SkConvolutionFilter1D::kShiftBits;
- accum[2] >>= SkConvolutionFilter1D::kShiftBits;
- if (hasAlpha) {
- accum[3] >>= SkConvolutionFilter1D::kShiftBits;
- }
-
- // Store the new pixel.
- outRow[byteOffset + 0] = ClampTo8(accum[0]);
- outRow[byteOffset + 1] = ClampTo8(accum[1]);
- outRow[byteOffset + 2] = ClampTo8(accum[2]);
- if (hasAlpha) {
- unsigned char alpha = ClampTo8(accum[3]);
-
- // Make sure the alpha channel doesn't come out smaller than any of the
- // color channels. We use premultipled alpha channels, so this should
- // never happen, but rounding errors will cause this from time to time.
- // These "impossible" colors will cause overflows (and hence random pixel
- // values) when the resulting bitmap is drawn to the screen.
- //
- // We only need to do this when generating the final output row (here).
- int maxColorChannel = SkTMax(outRow[byteOffset + 0],
- SkTMax(outRow[byteOffset + 1],
- outRow[byteOffset + 2]));
- if (alpha < maxColorChannel) {
- outRow[byteOffset + 3] = maxColorChannel;
- } else {
- outRow[byteOffset + 3] = alpha;
- }
- } else {
- // No alpha channel, the image is opaque.
- outRow[byteOffset + 3] = 0xff;
- }
- }
- }
-
- void ConvolveVertically(const SkConvolutionFilter1D::ConvolutionFixed* filterValues,
- int filterLength,
- unsigned char* const* sourceDataRows,
- int pixelWidth,
- unsigned char* outRow,
- bool sourceHasAlpha) {
- if (sourceHasAlpha) {
- ConvolveVertically<true>(filterValues, filterLength,
- sourceDataRows, pixelWidth,
- outRow);
- } else {
- ConvolveVertically<false>(filterValues, filterLength,
- sourceDataRows, pixelWidth,
- outRow);
- }
- }
-
} // namespace
// SkConvolutionFilter1D ---------------------------------------------------------
@@ -346,9 +171,7 @@ bool BGRAConvolve2D(const unsigned char* sourceData,
const SkConvolutionFilter1D& filterX,
const SkConvolutionFilter1D& filterY,
int outputByteRowStride,
- unsigned char* output,
- const SkConvolutionProcs& convolveProcs,
- bool useSimdIfPossible) {
+ unsigned char* output) {
int maxYFilterSize = filterY.maxFilter();
@@ -374,7 +197,7 @@ bool BGRAConvolve2D(const unsigned char* sourceData,
// convolution pass yet. Somehow Windows does not like it.
int rowBufferWidth = (filterX.numValues() + 15) & ~0xF;
int rowBufferHeight = maxYFilterSize +
- (convolveProcs.fConvolve4RowsHorizontally ? 4 : 0);
+ (SkOpts::convolve_4_rows_horizontally != nullptr ? 4 : 0);
// check for too-big allocation requests : crbug.com/528628
{
@@ -410,7 +233,7 @@ bool BGRAConvolve2D(const unsigned char* sourceData,
// Generate output rows until we have enough to run the current filter.
while (nextXRow < filterOffset + filterLength) {
- if (convolveProcs.fConvolve4RowsHorizontally &&
+ if (SkOpts::convolve_4_rows_horizontally != nullptr &&
nextXRow + 3 < lastFilterOffset + lastFilterLength) {
const unsigned char* src[4];
unsigned char* outRow[4];
@@ -418,24 +241,12 @@ bool BGRAConvolve2D(const unsigned char* sourceData,
src[i] = &sourceData[(uint64_t)(nextXRow + i) * sourceByteRowStride];
outRow[i] = rowBuffer.advanceRow();
}
- convolveProcs.fConvolve4RowsHorizontally(src, filterX, outRow, 4*rowBufferWidth);
+ SkOpts::convolve_4_rows_horizontally(src, filterX, outRow, 4*rowBufferWidth);
nextXRow += 4;
} else {
- if (convolveProcs.fConvolveHorizontally) {
- convolveProcs.fConvolveHorizontally(
+ SkOpts::convolve_horizontally(
&sourceData[(uint64_t)nextXRow * sourceByteRowStride],
filterX, rowBuffer.advanceRow(), sourceHasAlpha);
- } else {
- if (sourceHasAlpha) {
- ConvolveHorizontallyAlpha(
- &sourceData[(uint64_t)nextXRow * sourceByteRowStride],
- filterX, rowBuffer.advanceRow());
- } else {
- ConvolveHorizontallyNoAlpha(
- &sourceData[(uint64_t)nextXRow * sourceByteRowStride],
- filterX, rowBuffer.advanceRow());
- }
- }
nextXRow++;
}
}
@@ -448,22 +259,14 @@ bool BGRAConvolve2D(const unsigned char* sourceData,
unsigned char* const* rowsToConvolve =
rowBuffer.GetRowAddresses(&firstRowInCircularBuffer);
- // Now compute the start of the subset of those rows that the filter
- // needs.
+ // Now compute the start of the subset of those rows that the filter needs.
unsigned char* const* firstRowForFilter =
&rowsToConvolve[filterOffset - firstRowInCircularBuffer];
- if (convolveProcs.fConvolveVertically) {
- convolveProcs.fConvolveVertically(filterValues, filterLength,
- firstRowForFilter,
- filterX.numValues(), curOutputRow,
- sourceHasAlpha);
- } else {
- ConvolveVertically(filterValues, filterLength,
- firstRowForFilter,
- filterX.numValues(), curOutputRow,
- sourceHasAlpha);
- }
+ SkOpts::convolve_vertically(filterValues, filterLength,
+ firstRowForFilter,
+ filterX.numValues(), curOutputRow,
+ sourceHasAlpha);
}
return true;
}
« no previous file with comments | « src/core/SkConvolver.h ('k') | src/core/SkOpts.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698