1Index: sgl/SkBitmapProcState.h 2=================================================================== 3--- sgl/SkBitmapProcState.h (revision 42716) 4+++ sgl/SkBitmapProcState.h (working copy) 5@@ -39,8 +39,9 @@ 6 int count, 7 uint16_t colors[]); 8 9- typedef U16CPU (*FixedTileProc)(SkFixed); // returns 0..0xFFFF 10- 11+ typedef SkFixed (*FixedTileProc)(SkFixed, int); 12+ typedef int (*IntTileProc)(int, int); 13+ 14 MatrixProc fMatrixProc; // chooseProcs 15 SampleProc32 fSampleProc32; // chooseProcs 16 SampleProc16 fSampleProc16; // chooseProcs 17@@ -48,6 +49,8 @@ 18 SkMatrix fUnitInvMatrix; // chooseProcs 19 FixedTileProc fTileProcX; // chooseProcs 20 FixedTileProc fTileProcY; // chooseProcs 21+ IntTileProc iTileProcX; // chooseProcs 22+ IntTileProc iTileProcY; // chooseProcs 23 SkFixed fFilterOneX; 24 SkFixed fFilterOneY; 25 26Index: sgl/SkBitmapProcState.cpp 27=================================================================== 28--- sgl/SkBitmapProcState.cpp (revision 42716) 29+++ sgl/SkBitmapProcState.cpp (working copy) 30@@ -296,8 +296,9 @@ 31 } 32 const SkMatrix* m; 33 34- if (SkShader::kClamp_TileMode == fTileModeX && 35- SkShader::kClamp_TileMode == fTileModeY) { 36+ if (inv.getType() <= SkMatrix::kTranslate_Mask || 37+ (SkShader::kClamp_TileMode == fTileModeX && 38+ SkShader::kClamp_TileMode == fTileModeY)) { 39 m = &inv; 40 } else { 41 fUnitInvMatrix = inv; 42@@ -330,6 +331,16 @@ 43 fInvMatrix = m; 44 fInvProc = m->getMapXYProc(); 45 fInvType = m->getType(); 46+ if (fInvType <= SkMatrix::kTranslate_Mask && 47+ inv.getType() > SkMatrix::kTranslate_Mask) { 48+ SkASSERT(inv.getType() <= 49+ (SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)); 50+ // It is possible that by the calculation of fUnitInvMatrix, we have 51+ // eliminated the scale transformation of the matrix (e.g., if inv^(-1) 52+ // scales fOrigBitmap into an 1X1 rect). We add the scale flag back so 53+ // that we don't make wrong choice in chooseMatrixProc(). 54+ fInvType |= SkMatrix::kScale_Mask; 55+ } 56 fInvSx = SkScalarToFixed(m->getScaleX()); 57 fInvSy = SkScalarToFixed(m->getScaleY()); 58 fInvKy = SkScalarToFixed(m->getSkewY()); 59Index: sgl/SkBitmapProcState_matrix.h 60=================================================================== 61--- sgl/SkBitmapProcState_matrix.h (revision 42716) 62+++ sgl/SkBitmapProcState_matrix.h (working copy) 63@@ -1,4 +1,5 @@ 64 65+#define TRANSLATE_NOFILTER_NAME MAKENAME(_nofilter_translate) 66 #define SCALE_NOFILTER_NAME MAKENAME(_nofilter_scale) 67 #define SCALE_FILTER_NAME MAKENAME(_filter_scale) 68 #define AFFINE_NOFILTER_NAME MAKENAME(_nofilter_affine) 69@@ -17,6 +18,38 @@ 70 #define PREAMBLE_ARG_Y 71 #endif 72 73+#ifndef PREAMBLE_TRANS 74+ #define PREAMBLE_TRANS(state) 75+#endif 76+ 77+static void TRANSLATE_NOFILTER_NAME(const SkBitmapProcState& s, 78+ uint32_t xy[], int count, int x, int y) 79+{ 80+ SkASSERT((s.fInvType & ~SkMatrix::kTranslate_Mask) == 0); 81+ 82+ PREAMBLE_TRANS(s); 83+ 84+ x += SkScalarFloor(s.fInvMatrix->getTranslateX()); 85+ y += SkScalarFloor(s.fInvMatrix->getTranslateY()); 86+ 87+ *xy++ = (uint32_t)TILEY_TRANS(y, (s.fBitmap->height() - 1)); 88+ 89+ int maxX = s.fBitmap->width() - 1; 90+ int i; 91+ uint16_t* xx = (uint16_t*)xy; 92+ for (i = (count >> 2); i > 0; --i) 93+ { 94+ *xx++ = (uint16_t)TILEX_TRANS(x, maxX); x++; 95+ *xx++ = (uint16_t)TILEX_TRANS(x, maxX); x++; 96+ *xx++ = (uint16_t)TILEX_TRANS(x, maxX); x++; 97+ *xx++ = (uint16_t)TILEX_TRANS(x, maxX); x++; 98+ } 99+ for (i = (count & 3); i > 0; --i) 100+ { 101+ *xx++ = (uint16_t)TILEX_TRANS(x, maxX); x++; 102+ } 103+} 104+ 105 static void SCALE_NOFILTER_NAME(const SkBitmapProcState& s, 106 uint32_t xy[], int count, int x, int y) { 107 SkASSERT((s.fInvType & ~(SkMatrix::kTranslate_Mask | 108@@ -206,9 +239,9 @@ 109 unsigned maxY = s.fBitmap->height() - 1; 110 111 do { 112- *xy++ = PACK_FILTER_Y_NAME(fy, maxY, oneX PREAMBLE_ARG_Y); 113+ *xy++ = PACK_FILTER_Y_NAME(fy, maxY, oneY PREAMBLE_ARG_Y); 114 fy += dy; 115- *xy++ = PACK_FILTER_X_NAME(fx, maxX, oneY PREAMBLE_ARG_X); 116+ *xy++ = PACK_FILTER_X_NAME(fx, maxX, oneX PREAMBLE_ARG_X); 117 fx += dx; 118 } while (--count != 0); 119 } 120@@ -241,6 +274,9 @@ 121 } 122 123 static SkBitmapProcState::MatrixProc MAKENAME(_Procs)[] = { 124+ TRANSLATE_NOFILTER_NAME, 125+ TRANSLATE_NOFILTER_NAME, // No need to do filtering if the matrix is no 126+ // more complex than identity/translate. 127 SCALE_NOFILTER_NAME, 128 SCALE_FILTER_NAME, 129 AFFINE_NOFILTER_NAME, 130@@ -255,7 +291,10 @@ 131 #ifdef CHECK_FOR_DECAL 132 #undef CHECK_FOR_DECAL 133 #endif 134- 135+#undef TILEX_TRANS 136+#undef TILEY_TRANS 137+ 138+#undef TRANSLATE_NOFILTER_NAME 139 #undef SCALE_NOFILTER_NAME 140 #undef SCALE_FILTER_NAME 141 #undef AFFINE_NOFILTER_NAME 142@@ -268,6 +307,7 @@ 143 #undef PREAMBLE_PARAM_Y 144 #undef PREAMBLE_ARG_X 145 #undef PREAMBLE_ARG_Y 146+#undef PREAMBLE_TRANS 147 148 #undef TILEX_LOW_BITS 149 #undef TILEY_LOW_BITS 150Index: sgl/SkBitmapProcState_matrixProcs.cpp 151=================================================================== 152--- sgl/SkBitmapProcState_matrixProcs.cpp (revision 42716) 153+++ sgl/SkBitmapProcState_matrixProcs.cpp (working copy) 154@@ -28,6 +28,8 @@ 155 #define TILEX_LOW_BITS(fx, max) (((fx) >> 12) & 0xF) 156 #define TILEY_LOW_BITS(fy, max) (((fy) >> 12) & 0xF) 157 #define CHECK_FOR_DECAL 158+#define TILEX_TRANS(x, max) SkClampMax(x, max) 159+#define TILEY_TRANS(y, max) SkClampMax(y, max) 160 #include "SkBitmapProcState_matrix.h" 161 162 #define MAKENAME(suffix) RepeatX_RepeatY ## suffix 163@@ -35,6 +37,9 @@ 164 #define TILEY_PROCF(fy, max) (((fy) & 0xFFFF) * ((max) + 1) >> 16) 165 #define TILEX_LOW_BITS(fx, max) ((((fx) & 0xFFFF) * ((max) + 1) >> 12) & 0xF) 166 #define TILEY_LOW_BITS(fy, max) ((((fy) & 0xFFFF) * ((max) + 1) >> 12) & 0xF) 167+#define REAL_MOD(val, modulus) (((val)%(modulus)) + (modulus)*( (val)<0 )) 168+#define TILEX_TRANS(x, max) (REAL_MOD((x), ((max) + 1))) 169+#define TILEY_TRANS(y, max) (REAL_MOD((y), ((max) + 1))) 170 #include "SkBitmapProcState_matrix.h" 171 172 #define MAKENAME(suffix) GeneralXY ## suffix 173@@ -44,13 +49,17 @@ 174 #define PREAMBLE_PARAM_Y , SkBitmapProcState::FixedTileProc tileProcY 175 #define PREAMBLE_ARG_X , tileProcX 176 #define PREAMBLE_ARG_Y , tileProcY 177-#define TILEX_PROCF(fx, max) (tileProcX(fx) * ((max) + 1) >> 16) 178-#define TILEY_PROCF(fy, max) (tileProcY(fy) * ((max) + 1) >> 16) 179-#define TILEX_LOW_BITS(fx, max) ((tileProcX(fx) * ((max) + 1) >> 12) & 0xF) 180-#define TILEY_LOW_BITS(fy, max) ((tileProcY(fy) * ((max) + 1) >> 12) & 0xF) 181+#define TILEX_PROCF(fx, max) (tileProcX(fx, max) >> 16) 182+#define TILEY_PROCF(fy, max) (tileProcY(fy, max) >> 16) 183+#define TILEX_LOW_BITS(fx, max) ((tileProcX(fx, max) >> 14) & 0x3) 184+#define TILEY_LOW_BITS(fy, max) ((tileProcY(fy, max) >> 14) & 0x3) 185+#define PREAMBLE_TRANS(state) SkBitmapProcState::IntTileProc tileProcX = (state).iTileProcX; \ 186+ SkBitmapProcState::IntTileProc tileProcY = (state).iTileProcY 187+#define TILEX_TRANS(x, max) tileProcX(x, max) 188+#define TILEY_TRANS(y, max) tileProcY(y, max) 189 #include "SkBitmapProcState_matrix.h" 190 191-static inline U16CPU fixed_clamp(SkFixed x) 192+static inline SkFixed fixed_clamp(SkFixed x, int max) 193 { 194 #ifdef SK_CPU_HAS_CONDITIONAL_INSTR 195 if (x >> 16) 196@@ -66,19 +75,20 @@ 197 x = 0xFFFF; 198 } 199 #endif 200- return x; 201+ return x * (max + 1); 202 } 203 204-static inline U16CPU fixed_repeat(SkFixed x) 205+static inline SkFixed fixed_repeat(SkFixed x, int max) 206 { 207- return x & 0xFFFF; 208+ return (x & 0xFFFF) * (max + 1); 209 } 210 211-static inline U16CPU fixed_mirror(SkFixed x) 212+static inline SkFixed fixed_mirror(SkFixed x, int max) 213 { 214 SkFixed s = x << 15 >> 31; 215 // s is FFFFFFFF if we're on an odd interval, or 0 if an even interval 216- return (x ^ s) & 0xFFFF; 217+ x = ((x ^ s) & 0xFFFF) * (max + 1); 218+ return s ? (x ^ 0xFFFF) : x; 219 } 220 221 static SkBitmapProcState::FixedTileProc choose_tile_proc(unsigned m) 222@@ -90,15 +100,52 @@ 223 SkASSERT(SkShader::kMirror_TileMode == m); 224 return fixed_mirror; 225 } 226+ 227+static inline int int_clamp(int x, int max) 228+{ 229+ SkASSERT(max >= 0); 230+ 231+ return SkClampMax(x, max); 232+} 233 234+static inline int int_repeat(int x, int max) 235+{ 236+ SkASSERT(max >= 0); 237+ 238+ return x % (max + 1); 239+} 240+ 241+static inline int int_mirror(int x, int max) 242+{ 243+ SkASSERT(max >= 0); 244+ 245+ int dx = x % (max + 1); 246+ if (dx < 0) 247+ dx = -dx - 1; 248+ 249+ return (x / (max + 1) % 2) ? max - dx : dx; 250+} 251+ 252+static SkBitmapProcState::IntTileProc choose_int_tile_proc(unsigned m) 253+{ 254+ if (SkShader::kClamp_TileMode == m) 255+ return int_clamp; 256+ if (SkShader::kRepeat_TileMode == m) 257+ return int_repeat; 258+ SkASSERT(SkShader::kMirror_TileMode == m); 259+ return int_mirror; 260+} 261+ 262 SkBitmapProcState::MatrixProc SkBitmapProcState::chooseMatrixProc() 263 { 264 int index = 0; 265 if (fDoFilter) 266 index = 1; 267 if (fInvType & SkMatrix::kPerspective_Mask) 268+ index |= 6; 269+ else if (fInvType & SkMatrix::kAffine_Mask) 270 index |= 4; 271- else if (fInvType & SkMatrix::kAffine_Mask) 272+ else if (fInvType & SkMatrix::kScale_Mask) 273 index |= 2; 274 275 if (SkShader::kClamp_TileMode == fTileModeX && 276@@ -123,6 +170,8 @@ 277 // only general needs these procs 278 fTileProcX = choose_tile_proc(fTileModeX); 279 fTileProcY = choose_tile_proc(fTileModeY); 280+ iTileProcX = choose_int_tile_proc(fTileModeX); 281+ iTileProcY = choose_int_tile_proc(fTileModeY); 282 return GeneralXY_Procs[index]; 283 } 284 285