aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/SkBitmapController.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/SkBitmapController.cpp')
-rw-r--r--src/core/SkBitmapController.cpp144
1 files changed, 103 insertions, 41 deletions
diff --git a/src/core/SkBitmapController.cpp b/src/core/SkBitmapController.cpp
index 3c3e69413a..c75d2ea6bc 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) {