| Index: src/core/SkBitmapProcState.cpp
|
| diff --git a/src/core/SkBitmapProcState.cpp b/src/core/SkBitmapProcState.cpp
|
| index 0b50fbc32dc8f4d160a78bc54e4b46de300ff14b..314fdd74c6b1b2d6df83b8ef9fbb537cbefef700 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"
|
| @@ -36,6 +37,12 @@ extern void Clamp_S32_opaque_D32_nofilter_DX_shaderproc(const SkBitmapProcState&
|
| #include "SkBitmapProcState_filter.h"
|
| #include "SkBitmapProcState_procs.h"
|
|
|
| +SkBitmapProcState::SkBitmapProcState() : fBMState(NULL) {}
|
| +
|
| +SkBitmapProcState::~SkBitmapProcState() {
|
| + SkInPlaceDeleteCheck(fBMState, fBMStateStorage.get());
|
| +}
|
| +
|
| ///////////////////////////////////////////////////////////////////////////////
|
|
|
| // true iff the matrix contains, at most, scale and translate elements
|
| @@ -90,166 +97,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.
|
| *
|
| @@ -261,31 +114,21 @@ static bool valid_for_drawing(const SkBitmap& bm) {
|
| * and may be removed.
|
| */
|
| bool SkBitmapProcState::chooseProcs(const SkMatrix& inv, const SkPaint& paint) {
|
| - if (!valid_for_drawing(fOrigBitmap)) {
|
| - return false;
|
| - }
|
| -
|
| fBitmap = NULL;
|
| fInvMatrix = inv;
|
| fFilterLevel = paint.getFilterQuality();
|
|
|
| - if (kHigh_SkFilterQuality == fFilterLevel) {
|
| - this->processHQRequest();
|
| - }
|
| - SkASSERT(fFilterLevel < kHigh_SkFilterQuality);
|
| -
|
| - if (kMedium_SkFilterQuality == fFilterLevel) {
|
| - this->processMediumRequest();
|
| - }
|
| - SkASSERT(fFilterLevel < kMedium_SkFilterQuality);
|
| -
|
| - if (NULL == fBitmap) {
|
| - if (!this->lockBaseBitmap()) {
|
| - return false;
|
| - }
|
| + SkDefaultBitmapController controller;
|
| + fBMState = controller.requestBitmap(fOrigBitmap, inv, paint.getFilterQuality(),
|
| + fBMStateStorage.get(), fBMStateStorage.size());
|
| + if (NULL == fBMState) {
|
| + return false;
|
| }
|
| - SkASSERT(fBitmap);
|
| -
|
| + fBitmap = &fBMState->lockedBitmap();
|
| + fInvMatrix = fBMState->invMatrix();
|
| + fFilterLevel = fBMState->quality();
|
| + SkASSERT(fBitmap->getPixels());
|
| +
|
| bool trivialMatrix = (fInvMatrix.getType() & ~SkMatrix::kTranslate_Mask) == 0;
|
| bool clampClamp = SkShader::kClamp_TileMode == fTileModeX &&
|
| SkShader::kClamp_TileMode == fTileModeY;
|
|
|