1 /* 2 * Copyright 2011 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #include "SkBitmapCache.h" 9 #include "SkBitmapProcState.h" 10 #include "SkColorPriv.h" 11 #include "SkFilterProc.h" 12 #include "SkPaint.h" 13 #include "SkShader.h" // for tilemodes 14 #include "SkUtilsArm.h" 15 #include "SkBitmapScaler.h" 16 #include "SkMipMap.h" 17 #include "SkPixelRef.h" 18 #include "SkImageEncoder.h" 19 #include "SkResourceCache.h" 20 21 #if !SK_ARM_NEON_IS_NONE 22 // These are defined in src/opts/SkBitmapProcState_arm_neon.cpp 23 extern const SkBitmapProcState::SampleProc16 gSkBitmapProcStateSample16_neon[]; 24 extern const SkBitmapProcState::SampleProc32 gSkBitmapProcStateSample32_neon[]; 25 extern void S16_D16_filter_DX_neon(const SkBitmapProcState&, const uint32_t*, int, uint16_t*); 26 extern void Clamp_S16_D16_filter_DX_shaderproc_neon(const SkBitmapProcState&, int, int, uint16_t*, int); 27 extern void Repeat_S16_D16_filter_DX_shaderproc_neon(const SkBitmapProcState&, int, int, uint16_t*, int); 28 extern void SI8_opaque_D32_filter_DX_neon(const SkBitmapProcState&, const uint32_t*, int, SkPMColor*); 29 extern void SI8_opaque_D32_filter_DX_shaderproc_neon(const SkBitmapProcState&, int, int, uint32_t*, int); 30 extern void Clamp_SI8_opaque_D32_filter_DX_shaderproc_neon(const SkBitmapProcState&, int, int, uint32_t*, int); 31 #endif 32 33 #define NAME_WRAP(x) x 34 #include "SkBitmapProcState_filter.h" 35 #include "SkBitmapProcState_procs.h" 36 37 /////////////////////////////////////////////////////////////////////////////// 38 39 // true iff the matrix contains, at most, scale and translate elements 40 static bool matrix_only_scale_translate(const SkMatrix& m) { 41 return m.getType() <= (SkMatrix::kScale_Mask | SkMatrix::kTranslate_Mask); 42 } 43 44 /** 45 * For the purposes of drawing bitmaps, if a matrix is "almost" translate 46 * go ahead and treat it as if it were, so that subsequent code can go fast. 47 */ 48 static bool just_trans_clamp(const SkMatrix& matrix, const SkBitmap& bitmap) { 49 SkASSERT(matrix_only_scale_translate(matrix)); 50 51 if (matrix.getType() & SkMatrix::kScale_Mask) { 52 SkRect src, dst; 53 bitmap.getBounds(&src); 54 55 // Can't call mapRect(), since that will fix up inverted rectangles, 56 // e.g. when scale is negative, and we don't want to return true for 57 // those. 58 matrix.mapPoints(SkTCast<SkPoint*>(&dst), 59 SkTCast<const SkPoint*>(&src), 60 2); 61 62 // Now round all 4 edges to device space, and then compare the device 63 // width/height to the original. Note: we must map all 4 and subtract 64 // rather than map the "width" and compare, since we care about the 65 // phase (in pixel space) that any translate in the matrix might impart. 66 SkIRect idst; 67 dst.round(&idst); 68 return idst.width() == bitmap.width() && idst.height() == bitmap.height(); 69 } 70 // if we got here, we're either kTranslate_Mask or identity 71 return true; 72 } 73 74 static bool just_trans_general(const SkMatrix& matrix) { 75 SkASSERT(matrix_only_scale_translate(matrix)); 76 77 if (matrix.getType() & SkMatrix::kScale_Mask) { 78 const SkScalar tol = SK_Scalar1 / 32768; 79 80 if (!SkScalarNearlyZero(matrix[SkMatrix::kMScaleX] - SK_Scalar1, tol)) { 81 return false; 82 } 83 if (!SkScalarNearlyZero(matrix[SkMatrix::kMScaleY] - SK_Scalar1, tol)) { 84 return false; 85 } 86 } 87 // if we got here, treat us as either kTranslate_Mask or identity 88 return true; 89 } 90 91 /////////////////////////////////////////////////////////////////////////////// 92 93 static bool valid_for_filtering(unsigned dimension) { 94 // for filtering, width and height must fit in 14bits, since we use steal 95 // 2 bits from each to store our 4bit subpixel data 96 return (dimension & ~0x3FFF) == 0; 97 } 98 99 static SkScalar effective_matrix_scale_sqrd(const SkMatrix& mat) { 100 SkPoint v1, v2; 101 102 v1.fX = mat.getScaleX(); 103 v1.fY = mat.getSkewY(); 104 105 v2.fX = mat.getSkewX(); 106 v2.fY = mat.getScaleY(); 107 108 return SkMaxScalar(v1.lengthSqd(), v2.lengthSqd()); 109 } 110 111 // Check to see that the size of the bitmap that would be produced by 112 // scaling by the given inverted matrix is less than the maximum allowed. 113 static inline bool cache_size_okay(const SkBitmap& bm, const SkMatrix& invMat) { 114 size_t maximumAllocation = SkResourceCache::GetSingleAllocationByteLimit(); 115 if (0 == maximumAllocation) { 116 return true; 117 } 118 // float matrixScaleFactor = 1.0 / (invMat.scaleX * invMat.scaleY); 119 // return ((origBitmapSize * matrixScaleFactor) < maximumAllocationSize); 120 // Skip the division step: 121 return bm.info().getSafeSize(bm.info().minRowBytes()) 122 < (maximumAllocation * invMat.getScaleX() * invMat.getScaleY()); 123 } 124 125 // TODO -- we may want to pass the clip into this function so we only scale 126 // the portion of the image that we're going to need. This will complicate 127 // the interface to the cache, but might be well worth it. 128 129 bool SkBitmapProcState::possiblyScaleImage() { 130 SkASSERT(NULL == fBitmap); 131 132 fAdjustedMatrix = false; 133 134 if (fFilterLevel <= SkPaint::kLow_FilterLevel) { 135 return false; 136 } 137 // Check to see if the transformation matrix is simple, and if we're 138 // doing high quality scaling. If so, do the bitmap scale here and 139 // remove the (non-fractional) scaling component from the matrix. 140 141 SkScalar invScaleX = fInvMatrix.getScaleX(); 142 SkScalar invScaleY = fInvMatrix.getScaleY(); 143 144 float trueDestWidth = fOrigBitmap.width() / invScaleX; 145 float trueDestHeight = fOrigBitmap.height() / invScaleY; 146 147 #ifndef SK_IGNORE_PROPER_FRACTIONAL_SCALING 148 float roundedDestWidth = SkScalarRoundToScalar(trueDestWidth); 149 float roundedDestHeight = SkScalarRoundToScalar(trueDestHeight); 150 #else 151 float roundedDestWidth = trueDestWidth; 152 float roundedDestHeight = trueDestHeight; 153 #endif 154 155 if (SkPaint::kHigh_FilterLevel == fFilterLevel && 156 fInvMatrix.getType() <= (SkMatrix::kScale_Mask | SkMatrix::kTranslate_Mask) && 157 kN32_SkColorType == fOrigBitmap.colorType() && 158 cache_size_okay(fOrigBitmap, fInvMatrix)) { 159 160 if (SkScalarNearlyEqual(invScaleX,1.0f) && 161 SkScalarNearlyEqual(invScaleY,1.0f)) { 162 // short-circuit identity scaling; the output is supposed to 163 // be the same as the input, so we might as well go fast. 164 165 // Note(humper): We could also probably do this if the scales 166 // are close to -1 as well, since the flip doesn't require 167 // any fancy re-sampling... 168 169 // Set our filter level to low -- the only post-filtering this 170 // image might require is some interpolation if the translation 171 // is fractional. 172 fFilterLevel = SkPaint::kLow_FilterLevel; 173 return false; 174 } 175 176 if (!SkBitmapCache::Find(fOrigBitmap, roundedDestWidth, roundedDestHeight, &fScaledBitmap)) { 177 // All the criteria are met; let's make a new bitmap. 178 179 if (!SkBitmapScaler::Resize(&fScaledBitmap, 180 fOrigBitmap, 181 SkBitmapScaler::RESIZE_BEST, 182 roundedDestWidth, 183 roundedDestHeight, 184 SkResourceCache::GetAllocator())) { 185 // we failed to create fScaledBitmap, so just return and let 186 // the scanline proc handle it. 187 return false; 188 189 } 190 191 SkASSERT(fScaledBitmap.getPixels()); 192 fScaledBitmap.setImmutable(); 193 SkBitmapCache::Add(fOrigBitmap, roundedDestWidth, roundedDestHeight, fScaledBitmap); 194 } 195 196 SkASSERT(fScaledBitmap.getPixels()); 197 fBitmap = &fScaledBitmap; 198 199 // set the inv matrix type to translate-only; 200 fInvMatrix.setTranslate(fInvMatrix.getTranslateX() / fInvMatrix.getScaleX(), 201 fInvMatrix.getTranslateY() / fInvMatrix.getScaleY()); 202 203 #ifndef SK_IGNORE_PROPER_FRACTIONAL_SCALING 204 // reintroduce any fractional scaling missed by our integral scale done above. 205 206 float fractionalScaleX = roundedDestWidth/trueDestWidth; 207 float fractionalScaleY = roundedDestHeight/trueDestHeight; 208 209 fInvMatrix.postScale(fractionalScaleX, fractionalScaleY); 210 #endif 211 fAdjustedMatrix = true; 212 213 // Set our filter level to low -- the only post-filtering this 214 // image might require is some interpolation if the translation 215 // is fractional or if there's any remaining scaling to be done. 216 fFilterLevel = SkPaint::kLow_FilterLevel; 217 return true; 218 } 219 220 /* 221 * If High, then our special-case for scale-only did not take, and so we 222 * have to make a choice: 223 * 1. fall back on mipmaps + bilerp 224 * 2. fall back on scanline bicubic filter 225 * For now, we compute the "scale" value from the matrix, and have a 226 * threshold to decide when bicubic is better, and when mips are better. 227 * No doubt a fancier decision tree could be used uere. 228 * 229 * If Medium, then we just try to build a mipmap and select a level, 230 * setting the filter-level to kLow to signal that we just need bilerp 231 * to process the selected level. 232 */ 233 234 SkScalar scaleSqd = effective_matrix_scale_sqrd(fInvMatrix); 235 236 if (SkPaint::kHigh_FilterLevel == fFilterLevel) { 237 // Set the limit at 0.25 for the CTM... if the CTM is scaling smaller 238 // than this, then the mipmaps quality may be greater (certainly faster) 239 // so we only keep High quality if the scale is greater than this. 240 // 241 // Since we're dealing with the inverse, we compare against its inverse. 242 const SkScalar bicubicLimit = 4.0f; 243 const SkScalar bicubicLimitSqd = bicubicLimit * bicubicLimit; 244 if (scaleSqd < bicubicLimitSqd) { // use bicubic scanline 245 return false; 246 } 247 248 // else set the filter-level to Medium, since we're scaling down and 249 // want to reqeust mipmaps 250 fFilterLevel = SkPaint::kMedium_FilterLevel; 251 } 252 253 SkASSERT(SkPaint::kMedium_FilterLevel == fFilterLevel); 254 255 // HACK: Disable use of mipmaps in M39 since they do not use discardable 256 // memory in the cache. 257 fFilterLevel = SkPaint::kLow_FilterLevel; 258 259 return false; 260 } 261 262 static bool get_locked_pixels(const SkBitmap& src, int pow2, SkBitmap* dst) { 263 SkPixelRef* pr = src.pixelRef(); 264 if (pr && pr->decodeInto(pow2, dst)) { 265 return true; 266 } 267 268 /* 269 * If decodeInto() fails, it is possibe that we have an old subclass that 270 * does not, or cannot, implement that. In that case we fall back to the 271 * older protocol of having the pixelRef handle the caching for us. 272 */ 273 *dst = src; 274 dst->lockPixels(); 275 return SkToBool(dst->getPixels()); 276 } 277 278 bool SkBitmapProcState::lockBaseBitmap() { 279 SkPixelRef* pr = fOrigBitmap.pixelRef(); 280 281 if (pr->isLocked() || !pr->implementsDecodeInto()) { 282 // fast-case, no need to look in our cache 283 fScaledBitmap = fOrigBitmap; 284 fScaledBitmap.lockPixels(); 285 if (NULL == fScaledBitmap.getPixels()) { 286 return false; 287 } 288 } else { 289 if (!SkBitmapCache::Find(fOrigBitmap, 1, 1, &fScaledBitmap)) { 290 if (!get_locked_pixels(fOrigBitmap, 0, &fScaledBitmap)) { 291 return false; 292 } 293 294 // TODO: if fScaled comes back at a different width/height than fOrig, 295 // we need to update the matrix we are using to sample from this guy. 296 297 SkBitmapCache::Add(fOrigBitmap, 1, 1, fScaledBitmap); 298 } 299 } 300 fBitmap = &fScaledBitmap; 301 return true; 302 } 303 304 SkBitmapProcState::~SkBitmapProcState() { 305 SkDELETE(fBitmapFilter); 306 } 307 308 bool SkBitmapProcState::chooseProcs(const SkMatrix& inv, const SkPaint& paint) { 309 SkASSERT(fOrigBitmap.width() && fOrigBitmap.height()); 310 311 fBitmap = NULL; 312 fInvMatrix = inv; 313 fFilterLevel = paint.getFilterLevel(); 314 315 // possiblyScaleImage will look to see if it can rescale the image as a 316 // preprocess; either by scaling up to the target size, or by selecting 317 // a nearby mipmap level. If it does, it will adjust the working 318 // matrix as well as the working bitmap. It may also adjust the filter 319 // quality to avoid re-filtering an already perfectly scaled image. 320 if (!this->possiblyScaleImage()) { 321 if (!this->lockBaseBitmap()) { 322 return false; 323 } 324 } 325 // The above logic should have always assigned fBitmap, but in case it 326 // didn't, we check for that now... 327 // TODO(dominikg): Ask humper@ if we can just use an SkASSERT(fBitmap)? 328 if (NULL == fBitmap) { 329 return false; 330 } 331 332 // If we are "still" kMedium_FilterLevel, then the request was not fulfilled by possiblyScale, 333 // so we downgrade to kLow (so the rest of the sniffing code can assume that) 334 if (SkPaint::kMedium_FilterLevel == fFilterLevel) { 335 fFilterLevel = SkPaint::kLow_FilterLevel; 336 } 337 338 bool trivialMatrix = (fInvMatrix.getType() & ~SkMatrix::kTranslate_Mask) == 0; 339 bool clampClamp = SkShader::kClamp_TileMode == fTileModeX && 340 SkShader::kClamp_TileMode == fTileModeY; 341 342 if (!(fAdjustedMatrix || clampClamp || trivialMatrix)) { 343 fInvMatrix.postIDiv(fOrigBitmap.width(), fOrigBitmap.height()); 344 } 345 346 // Now that all possible changes to the matrix have taken place, check 347 // to see if we're really close to a no-scale matrix. If so, explicitly 348 // set it to be so. Subsequent code may inspect this matrix to choose 349 // a faster path in this case. 350 351 // This code will only execute if the matrix has some scale component; 352 // if it's already pure translate then we won't do this inversion. 353 354 if (matrix_only_scale_translate(fInvMatrix)) { 355 SkMatrix forward; 356 if (fInvMatrix.invert(&forward)) { 357 if (clampClamp ? just_trans_clamp(forward, *fBitmap) 358 : just_trans_general(forward)) { 359 SkScalar tx = -SkScalarRoundToScalar(forward.getTranslateX()); 360 SkScalar ty = -SkScalarRoundToScalar(forward.getTranslateY()); 361 fInvMatrix.setTranslate(tx, ty); 362 } 363 } 364 } 365 366 fInvProc = fInvMatrix.getMapXYProc(); 367 fInvType = fInvMatrix.getType(); 368 fInvSx = SkScalarToFixed(fInvMatrix.getScaleX()); 369 fInvSxFractionalInt = SkScalarToFractionalInt(fInvMatrix.getScaleX()); 370 fInvKy = SkScalarToFixed(fInvMatrix.getSkewY()); 371 fInvKyFractionalInt = SkScalarToFractionalInt(fInvMatrix.getSkewY()); 372 373 fAlphaScale = SkAlpha255To256(paint.getAlpha()); 374 375 fShaderProc32 = NULL; 376 fShaderProc16 = NULL; 377 fSampleProc32 = NULL; 378 fSampleProc16 = NULL; 379 380 // recompute the triviality of the matrix here because we may have 381 // changed it! 382 383 trivialMatrix = (fInvMatrix.getType() & ~SkMatrix::kTranslate_Mask) == 0; 384 385 if (SkPaint::kHigh_FilterLevel == fFilterLevel) { 386 // If this is still set, that means we wanted HQ sampling 387 // but couldn't do it as a preprocess. Let's try to install 388 // the scanline version of the HQ sampler. If that process fails, 389 // downgrade to bilerp. 390 391 // NOTE: Might need to be careful here in the future when we want 392 // to have the platform proc have a shot at this; it's possible that 393 // the chooseBitmapFilterProc will fail to install a shader but a 394 // platform-specific one might succeed, so it might be premature here 395 // to fall back to bilerp. This needs thought. 396 397 if (!this->setBitmapFilterProcs()) { 398 fFilterLevel = SkPaint::kLow_FilterLevel; 399 } 400 } 401 402 if (SkPaint::kLow_FilterLevel == fFilterLevel) { 403 // Only try bilerp if the matrix is "interesting" and 404 // the image has a suitable size. 405 406 if (fInvType <= SkMatrix::kTranslate_Mask || 407 !valid_for_filtering(fBitmap->width() | fBitmap->height())) { 408 fFilterLevel = SkPaint::kNone_FilterLevel; 409 } 410 } 411 412 // At this point, we know exactly what kind of sampling the per-scanline 413 // shader will perform. 414 415 fMatrixProc = this->chooseMatrixProc(trivialMatrix); 416 // TODO(dominikg): SkASSERT(fMatrixProc) instead? chooseMatrixProc never returns NULL. 417 if (NULL == fMatrixProc) { 418 return false; 419 } 420 421 /////////////////////////////////////////////////////////////////////// 422 423 const SkAlphaType at = fBitmap->alphaType(); 424 425 // No need to do this if we're doing HQ sampling; if filter quality is 426 // still set to HQ by the time we get here, then we must have installed 427 // the shader procs above and can skip all this. 428 429 if (fFilterLevel < SkPaint::kHigh_FilterLevel) { 430 431 int index = 0; 432 if (fAlphaScale < 256) { // note: this distinction is not used for D16 433 index |= 1; 434 } 435 if (fInvType <= (SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)) { 436 index |= 2; 437 } 438 if (fFilterLevel > SkPaint::kNone_FilterLevel) { 439 index |= 4; 440 } 441 // bits 3,4,5 encoding the source bitmap format 442 switch (fBitmap->colorType()) { 443 case kN32_SkColorType: 444 if (kPremul_SkAlphaType != at && kOpaque_SkAlphaType != at) { 445 return false; 446 } 447 index |= 0; 448 break; 449 case kRGB_565_SkColorType: 450 index |= 8; 451 break; 452 case kIndex_8_SkColorType: 453 if (kPremul_SkAlphaType != at && kOpaque_SkAlphaType != at) { 454 return false; 455 } 456 index |= 16; 457 break; 458 case kARGB_4444_SkColorType: 459 if (kPremul_SkAlphaType != at && kOpaque_SkAlphaType != at) { 460 return false; 461 } 462 index |= 24; 463 break; 464 case kAlpha_8_SkColorType: 465 index |= 32; 466 fPaintPMColor = SkPreMultiplyColor(paint.getColor()); 467 break; 468 default: 469 // TODO(dominikg): Should we ever get here? SkASSERT(false) instead? 470 return false; 471 } 472 473 #if !SK_ARM_NEON_IS_ALWAYS 474 static const SampleProc32 gSkBitmapProcStateSample32[] = { 475 S32_opaque_D32_nofilter_DXDY, 476 S32_alpha_D32_nofilter_DXDY, 477 S32_opaque_D32_nofilter_DX, 478 S32_alpha_D32_nofilter_DX, 479 S32_opaque_D32_filter_DXDY, 480 S32_alpha_D32_filter_DXDY, 481 S32_opaque_D32_filter_DX, 482 S32_alpha_D32_filter_DX, 483 484 S16_opaque_D32_nofilter_DXDY, 485 S16_alpha_D32_nofilter_DXDY, 486 S16_opaque_D32_nofilter_DX, 487 S16_alpha_D32_nofilter_DX, 488 S16_opaque_D32_filter_DXDY, 489 S16_alpha_D32_filter_DXDY, 490 S16_opaque_D32_filter_DX, 491 S16_alpha_D32_filter_DX, 492 493 SI8_opaque_D32_nofilter_DXDY, 494 SI8_alpha_D32_nofilter_DXDY, 495 SI8_opaque_D32_nofilter_DX, 496 SI8_alpha_D32_nofilter_DX, 497 SI8_opaque_D32_filter_DXDY, 498 SI8_alpha_D32_filter_DXDY, 499 SI8_opaque_D32_filter_DX, 500 SI8_alpha_D32_filter_DX, 501 502 S4444_opaque_D32_nofilter_DXDY, 503 S4444_alpha_D32_nofilter_DXDY, 504 S4444_opaque_D32_nofilter_DX, 505 S4444_alpha_D32_nofilter_DX, 506 S4444_opaque_D32_filter_DXDY, 507 S4444_alpha_D32_filter_DXDY, 508 S4444_opaque_D32_filter_DX, 509 S4444_alpha_D32_filter_DX, 510 511 // A8 treats alpha/opaque the same (equally efficient) 512 SA8_alpha_D32_nofilter_DXDY, 513 SA8_alpha_D32_nofilter_DXDY, 514 SA8_alpha_D32_nofilter_DX, 515 SA8_alpha_D32_nofilter_DX, 516 SA8_alpha_D32_filter_DXDY, 517 SA8_alpha_D32_filter_DXDY, 518 SA8_alpha_D32_filter_DX, 519 SA8_alpha_D32_filter_DX 520 }; 521 522 static const SampleProc16 gSkBitmapProcStateSample16[] = { 523 S32_D16_nofilter_DXDY, 524 S32_D16_nofilter_DX, 525 S32_D16_filter_DXDY, 526 S32_D16_filter_DX, 527 528 S16_D16_nofilter_DXDY, 529 S16_D16_nofilter_DX, 530 S16_D16_filter_DXDY, 531 S16_D16_filter_DX, 532 533 SI8_D16_nofilter_DXDY, 534 SI8_D16_nofilter_DX, 535 SI8_D16_filter_DXDY, 536 SI8_D16_filter_DX, 537 538 // Don't support 4444 -> 565 539 NULL, NULL, NULL, NULL, 540 // Don't support A8 -> 565 541 NULL, NULL, NULL, NULL 542 }; 543 #endif 544 545 fSampleProc32 = SK_ARM_NEON_WRAP(gSkBitmapProcStateSample32)[index]; 546 index >>= 1; // shift away any opaque/alpha distinction 547 fSampleProc16 = SK_ARM_NEON_WRAP(gSkBitmapProcStateSample16)[index]; 548 549 // our special-case shaderprocs 550 if (SK_ARM_NEON_WRAP(S16_D16_filter_DX) == fSampleProc16) { 551 if (clampClamp) { 552 fShaderProc16 = SK_ARM_NEON_WRAP(Clamp_S16_D16_filter_DX_shaderproc); 553 } else if (SkShader::kRepeat_TileMode == fTileModeX && 554 SkShader::kRepeat_TileMode == fTileModeY) { 555 fShaderProc16 = SK_ARM_NEON_WRAP(Repeat_S16_D16_filter_DX_shaderproc); 556 } 557 } else if (SK_ARM_NEON_WRAP(SI8_opaque_D32_filter_DX) == fSampleProc32 && clampClamp) { 558 fShaderProc32 = SK_ARM_NEON_WRAP(Clamp_SI8_opaque_D32_filter_DX_shaderproc); 559 } 560 561 if (NULL == fShaderProc32) { 562 fShaderProc32 = this->chooseShaderProc32(); 563 } 564 } 565 566 // see if our platform has any accelerated overrides 567 this->platformProcs(); 568 569 return true; 570 } 571 572 static void Clamp_S32_D32_nofilter_trans_shaderproc(const SkBitmapProcState& s, 573 int x, int y, 574 SkPMColor* SK_RESTRICT colors, 575 int count) { 576 SkASSERT(((s.fInvType & ~SkMatrix::kTranslate_Mask)) == 0); 577 SkASSERT(s.fInvKy == 0); 578 SkASSERT(count > 0 && colors != NULL); 579 SkASSERT(SkPaint::kNone_FilterLevel == s.fFilterLevel); 580 581 const int maxX = s.fBitmap->width() - 1; 582 const int maxY = s.fBitmap->height() - 1; 583 int ix = s.fFilterOneX + x; 584 int iy = SkClampMax(s.fFilterOneY + y, maxY); 585 #ifdef SK_DEBUG 586 { 587 SkPoint pt; 588 s.fInvProc(s.fInvMatrix, SkIntToScalar(x) + SK_ScalarHalf, 589 SkIntToScalar(y) + SK_ScalarHalf, &pt); 590 int iy2 = SkClampMax(SkScalarFloorToInt(pt.fY), maxY); 591 int ix2 = SkScalarFloorToInt(pt.fX); 592 593 SkASSERT(iy == iy2); 594 SkASSERT(ix == ix2); 595 } 596 #endif 597 const SkPMColor* row = s.fBitmap->getAddr32(0, iy); 598 599 // clamp to the left 600 if (ix < 0) { 601 int n = SkMin32(-ix, count); 602 sk_memset32(colors, row[0], n); 603 count -= n; 604 if (0 == count) { 605 return; 606 } 607 colors += n; 608 SkASSERT(-ix == n); 609 ix = 0; 610 } 611 // copy the middle 612 if (ix <= maxX) { 613 int n = SkMin32(maxX - ix + 1, count); 614 memcpy(colors, row + ix, n * sizeof(SkPMColor)); 615 count -= n; 616 if (0 == count) { 617 return; 618 } 619 colors += n; 620 } 621 SkASSERT(count > 0); 622 // clamp to the right 623 sk_memset32(colors, row[maxX], count); 624 } 625 626 static inline int sk_int_mod(int x, int n) { 627 SkASSERT(n > 0); 628 if ((unsigned)x >= (unsigned)n) { 629 if (x < 0) { 630 x = n + ~(~x % n); 631 } else { 632 x = x % n; 633 } 634 } 635 return x; 636 } 637 638 static inline int sk_int_mirror(int x, int n) { 639 x = sk_int_mod(x, 2 * n); 640 if (x >= n) { 641 x = n + ~(x - n); 642 } 643 return x; 644 } 645 646 static void Repeat_S32_D32_nofilter_trans_shaderproc(const SkBitmapProcState& s, 647 int x, int y, 648 SkPMColor* SK_RESTRICT colors, 649 int count) { 650 SkASSERT(((s.fInvType & ~SkMatrix::kTranslate_Mask)) == 0); 651 SkASSERT(s.fInvKy == 0); 652 SkASSERT(count > 0 && colors != NULL); 653 SkASSERT(SkPaint::kNone_FilterLevel == s.fFilterLevel); 654 655 const int stopX = s.fBitmap->width(); 656 const int stopY = s.fBitmap->height(); 657 int ix = s.fFilterOneX + x; 658 int iy = sk_int_mod(s.fFilterOneY + y, stopY); 659 #ifdef SK_DEBUG 660 { 661 SkPoint pt; 662 s.fInvProc(s.fInvMatrix, SkIntToScalar(x) + SK_ScalarHalf, 663 SkIntToScalar(y) + SK_ScalarHalf, &pt); 664 int iy2 = sk_int_mod(SkScalarFloorToInt(pt.fY), stopY); 665 int ix2 = SkScalarFloorToInt(pt.fX); 666 667 SkASSERT(iy == iy2); 668 SkASSERT(ix == ix2); 669 } 670 #endif 671 const SkPMColor* row = s.fBitmap->getAddr32(0, iy); 672 673 ix = sk_int_mod(ix, stopX); 674 for (;;) { 675 int n = SkMin32(stopX - ix, count); 676 memcpy(colors, row + ix, n * sizeof(SkPMColor)); 677 count -= n; 678 if (0 == count) { 679 return; 680 } 681 colors += n; 682 ix = 0; 683 } 684 } 685 686 static void S32_D32_constX_shaderproc(const SkBitmapProcState& s, 687 int x, int y, 688 SkPMColor* SK_RESTRICT colors, 689 int count) { 690 SkASSERT((s.fInvType & ~(SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)) == 0); 691 SkASSERT(s.fInvKy == 0); 692 SkASSERT(count > 0 && colors != NULL); 693 SkASSERT(1 == s.fBitmap->width()); 694 695 int iY0; 696 int iY1 SK_INIT_TO_AVOID_WARNING; 697 int iSubY SK_INIT_TO_AVOID_WARNING; 698 699 if (SkPaint::kNone_FilterLevel != s.fFilterLevel) { 700 SkBitmapProcState::MatrixProc mproc = s.getMatrixProc(); 701 uint32_t xy[2]; 702 703 mproc(s, xy, 1, x, y); 704 705 iY0 = xy[0] >> 18; 706 iY1 = xy[0] & 0x3FFF; 707 iSubY = (xy[0] >> 14) & 0xF; 708 } else { 709 int yTemp; 710 711 if (s.fInvType > SkMatrix::kTranslate_Mask) { 712 SkPoint pt; 713 s.fInvProc(s.fInvMatrix, 714 SkIntToScalar(x) + SK_ScalarHalf, 715 SkIntToScalar(y) + SK_ScalarHalf, 716 &pt); 717 // When the matrix has a scale component the setup code in 718 // chooseProcs multiples the inverse matrix by the inverse of the 719 // bitmap's width and height. Since this method is going to do 720 // its own tiling and sampling we need to undo that here. 721 if (SkShader::kClamp_TileMode != s.fTileModeX || 722 SkShader::kClamp_TileMode != s.fTileModeY) { 723 yTemp = SkScalarFloorToInt(pt.fY * s.fBitmap->height()); 724 } else { 725 yTemp = SkScalarFloorToInt(pt.fY); 726 } 727 } else { 728 yTemp = s.fFilterOneY + y; 729 } 730 731 const int stopY = s.fBitmap->height(); 732 switch (s.fTileModeY) { 733 case SkShader::kClamp_TileMode: 734 iY0 = SkClampMax(yTemp, stopY-1); 735 break; 736 case SkShader::kRepeat_TileMode: 737 iY0 = sk_int_mod(yTemp, stopY); 738 break; 739 case SkShader::kMirror_TileMode: 740 default: 741 iY0 = sk_int_mirror(yTemp, stopY); 742 break; 743 } 744 745 #ifdef SK_DEBUG 746 { 747 SkPoint pt; 748 s.fInvProc(s.fInvMatrix, 749 SkIntToScalar(x) + SK_ScalarHalf, 750 SkIntToScalar(y) + SK_ScalarHalf, 751 &pt); 752 if (s.fInvType > SkMatrix::kTranslate_Mask && 753 (SkShader::kClamp_TileMode != s.fTileModeX || 754 SkShader::kClamp_TileMode != s.fTileModeY)) { 755 pt.fY *= s.fBitmap->height(); 756 } 757 int iY2; 758 759 switch (s.fTileModeY) { 760 case SkShader::kClamp_TileMode: 761 iY2 = SkClampMax(SkScalarFloorToInt(pt.fY), stopY-1); 762 break; 763 case SkShader::kRepeat_TileMode: 764 iY2 = sk_int_mod(SkScalarFloorToInt(pt.fY), stopY); 765 break; 766 case SkShader::kMirror_TileMode: 767 default: 768 iY2 = sk_int_mirror(SkScalarFloorToInt(pt.fY), stopY); 769 break; 770 } 771 772 SkASSERT(iY0 == iY2); 773 } 774 #endif 775 } 776 777 const SkPMColor* row0 = s.fBitmap->getAddr32(0, iY0); 778 SkPMColor color; 779 780 if (SkPaint::kNone_FilterLevel != s.fFilterLevel) { 781 const SkPMColor* row1 = s.fBitmap->getAddr32(0, iY1); 782 783 if (s.fAlphaScale < 256) { 784 Filter_32_alpha(iSubY, *row0, *row1, &color, s.fAlphaScale); 785 } else { 786 Filter_32_opaque(iSubY, *row0, *row1, &color); 787 } 788 } else { 789 if (s.fAlphaScale < 256) { 790 color = SkAlphaMulQ(*row0, s.fAlphaScale); 791 } else { 792 color = *row0; 793 } 794 } 795 796 sk_memset32(colors, color, count); 797 } 798 799 static void DoNothing_shaderproc(const SkBitmapProcState&, int x, int y, 800 SkPMColor* SK_RESTRICT colors, int count) { 801 // if we get called, the matrix is too tricky, so we just draw nothing 802 sk_memset32(colors, 0, count); 803 } 804 805 bool SkBitmapProcState::setupForTranslate() { 806 SkPoint pt; 807 fInvProc(fInvMatrix, SK_ScalarHalf, SK_ScalarHalf, &pt); 808 809 /* 810 * if the translate is larger than our ints, we can get random results, or 811 * worse, we might get 0x80000000, which wreaks havoc on us, since we can't 812 * negate it. 813 */ 814 const SkScalar too_big = SkIntToScalar(1 << 30); 815 if (SkScalarAbs(pt.fX) > too_big || SkScalarAbs(pt.fY) > too_big) { 816 return false; 817 } 818 819 // Since we know we're not filtered, we re-purpose these fields allow 820 // us to go from device -> src coordinates w/ just an integer add, 821 // rather than running through the inverse-matrix 822 fFilterOneX = SkScalarFloorToInt(pt.fX); 823 fFilterOneY = SkScalarFloorToInt(pt.fY); 824 return true; 825 } 826 827 SkBitmapProcState::ShaderProc32 SkBitmapProcState::chooseShaderProc32() { 828 829 if (kN32_SkColorType != fBitmap->colorType()) { 830 return NULL; 831 } 832 833 static const unsigned kMask = SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask; 834 835 if (1 == fBitmap->width() && 0 == (fInvType & ~kMask)) { 836 if (SkPaint::kNone_FilterLevel == fFilterLevel && 837 fInvType <= SkMatrix::kTranslate_Mask && 838 !this->setupForTranslate()) { 839 return DoNothing_shaderproc; 840 } 841 return S32_D32_constX_shaderproc; 842 } 843 844 if (fAlphaScale < 256) { 845 return NULL; 846 } 847 if (fInvType > SkMatrix::kTranslate_Mask) { 848 return NULL; 849 } 850 if (SkPaint::kNone_FilterLevel != fFilterLevel) { 851 return NULL; 852 } 853 854 SkShader::TileMode tx = (SkShader::TileMode)fTileModeX; 855 SkShader::TileMode ty = (SkShader::TileMode)fTileModeY; 856 857 if (SkShader::kClamp_TileMode == tx && SkShader::kClamp_TileMode == ty) { 858 if (this->setupForTranslate()) { 859 return Clamp_S32_D32_nofilter_trans_shaderproc; 860 } 861 return DoNothing_shaderproc; 862 } 863 if (SkShader::kRepeat_TileMode == tx && SkShader::kRepeat_TileMode == ty) { 864 if (this->setupForTranslate()) { 865 return Repeat_S32_D32_nofilter_trans_shaderproc; 866 } 867 return DoNothing_shaderproc; 868 } 869 return NULL; 870 } 871 872 /////////////////////////////////////////////////////////////////////////////// 873 874 #ifdef SK_DEBUG 875 876 static void check_scale_nofilter(uint32_t bitmapXY[], int count, 877 unsigned mx, unsigned my) { 878 unsigned y = *bitmapXY++; 879 SkASSERT(y < my); 880 881 const uint16_t* xptr = reinterpret_cast<const uint16_t*>(bitmapXY); 882 for (int i = 0; i < count; ++i) { 883 SkASSERT(xptr[i] < mx); 884 } 885 } 886 887 static void check_scale_filter(uint32_t bitmapXY[], int count, 888 unsigned mx, unsigned my) { 889 uint32_t YY = *bitmapXY++; 890 unsigned y0 = YY >> 18; 891 unsigned y1 = YY & 0x3FFF; 892 SkASSERT(y0 < my); 893 SkASSERT(y1 < my); 894 895 for (int i = 0; i < count; ++i) { 896 uint32_t XX = bitmapXY[i]; 897 unsigned x0 = XX >> 18; 898 unsigned x1 = XX & 0x3FFF; 899 SkASSERT(x0 < mx); 900 SkASSERT(x1 < mx); 901 } 902 } 903 904 static void check_affine_nofilter(uint32_t bitmapXY[], int count, 905 unsigned mx, unsigned my) { 906 for (int i = 0; i < count; ++i) { 907 uint32_t XY = bitmapXY[i]; 908 unsigned x = XY & 0xFFFF; 909 unsigned y = XY >> 16; 910 SkASSERT(x < mx); 911 SkASSERT(y < my); 912 } 913 } 914 915 static void check_affine_filter(uint32_t bitmapXY[], int count, 916 unsigned mx, unsigned my) { 917 for (int i = 0; i < count; ++i) { 918 uint32_t YY = *bitmapXY++; 919 unsigned y0 = YY >> 18; 920 unsigned y1 = YY & 0x3FFF; 921 SkASSERT(y0 < my); 922 SkASSERT(y1 < my); 923 924 uint32_t XX = *bitmapXY++; 925 unsigned x0 = XX >> 18; 926 unsigned x1 = XX & 0x3FFF; 927 SkASSERT(x0 < mx); 928 SkASSERT(x1 < mx); 929 } 930 } 931 932 void SkBitmapProcState::DebugMatrixProc(const SkBitmapProcState& state, 933 uint32_t bitmapXY[], int count, 934 int x, int y) { 935 SkASSERT(bitmapXY); 936 SkASSERT(count > 0); 937 938 state.fMatrixProc(state, bitmapXY, count, x, y); 939 940 void (*proc)(uint32_t bitmapXY[], int count, unsigned mx, unsigned my); 941 942 // There are four formats possible: 943 // scale -vs- affine 944 // filter -vs- nofilter 945 if (state.fInvType <= (SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)) { 946 proc = state.fFilterLevel != SkPaint::kNone_FilterLevel ? check_scale_filter : check_scale_nofilter; 947 } else { 948 proc = state.fFilterLevel != SkPaint::kNone_FilterLevel ? check_affine_filter : check_affine_nofilter; 949 } 950 proc(bitmapXY, count, state.fBitmap->width(), state.fBitmap->height()); 951 } 952 953 SkBitmapProcState::MatrixProc SkBitmapProcState::getMatrixProc() const { 954 return DebugMatrixProc; 955 } 956 957 #endif 958 959 /////////////////////////////////////////////////////////////////////////////// 960 /* 961 The storage requirements for the different matrix procs are as follows, 962 where each X or Y is 2 bytes, and N is the number of pixels/elements: 963 964 scale/translate nofilter Y(4bytes) + N * X 965 affine/perspective nofilter N * (X Y) 966 scale/translate filter Y Y + N * (X X) 967 affine/perspective filter N * (Y Y X X) 968 */ 969 int SkBitmapProcState::maxCountForBufferSize(size_t bufferSize) const { 970 int32_t size = static_cast<int32_t>(bufferSize); 971 972 size &= ~3; // only care about 4-byte aligned chunks 973 if (fInvType <= (SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)) { 974 size -= 4; // the shared Y (or YY) coordinate 975 if (size < 0) { 976 size = 0; 977 } 978 size >>= 1; 979 } else { 980 size >>= 2; 981 } 982 983 if (fFilterLevel != SkPaint::kNone_FilterLevel) { 984 size >>= 1; 985 } 986 987 return size; 988 } 989