Index: src/core/SkBitmapController.cpp |
diff --git a/src/core/SkBitmapController.cpp b/src/core/SkBitmapController.cpp |
index 3c3e69413ab2e12f3dbbc66ca28fd56aa996a446..c75d2ea6bc825c497862c7193b7d74815b105669 100644 |
--- a/src/core/SkBitmapController.cpp |
+++ b/src/core/SkBitmapController.cpp |
@@ -7,7 +7,9 @@ |
#include "SkBitmap.h" |
#include "SkBitmapController.h" |
+#include "SkImage_Base.h" |
#include "SkMatrix.h" |
+#include "SkPixelRef.h" |
#include "SkTemplates.h" |
// RESIZE_LANCZOS3 is another good option, but chrome prefers mitchell at the moment |
@@ -15,36 +17,85 @@ |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
-static bool valid_for_drawing(const SkBitmap& bm) { |
- if (0 == bm.width() || 0 == bm.height()) { |
- return false; // nothing to draw |
- } |
- if (nullptr == 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()) { |
+int SkBitmapProvider::width() const { |
+ return fImage ? fImage->width() : fBitmap.width(); |
+} |
+ |
+int SkBitmapProvider::height() const { |
+ return fImage ? fImage->height() : fBitmap.height(); |
+} |
+ |
+uint32_t SkBitmapProvider::getID() const { |
+ return fImage ? fImage->uniqueID() : fBitmap.getGenerationID(); |
+} |
+ |
+bool SkBitmapProvider::validForDrawing() const { |
+ if (!fImage) { |
+ if (0 == fBitmap.width() || 0 == fBitmap.height()) { |
return false; |
} |
+ if (nullptr == fBitmap.pixelRef()) { |
+ return false; // no pixels to read |
+ } |
+ if (fBitmap.getTexture()) { |
+ // we can handle texture (ugh) since lockPixels will perform a read-back |
+ return true; |
+ } |
+ if (kIndex_8_SkColorType == fBitmap.colorType()) { |
+ SkAutoLockPixels alp(fBitmap); // but we need to call it before getColorTable() is safe. |
+ if (!fBitmap.getColorTable()) { |
+ return false; |
+ } |
+ } |
} |
return true; |
} |
-SkBitmapController::State* SkBitmapController::requestBitmap(const SkBitmap& bm, |
+SkImageInfo SkBitmapProvider::info() const { |
+ if (fImage) { |
+ SkAlphaType at = fImage->isOpaque() ? kOpaque_SkAlphaType : kPremul_SkAlphaType; |
+ return SkImageInfo::MakeN32(fImage->width(), fImage->height(), at); |
+ } else { |
+ return fBitmap.info(); |
+ } |
+} |
+ |
+SkBitmapCacheDesc SkBitmapProvider::makeCacheDesc(int w, int h) const { |
+ return fImage ? SkBitmapCacheDesc::Make(fImage, w, h) : SkBitmapCacheDesc::Make(fBitmap, w, h); |
+} |
+ |
+SkBitmapCacheDesc SkBitmapProvider::makeCacheDesc() const { |
+ return fImage ? SkBitmapCacheDesc::Make(fImage) : SkBitmapCacheDesc::Make(fBitmap); |
+} |
+ |
+void SkBitmapProvider::notifyAddedToCache() const { |
+ if (fImage) { |
+ // TODO |
+ } else { |
+ fBitmap.pixelRef()->notifyAddedToCache(); |
+ } |
+} |
+ |
+bool SkBitmapProvider::asBitmap(SkBitmap* bm) const { |
+ if (fImage) { |
+ return as_IB(fImage)->getROPixels(bm); |
+ } else { |
+ *bm = fBitmap; |
+ return true; |
+ } |
+} |
+ |
+/////////////////////////////////////////////////////////////////////////////////////////////////// |
+ |
+SkBitmapController::State* SkBitmapController::requestBitmap(const SkBitmapProvider& provider, |
const SkMatrix& inv, |
SkFilterQuality quality, |
void* storage, size_t storageSize) { |
- |
- if (!valid_for_drawing(bm)) { |
+ if (!provider.validForDrawing()) { |
return nullptr; |
} |
- State* state = this->onRequestBitmap(bm, inv, quality, storage, storageSize); |
+ State* state = this->onRequestBitmap(provider, inv, quality, storage, storageSize); |
if (state) { |
if (nullptr == state->fPixmap.addr()) { |
SkInPlaceDeleteCheck(state, storage); |
@@ -63,19 +114,19 @@ SkBitmapController::State* SkBitmapController::requestBitmap(const SkBitmap& bm, |
class SkDefaultBitmapControllerState : public SkBitmapController::State { |
public: |
- SkDefaultBitmapControllerState(const SkBitmap& src, const SkMatrix& inv, SkFilterQuality qual); |
+ SkDefaultBitmapControllerState(const SkBitmapProvider&, const SkMatrix& inv, SkFilterQuality); |
private: |
SkBitmap fResultBitmap; |
SkAutoTUnref<const SkMipMap> fCurrMip; |
- bool processHQRequest(const SkBitmap& orig); |
- bool processMediumRequest(const SkBitmap& orig); |
+ bool processHQRequest(const SkBitmapProvider&); |
+ bool processMediumRequest(const SkBitmapProvider&); |
}; |
// 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) { |
+static inline bool cache_size_okay(const SkBitmapProvider& provider, const SkMatrix& invMat) { |
size_t maximumAllocation = SkResourceCache::GetEffectiveSingleAllocationByteLimit(); |
if (0 == maximumAllocation) { |
return true; |
@@ -83,7 +134,7 @@ static inline bool cache_size_okay(const SkBitmap& bm, const SkMatrix& invMat) { |
// float matrixScaleFactor = 1.0 / (invMat.scaleX * invMat.scaleY); |
// return ((origBitmapSize * matrixScaleFactor) < maximumAllocationSize); |
// Skip the division step: |
- const size_t size = bm.info().getSafeSize(bm.info().minRowBytes()); |
+ const size_t size = provider.info().getSafeSize(provider.info().minRowBytes()); |
return size < (maximumAllocation * invMat.getScaleX() * invMat.getScaleY()); |
} |
@@ -91,7 +142,7 @@ static inline bool cache_size_okay(const SkBitmap& bm, const SkMatrix& invMat) { |
* High quality is implemented by performing up-right scale-only filtering and then |
* using bilerp for any remaining transformations. |
*/ |
-bool SkDefaultBitmapControllerState::processHQRequest(const SkBitmap& origBitmap) { |
+bool SkDefaultBitmapControllerState::processHQRequest(const SkBitmapProvider& provider) { |
if (fQuality != kHigh_SkFilterQuality) { |
return false; |
} |
@@ -100,7 +151,7 @@ bool SkDefaultBitmapControllerState::processHQRequest(const SkBitmap& origBitmap |
// to a valid bitmap. If we succeed, we will set this to Low instead. |
fQuality = kMedium_SkFilterQuality; |
- if (kN32_SkColorType != origBitmap.colorType() || !cache_size_okay(origBitmap, fInvMatrix) || |
+ if (kN32_SkColorType != provider.info().colorType() || !cache_size_okay(provider, fInvMatrix) || |
fInvMatrix.hasPerspective()) |
{ |
return false; // can't handle the reqeust |
@@ -120,12 +171,17 @@ bool SkDefaultBitmapControllerState::processHQRequest(const SkBitmap& origBitmap |
return false; // no need for HQ |
} |
- const int dstW = SkScalarRoundToScalar(origBitmap.width() / invScaleX); |
- const int dstH = SkScalarRoundToScalar(origBitmap.height() / invScaleY); |
- |
- if (!SkBitmapCache::FindWH(origBitmap, dstW, dstH, &fResultBitmap)) { |
+ const int dstW = SkScalarRoundToScalar(provider.width() / invScaleX); |
+ const int dstH = SkScalarRoundToScalar(provider.height() / invScaleY); |
+ const SkBitmapCacheDesc desc = provider.makeCacheDesc(dstW, dstH); |
+ |
+ if (!SkBitmapCache::FindWH(desc, &fResultBitmap)) { |
+ SkBitmap orig; |
+ if (!provider.asBitmap(&orig)) { |
+ return false; |
+ } |
SkAutoPixmapUnlock src; |
- if (!origBitmap.requestLock(&src)) { |
+ if (!orig.requestLock(&src)) { |
return false; |
} |
if (!SkBitmapScaler::Resize(&fResultBitmap, src.pixmap(), kHQ_RESIZE_METHOD, |
@@ -135,13 +191,15 @@ bool SkDefaultBitmapControllerState::processHQRequest(const SkBitmap& origBitmap |
SkASSERT(fResultBitmap.getPixels()); |
fResultBitmap.setImmutable(); |
- SkBitmapCache::AddWH(origBitmap, dstW, dstH, fResultBitmap); |
+ if (SkBitmapCache::AddWH(desc, fResultBitmap)) { |
+ provider.notifyAddedToCache(); |
+ } |
} |
SkASSERT(fResultBitmap.getPixels()); |
- fInvMatrix.postScale(SkIntToScalar(dstW) / origBitmap.width(), |
- SkIntToScalar(dstH) / origBitmap.height()); |
+ fInvMatrix.postScale(SkIntToScalar(dstW) / provider.width(), |
+ SkIntToScalar(dstH) / provider.height()); |
fQuality = kLow_SkFilterQuality; |
return true; |
} |
@@ -150,7 +208,7 @@ bool SkDefaultBitmapControllerState::processHQRequest(const SkBitmap& origBitmap |
* 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) |
*/ |
-bool SkDefaultBitmapControllerState::processMediumRequest(const SkBitmap& origBitmap) { |
+bool SkDefaultBitmapControllerState::processMediumRequest(const SkBitmapProvider& provider) { |
SkASSERT(fQuality <= kMedium_SkFilterQuality); |
if (fQuality != kMedium_SkFilterQuality) { |
return false; |
@@ -167,9 +225,13 @@ bool SkDefaultBitmapControllerState::processMediumRequest(const SkBitmap& origBi |
SkScalar invScale = SkScalarSqrt(invScaleSize.width() * invScaleSize.height()); |
if (invScale > SK_Scalar1) { |
- fCurrMip.reset(SkMipMapCache::FindAndRef(origBitmap)); |
+ fCurrMip.reset(SkMipMapCache::FindAndRef(provider.makeCacheDesc())); |
if (nullptr == fCurrMip.get()) { |
- fCurrMip.reset(SkMipMapCache::AddAndRef(origBitmap)); |
+ SkBitmap orig; |
+ if (!provider.asBitmap(&orig)) { |
+ return false; |
+ } |
+ fCurrMip.reset(SkMipMapCache::AddAndRef(orig)); |
if (nullptr == fCurrMip.get()) { |
return false; |
} |
@@ -185,7 +247,7 @@ bool SkDefaultBitmapControllerState::processMediumRequest(const SkBitmap& origBi |
SkScalar invScaleFixup = level.fScale; |
fInvMatrix.postScale(invScaleFixup, invScaleFixup); |
- const SkImageInfo info = origBitmap.info().makeWH(level.fWidth, level.fHeight); |
+ const SkImageInfo info = provider.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. |
return fResultBitmap.installPixels(info, level.fPixels, level.fRowBytes); |
@@ -197,16 +259,16 @@ bool SkDefaultBitmapControllerState::processMediumRequest(const SkBitmap& origBi |
return false; |
} |
-SkDefaultBitmapControllerState::SkDefaultBitmapControllerState(const SkBitmap& src, |
+SkDefaultBitmapControllerState::SkDefaultBitmapControllerState(const SkBitmapProvider& provider, |
const SkMatrix& inv, |
SkFilterQuality qual) { |
fInvMatrix = inv; |
fQuality = qual; |
- if (this->processHQRequest(src) || this->processMediumRequest(src)) { |
+ if (this->processHQRequest(provider) || this->processMediumRequest(provider)) { |
SkASSERT(fResultBitmap.getPixels()); |
} else { |
- fResultBitmap = src; |
+ (void)provider.asBitmap(&fResultBitmap); |
fResultBitmap.lockPixels(); |
// lock may fail to give us pixels |
} |
@@ -218,7 +280,7 @@ SkDefaultBitmapControllerState::SkDefaultBitmapControllerState(const SkBitmap& s |
fResultBitmap.getColorTable()); |
} |
-SkBitmapController::State* SkDefaultBitmapController::onRequestBitmap(const SkBitmap& bm, |
+SkBitmapController::State* SkDefaultBitmapController::onRequestBitmap(const SkBitmapProvider& bm, |
const SkMatrix& inverse, |
SkFilterQuality quality, |
void* storage, size_t size) { |