Index: sgl/SkBitmapProcState.h =================================================================== --- sgl/SkBitmapProcState.h (revision 42716) +++ sgl/SkBitmapProcState.h (working copy) @@ -39,8 +39,9 @@ int count, uint16_t colors[]); - typedef U16CPU (*FixedTileProc)(SkFixed); // returns 0..0xFFFF - + typedef SkFixed (*FixedTileProc)(SkFixed, int); + typedef int (*IntTileProc)(int, int); + MatrixProc fMatrixProc; // chooseProcs SampleProc32 fSampleProc32; // chooseProcs SampleProc16 fSampleProc16; // chooseProcs @@ -48,6 +49,8 @@ SkMatrix fUnitInvMatrix; // chooseProcs FixedTileProc fTileProcX; // chooseProcs FixedTileProc fTileProcY; // chooseProcs + IntTileProc iTileProcX; // chooseProcs + IntTileProc iTileProcY; // chooseProcs SkFixed fFilterOneX; SkFixed fFilterOneY; Index: sgl/SkBitmapProcState.cpp =================================================================== --- sgl/SkBitmapProcState.cpp (revision 42716) +++ sgl/SkBitmapProcState.cpp (working copy) @@ -296,8 +296,9 @@ } const SkMatrix* m; - if (SkShader::kClamp_TileMode == fTileModeX && - SkShader::kClamp_TileMode == fTileModeY) { + if (inv.getType() <= SkMatrix::kTranslate_Mask || + (SkShader::kClamp_TileMode == fTileModeX && + SkShader::kClamp_TileMode == fTileModeY)) { m = &inv; } else { fUnitInvMatrix = inv; @@ -330,6 +331,16 @@ fInvMatrix = m; fInvProc = m->getMapXYProc(); fInvType = m->getType(); + if (fInvType <= SkMatrix::kTranslate_Mask && + inv.getType() > SkMatrix::kTranslate_Mask) { + SkASSERT(inv.getType() <= + (SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)); + // It is possible that by the calculation of fUnitInvMatrix, we have + // eliminated the scale transformation of the matrix (e.g., if inv^(-1) + // scales fOrigBitmap into an 1X1 rect). We add the scale flag back so + // that we don't make wrong choice in chooseMatrixProc(). + fInvType |= SkMatrix::kScale_Mask; + } fInvSx = SkScalarToFixed(m->getScaleX()); fInvSy = SkScalarToFixed(m->getScaleY()); fInvKy = SkScalarToFixed(m->getSkewY()); Index: sgl/SkBitmapProcState_matrix.h =================================================================== --- sgl/SkBitmapProcState_matrix.h (revision 42716) +++ sgl/SkBitmapProcState_matrix.h (working copy) @@ -1,4 +1,5 @@ +#define TRANSLATE_NOFILTER_NAME MAKENAME(_nofilter_translate) #define SCALE_NOFILTER_NAME MAKENAME(_nofilter_scale) #define SCALE_FILTER_NAME MAKENAME(_filter_scale) #define AFFINE_NOFILTER_NAME MAKENAME(_nofilter_affine) @@ -17,6 +18,38 @@ #define PREAMBLE_ARG_Y #endif +#ifndef PREAMBLE_TRANS + #define PREAMBLE_TRANS(state) +#endif + +static void TRANSLATE_NOFILTER_NAME(const SkBitmapProcState& s, + uint32_t xy[], int count, int x, int y) +{ + SkASSERT((s.fInvType & ~SkMatrix::kTranslate_Mask) == 0); + + PREAMBLE_TRANS(s); + + x += SkScalarFloor(s.fInvMatrix->getTranslateX()); + y += SkScalarFloor(s.fInvMatrix->getTranslateY()); + + *xy++ = (uint32_t)TILEY_TRANS(y, (s.fBitmap->height() - 1)); + + int maxX = s.fBitmap->width() - 1; + int i; + uint16_t* xx = (uint16_t*)xy; + for (i = (count >> 2); i > 0; --i) + { + *xx++ = (uint16_t)TILEX_TRANS(x, maxX); x++; + *xx++ = (uint16_t)TILEX_TRANS(x, maxX); x++; + *xx++ = (uint16_t)TILEX_TRANS(x, maxX); x++; + *xx++ = (uint16_t)TILEX_TRANS(x, maxX); x++; + } + for (i = (count & 3); i > 0; --i) + { + *xx++ = (uint16_t)TILEX_TRANS(x, maxX); x++; + } +} + static void SCALE_NOFILTER_NAME(const SkBitmapProcState& s, uint32_t xy[], int count, int x, int y) { SkASSERT((s.fInvType & ~(SkMatrix::kTranslate_Mask | @@ -206,9 +239,9 @@ unsigned maxY = s.fBitmap->height() - 1; do { - *xy++ = PACK_FILTER_Y_NAME(fy, maxY, oneX PREAMBLE_ARG_Y); + *xy++ = PACK_FILTER_Y_NAME(fy, maxY, oneY PREAMBLE_ARG_Y); fy += dy; - *xy++ = PACK_FILTER_X_NAME(fx, maxX, oneY PREAMBLE_ARG_X); + *xy++ = PACK_FILTER_X_NAME(fx, maxX, oneX PREAMBLE_ARG_X); fx += dx; } while (--count != 0); } @@ -241,6 +274,9 @@ } static SkBitmapProcState::MatrixProc MAKENAME(_Procs)[] = { + TRANSLATE_NOFILTER_NAME, + TRANSLATE_NOFILTER_NAME, // No need to do filtering if the matrix is no + // more complex than identity/translate. SCALE_NOFILTER_NAME, SCALE_FILTER_NAME, AFFINE_NOFILTER_NAME, @@ -255,7 +291,10 @@ #ifdef CHECK_FOR_DECAL #undef CHECK_FOR_DECAL #endif - +#undef TILEX_TRANS +#undef TILEY_TRANS + +#undef TRANSLATE_NOFILTER_NAME #undef SCALE_NOFILTER_NAME #undef SCALE_FILTER_NAME #undef AFFINE_NOFILTER_NAME @@ -268,6 +307,7 @@ #undef PREAMBLE_PARAM_Y #undef PREAMBLE_ARG_X #undef PREAMBLE_ARG_Y +#undef PREAMBLE_TRANS #undef TILEX_LOW_BITS #undef TILEY_LOW_BITS Index: sgl/SkBitmapProcState_matrixProcs.cpp =================================================================== --- sgl/SkBitmapProcState_matrixProcs.cpp (revision 42716) +++ sgl/SkBitmapProcState_matrixProcs.cpp (working copy) @@ -28,6 +28,8 @@ #define TILEX_LOW_BITS(fx, max) (((fx) >> 12) & 0xF) #define TILEY_LOW_BITS(fy, max) (((fy) >> 12) & 0xF) #define CHECK_FOR_DECAL +#define TILEX_TRANS(x, max) SkClampMax(x, max) +#define TILEY_TRANS(y, max) SkClampMax(y, max) #include "SkBitmapProcState_matrix.h" #define MAKENAME(suffix) RepeatX_RepeatY ## suffix @@ -35,6 +37,9 @@ #define TILEY_PROCF(fy, max) (((fy) & 0xFFFF) * ((max) + 1) >> 16) #define TILEX_LOW_BITS(fx, max) ((((fx) & 0xFFFF) * ((max) + 1) >> 12) & 0xF) #define TILEY_LOW_BITS(fy, max) ((((fy) & 0xFFFF) * ((max) + 1) >> 12) & 0xF) +#define REAL_MOD(val, modulus) (((val)%(modulus)) + (modulus)*( (val)<0 )) +#define TILEX_TRANS(x, max) (REAL_MOD((x), ((max) + 1))) +#define TILEY_TRANS(y, max) (REAL_MOD((y), ((max) + 1))) #include "SkBitmapProcState_matrix.h" #define MAKENAME(suffix) GeneralXY ## suffix @@ -44,13 +49,17 @@ #define PREAMBLE_PARAM_Y , SkBitmapProcState::FixedTileProc tileProcY #define PREAMBLE_ARG_X , tileProcX #define PREAMBLE_ARG_Y , tileProcY -#define TILEX_PROCF(fx, max) (tileProcX(fx) * ((max) + 1) >> 16) -#define TILEY_PROCF(fy, max) (tileProcY(fy) * ((max) + 1) >> 16) -#define TILEX_LOW_BITS(fx, max) ((tileProcX(fx) * ((max) + 1) >> 12) & 0xF) -#define TILEY_LOW_BITS(fy, max) ((tileProcY(fy) * ((max) + 1) >> 12) & 0xF) +#define TILEX_PROCF(fx, max) (tileProcX(fx, max) >> 16) +#define TILEY_PROCF(fy, max) (tileProcY(fy, max) >> 16) +#define TILEX_LOW_BITS(fx, max) ((tileProcX(fx, max) >> 14) & 0x3) +#define TILEY_LOW_BITS(fy, max) ((tileProcY(fy, max) >> 14) & 0x3) +#define PREAMBLE_TRANS(state) SkBitmapProcState::IntTileProc tileProcX = (state).iTileProcX; \ + SkBitmapProcState::IntTileProc tileProcY = (state).iTileProcY +#define TILEX_TRANS(x, max) tileProcX(x, max) +#define TILEY_TRANS(y, max) tileProcY(y, max) #include "SkBitmapProcState_matrix.h" -static inline U16CPU fixed_clamp(SkFixed x) +static inline SkFixed fixed_clamp(SkFixed x, int max) { #ifdef SK_CPU_HAS_CONDITIONAL_INSTR if (x >> 16) @@ -66,19 +75,20 @@ x = 0xFFFF; } #endif - return x; + return x * (max + 1); } -static inline U16CPU fixed_repeat(SkFixed x) +static inline SkFixed fixed_repeat(SkFixed x, int max) { - return x & 0xFFFF; + return (x & 0xFFFF) * (max + 1); } -static inline U16CPU fixed_mirror(SkFixed x) +static inline SkFixed fixed_mirror(SkFixed x, int max) { 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; + x = ((x ^ s) & 0xFFFF) * (max + 1); + return s ? (x ^ 0xFFFF) : x; } static SkBitmapProcState::FixedTileProc choose_tile_proc(unsigned m) @@ -90,15 +100,52 @@ SkASSERT(SkShader::kMirror_TileMode == m); return fixed_mirror; } + +static inline int int_clamp(int x, int max) +{ + SkASSERT(max >= 0); + + return SkClampMax(x, max); +} +static inline int int_repeat(int x, int max) +{ + SkASSERT(max >= 0); + + return x % (max + 1); +} + +static inline int int_mirror(int x, int max) +{ + SkASSERT(max >= 0); + + int dx = x % (max + 1); + if (dx < 0) + dx = -dx - 1; + + return (x / (max + 1) % 2) ? max - dx : dx; +} + +static SkBitmapProcState::IntTileProc choose_int_tile_proc(unsigned m) +{ + if (SkShader::kClamp_TileMode == m) + return int_clamp; + if (SkShader::kRepeat_TileMode == m) + return int_repeat; + SkASSERT(SkShader::kMirror_TileMode == m); + return int_mirror; +} + SkBitmapProcState::MatrixProc SkBitmapProcState::chooseMatrixProc() { int index = 0; if (fDoFilter) index = 1; if (fInvType & SkMatrix::kPerspective_Mask) + index |= 6; + else if (fInvType & SkMatrix::kAffine_Mask) index |= 4; - else if (fInvType & SkMatrix::kAffine_Mask) + else if (fInvType & SkMatrix::kScale_Mask) index |= 2; if (SkShader::kClamp_TileMode == fTileModeX && @@ -123,6 +170,8 @@ // only general needs these procs fTileProcX = choose_tile_proc(fTileModeX); fTileProcY = choose_tile_proc(fTileModeY); + iTileProcX = choose_int_tile_proc(fTileModeX); + iTileProcY = choose_int_tile_proc(fTileModeY); return GeneralXY_Procs[index]; }