#include "SkMath.h"
#include "SkMathPriv.h"
-#define SCALE_NOFILTER_NAME MAKENAME(_nofilter_scale)
#define SCALE_FILTER_NAME MAKENAME(_filter_scale)
-#define AFFINE_NOFILTER_NAME MAKENAME(_nofilter_affine)
#define AFFINE_FILTER_NAME MAKENAME(_filter_affine)
-#define PERSP_NOFILTER_NAME MAKENAME(_nofilter_persp)
#define PERSP_FILTER_NAME MAKENAME(_filter_persp)
#define PACK_FILTER_X_NAME MAKENAME(_pack_filter_x)
#endif
// declare functions externally to suppress warnings.
-void SCALE_NOFILTER_NAME(const SkBitmapProcState& s,
- uint32_t xy[], int count, int x, int y);
-void AFFINE_NOFILTER_NAME(const SkBitmapProcState& s,
- uint32_t xy[], int count, int x, int y);
-void PERSP_NOFILTER_NAME(const SkBitmapProcState& s,
- uint32_t* SK_RESTRICT xy,
- int count, int x, int y);
void SCALE_FILTER_NAME(const SkBitmapProcState& s,
uint32_t xy[], int count, int x, int y);
void AFFINE_FILTER_NAME(const SkBitmapProcState& s,
uint32_t* SK_RESTRICT xy, int count,
int x, int y);
-void SCALE_NOFILTER_NAME(const SkBitmapProcState& s,
- uint32_t xy[], int count, int x, int y) {
- SkASSERT((s.fInvType & ~(SkMatrix::kTranslate_Mask |
- SkMatrix::kScale_Mask)) == 0);
-
- PREAMBLE(s);
- // we store y, x, x, x, x, x
-
- const unsigned maxX = s.fBitmap->width() - 1;
- SkFractionalInt fx;
- {
- SkPoint pt;
- s.fInvProc(s.fInvMatrix, SkIntToScalar(x) + SK_ScalarHalf,
- SkIntToScalar(y) + SK_ScalarHalf, &pt);
- fx = SkScalarToFractionalInt(pt.fY);
- const unsigned maxY = s.fBitmap->height() - 1;
- *xy++ = TILEY_PROCF(SkFractionalIntToFixed(fx), maxY);
- fx = SkScalarToFractionalInt(pt.fX);
- }
-
- if (0 == maxX) {
- // all of the following X values must be 0
- memset(xy, 0, count * sizeof(uint16_t));
- return;
- }
-
- const SkFractionalInt dx = s.fInvSxFractionalInt;
-
-#ifdef CHECK_FOR_DECAL
- if (can_truncate_to_fixed_for_decal(fx, dx, count, maxX)) {
- decal_nofilter_scale(xy, SkFractionalIntToFixed(fx),
- SkFractionalIntToFixed(dx), count);
- } else
-#endif
- {
- int i;
- for (i = (count >> 2); i > 0; --i) {
- unsigned a, b;
- a = TILEX_PROCF(SkFractionalIntToFixed(fx), maxX); fx += dx;
- b = TILEX_PROCF(SkFractionalIntToFixed(fx), maxX); fx += dx;
-#ifdef SK_CPU_BENDIAN
- *xy++ = (a << 16) | b;
-#else
- *xy++ = (b << 16) | a;
-#endif
- a = TILEX_PROCF(SkFractionalIntToFixed(fx), maxX); fx += dx;
- b = TILEX_PROCF(SkFractionalIntToFixed(fx), maxX); fx += dx;
-#ifdef SK_CPU_BENDIAN
- *xy++ = (a << 16) | b;
-#else
- *xy++ = (b << 16) | a;
-#endif
- }
- uint16_t* xx = (uint16_t*)xy;
- for (i = (count & 3); i > 0; --i) {
- *xx++ = TILEX_PROCF(SkFractionalIntToFixed(fx), maxX); fx += dx;
- }
- }
-}
-
-// note: we could special-case on a matrix which is skewed in X but not Y.
-// this would require a more general setup thatn SCALE does, but could use
-// SCALE's inner loop that only looks at dx
-
-void AFFINE_NOFILTER_NAME(const SkBitmapProcState& s,
- uint32_t xy[], int count, int x, int y) {
- SkASSERT(s.fInvType & SkMatrix::kAffine_Mask);
- SkASSERT((s.fInvType & ~(SkMatrix::kTranslate_Mask |
- SkMatrix::kScale_Mask |
- SkMatrix::kAffine_Mask)) == 0);
-
- PREAMBLE(s);
- SkPoint srcPt;
- s.fInvProc(s.fInvMatrix,
- SkIntToScalar(x) + SK_ScalarHalf,
- SkIntToScalar(y) + SK_ScalarHalf, &srcPt);
-
- SkFractionalInt fx = SkScalarToFractionalInt(srcPt.fX);
- SkFractionalInt fy = SkScalarToFractionalInt(srcPt.fY);
- SkFractionalInt dx = s.fInvSxFractionalInt;
- SkFractionalInt dy = s.fInvKyFractionalInt;
- int maxX = s.fBitmap->width() - 1;
- int maxY = s.fBitmap->height() - 1;
-
- for (int i = count; i > 0; --i) {
- *xy++ = (TILEY_PROCF(SkFractionalIntToFixed(fy), maxY) << 16) |
- TILEX_PROCF(SkFractionalIntToFixed(fx), maxX);
- fx += dx; fy += dy;
- }
-}
-
-void PERSP_NOFILTER_NAME(const SkBitmapProcState& s,
- uint32_t* SK_RESTRICT xy,
- int count, int x, int y) {
- SkASSERT(s.fInvType & SkMatrix::kPerspective_Mask);
-
- PREAMBLE(s);
- int maxX = s.fBitmap->width() - 1;
- int maxY = s.fBitmap->height() - 1;
-
- SkPerspIter iter(s.fInvMatrix,
- SkIntToScalar(x) + SK_ScalarHalf,
- SkIntToScalar(y) + SK_ScalarHalf, count);
-
- while ((count = iter.next()) != 0) {
- const SkFixed* SK_RESTRICT srcXY = iter.getXY();
- while (--count >= 0) {
- *xy++ = (TILEY_PROCF(srcXY[1], maxY) << 16) |
- TILEX_PROCF(srcXY[0], maxX);
- srcXY += 2;
- }
- }
-}
-
-//////////////////////////////////////////////////////////////////////////////
-
static inline uint32_t PACK_FILTER_Y_NAME(SkFixed f, unsigned max,
SkFixed one PREAMBLE_PARAM_Y) {
unsigned i = TILEY_PROCF(f, max);
}
}
-static SkBitmapProcState::MatrixProc MAKENAME(_Procs)[] = {
- SCALE_NOFILTER_NAME,
- SCALE_FILTER_NAME,
- AFFINE_NOFILTER_NAME,
- AFFINE_FILTER_NAME,
- PERSP_NOFILTER_NAME,
- PERSP_FILTER_NAME
-};
-
#undef MAKENAME
#undef TILEX_PROCF
#undef TILEY_PROCF
#undef CHECK_FOR_DECAL
#endif
-#undef SCALE_NOFILTER_NAME
#undef SCALE_FILTER_NAME
-#undef AFFINE_NOFILTER_NAME
#undef AFFINE_FILTER_NAME
-#undef PERSP_NOFILTER_NAME
#undef PERSP_FILTER_NAME
#undef PREAMBLE
void decal_nofilter_scale(uint32_t dst[], SkFixed fx, SkFixed dx, int count);
void decal_filter_scale(uint32_t dst[], SkFixed fx, SkFixed dx, int count);
+#include "SkBitmapProcState_matrix_template.h"
+
+///////////////////////////////////////////////////////////////////////////////
+
// Compile neon code paths if needed
#if !SK_ARM_NEON_IS_NONE
#define CHECK_FOR_DECAL
#include "SkBitmapProcState_matrix.h"
+struct ClampTileProcs {
+ static unsigned X(const SkBitmapProcState&, SkFixed fx, int max) {
+ return SkClampMax(fx >> 16, max);
+ }
+ static unsigned Y(const SkBitmapProcState&, SkFixed fy, int max) {
+ return SkClampMax(fy >> 16, max);
+ }
+};
+
+// Referenced in opts_check_SSE2.cpp
+void ClampX_ClampY_nofilter_scale(const SkBitmapProcState& s, uint32_t xy[],
+ int count, int x, int y) {
+ return NoFilterProc_Scale<ClampTileProcs, true>(s, xy, count, x, y);
+}
+void ClampX_ClampY_nofilter_affine(const SkBitmapProcState& s, uint32_t xy[],
+ int count, int x, int y) {
+ return NoFilterProc_Affine<ClampTileProcs>(s, xy, count, x, y);
+}
+
+static SkBitmapProcState::MatrixProc ClampX_ClampY_Procs[] = {
+ // only clamp lives in the right coord space to check for decal
+ ClampX_ClampY_nofilter_scale,
+ ClampX_ClampY_filter_scale,
+ ClampX_ClampY_nofilter_affine,
+ ClampX_ClampY_filter_affine,
+ NoFilterProc_Persp<ClampTileProcs>,
+ ClampX_ClampY_filter_persp
+};
+
#define MAKENAME(suffix) RepeatX_RepeatY ## suffix
#define TILEX_PROCF(fx, max) SK_USHIFT16(((fx) & 0xFFFF) * ((max) + 1))
#define TILEY_PROCF(fy, max) SK_USHIFT16(((fy) & 0xFFFF) * ((max) + 1))
#define TILEX_LOW_BITS(fx, max) ((((fx) & 0xFFFF) * ((max) + 1) >> 12) & 0xF)
#define TILEY_LOW_BITS(fy, max) ((((fy) & 0xFFFF) * ((max) + 1) >> 12) & 0xF)
#include "SkBitmapProcState_matrix.h"
+
+struct RepeatTileProcs {
+ static unsigned X(const SkBitmapProcState&, SkFixed fx, int max) {
+ return SK_USHIFT16(((fx) & 0xFFFF) * ((max) + 1));
+ }
+ static unsigned Y(const SkBitmapProcState&, SkFixed fy, int max) {
+ return SK_USHIFT16(((fy) & 0xFFFF) * ((max) + 1));
+ }
+};
+
+static SkBitmapProcState::MatrixProc RepeatX_RepeatY_Procs[] = {
+ NoFilterProc_Scale<RepeatTileProcs, false>,
+ RepeatX_RepeatY_filter_scale,
+ NoFilterProc_Affine<RepeatTileProcs>,
+ RepeatX_RepeatY_filter_affine,
+ NoFilterProc_Persp<RepeatTileProcs>,
+ RepeatX_RepeatY_filter_persp
+};
#endif
#define MAKENAME(suffix) GeneralXY ## suffix
#define TILEY_LOW_BITS(fy, max) tileLowBitsProcY(fy, (max) + 1)
#include "SkBitmapProcState_matrix.h"
-static inline U16CPU fixed_clamp(SkFixed x)
-{
+struct GeneralTileProcs {
+ static unsigned X(const SkBitmapProcState& s, SkFixed fx, int max) {
+ return SK_USHIFT16(s.fTileProcX(fx) * ((max) + 1));
+ }
+ static unsigned Y(const SkBitmapProcState& s, SkFixed fy, int max) {
+ return SK_USHIFT16(s.fTileProcY(fy) * ((max) + 1));
+ }
+};
+
+static SkBitmapProcState::MatrixProc GeneralXY_Procs[] = {
+ NoFilterProc_Scale<GeneralTileProcs, false>,
+ GeneralXY_filter_scale,
+ NoFilterProc_Affine<GeneralTileProcs>,
+ GeneralXY_filter_affine,
+ NoFilterProc_Persp<GeneralTileProcs>,
+ GeneralXY_filter_persp
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+static inline U16CPU fixed_clamp(SkFixed x) {
if (x < 0) {
x = 0;
}
return x;
}
-static inline U16CPU fixed_repeat(SkFixed x)
-{
+static inline U16CPU fixed_repeat(SkFixed x) {
return x & 0xFFFF;
}
#pragma optimize("", off)
#endif
-static inline U16CPU fixed_mirror(SkFixed x)
-{
+static inline U16CPU fixed_mirror(SkFixed x) {
SkFixed s = x << 15 >> 31;
// s is FFFFFFFF if we're on an odd interval, or 0 if an even interval
return (x ^ s) & 0xFFFF;
#pragma optimize("", on)
#endif
-static SkBitmapProcState::FixedTileProc choose_tile_proc(unsigned m)
-{
- if (SkShader::kClamp_TileMode == m)
+static SkBitmapProcState::FixedTileProc choose_tile_proc(unsigned m) {
+ if (SkShader::kClamp_TileMode == m) {
return fixed_clamp;
- if (SkShader::kRepeat_TileMode == m)
+ }
+ if (SkShader::kRepeat_TileMode == m) {
return fixed_repeat;
+ }
SkASSERT(SkShader::kMirror_TileMode == m);
return fixed_mirror;
}
//////////////////////////////////////////////////////////////////////////////
-void decal_nofilter_scale(uint32_t dst[], SkFixed fx, SkFixed dx, int count)
-{
+void decal_nofilter_scale(uint32_t dst[], SkFixed fx, SkFixed dx, int count) {
int i;
- for (i = (count >> 2); i > 0; --i)
- {
+ for (i = (count >> 2); i > 0; --i) {
*dst++ = pack_two_shorts(fx >> 16, (fx + dx) >> 16);
fx += dx+dx;
*dst++ = pack_two_shorts(fx >> 16, (fx + dx) >> 16);
}
}
-void decal_filter_scale(uint32_t dst[], SkFixed fx, SkFixed dx, int count)
-{
-
-
- if (count & 1)
- {
+void decal_filter_scale(uint32_t dst[], SkFixed fx, SkFixed dx, int count) {
+ if (count & 1) {
SkASSERT((fx >> (16 + 14)) == 0);
*dst++ = (fx >> 12 << 14) | ((fx >> 16) + 1);
fx += dx;
}
- while ((count -= 2) >= 0)
- {
+ while ((count -= 2) >= 0) {
SkASSERT((fx >> (16 + 14)) == 0);
*dst++ = (fx >> 12 << 14) | ((fx >> 16) + 1);
fx += dx;
///////////////////////////////////////////////////////////////////////////////
-SkBitmapProcState::MatrixProc
-SkBitmapProcState::chooseMatrixProc(bool trivial_matrix) {
+SkBitmapProcState::MatrixProc SkBitmapProcState::chooseMatrixProc(bool trivial_matrix) {
// test_int_tileprocs();
// check for our special case when there is no scale/affine/perspective
if (trivial_matrix) {
index += 2;
}
- if (SkShader::kClamp_TileMode == fTileModeX &&
- SkShader::kClamp_TileMode == fTileModeY)
- {
+ if (SkShader::kClamp_TileMode == fTileModeX && SkShader::kClamp_TileMode == fTileModeY) {
// clamp gets special version of filterOne
fFilterOneX = SK_Fixed1;
fFilterOneY = SK_Fixed1;
fFilterOneX = SK_Fixed1 / fBitmap->width();
fFilterOneY = SK_Fixed1 / fBitmap->height();
- if (SkShader::kRepeat_TileMode == fTileModeX &&
- SkShader::kRepeat_TileMode == fTileModeY)
- {
+ if (SkShader::kRepeat_TileMode == fTileModeX && SkShader::kRepeat_TileMode == fTileModeY) {
return SK_ARM_NEON_WRAP(RepeatX_RepeatY_Procs)[index];
}
--- /dev/null
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkBitmapProcState_MatrixTemplates_DEFINED
+#define SkBitmapProcState_MatrixTemplates_DEFINED
+
+#include "SkMath.h"
+#include "SkMathPriv.h"
+
+template <typename TileProc, bool tryDecal>
+void NoFilterProc_Scale(const SkBitmapProcState& s, uint32_t xy[],
+ int count, int x, int y) {
+ SkASSERT((s.fInvType & ~(SkMatrix::kTranslate_Mask |
+ SkMatrix::kScale_Mask)) == 0);
+
+ // we store y, x, x, x, x, x
+
+ const unsigned maxX = s.fBitmap->width() - 1;
+ SkFractionalInt fx;
+ {
+ SkPoint pt;
+ s.fInvProc(s.fInvMatrix, SkIntToScalar(x) + SK_ScalarHalf,
+ SkIntToScalar(y) + SK_ScalarHalf, &pt);
+ fx = SkScalarToFractionalInt(pt.fY);
+ const unsigned maxY = s.fBitmap->height() - 1;
+ *xy++ = TileProc::Y(s, SkFractionalIntToFixed(fx), maxY);
+ fx = SkScalarToFractionalInt(pt.fX);
+ }
+
+ if (0 == maxX) {
+ // all of the following X values must be 0
+ memset(xy, 0, count * sizeof(uint16_t));
+ return;
+ }
+
+ const SkFractionalInt dx = s.fInvSxFractionalInt;
+
+ if (tryDecal && can_truncate_to_fixed_for_decal(fx, dx, count, maxX)) {
+ decal_nofilter_scale(xy, SkFractionalIntToFixed(fx),
+ SkFractionalIntToFixed(dx), count);
+ } else {
+ int i;
+ for (i = (count >> 2); i > 0; --i) {
+ unsigned a, b;
+ a = TileProc::X(s, SkFractionalIntToFixed(fx), maxX); fx += dx;
+ b = TileProc::X(s, SkFractionalIntToFixed(fx), maxX); fx += dx;
+#ifdef SK_CPU_BENDIAN
+ *xy++ = (a << 16) | b;
+#else
+ *xy++ = (b << 16) | a;
+#endif
+ a = TileProc::X(s, SkFractionalIntToFixed(fx), maxX); fx += dx;
+ b = TileProc::X(s, SkFractionalIntToFixed(fx), maxX); fx += dx;
+#ifdef SK_CPU_BENDIAN
+ *xy++ = (a << 16) | b;
+#else
+ *xy++ = (b << 16) | a;
+#endif
+ }
+ uint16_t* xx = (uint16_t*)xy;
+ for (i = (count & 3); i > 0; --i) {
+ *xx++ = TileProc::X(s, SkFractionalIntToFixed(fx), maxX); fx += dx;
+ }
+ }
+}
+
+// note: we could special-case on a matrix which is skewed in X but not Y.
+// this would require a more general setup thatn SCALE does, but could use
+// SCALE's inner loop that only looks at dx
+
+template <typename TileProc>
+void NoFilterProc_Affine(const SkBitmapProcState& s, uint32_t xy[],
+ int count, int x, int y) {
+ SkASSERT(s.fInvType & SkMatrix::kAffine_Mask);
+ SkASSERT((s.fInvType & ~(SkMatrix::kTranslate_Mask |
+ SkMatrix::kScale_Mask |
+ SkMatrix::kAffine_Mask)) == 0);
+
+ SkPoint srcPt;
+ s.fInvProc(s.fInvMatrix,
+ SkIntToScalar(x) + SK_ScalarHalf,
+ SkIntToScalar(y) + SK_ScalarHalf, &srcPt);
+
+ SkFractionalInt fx = SkScalarToFractionalInt(srcPt.fX);
+ SkFractionalInt fy = SkScalarToFractionalInt(srcPt.fY);
+ SkFractionalInt dx = s.fInvSxFractionalInt;
+ SkFractionalInt dy = s.fInvKyFractionalInt;
+ int maxX = s.fBitmap->width() - 1;
+ int maxY = s.fBitmap->height() - 1;
+
+ for (int i = count; i > 0; --i) {
+ *xy++ = (TileProc::Y(s, SkFractionalIntToFixed(fy), maxY) << 16) |
+ TileProc::X(s, SkFractionalIntToFixed(fx), maxX);
+ fx += dx; fy += dy;
+ }
+}
+
+template <typename TileProc>
+void NoFilterProc_Persp(const SkBitmapProcState& s, uint32_t* SK_RESTRICT xy,
+ int count, int x, int y) {
+ SkASSERT(s.fInvType & SkMatrix::kPerspective_Mask);
+
+ int maxX = s.fBitmap->width() - 1;
+ int maxY = s.fBitmap->height() - 1;
+
+ SkPerspIter iter(s.fInvMatrix,
+ SkIntToScalar(x) + SK_ScalarHalf,
+ SkIntToScalar(y) + SK_ScalarHalf, count);
+
+ while ((count = iter.next()) != 0) {
+ const SkFixed* SK_RESTRICT srcXY = iter.getXY();
+ while (--count >= 0) {
+ *xy++ = (TileProc::Y(s, srcXY[1], maxY) << 16) |
+ TileProc::X(s, srcXY[0], maxX);
+ srcXY += 2;
+ }
+ }
+}
+
+#endif