Chromium Code Reviews| Index: src/core/SkBitmapProcState.cpp |
| diff --git a/src/core/SkBitmapProcState.cpp b/src/core/SkBitmapProcState.cpp |
| index 0b50fbc32dc8f4d160a78bc54e4b46de300ff14b..32ff145157d38407e8d5ce2266205ffef7b4c806 100644 |
| --- a/src/core/SkBitmapProcState.cpp |
| +++ b/src/core/SkBitmapProcState.cpp |
| @@ -6,6 +6,7 @@ |
| */ |
| #include "SkBitmapCache.h" |
| +#include "SkBitmapController.h" |
| #include "SkBitmapProcState.h" |
| #include "SkColorPriv.h" |
| #include "SkFilterProc.h" |
| @@ -38,6 +39,26 @@ extern void Clamp_S32_opaque_D32_nofilter_DX_shaderproc(const SkBitmapProcState& |
| /////////////////////////////////////////////////////////////////////////////// |
| +static bool valid_for_drawing(const SkBitmap& bm) { |
|
scroggo
2015/06/02 13:24:54
Can we share this code? (My first thought when I s
reed1
2015/06/02 14:07:46
Acknowledged.
|
| + if (0 == bm.width() || 0 == bm.height()) { |
| + return false; // nothing to draw |
| + } |
| + if (NULL == bm.pixelRef()) { |
| + return false; // no pixels to read |
| + } |
| + if (bm.getTexture()) { |
| + // we can handle texture (ugh) since lockPixels will perform a read-back |
| + return true; |
| + } |
| + if (kIndex_8_SkColorType == bm.colorType()) { |
| + SkAutoLockPixels alp(bm); // but we need to call it before getColorTable() is safe. |
| + if (!bm.getColorTable()) { |
| + return false; |
| + } |
| + } |
| + return true; |
| +} |
| + |
| // true iff the matrix contains, at most, scale and translate elements |
| static bool matrix_only_scale_translate(const SkMatrix& m) { |
| return m.getType() <= (SkMatrix::kScale_Mask | SkMatrix::kTranslate_Mask); |
| @@ -90,166 +111,12 @@ static bool just_trans_general(const SkMatrix& matrix) { |
| return true; |
| } |
| -/////////////////////////////////////////////////////////////////////////////// |
| - |
| static bool valid_for_filtering(unsigned dimension) { |
| // for filtering, width and height must fit in 14bits, since we use steal |
| // 2 bits from each to store our 4bit subpixel data |
| return (dimension & ~0x3FFF) == 0; |
| } |
| -// Check to see that the size of the bitmap that would be produced by |
| -// scaling by the given inverted matrix is less than the maximum allowed. |
| -static inline bool cache_size_okay(const SkBitmap& bm, const SkMatrix& invMat) { |
| - size_t maximumAllocation = SkResourceCache::GetEffectiveSingleAllocationByteLimit(); |
| - if (0 == maximumAllocation) { |
| - return true; |
| - } |
| - // float matrixScaleFactor = 1.0 / (invMat.scaleX * invMat.scaleY); |
| - // return ((origBitmapSize * matrixScaleFactor) < maximumAllocationSize); |
| - // Skip the division step: |
| - return bm.info().getSafeSize(bm.info().minRowBytes()) |
| - < (maximumAllocation * invMat.getScaleX() * invMat.getScaleY()); |
| -} |
| - |
| -/* |
| - * High quality is implemented by performing up-right scale-only filtering and then |
| - * using bilerp for any remaining transformations. |
| - */ |
| -void SkBitmapProcState::processHQRequest() { |
| - SkASSERT(kHigh_SkFilterQuality == fFilterLevel); |
| - |
| - // Our default return state is to downgrade the request to Medium, w/ or w/o setting fBitmap |
| - // to a valid bitmap. If we succeed, we will set this to Low instead. |
| - fFilterLevel = kMedium_SkFilterQuality; |
| - |
| - if (kN32_SkColorType != fOrigBitmap.colorType() || !cache_size_okay(fOrigBitmap, fInvMatrix) || |
| - fInvMatrix.hasPerspective()) |
| - { |
| - return; // can't handle the reqeust |
| - } |
| - |
| - SkScalar invScaleX = fInvMatrix.getScaleX(); |
| - SkScalar invScaleY = fInvMatrix.getScaleY(); |
| - if (fInvMatrix.getType() & SkMatrix::kAffine_Mask) { |
| - SkSize scale; |
| - if (!fInvMatrix.decomposeScale(&scale)) { |
| - return; |
| - } |
| - invScaleX = scale.width(); |
| - invScaleY = scale.height(); |
| - } |
| - if (SkScalarNearlyEqual(invScaleX, 1) && SkScalarNearlyEqual(invScaleY, 1)) { |
| - return; // no need for HQ |
| - } |
| - |
| - SkScalar trueDestWidth = fOrigBitmap.width() / invScaleX; |
| - SkScalar trueDestHeight = fOrigBitmap.height() / invScaleY; |
| - SkScalar roundedDestWidth = SkScalarRoundToScalar(trueDestWidth); |
| - SkScalar roundedDestHeight = SkScalarRoundToScalar(trueDestHeight); |
| - |
| - if (!SkBitmapCache::Find(fOrigBitmap, roundedDestWidth, roundedDestHeight, &fScaledBitmap)) { |
| - if (!SkBitmapScaler::Resize(&fScaledBitmap, |
| - fOrigBitmap, |
| - SkBitmapScaler::RESIZE_BEST, |
| - roundedDestWidth, |
| - roundedDestHeight, |
| - SkResourceCache::GetAllocator())) { |
| - return; // we failed to create fScaledBitmap |
| - } |
| - |
| - SkASSERT(fScaledBitmap.getPixels()); |
| - fScaledBitmap.setImmutable(); |
| - SkBitmapCache::Add(fOrigBitmap, roundedDestWidth, roundedDestHeight, fScaledBitmap); |
| - } |
| - |
| - SkASSERT(fScaledBitmap.getPixels()); |
| - fBitmap = &fScaledBitmap; |
| - |
| - fInvMatrix.postScale(roundedDestWidth / fOrigBitmap.width(), |
| - roundedDestHeight / fOrigBitmap.height()); |
| - fFilterLevel = kLow_SkFilterQuality; |
| -} |
| - |
| -/* |
| - * Modulo internal errors, this should always succeed *if* the matrix is downscaling |
| - * (in this case, we have the inverse, so it succeeds if fInvMatrix is upscaling) |
| - */ |
| -void SkBitmapProcState::processMediumRequest() { |
| - SkASSERT(kMedium_SkFilterQuality == fFilterLevel); |
| - |
| - // Our default return state is to downgrade the request to Low, w/ or w/o setting fBitmap |
| - // to a valid bitmap. |
| - fFilterLevel = kLow_SkFilterQuality; |
| - |
| - SkSize invScaleSize; |
| - if (!fInvMatrix.decomposeScale(&invScaleSize, NULL)) { |
| - return; |
| - } |
| - SkScalar invScale = SkScalarSqrt(invScaleSize.width() * invScaleSize.height()); |
| - |
| - if (invScale > SK_Scalar1) { |
| - fCurrMip.reset(SkMipMapCache::FindAndRef(fOrigBitmap)); |
| - if (NULL == fCurrMip.get()) { |
| - fCurrMip.reset(SkMipMapCache::AddAndRef(fOrigBitmap)); |
| - if (NULL == fCurrMip.get()) { |
| - return; |
| - } |
| - } |
| - // diagnostic for a crasher... |
| - if (NULL == fCurrMip->data()) { |
| - sk_throw(); |
| - } |
| - |
| - SkScalar levelScale = SkScalarInvert(invScale); |
| - SkMipMap::Level level; |
| - if (fCurrMip->extractLevel(levelScale, &level)) { |
| - SkScalar invScaleFixup = level.fScale; |
| - fInvMatrix.postScale(invScaleFixup, invScaleFixup); |
| - |
| - const SkImageInfo info = fOrigBitmap.info().makeWH(level.fWidth, level.fHeight); |
| - // todo: if we could wrap the fCurrMip in a pixelref, then we could just install |
| - // that here, and not need to explicitly track it ourselves. |
| - fScaledBitmap.installPixels(info, level.fPixels, level.fRowBytes); |
| - fBitmap = &fScaledBitmap; |
| - } else { |
| - // failed to extract, so release the mipmap |
| - fCurrMip.reset(NULL); |
| - } |
| - } |
| -} |
| - |
| -bool SkBitmapProcState::lockBaseBitmap() { |
| - // TODO(reed): use bitmap cache here? |
| - fScaledBitmap = fOrigBitmap; |
| - fScaledBitmap.lockPixels(); |
| - if (NULL == fScaledBitmap.getPixels()) { |
| - return false; |
| - } |
| - fBitmap = &fScaledBitmap; |
| - return true; |
| -} |
| - |
| -static bool valid_for_drawing(const SkBitmap& bm) { |
| - if (0 == bm.width() || 0 == bm.height()) { |
| - return false; // nothing to draw |
| - } |
| - if (NULL == bm.pixelRef()) { |
| - return false; // no pixels to read |
| - } |
| - if (bm.getTexture()) { |
| - // we can handle texture (ugh) since lockPixels will perform a read-back |
| - return true; |
| - } |
| - if (kIndex_8_SkColorType == bm.colorType()) { |
| - SkAutoLockPixels alp(bm); // but we need to call it before getColorTable() is safe. |
| - if (!bm.getColorTable()) { |
| - return false; |
| - } |
| - } |
| - return true; |
| -} |
| - |
| /* |
| * Analyze filter-quality and matrix, and decide how to implement that. |
| * |
| @@ -269,21 +136,16 @@ bool SkBitmapProcState::chooseProcs(const SkMatrix& inv, const SkPaint& paint) { |
| fInvMatrix = inv; |
| fFilterLevel = paint.getFilterQuality(); |
| - if (kHigh_SkFilterQuality == fFilterLevel) { |
| - this->processHQRequest(); |
| - } |
| - SkASSERT(fFilterLevel < kHigh_SkFilterQuality); |
| + SkDefaultBitmapController controller; |
| - if (kMedium_SkFilterQuality == fFilterLevel) { |
| - this->processMediumRequest(); |
| - } |
| - SkASSERT(fFilterLevel < kMedium_SkFilterQuality); |
| - |
| - if (NULL == fBitmap) { |
| - if (!this->lockBaseBitmap()) { |
| - return false; |
| - } |
| + SkFilterQuality outQuality; |
| + if (!controller.requestBitmap(fOrigBitmap, inv, paint.getFilterQuality(), |
| + &fScaledBitmap, &fInvMatrix, &outQuality)) { |
| + return false; |
| } |
| + fFilterLevel = outQuality; |
| + fBitmap = &fScaledBitmap; |
| + |
| SkASSERT(fBitmap); |
| bool trivialMatrix = (fInvMatrix.getType() & ~SkMatrix::kTranslate_Mask) == 0; |