| OLD | NEW |
| 1 | 1 |
| 2 /* | 2 /* |
| 3 * Copyright 2011 Google Inc. | 3 * Copyright 2011 Google Inc. |
| 4 * | 4 * |
| 5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
| 6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
| 7 */ | 7 */ |
| 8 #include "SkBitmapProcState.h" | 8 #include "SkBitmapProcState.h" |
| 9 #include "SkColorPriv.h" | 9 #include "SkColorPriv.h" |
| 10 #include "SkFilterProc.h" | 10 #include "SkFilterProc.h" |
| 11 #include "SkPaint.h" | 11 #include "SkPaint.h" |
| 12 #include "SkShader.h" // for tilemodes | 12 #include "SkShader.h" // for tilemodes |
| 13 #include "SkUtilsArm.h" | 13 #include "SkUtilsArm.h" |
| 14 #include "SkBitmapScaler.h" | 14 #include "SkBitmapScaler.h" |
| 15 #include "SkMatrixUtils.h" |
| 15 #include "SkMipMap.h" | 16 #include "SkMipMap.h" |
| 16 #include "SkPixelRef.h" | 17 #include "SkPixelRef.h" |
| 17 #include "SkScaledImageCache.h" | 18 #include "SkScaledImageCache.h" |
| 18 #include "SkImageEncoder.h" | 19 #include "SkImageEncoder.h" |
| 19 | 20 |
| 21 static int paintfilter_to_subpixelbits(SkPaint::FilterLevel level) { |
| 22 const int gBits[] = { 0, 4, 4, 4, }; |
| 23 return gBits[level]; |
| 24 } |
| 25 |
| 20 #if !SK_ARM_NEON_IS_NONE | 26 #if !SK_ARM_NEON_IS_NONE |
| 21 // These are defined in src/opts/SkBitmapProcState_arm_neon.cpp | 27 // These are defined in src/opts/SkBitmapProcState_arm_neon.cpp |
| 22 extern const SkBitmapProcState::SampleProc16 gSkBitmapProcStateSample16_neon[]; | 28 extern const SkBitmapProcState::SampleProc16 gSkBitmapProcStateSample16_neon[]; |
| 23 extern const SkBitmapProcState::SampleProc32 gSkBitmapProcStateSample32_neon[]; | 29 extern const SkBitmapProcState::SampleProc32 gSkBitmapProcStateSample32_neon[]; |
| 24 extern void S16_D16_filter_DX_neon(const SkBitmapProcState&, const uint32_t*, i
nt, uint16_t*); | 30 extern void S16_D16_filter_DX_neon(const SkBitmapProcState&, const uint32_t*, i
nt, uint16_t*); |
| 25 extern void Clamp_S16_D16_filter_DX_shaderproc_neon(const SkBitmapProcState&, i
nt, int, uint16_t*, int); | 31 extern void Clamp_S16_D16_filter_DX_shaderproc_neon(const SkBitmapProcState&, i
nt, int, uint16_t*, int); |
| 26 extern void Repeat_S16_D16_filter_DX_shaderproc_neon(const SkBitmapProcState&,
int, int, uint16_t*, int); | 32 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 uint3
2_t*, int, SkPMColor*); | 33 extern void SI8_opaque_D32_filter_DX_neon(const SkBitmapProcState&, const uint3
2_t*, int, SkPMColor*); |
| 28 extern void SI8_opaque_D32_filter_DX_shaderproc_neon(const SkBitmapProcState&,
int, int, uint32_t*, int); | 34 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 SkBitmapProcSt
ate&, int, int, uint32_t*, int); | 35 extern void Clamp_SI8_opaque_D32_filter_DX_shaderproc_neon(const SkBitmapProcSt
ate&, int, int, uint32_t*, int); |
| (...skipping 337 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 367 return true; | 373 return true; |
| 368 } | 374 } |
| 369 | 375 |
| 370 SkBitmapProcState::~SkBitmapProcState() { | 376 SkBitmapProcState::~SkBitmapProcState() { |
| 371 if (fScaledCacheID) { | 377 if (fScaledCacheID) { |
| 372 SkScaledImageCache::Unlock(fScaledCacheID); | 378 SkScaledImageCache::Unlock(fScaledCacheID); |
| 373 } | 379 } |
| 374 SkDELETE(fBitmapFilter); | 380 SkDELETE(fBitmapFilter); |
| 375 } | 381 } |
| 376 | 382 |
| 383 bool SkBitmapProcState::isInverseTrivial() const { |
| 384 unsigned bits = paintfilter_to_subpixelbits((SkPaint::FilterLevel)fFilterLev
el); |
| 385 return SkTreatAsSprite(fInvMatrix, fBitmap->width(), fBitmap->height(), bits
); |
| 386 } |
| 387 |
| 377 bool SkBitmapProcState::chooseProcs(const SkMatrix& inv, const SkPaint& paint) { | 388 bool SkBitmapProcState::chooseProcs(const SkMatrix& inv, const SkPaint& paint) { |
| 378 SkASSERT(fOrigBitmap.width() && fOrigBitmap.height()); | 389 SkASSERT(fOrigBitmap.width() && fOrigBitmap.height()); |
| 390 SkASSERT(NULL == fScaledCacheID); |
| 379 | 391 |
| 380 fBitmap = NULL; | |
| 381 fInvMatrix = inv; | 392 fInvMatrix = inv; |
| 382 fFilterLevel = paint.getFilterLevel(); | 393 fFilterLevel = paint.getFilterLevel(); |
| 394 fBitmap = &fOrigBitmap; |
| 383 | 395 |
| 384 SkASSERT(NULL == fScaledCacheID); | 396 bool trivialMX = this->isInverseTrivial(); |
| 397 if (trivialMX) { |
| 398 fFilterLevel = SkPaint::kNone_FilterLevel; |
| 399 } |
| 400 |
| 401 // Reset to null for possiblyScaleImage() |
| 402 fBitmap = NULL; |
| 385 | 403 |
| 386 // possiblyScaleImage will look to see if it can rescale the image as a | 404 // possiblyScaleImage will look to see if it can rescale the image as a |
| 387 // preprocess; either by scaling up to the target size, or by selecting | 405 // preprocess; either by scaling up to the target size, or by selecting |
| 388 // a nearby mipmap level. If it does, it will adjust the working | 406 // a nearby mipmap level. If it does, it will adjust the working |
| 389 // matrix as well as the working bitmap. It may also adjust the filter | 407 // matrix as well as the working bitmap. It may also adjust the filter |
| 390 // quality to avoid re-filtering an already perfectly scaled image. | 408 // quality to avoid re-filtering an already perfectly scaled image. |
| 391 if (!this->possiblyScaleImage()) { | 409 if (!this->possiblyScaleImage()) { |
| 392 if (!this->lockBaseBitmap()) { | 410 if (!this->lockBaseBitmap()) { |
| 393 return false; | 411 return false; |
| 394 } | 412 } |
| 395 } | 413 } |
| 396 // The above logic should have always assigned fBitmap, but in case it | 414 // The above logic should have always assigned fBitmap, but in case it |
| 397 // didn't, we check for that now... | 415 // didn't, we check for that now... |
| 398 // TODO(dominikg): Ask humper@ if we can just use an SkASSERT(fBitmap)? | 416 // TODO(dominikg): Ask humper@ if we can just use an SkASSERT(fBitmap)? |
| 399 if (NULL == fBitmap) { | 417 if (NULL == fBitmap) { |
| 400 return false; | 418 return false; |
| 401 } | 419 } |
| 402 | 420 |
| 403 // If we are "still" kMedium_FilterLevel, then the request was not fulfilled
by possiblyScale, | 421 // If we are "still" kMedium_FilterLevel, then the request was not fulfilled
by possiblyScale, |
| 404 // so we downgrade to kLow (so the rest of the sniffing code can assume that
) | 422 // so we downgrade to kLow (so the rest of the sniffing code can assume that
) |
| 405 if (SkPaint::kMedium_FilterLevel == fFilterLevel) { | 423 if (SkPaint::kMedium_FilterLevel == fFilterLevel) { |
| 406 fFilterLevel = SkPaint::kLow_FilterLevel; | 424 fFilterLevel = SkPaint::kLow_FilterLevel; |
| 407 } | 425 } |
| 408 | 426 |
| 409 bool trivialMatrix = (fInvMatrix.getType() & ~SkMatrix::kTranslate_Mask) ==
0; | 427 trivialMX = this->isInverseTrivial(); |
| 428 if (trivialMX) { |
| 429 fFilterLevel = SkPaint::kNone_FilterLevel; |
| 430 } |
| 431 |
| 410 bool clampClamp = SkShader::kClamp_TileMode == fTileModeX && | 432 bool clampClamp = SkShader::kClamp_TileMode == fTileModeX && |
| 411 SkShader::kClamp_TileMode == fTileModeY; | 433 SkShader::kClamp_TileMode == fTileModeY; |
| 412 | 434 |
| 413 if (!(clampClamp || trivialMatrix)) { | 435 if (!(clampClamp || trivialMX)) { |
| 414 fInvMatrix.postIDiv(fOrigBitmap.width(), fOrigBitmap.height()); | 436 fInvMatrix.postIDiv(fOrigBitmap.width(), fOrigBitmap.height()); |
| 415 } | 437 } |
| 416 | 438 |
| 417 // Now that all possible changes to the matrix have taken place, check | 439 // Now that all possible changes to the matrix have taken place, check |
| 418 // to see if we're really close to a no-scale matrix. If so, explicitly | 440 // to see if we're really close to a no-scale matrix. If so, explicitly |
| 419 // set it to be so. Subsequent code may inspect this matrix to choose | 441 // set it to be so. Subsequent code may inspect this matrix to choose |
| 420 // a faster path in this case. | 442 // a faster path in this case. |
| 421 | 443 |
| 422 // This code will only execute if the matrix has some scale component; | 444 // This code will only execute if the matrix has some scale component; |
| 423 // if it's already pure translate then we won't do this inversion. | 445 // if it's already pure translate then we won't do this inversion. |
| 424 | 446 |
| 425 if (matrix_only_scale_translate(fInvMatrix)) { | 447 // if (matrix_only_scale_translate(fInvMatrix)) { |
| 448 if (trivialMX) { |
| 426 SkMatrix forward; | 449 SkMatrix forward; |
| 427 if (fInvMatrix.invert(&forward)) { | 450 if (fInvMatrix.invert(&forward)) { |
| 428 if (clampClamp ? just_trans_clamp(forward, *fBitmap) | 451 if (clampClamp ? just_trans_clamp(forward, *fBitmap) |
| 429 : just_trans_general(forward)) { | 452 : just_trans_general(forward)) { |
| 430 SkScalar tx = -SkScalarRoundToScalar(forward.getTranslateX()); | 453 SkScalar tx = -SkScalarRoundToScalar(forward.getTranslateX()); |
| 431 SkScalar ty = -SkScalarRoundToScalar(forward.getTranslateY()); | 454 SkScalar ty = -SkScalarRoundToScalar(forward.getTranslateY()); |
| 432 fInvMatrix.setTranslate(tx, ty); | 455 fInvMatrix.setTranslate(tx, ty); |
| 433 } | 456 } |
| 434 } | 457 } |
| 435 } | 458 } |
| 436 | 459 |
| 460 if (trivialMX && (fInvMatrix.getType() & ~SkMatrix::kTranslate_Mask)) { |
| 461 // SkDebugf("sfsd\n"); |
| 462 } |
| 463 |
| 437 fInvProc = fInvMatrix.getMapXYProc(); | 464 fInvProc = fInvMatrix.getMapXYProc(); |
| 438 fInvType = fInvMatrix.getType(); | 465 fInvType = fInvMatrix.getType(); |
| 439 fInvSx = SkScalarToFixed(fInvMatrix.getScaleX()); | 466 fInvSx = SkScalarToFixed(fInvMatrix.getScaleX()); |
| 440 fInvSxFractionalInt = SkScalarToFractionalInt(fInvMatrix.getScaleX()); | 467 fInvSxFractionalInt = SkScalarToFractionalInt(fInvMatrix.getScaleX()); |
| 441 fInvKy = SkScalarToFixed(fInvMatrix.getSkewY()); | 468 fInvKy = SkScalarToFixed(fInvMatrix.getSkewY()); |
| 442 fInvKyFractionalInt = SkScalarToFractionalInt(fInvMatrix.getSkewY()); | 469 fInvKyFractionalInt = SkScalarToFractionalInt(fInvMatrix.getSkewY()); |
| 443 | 470 |
| 444 fAlphaScale = SkAlpha255To256(paint.getAlpha()); | 471 fAlphaScale = SkAlpha255To256(paint.getAlpha()); |
| 445 | 472 |
| 446 fShaderProc32 = NULL; | 473 fShaderProc32 = NULL; |
| 447 fShaderProc16 = NULL; | 474 fShaderProc16 = NULL; |
| 448 fSampleProc32 = NULL; | 475 fSampleProc32 = NULL; |
| 449 fSampleProc16 = NULL; | 476 fSampleProc16 = NULL; |
| 450 | 477 |
| 451 // recompute the triviality of the matrix here because we may have | |
| 452 // changed it! | |
| 453 | |
| 454 trivialMatrix = (fInvMatrix.getType() & ~SkMatrix::kTranslate_Mask) == 0; | |
| 455 | |
| 456 if (SkPaint::kHigh_FilterLevel == fFilterLevel) { | 478 if (SkPaint::kHigh_FilterLevel == fFilterLevel) { |
| 457 // If this is still set, that means we wanted HQ sampling | 479 // If this is still set, that means we wanted HQ sampling |
| 458 // but couldn't do it as a preprocess. Let's try to install | 480 // but couldn't do it as a preprocess. Let's try to install |
| 459 // the scanline version of the HQ sampler. If that process fails, | 481 // the scanline version of the HQ sampler. If that process fails, |
| 460 // downgrade to bilerp. | 482 // downgrade to bilerp. |
| 461 | 483 |
| 462 // NOTE: Might need to be careful here in the future when we want | 484 // NOTE: Might need to be careful here in the future when we want |
| 463 // to have the platform proc have a shot at this; it's possible that | 485 // to have the platform proc have a shot at this; it's possible that |
| 464 // the chooseBitmapFilterProc will fail to install a shader but a | 486 // the chooseBitmapFilterProc will fail to install a shader but a |
| 465 // platform-specific one might succeed, so it might be premature here | 487 // platform-specific one might succeed, so it might be premature here |
| 466 // to fall back to bilerp. This needs thought. | 488 // to fall back to bilerp. This needs thought. |
| 467 | 489 |
| 468 if (!this->setBitmapFilterProcs()) { | 490 if (!this->setBitmapFilterProcs()) { |
| 469 fFilterLevel = SkPaint::kLow_FilterLevel; | 491 fFilterLevel = SkPaint::kLow_FilterLevel; |
| 470 } | 492 } |
| 471 } | 493 } |
| 472 | 494 |
| 473 if (SkPaint::kLow_FilterLevel == fFilterLevel) { | |
| 474 // Only try bilerp if the matrix is "interesting" and | |
| 475 // the image has a suitable size. | |
| 476 | |
| 477 if (fInvType <= SkMatrix::kTranslate_Mask || | |
| 478 !valid_for_filtering(fBitmap->width() | fBitmap->height())) { | |
| 479 fFilterLevel = SkPaint::kNone_FilterLevel; | |
| 480 } | |
| 481 } | |
| 482 | |
| 483 // At this point, we know exactly what kind of sampling the per-scanline | 495 // At this point, we know exactly what kind of sampling the per-scanline |
| 484 // shader will perform. | 496 // shader will perform. |
| 485 | 497 |
| 486 fMatrixProc = this->chooseMatrixProc(trivialMatrix); | 498 fMatrixProc = this->chooseMatrixProc(trivialMX); |
| 487 // TODO(dominikg): SkASSERT(fMatrixProc) instead? chooseMatrixProc never ret
urns NULL. | 499 // TODO(dominikg): SkASSERT(fMatrixProc) instead? chooseMatrixProc never ret
urns NULL. |
| 488 if (NULL == fMatrixProc) { | 500 if (NULL == fMatrixProc) { |
| 489 return false; | 501 return false; |
| 490 } | 502 } |
| 491 | 503 |
| 492 /////////////////////////////////////////////////////////////////////// | 504 /////////////////////////////////////////////////////////////////////// |
| 493 | 505 |
| 494 // No need to do this if we're doing HQ sampling; if filter quality is | 506 // No need to do this if we're doing HQ sampling; if filter quality is |
| 495 // still set to HQ by the time we get here, then we must have installed | 507 // still set to HQ by the time we get here, then we must have installed |
| 496 // the shader procs above and can skip all this. | 508 // the shader procs above and can skip all this. |
| (...skipping 542 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1039 } else { | 1051 } else { |
| 1040 size >>= 2; | 1052 size >>= 2; |
| 1041 } | 1053 } |
| 1042 | 1054 |
| 1043 if (fFilterLevel != SkPaint::kNone_FilterLevel) { | 1055 if (fFilterLevel != SkPaint::kNone_FilterLevel) { |
| 1044 size >>= 1; | 1056 size >>= 1; |
| 1045 } | 1057 } |
| 1046 | 1058 |
| 1047 return size; | 1059 return size; |
| 1048 } | 1060 } |
| OLD | NEW |