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