| Index: src/core/SkBitmapProcState.cpp
|
| diff --git a/src/core/SkBitmapProcState.cpp b/src/core/SkBitmapProcState.cpp
|
| index f880a86196e4c0a267751320f3b21836c0124341..c7d367b82c98f5ed80f44d6e49e66c55dfa93ca4 100644
|
| --- a/src/core/SkBitmapProcState.cpp
|
| +++ b/src/core/SkBitmapProcState.cpp
|
| @@ -12,6 +12,7 @@
|
| #include "SkShader.h" // for tilemodes
|
| #include "SkUtilsArm.h"
|
| #include "SkBitmapScaler.h"
|
| +#include "SkMipMap.h"
|
| #include "SkScaledImageCache.h"
|
|
|
| #if !SK_ARM_NEON_IS_NONE
|
| @@ -92,7 +93,7 @@ static bool valid_for_filtering(unsigned dimension) {
|
| return (dimension & ~0x3FFF) == 0;
|
| }
|
|
|
| -static bool effective_matrix_scale_sqrd(const SkMatrix& mat) {
|
| +static SkScalar effective_matrix_scale_sqrd(const SkMatrix& mat) {
|
| SkPoint v1, v2;
|
|
|
| v1.fX = mat.getScaleX();
|
| @@ -225,24 +226,43 @@ void SkBitmapProcState::possiblyScaleImage() {
|
| * a scale > 1 to indicate down scaling by the CTM.
|
| */
|
| if (scaleSqd > SK_Scalar1) {
|
| - if (!fOrigBitmap.hasMipMap()) {
|
| - fOrigBitmap.buildMipMap();
|
| - // build may fail, so we need to check again
|
| + const SkMipMap* mip = NULL;
|
| +
|
| + SkASSERT(NULL == fScaledCacheID);
|
| + fScaledCacheID = SkScaledImageCache::FindAndLockMip(fOrigBitmap, &mip);
|
| + if (!fScaledCacheID) {
|
| + SkASSERT(NULL == mip);
|
| + mip = SkMipMap::Build(fOrigBitmap);
|
| + if (mip) {
|
| + fScaledCacheID = SkScaledImageCache::AddAndLockMip(fOrigBitmap,
|
| + mip);
|
| + mip->unref(); // the cache took a ref
|
| + SkASSERT(fScaledCacheID);
|
| + }
|
| + } else {
|
| + SkASSERT(mip);
|
| }
|
| - if (fOrigBitmap.hasMipMap()) {
|
| - int shift = fOrigBitmap.extractMipLevel(&fScaledBitmap,
|
| - SkScalarToFixed(fInvMatrix.getScaleX()),
|
| - SkScalarToFixed(fInvMatrix.getSkewY()));
|
| - if (shift > 0) {
|
| - SkScalar scale = SkFixedToScalar(SK_Fixed1 >> shift);
|
| - fInvMatrix.postScale(scale, scale);
|
| +
|
| + if (mip) {
|
| + SkScalar levelScale = SkScalarInvert(SkScalarSqrt(scaleSqd));
|
| + SkMipMap::Level level;
|
| + if (mip->extractLevel(levelScale, &level)) {
|
| + SkScalar invScaleFixup = level.fScale;
|
| + fInvMatrix.postScale(invScaleFixup, invScaleFixup);
|
| +
|
| + fScaledBitmap.setConfig(fOrigBitmap.config(),
|
| + level.fWidth, level.fHeight,
|
| + level.fRowBytes);
|
| + fScaledBitmap.setPixels(level.fPixels);
|
| fBitmap = &fScaledBitmap;
|
| }
|
| }
|
| }
|
|
|
| - // Now that we've built the mipmaps (if applicable), we set the filter-level
|
| - // bilinear interpolation.
|
| + /*
|
| + * At this point, we may or may not have built a mipmap. Regardless, we
|
| + * now fall back on Low so will bilerp whatever fBitmap now points at.
|
| + */
|
| fFilterLevel = SkPaint::kLow_FilterLevel;
|
| }
|
|
|
|
|