gfx/skia/trunk/src/core/SkBitmapProcState_matrixProcs.cpp

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

michael@0 1 /* NEON optimized code (C) COPYRIGHT 2009 Motorola
michael@0 2 *
michael@0 3 * Use of this source code is governed by a BSD-style license that can be
michael@0 4 * found in the LICENSE file.
michael@0 5 */
michael@0 6
michael@0 7 #include "SkBitmapProcState.h"
michael@0 8 #include "SkPerspIter.h"
michael@0 9 #include "SkShader.h"
michael@0 10 #include "SkUtils.h"
michael@0 11 #include "SkUtilsArm.h"
michael@0 12 #include "SkBitmapProcState_utils.h"
michael@0 13
michael@0 14 /* returns 0...(n-1) given any x (positive or negative).
michael@0 15
michael@0 16 As an example, if n (which is always positive) is 5...
michael@0 17
michael@0 18 x: -8 -7 -6 -5 -4 -3 -2 -1 0 1 2 3 4 5 6 7 8
michael@0 19 returns: 2 3 4 0 1 2 3 4 0 1 2 3 4 0 1 2 3
michael@0 20 */
michael@0 21 static inline int sk_int_mod(int x, int n) {
michael@0 22 SkASSERT(n > 0);
michael@0 23 if ((unsigned)x >= (unsigned)n) {
michael@0 24 if (x < 0) {
michael@0 25 x = n + ~(~x % n);
michael@0 26 } else {
michael@0 27 x = x % n;
michael@0 28 }
michael@0 29 }
michael@0 30 return x;
michael@0 31 }
michael@0 32
michael@0 33 void decal_nofilter_scale(uint32_t dst[], SkFixed fx, SkFixed dx, int count);
michael@0 34 void decal_filter_scale(uint32_t dst[], SkFixed fx, SkFixed dx, int count);
michael@0 35
michael@0 36 // Compile neon code paths if needed
michael@0 37 #if !SK_ARM_NEON_IS_NONE
michael@0 38
michael@0 39 // These are defined in src/opts/SkBitmapProcState_matrixProcs_neon.cpp
michael@0 40 extern const SkBitmapProcState::MatrixProc ClampX_ClampY_Procs_neon[];
michael@0 41 extern const SkBitmapProcState::MatrixProc RepeatX_RepeatY_Procs_neon[];
michael@0 42
michael@0 43 #endif // !SK_ARM_NEON_IS_NONE
michael@0 44
michael@0 45 // Compile non-neon code path if needed
michael@0 46 #if !SK_ARM_NEON_IS_ALWAYS
michael@0 47 #define MAKENAME(suffix) ClampX_ClampY ## suffix
michael@0 48 #define TILEX_PROCF(fx, max) SkClampMax((fx) >> 16, max)
michael@0 49 #define TILEY_PROCF(fy, max) SkClampMax((fy) >> 16, max)
michael@0 50 #define TILEX_LOW_BITS(fx, max) (((fx) >> 12) & 0xF)
michael@0 51 #define TILEY_LOW_BITS(fy, max) (((fy) >> 12) & 0xF)
michael@0 52 #define CHECK_FOR_DECAL
michael@0 53 #include "SkBitmapProcState_matrix.h"
michael@0 54
michael@0 55 #define MAKENAME(suffix) RepeatX_RepeatY ## suffix
michael@0 56 #define TILEX_PROCF(fx, max) SK_USHIFT16(((fx) & 0xFFFF) * ((max) + 1))
michael@0 57 #define TILEY_PROCF(fy, max) SK_USHIFT16(((fy) & 0xFFFF) * ((max) + 1))
michael@0 58 #define TILEX_LOW_BITS(fx, max) ((((fx) & 0xFFFF) * ((max) + 1) >> 12) & 0xF)
michael@0 59 #define TILEY_LOW_BITS(fy, max) ((((fy) & 0xFFFF) * ((max) + 1) >> 12) & 0xF)
michael@0 60 #include "SkBitmapProcState_matrix.h"
michael@0 61 #endif
michael@0 62
michael@0 63 #define MAKENAME(suffix) GeneralXY ## suffix
michael@0 64 #define PREAMBLE(state) SkBitmapProcState::FixedTileProc tileProcX = (state).fTileProcX; (void) tileProcX; \
michael@0 65 SkBitmapProcState::FixedTileProc tileProcY = (state).fTileProcY; (void) tileProcY; \
michael@0 66 SkBitmapProcState::FixedTileLowBitsProc tileLowBitsProcX = (state).fTileLowBitsProcX; (void) tileLowBitsProcX; \
michael@0 67 SkBitmapProcState::FixedTileLowBitsProc tileLowBitsProcY = (state).fTileLowBitsProcY; (void) tileLowBitsProcY
michael@0 68 #define PREAMBLE_PARAM_X , SkBitmapProcState::FixedTileProc tileProcX, SkBitmapProcState::FixedTileLowBitsProc tileLowBitsProcX
michael@0 69 #define PREAMBLE_PARAM_Y , SkBitmapProcState::FixedTileProc tileProcY, SkBitmapProcState::FixedTileLowBitsProc tileLowBitsProcY
michael@0 70 #define PREAMBLE_ARG_X , tileProcX, tileLowBitsProcX
michael@0 71 #define PREAMBLE_ARG_Y , tileProcY, tileLowBitsProcY
michael@0 72 #define TILEX_PROCF(fx, max) SK_USHIFT16(tileProcX(fx) * ((max) + 1))
michael@0 73 #define TILEY_PROCF(fy, max) SK_USHIFT16(tileProcY(fy) * ((max) + 1))
michael@0 74 #define TILEX_LOW_BITS(fx, max) tileLowBitsProcX(fx, (max) + 1)
michael@0 75 #define TILEY_LOW_BITS(fy, max) tileLowBitsProcY(fy, (max) + 1)
michael@0 76 #include "SkBitmapProcState_matrix.h"
michael@0 77
michael@0 78 static inline U16CPU fixed_clamp(SkFixed x)
michael@0 79 {
michael@0 80 if (x < 0) {
michael@0 81 x = 0;
michael@0 82 }
michael@0 83 if (x >> 16) {
michael@0 84 x = 0xFFFF;
michael@0 85 }
michael@0 86 return x;
michael@0 87 }
michael@0 88
michael@0 89 static inline U16CPU fixed_repeat(SkFixed x)
michael@0 90 {
michael@0 91 return x & 0xFFFF;
michael@0 92 }
michael@0 93
michael@0 94 // Visual Studio 2010 (MSC_VER=1600) optimizes bit-shift code incorrectly.
michael@0 95 // See http://code.google.com/p/skia/issues/detail?id=472
michael@0 96 #if defined(_MSC_VER) && (_MSC_VER >= 1600)
michael@0 97 #pragma optimize("", off)
michael@0 98 #endif
michael@0 99
michael@0 100 static inline U16CPU fixed_mirror(SkFixed x)
michael@0 101 {
michael@0 102 SkFixed s = x << 15 >> 31;
michael@0 103 // s is FFFFFFFF if we're on an odd interval, or 0 if an even interval
michael@0 104 return (x ^ s) & 0xFFFF;
michael@0 105 }
michael@0 106
michael@0 107 #if defined(_MSC_VER) && (_MSC_VER >= 1600)
michael@0 108 #pragma optimize("", on)
michael@0 109 #endif
michael@0 110
michael@0 111 static SkBitmapProcState::FixedTileProc choose_tile_proc(unsigned m)
michael@0 112 {
michael@0 113 if (SkShader::kClamp_TileMode == m)
michael@0 114 return fixed_clamp;
michael@0 115 if (SkShader::kRepeat_TileMode == m)
michael@0 116 return fixed_repeat;
michael@0 117 SkASSERT(SkShader::kMirror_TileMode == m);
michael@0 118 return fixed_mirror;
michael@0 119 }
michael@0 120
michael@0 121 static inline U16CPU fixed_clamp_lowbits(SkFixed x, int) {
michael@0 122 return (x >> 12) & 0xF;
michael@0 123 }
michael@0 124
michael@0 125 static inline U16CPU fixed_repeat_or_mirrow_lowbits(SkFixed x, int scale) {
michael@0 126 return ((x * scale) >> 12) & 0xF;
michael@0 127 }
michael@0 128
michael@0 129 static SkBitmapProcState::FixedTileLowBitsProc choose_tile_lowbits_proc(unsigned m) {
michael@0 130 if (SkShader::kClamp_TileMode == m) {
michael@0 131 return fixed_clamp_lowbits;
michael@0 132 } else {
michael@0 133 SkASSERT(SkShader::kMirror_TileMode == m ||
michael@0 134 SkShader::kRepeat_TileMode == m);
michael@0 135 // mirror and repeat have the same behavior for the low bits.
michael@0 136 return fixed_repeat_or_mirrow_lowbits;
michael@0 137 }
michael@0 138 }
michael@0 139
michael@0 140 static inline U16CPU int_clamp(int x, int n) {
michael@0 141 if (x >= n) {
michael@0 142 x = n - 1;
michael@0 143 }
michael@0 144 if (x < 0) {
michael@0 145 x = 0;
michael@0 146 }
michael@0 147 return x;
michael@0 148 }
michael@0 149
michael@0 150 static inline U16CPU int_repeat(int x, int n) {
michael@0 151 return sk_int_mod(x, n);
michael@0 152 }
michael@0 153
michael@0 154 static inline U16CPU int_mirror(int x, int n) {
michael@0 155 x = sk_int_mod(x, 2 * n);
michael@0 156 if (x >= n) {
michael@0 157 x = n + ~(x - n);
michael@0 158 }
michael@0 159 return x;
michael@0 160 }
michael@0 161
michael@0 162 #if 0
michael@0 163 static void test_int_tileprocs() {
michael@0 164 for (int i = -8; i <= 8; i++) {
michael@0 165 SkDebugf(" int_mirror(%2d, 3) = %d\n", i, int_mirror(i, 3));
michael@0 166 }
michael@0 167 }
michael@0 168 #endif
michael@0 169
michael@0 170 static SkBitmapProcState::IntTileProc choose_int_tile_proc(unsigned tm) {
michael@0 171 if (SkShader::kClamp_TileMode == tm)
michael@0 172 return int_clamp;
michael@0 173 if (SkShader::kRepeat_TileMode == tm)
michael@0 174 return int_repeat;
michael@0 175 SkASSERT(SkShader::kMirror_TileMode == tm);
michael@0 176 return int_mirror;
michael@0 177 }
michael@0 178
michael@0 179 //////////////////////////////////////////////////////////////////////////////
michael@0 180
michael@0 181 void decal_nofilter_scale(uint32_t dst[], SkFixed fx, SkFixed dx, int count)
michael@0 182 {
michael@0 183 int i;
michael@0 184
michael@0 185 for (i = (count >> 2); i > 0; --i)
michael@0 186 {
michael@0 187 *dst++ = pack_two_shorts(fx >> 16, (fx + dx) >> 16);
michael@0 188 fx += dx+dx;
michael@0 189 *dst++ = pack_two_shorts(fx >> 16, (fx + dx) >> 16);
michael@0 190 fx += dx+dx;
michael@0 191 }
michael@0 192 count &= 3;
michael@0 193
michael@0 194 uint16_t* xx = (uint16_t*)dst;
michael@0 195 for (i = count; i > 0; --i) {
michael@0 196 *xx++ = SkToU16(fx >> 16); fx += dx;
michael@0 197 }
michael@0 198 }
michael@0 199
michael@0 200 void decal_filter_scale(uint32_t dst[], SkFixed fx, SkFixed dx, int count)
michael@0 201 {
michael@0 202
michael@0 203
michael@0 204 if (count & 1)
michael@0 205 {
michael@0 206 SkASSERT((fx >> (16 + 14)) == 0);
michael@0 207 *dst++ = (fx >> 12 << 14) | ((fx >> 16) + 1);
michael@0 208 fx += dx;
michael@0 209 }
michael@0 210 while ((count -= 2) >= 0)
michael@0 211 {
michael@0 212 SkASSERT((fx >> (16 + 14)) == 0);
michael@0 213 *dst++ = (fx >> 12 << 14) | ((fx >> 16) + 1);
michael@0 214 fx += dx;
michael@0 215
michael@0 216 *dst++ = (fx >> 12 << 14) | ((fx >> 16) + 1);
michael@0 217 fx += dx;
michael@0 218 }
michael@0 219 }
michael@0 220
michael@0 221 ///////////////////////////////////////////////////////////////////////////////
michael@0 222 // stores the same as SCALE, but is cheaper to compute. Also since there is no
michael@0 223 // scale, we don't need/have a FILTER version
michael@0 224
michael@0 225 static void fill_sequential(uint16_t xptr[], int start, int count) {
michael@0 226 #if 1
michael@0 227 if (reinterpret_cast<intptr_t>(xptr) & 0x2) {
michael@0 228 *xptr++ = start++;
michael@0 229 count -= 1;
michael@0 230 }
michael@0 231 if (count > 3) {
michael@0 232 uint32_t* xxptr = reinterpret_cast<uint32_t*>(xptr);
michael@0 233 uint32_t pattern0 = PACK_TWO_SHORTS(start + 0, start + 1);
michael@0 234 uint32_t pattern1 = PACK_TWO_SHORTS(start + 2, start + 3);
michael@0 235 start += count & ~3;
michael@0 236 int qcount = count >> 2;
michael@0 237 do {
michael@0 238 *xxptr++ = pattern0;
michael@0 239 pattern0 += 0x40004;
michael@0 240 *xxptr++ = pattern1;
michael@0 241 pattern1 += 0x40004;
michael@0 242 } while (--qcount != 0);
michael@0 243 xptr = reinterpret_cast<uint16_t*>(xxptr);
michael@0 244 count &= 3;
michael@0 245 }
michael@0 246 while (--count >= 0) {
michael@0 247 *xptr++ = start++;
michael@0 248 }
michael@0 249 #else
michael@0 250 for (int i = 0; i < count; i++) {
michael@0 251 *xptr++ = start++;
michael@0 252 }
michael@0 253 #endif
michael@0 254 }
michael@0 255
michael@0 256 static int nofilter_trans_preamble(const SkBitmapProcState& s, uint32_t** xy,
michael@0 257 int x, int y) {
michael@0 258 SkPoint pt;
michael@0 259 s.fInvProc(s.fInvMatrix, SkIntToScalar(x) + SK_ScalarHalf,
michael@0 260 SkIntToScalar(y) + SK_ScalarHalf, &pt);
michael@0 261 **xy = s.fIntTileProcY(SkScalarToFixed(pt.fY) >> 16,
michael@0 262 s.fBitmap->height());
michael@0 263 *xy += 1; // bump the ptr
michael@0 264 // return our starting X position
michael@0 265 return SkScalarToFixed(pt.fX) >> 16;
michael@0 266 }
michael@0 267
michael@0 268 static void clampx_nofilter_trans(const SkBitmapProcState& s,
michael@0 269 uint32_t xy[], int count, int x, int y) {
michael@0 270 SkASSERT((s.fInvType & ~SkMatrix::kTranslate_Mask) == 0);
michael@0 271
michael@0 272 int xpos = nofilter_trans_preamble(s, &xy, x, y);
michael@0 273 const int width = s.fBitmap->width();
michael@0 274 if (1 == width) {
michael@0 275 // all of the following X values must be 0
michael@0 276 memset(xy, 0, count * sizeof(uint16_t));
michael@0 277 return;
michael@0 278 }
michael@0 279
michael@0 280 uint16_t* xptr = reinterpret_cast<uint16_t*>(xy);
michael@0 281 int n;
michael@0 282
michael@0 283 // fill before 0 as needed
michael@0 284 if (xpos < 0) {
michael@0 285 n = -xpos;
michael@0 286 if (n > count) {
michael@0 287 n = count;
michael@0 288 }
michael@0 289 memset(xptr, 0, n * sizeof(uint16_t));
michael@0 290 count -= n;
michael@0 291 if (0 == count) {
michael@0 292 return;
michael@0 293 }
michael@0 294 xptr += n;
michael@0 295 xpos = 0;
michael@0 296 }
michael@0 297
michael@0 298 // fill in 0..width-1 if needed
michael@0 299 if (xpos < width) {
michael@0 300 n = width - xpos;
michael@0 301 if (n > count) {
michael@0 302 n = count;
michael@0 303 }
michael@0 304 fill_sequential(xptr, xpos, n);
michael@0 305 count -= n;
michael@0 306 if (0 == count) {
michael@0 307 return;
michael@0 308 }
michael@0 309 xptr += n;
michael@0 310 }
michael@0 311
michael@0 312 // fill the remaining with the max value
michael@0 313 sk_memset16(xptr, width - 1, count);
michael@0 314 }
michael@0 315
michael@0 316 static void repeatx_nofilter_trans(const SkBitmapProcState& s,
michael@0 317 uint32_t xy[], int count, int x, int y) {
michael@0 318 SkASSERT((s.fInvType & ~SkMatrix::kTranslate_Mask) == 0);
michael@0 319
michael@0 320 int xpos = nofilter_trans_preamble(s, &xy, x, y);
michael@0 321 const int width = s.fBitmap->width();
michael@0 322 if (1 == width) {
michael@0 323 // all of the following X values must be 0
michael@0 324 memset(xy, 0, count * sizeof(uint16_t));
michael@0 325 return;
michael@0 326 }
michael@0 327
michael@0 328 uint16_t* xptr = reinterpret_cast<uint16_t*>(xy);
michael@0 329 int start = sk_int_mod(xpos, width);
michael@0 330 int n = width - start;
michael@0 331 if (n > count) {
michael@0 332 n = count;
michael@0 333 }
michael@0 334 fill_sequential(xptr, start, n);
michael@0 335 xptr += n;
michael@0 336 count -= n;
michael@0 337
michael@0 338 while (count >= width) {
michael@0 339 fill_sequential(xptr, 0, width);
michael@0 340 xptr += width;
michael@0 341 count -= width;
michael@0 342 }
michael@0 343
michael@0 344 if (count > 0) {
michael@0 345 fill_sequential(xptr, 0, count);
michael@0 346 }
michael@0 347 }
michael@0 348
michael@0 349 static void fill_backwards(uint16_t xptr[], int pos, int count) {
michael@0 350 for (int i = 0; i < count; i++) {
michael@0 351 SkASSERT(pos >= 0);
michael@0 352 xptr[i] = pos--;
michael@0 353 }
michael@0 354 }
michael@0 355
michael@0 356 static void mirrorx_nofilter_trans(const SkBitmapProcState& s,
michael@0 357 uint32_t xy[], int count, int x, int y) {
michael@0 358 SkASSERT((s.fInvType & ~SkMatrix::kTranslate_Mask) == 0);
michael@0 359
michael@0 360 int xpos = nofilter_trans_preamble(s, &xy, x, y);
michael@0 361 const int width = s.fBitmap->width();
michael@0 362 if (1 == width) {
michael@0 363 // all of the following X values must be 0
michael@0 364 memset(xy, 0, count * sizeof(uint16_t));
michael@0 365 return;
michael@0 366 }
michael@0 367
michael@0 368 uint16_t* xptr = reinterpret_cast<uint16_t*>(xy);
michael@0 369 // need to know our start, and our initial phase (forward or backward)
michael@0 370 bool forward;
michael@0 371 int n;
michael@0 372 int start = sk_int_mod(xpos, 2 * width);
michael@0 373 if (start >= width) {
michael@0 374 start = width + ~(start - width);
michael@0 375 forward = false;
michael@0 376 n = start + 1; // [start .. 0]
michael@0 377 } else {
michael@0 378 forward = true;
michael@0 379 n = width - start; // [start .. width)
michael@0 380 }
michael@0 381 if (n > count) {
michael@0 382 n = count;
michael@0 383 }
michael@0 384 if (forward) {
michael@0 385 fill_sequential(xptr, start, n);
michael@0 386 } else {
michael@0 387 fill_backwards(xptr, start, n);
michael@0 388 }
michael@0 389 forward = !forward;
michael@0 390 xptr += n;
michael@0 391 count -= n;
michael@0 392
michael@0 393 while (count >= width) {
michael@0 394 if (forward) {
michael@0 395 fill_sequential(xptr, 0, width);
michael@0 396 } else {
michael@0 397 fill_backwards(xptr, width - 1, width);
michael@0 398 }
michael@0 399 forward = !forward;
michael@0 400 xptr += width;
michael@0 401 count -= width;
michael@0 402 }
michael@0 403
michael@0 404 if (count > 0) {
michael@0 405 if (forward) {
michael@0 406 fill_sequential(xptr, 0, count);
michael@0 407 } else {
michael@0 408 fill_backwards(xptr, width - 1, count);
michael@0 409 }
michael@0 410 }
michael@0 411 }
michael@0 412
michael@0 413 ///////////////////////////////////////////////////////////////////////////////
michael@0 414
michael@0 415 SkBitmapProcState::MatrixProc
michael@0 416 SkBitmapProcState::chooseMatrixProc(bool trivial_matrix) {
michael@0 417 // test_int_tileprocs();
michael@0 418 // check for our special case when there is no scale/affine/perspective
michael@0 419 if (trivial_matrix) {
michael@0 420 SkASSERT(SkPaint::kNone_FilterLevel == fFilterLevel);
michael@0 421 fIntTileProcY = choose_int_tile_proc(fTileModeY);
michael@0 422 switch (fTileModeX) {
michael@0 423 case SkShader::kClamp_TileMode:
michael@0 424 return clampx_nofilter_trans;
michael@0 425 case SkShader::kRepeat_TileMode:
michael@0 426 return repeatx_nofilter_trans;
michael@0 427 case SkShader::kMirror_TileMode:
michael@0 428 return mirrorx_nofilter_trans;
michael@0 429 }
michael@0 430 }
michael@0 431
michael@0 432 int index = 0;
michael@0 433 if (fFilterLevel != SkPaint::kNone_FilterLevel) {
michael@0 434 index = 1;
michael@0 435 }
michael@0 436 if (fInvType & SkMatrix::kPerspective_Mask) {
michael@0 437 index += 4;
michael@0 438 } else if (fInvType & SkMatrix::kAffine_Mask) {
michael@0 439 index += 2;
michael@0 440 }
michael@0 441
michael@0 442 if (SkShader::kClamp_TileMode == fTileModeX &&
michael@0 443 SkShader::kClamp_TileMode == fTileModeY)
michael@0 444 {
michael@0 445 // clamp gets special version of filterOne
michael@0 446 fFilterOneX = SK_Fixed1;
michael@0 447 fFilterOneY = SK_Fixed1;
michael@0 448 return SK_ARM_NEON_WRAP(ClampX_ClampY_Procs)[index];
michael@0 449 }
michael@0 450
michael@0 451 // all remaining procs use this form for filterOne
michael@0 452 fFilterOneX = SK_Fixed1 / fBitmap->width();
michael@0 453 fFilterOneY = SK_Fixed1 / fBitmap->height();
michael@0 454
michael@0 455 if (SkShader::kRepeat_TileMode == fTileModeX &&
michael@0 456 SkShader::kRepeat_TileMode == fTileModeY)
michael@0 457 {
michael@0 458 return SK_ARM_NEON_WRAP(RepeatX_RepeatY_Procs)[index];
michael@0 459 }
michael@0 460
michael@0 461 fTileProcX = choose_tile_proc(fTileModeX);
michael@0 462 fTileProcY = choose_tile_proc(fTileModeY);
michael@0 463 fTileLowBitsProcX = choose_tile_lowbits_proc(fTileModeX);
michael@0 464 fTileLowBitsProcY = choose_tile_lowbits_proc(fTileModeY);
michael@0 465 return GeneralXY_Procs[index];
michael@0 466 }

mercurial