create SkBitmapProvider to abstract images and bitmaps
BUG=skia: Review URL: https://codereview.chromium.org/1340223003
This commit is contained in:
parent
5598b63cd2
commit
98ed7b6d01
@ -6,6 +6,7 @@
|
||||
*/
|
||||
|
||||
#include "SkBitmapCache.h"
|
||||
#include "SkImage.h"
|
||||
#include "SkResourceCache.h"
|
||||
#include "SkMipMap.h"
|
||||
#include "SkPixelRef.h"
|
||||
@ -43,6 +44,41 @@ static SkIRect get_bounds_from_bitmap(const SkBitmap& bm) {
|
||||
return SkIRect::MakeXYWH(origin.fX, origin.fY, bm.width(), bm.height());
|
||||
}
|
||||
|
||||
/**
|
||||
* This function finds the bounds of the image. Today this is just the entire bounds,
|
||||
* but in the future we may support subsets within an image, in which case this should
|
||||
* return that subset (see get_bounds_from_bitmap).
|
||||
*/
|
||||
static SkIRect get_bounds_from_image(const SkImage* image) {
|
||||
return SkIRect::MakeWH(image->width(), image->height());
|
||||
}
|
||||
|
||||
SkBitmapCacheDesc SkBitmapCacheDesc::Make(const SkBitmap& bm, int width, int height) {
|
||||
SkBitmapCacheDesc desc;
|
||||
desc.fImageID = bm.getGenerationID();
|
||||
desc.fWidth = width;
|
||||
desc.fHeight = height;
|
||||
desc.fBounds = get_bounds_from_bitmap(bm);
|
||||
return desc;
|
||||
}
|
||||
|
||||
SkBitmapCacheDesc SkBitmapCacheDesc::Make(const SkBitmap& bm) {
|
||||
return Make(bm, bm.width(), bm.height());
|
||||
}
|
||||
|
||||
SkBitmapCacheDesc SkBitmapCacheDesc::Make(const SkImage* image, int width, int height) {
|
||||
SkBitmapCacheDesc desc;
|
||||
desc.fImageID = image->uniqueID();
|
||||
desc.fWidth = width;
|
||||
desc.fHeight = height;
|
||||
desc.fBounds = get_bounds_from_image(image);
|
||||
return desc;
|
||||
}
|
||||
|
||||
SkBitmapCacheDesc SkBitmapCacheDesc::Make(const SkImage* image) {
|
||||
return Make(image, image->width(), image->height());
|
||||
}
|
||||
|
||||
namespace {
|
||||
static unsigned gBitmapKeyNamespaceLabel;
|
||||
|
||||
@ -54,7 +90,17 @@ public:
|
||||
, fHeight(height)
|
||||
, fBounds(bounds)
|
||||
{
|
||||
this->init(&gBitmapKeyNamespaceLabel, SkMakeResourceCacheSharedIDForBitmap(genID),
|
||||
this->init(&gBitmapKeyNamespaceLabel, SkMakeResourceCacheSharedIDForBitmap(fGenID),
|
||||
sizeof(fGenID) + sizeof(fWidth) + sizeof(fHeight) + sizeof(fBounds));
|
||||
}
|
||||
|
||||
BitmapKey(const SkBitmapCacheDesc& desc)
|
||||
: fGenID(desc.fImageID)
|
||||
, fWidth(desc.fWidth)
|
||||
, fHeight(desc.fHeight)
|
||||
, fBounds(desc.fBounds)
|
||||
{
|
||||
this->init(&gBitmapKeyNamespaceLabel, SkMakeResourceCacheSharedIDForBitmap(fGenID),
|
||||
sizeof(fGenID) + sizeof(fWidth) + sizeof(fHeight) + sizeof(fBounds));
|
||||
}
|
||||
|
||||
@ -80,6 +126,15 @@ struct BitmapRec : public SkResourceCache::Rec {
|
||||
#endif
|
||||
}
|
||||
|
||||
BitmapRec(const SkBitmapCacheDesc& desc, const SkBitmap& result)
|
||||
: fKey(desc)
|
||||
, fBitmap(result)
|
||||
{
|
||||
#ifdef TRACE_NEW_BITMAP_CACHE_RECS
|
||||
fKey.dump();
|
||||
#endif
|
||||
}
|
||||
|
||||
const Key& getKey() const override { return fKey; }
|
||||
size_t bytesUsed() const override { return sizeof(fKey) + fBitmap.getSize(); }
|
||||
|
||||
@ -106,28 +161,25 @@ private:
|
||||
#define CHECK_LOCAL(localCache, localName, globalName, ...) \
|
||||
((localCache) ? localCache->localName(__VA_ARGS__) : SkResourceCache::globalName(__VA_ARGS__))
|
||||
|
||||
bool SkBitmapCache::FindWH(const SkBitmap& src, int width, int height, SkBitmap* result,
|
||||
bool SkBitmapCache::FindWH(const SkBitmapCacheDesc& desc, SkBitmap* result,
|
||||
SkResourceCache* localCache) {
|
||||
if (0 == width || 0 == height) {
|
||||
if (0 == desc.fWidth || 0 == desc.fHeight) {
|
||||
// degenerate
|
||||
return false;
|
||||
}
|
||||
return CHECK_LOCAL(localCache, find, Find, BitmapKey(desc), BitmapRec::Finder, result);
|
||||
}
|
||||
|
||||
bool SkBitmapCache::AddWH(const SkBitmapCacheDesc& desc, const SkBitmap& result,
|
||||
SkResourceCache* localCache) {
|
||||
if (0 == desc.fWidth || 0 == desc.fHeight) {
|
||||
// degenerate, and the key we use for mipmaps
|
||||
return false;
|
||||
}
|
||||
BitmapKey key(src.getGenerationID(), width, height, get_bounds_from_bitmap(src));
|
||||
|
||||
return CHECK_LOCAL(localCache, find, Find, key, BitmapRec::Finder, result);
|
||||
}
|
||||
|
||||
void SkBitmapCache::AddWH(const SkBitmap& src, int width, int height,
|
||||
const SkBitmap& result, SkResourceCache* localCache) {
|
||||
if (0 == width || 0 == height) {
|
||||
// degenerate, and the key we use for mipmaps
|
||||
return;
|
||||
}
|
||||
SkASSERT(result.isImmutable());
|
||||
BitmapRec* rec = new BitmapRec(src.getGenerationID(), width, height,
|
||||
get_bounds_from_bitmap(src), result);
|
||||
BitmapRec* rec = new BitmapRec(desc, result);
|
||||
CHECK_LOCAL(localCache, add, Add, rec);
|
||||
src.pixelRef()->notifyAddedToCache();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SkBitmapCache::Find(uint32_t genID, const SkIRect& subset, SkBitmap* result,
|
||||
@ -226,8 +278,10 @@ private:
|
||||
};
|
||||
}
|
||||
|
||||
const SkMipMap* SkMipMapCache::FindAndRef(const SkBitmap& src, SkResourceCache* localCache) {
|
||||
MipMapKey key(src.getGenerationID(), get_bounds_from_bitmap(src));
|
||||
const SkMipMap* SkMipMapCache::FindAndRef(const SkBitmapCacheDesc& desc,
|
||||
SkResourceCache* localCache) {
|
||||
// Note: we ignore width/height from desc, just need id and bounds
|
||||
MipMapKey key(desc.fImageID, desc.fBounds);
|
||||
const SkMipMap* result;
|
||||
|
||||
if (!CHECK_LOCAL(localCache, find, Find, key, MipMapRec::Finder, &result)) {
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "SkScalar.h"
|
||||
#include "SkBitmap.h"
|
||||
|
||||
class SkImage;
|
||||
class SkResourceCache;
|
||||
class SkMipMap;
|
||||
|
||||
@ -18,6 +19,18 @@ uint64_t SkMakeResourceCacheSharedIDForBitmap(uint32_t bitmapGenID);
|
||||
|
||||
void SkNotifyBitmapGenIDIsStale(uint32_t bitmapGenID);
|
||||
|
||||
struct SkBitmapCacheDesc {
|
||||
uint32_t fImageID;
|
||||
int32_t fWidth;
|
||||
int32_t fHeight;
|
||||
SkIRect fBounds;
|
||||
|
||||
static SkBitmapCacheDesc Make(const SkBitmap&, int width, int height);
|
||||
static SkBitmapCacheDesc Make(const SkBitmap&);
|
||||
static SkBitmapCacheDesc Make(const SkImage*, int width, int height);
|
||||
static SkBitmapCacheDesc Make(const SkImage*);
|
||||
};
|
||||
|
||||
class SkBitmapCache {
|
||||
public:
|
||||
/**
|
||||
@ -27,16 +40,16 @@ public:
|
||||
static SkBitmap::Allocator* GetAllocator();
|
||||
|
||||
/**
|
||||
* Search based on the src bitmap and scaled width/height. If found, returns true and
|
||||
* Search based on the desc. If found, returns true and
|
||||
* result will be set to the matching bitmap with its pixels already locked.
|
||||
*/
|
||||
static bool FindWH(const SkBitmap& src, int width, int height, SkBitmap* result,
|
||||
static bool FindWH(const SkBitmapCacheDesc&, SkBitmap* result,
|
||||
SkResourceCache* localCache = nullptr);
|
||||
|
||||
/*
|
||||
* result must be marked isImmutable()
|
||||
*/
|
||||
static void AddWH(const SkBitmap& src, int width, int height, const SkBitmap& result,
|
||||
static bool AddWH(const SkBitmapCacheDesc&, const SkBitmap& result,
|
||||
SkResourceCache* localCache = nullptr);
|
||||
|
||||
/**
|
||||
@ -60,7 +73,8 @@ public:
|
||||
|
||||
class SkMipMapCache {
|
||||
public:
|
||||
static const SkMipMap* FindAndRef(const SkBitmap& src, SkResourceCache* localCache = nullptr);
|
||||
static const SkMipMap* FindAndRef(const SkBitmapCacheDesc&,
|
||||
SkResourceCache* localCache = nullptr);
|
||||
static const SkMipMap* AddAndRef(const SkBitmap& src, SkResourceCache* localCache = nullptr);
|
||||
};
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -9,9 +9,36 @@
|
||||
#define SkBitmapController_DEFINED
|
||||
|
||||
#include "SkBitmap.h"
|
||||
#include "SkBitmapCache.h"
|
||||
#include "SkFilterQuality.h"
|
||||
#include "SkImage.h"
|
||||
#include "SkMatrix.h"
|
||||
|
||||
class SkBitmapProvider {
|
||||
public:
|
||||
SkBitmapProvider(const SkBitmap& bm) : fBitmap(bm) {}
|
||||
SkBitmapProvider(const SkImage* img) : fImage(SkRef(img)) {}
|
||||
|
||||
int width() const;
|
||||
int height() const;
|
||||
uint32_t getID() const;
|
||||
|
||||
bool validForDrawing() const;
|
||||
SkImageInfo info() const;
|
||||
|
||||
SkBitmapCacheDesc makeCacheDesc(int w, int h) const;
|
||||
SkBitmapCacheDesc makeCacheDesc() const;
|
||||
void notifyAddedToCache() const;
|
||||
|
||||
// Only call this if you're sure you need the bits, since it make be expensive
|
||||
// ... cause a decode and cache, or gpu-readback
|
||||
bool asBitmap(SkBitmap*) const;
|
||||
|
||||
private:
|
||||
SkBitmap fBitmap;
|
||||
SkAutoTUnref<const SkImage> fImage;
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles request to scale, filter, and lock a bitmap to be rasterized.
|
||||
*/
|
||||
@ -36,15 +63,15 @@ public:
|
||||
|
||||
virtual ~SkBitmapController() {}
|
||||
|
||||
State* requestBitmap(const SkBitmap&, const SkMatrix& inverse, SkFilterQuality,
|
||||
State* requestBitmap(const SkBitmapProvider&, const SkMatrix& inverse, SkFilterQuality,
|
||||
void* storage, size_t storageSize);
|
||||
|
||||
State* requestBitmap(const SkBitmap& bm, const SkMatrix& inverse, SkFilterQuality quality) {
|
||||
return this->requestBitmap(bm, inverse, quality, nullptr, 0);
|
||||
State* requestBitmap(const SkBitmapProvider& bp, const SkMatrix& inv, SkFilterQuality quality) {
|
||||
return this->requestBitmap(bp, inv, quality, nullptr, 0);
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual State* onRequestBitmap(const SkBitmap&, const SkMatrix& inverse, SkFilterQuality,
|
||||
virtual State* onRequestBitmap(const SkBitmapProvider&, const SkMatrix& inv, SkFilterQuality,
|
||||
void* storage, size_t storageSize) = 0;
|
||||
};
|
||||
|
||||
@ -55,7 +82,7 @@ public:
|
||||
SkDefaultBitmapController() {}
|
||||
|
||||
protected:
|
||||
State* onRequestBitmap(const SkBitmap&, const SkMatrix& inverse, SkFilterQuality,
|
||||
State* onRequestBitmap(const SkBitmapProvider&, const SkMatrix& inverse, SkFilterQuality,
|
||||
void* storage, size_t storageSize) override;
|
||||
};
|
||||
|
||||
|
@ -23,7 +23,7 @@ static bool is_in_scaled_image_cache(const SkBitmap& orig,
|
||||
SkBitmap scaled;
|
||||
int width = SkScalarRoundToInt(orig.width() * xScale);
|
||||
int height = SkScalarRoundToInt(orig.height() * yScale);
|
||||
return SkBitmapCache::FindWH(orig, width, height, &scaled);
|
||||
return SkBitmapCache::FindWH(SkBitmapCacheDesc::Make(orig, width, height), &scaled);
|
||||
}
|
||||
|
||||
// Draw a scaled bitmap, then return true if it has been cached.
|
||||
@ -153,14 +153,14 @@ static void test_mipmapcache(skiatest::Reporter* reporter, SkResourceCache* cach
|
||||
src.allocN32Pixels(5, 5);
|
||||
src.setImmutable();
|
||||
|
||||
const SkMipMap* mipmap = SkMipMapCache::FindAndRef(src, cache);
|
||||
const SkMipMap* mipmap = SkMipMapCache::FindAndRef(SkBitmapCacheDesc::Make(src), cache);
|
||||
REPORTER_ASSERT(reporter, nullptr == mipmap);
|
||||
|
||||
mipmap = SkMipMapCache::AddAndRef(src, cache);
|
||||
REPORTER_ASSERT(reporter, mipmap);
|
||||
|
||||
{
|
||||
const SkMipMap* mm = SkMipMapCache::FindAndRef(src, cache);
|
||||
const SkMipMap* mm = SkMipMapCache::FindAndRef(SkBitmapCacheDesc::Make(src), cache);
|
||||
REPORTER_ASSERT(reporter, mm);
|
||||
REPORTER_ASSERT(reporter, mm == mipmap);
|
||||
mm->unref();
|
||||
@ -174,7 +174,7 @@ static void test_mipmapcache(skiatest::Reporter* reporter, SkResourceCache* cach
|
||||
check_data(reporter, mipmap, 1, kInCache, kNotLocked);
|
||||
|
||||
// find us again
|
||||
mipmap = SkMipMapCache::FindAndRef(src, cache);
|
||||
mipmap = SkMipMapCache::FindAndRef(SkBitmapCacheDesc::Make(src), cache);
|
||||
check_data(reporter, mipmap, 2, kInCache, kLocked);
|
||||
|
||||
cache->purgeAll();
|
||||
@ -193,7 +193,7 @@ static void test_mipmap_notify(skiatest::Reporter* reporter, SkResourceCache* ca
|
||||
}
|
||||
|
||||
for (int i = 0; i < N; ++i) {
|
||||
const SkMipMap* mipmap = SkMipMapCache::FindAndRef(src[i], cache);
|
||||
const SkMipMap* mipmap = SkMipMapCache::FindAndRef(SkBitmapCacheDesc::Make(src[i]), cache);
|
||||
if (cache) {
|
||||
// if cache is null, we're working on the global cache, and other threads might purge
|
||||
// it, making this check fragile.
|
||||
@ -203,7 +203,7 @@ static void test_mipmap_notify(skiatest::Reporter* reporter, SkResourceCache* ca
|
||||
|
||||
src[i].reset(); // delete the underlying pixelref, which *should* remove us from the cache
|
||||
|
||||
mipmap = SkMipMapCache::FindAndRef(src[i], cache);
|
||||
mipmap = SkMipMapCache::FindAndRef(SkBitmapCacheDesc::Make(src[i]), cache);
|
||||
REPORTER_ASSERT(reporter, !mipmap);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user