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