aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar bsalomon <bsalomon@google.com>2015-02-06 11:54:28 -0800
committerGravatar Commit bot <commit-bot@chromium.org>2015-02-06 11:54:28 -0800
commit23e619cf462b2a8a500f3ca750e099f79601f508 (patch)
treeee448aaed72aa80f035a8b7b2ec285cd8aadfd2b
parentd0423587ac56ae84d3f1eb796d5c1e2dfba9646e (diff)
Reimplement gpu message bus for invalidated bitmap gen IDs
-rw-r--r--include/core/SkTArray.h27
-rw-r--r--include/gpu/GrGpuResource.h1
-rw-r--r--include/gpu/GrResourceKey.h15
-rw-r--r--include/gpu/SkGr.h5
-rw-r--r--src/core/SkMessageBus.h11
-rw-r--r--src/gpu/GrGpuResource.cpp7
-rw-r--r--src/gpu/GrGpuResourceCacheAccess.h2
-rw-r--r--src/gpu/GrLayerCache.cpp2
-rw-r--r--src/gpu/GrResourceCache2.cpp20
-rw-r--r--src/gpu/GrResourceCache2.h38
-rw-r--r--src/gpu/SkGr.cpp89
-rw-r--r--tests/MessageBusTest.cpp2
-rw-r--r--tests/ResourceCacheTest.cpp117
13 files changed, 210 insertions, 126 deletions
diff --git a/include/core/SkTArray.h b/include/core/SkTArray.h
index 9de21179f0..9d410c12ea 100644
--- a/include/core/SkTArray.h
+++ b/include/core/SkTArray.h
@@ -270,6 +270,23 @@ public:
}
}
+ /** Swaps the contents of this array with that array. Does a pointer swap if possible,
+ otherwise copies the T values. */
+ void swap(SkTArray* that) {
+ if (this->fPreAllocMemArray != this->fItemArray &&
+ that->fPreAllocMemArray != that->fItemArray) {
+ // If neither is using a preallocated array then just swap.
+ SkTSwap(fItemArray, that->fItemArray);
+ SkTSwap(fCount, that->fCount);
+ SkTSwap(fAllocCount, that->fAllocCount);
+ } else {
+ // This could be more optimal...
+ SkTArray copy(*that);
+ *that = *this;
+ *this = copy;
+ }
+ }
+
T* begin() {
return fItemArray;
}
@@ -375,7 +392,7 @@ protected:
}
void init(const T* array, int count,
- void* preAllocStorage, int preAllocOrReserveCount) {
+ void* preAllocStorage, int preAllocOrReserveCount) {
SkASSERT(count >= 0);
SkASSERT(preAllocOrReserveCount >= 0);
fCount = count;
@@ -452,10 +469,10 @@ private:
template<typename X> friend void SkTArrayExt::copy(SkTArray<X, false>* that, const X*);
template<typename X> friend void SkTArrayExt::copyAndDelete(SkTArray<X, false>* that, char*);
- int fReserveCount;
- int fCount;
- int fAllocCount;
- void* fPreAllocMemArray;
+ int fReserveCount;
+ int fCount;
+ int fAllocCount;
+ void* fPreAllocMemArray;
union {
T* fItemArray;
void* fMemArray;
diff --git a/include/gpu/GrGpuResource.h b/include/gpu/GrGpuResource.h
index 7896ab3e84..dcb4a47d2c 100644
--- a/include/gpu/GrGpuResource.h
+++ b/include/gpu/GrGpuResource.h
@@ -264,6 +264,7 @@ private:
// See comments in CacheAccess.
bool setContentKey(const GrContentKey& contentKey);
+ void removeContentKey();
void notifyIsPurgeable() const;
void removeScratchKey();
void makeBudgeted();
diff --git a/include/gpu/GrResourceKey.h b/include/gpu/GrResourceKey.h
index e09a2c710f..906bc6a4be 100644
--- a/include/gpu/GrResourceKey.h
+++ b/include/gpu/GrResourceKey.h
@@ -46,11 +46,13 @@ protected:
}
GrResourceKey& operator=(const GrResourceKey& that) {
+ SkASSERT(that.isValid());
if (this != &that) {
size_t bytes = that.size();
SkASSERT(SkIsAlign4(bytes));
fKey.reset(SkToInt(bytes / sizeof(uint32_t)));
memcpy(fKey.get(), that.fKey.get(), bytes);
+ this->validate();
}
return *this;
}
@@ -236,4 +238,17 @@ public:
};
};
+// The cache listens for these messages to purge junk resources proactively.
+class GrContentKeyInvalidatedMessage {
+public:
+ explicit GrContentKeyInvalidatedMessage(const GrContentKey& key) : fKey(key) {}
+ GrContentKeyInvalidatedMessage(const GrContentKeyInvalidatedMessage& that) : fKey(that.fKey) {}
+ GrContentKeyInvalidatedMessage& operator=(const GrContentKeyInvalidatedMessage& that) {
+ fKey = that.fKey;
+ return *this;
+ }
+ const GrContentKey& key() const { return fKey; }
+private:
+ GrContentKey fKey;
+};
#endif
diff --git a/include/gpu/SkGr.h b/include/gpu/SkGr.h
index 1dc1a0e142..84b0c1c356 100644
--- a/include/gpu/SkGr.h
+++ b/include/gpu/SkGr.h
@@ -68,11 +68,6 @@ static inline GrColor SkColor2GrColorJustAlpha(SkColor c) {
////////////////////////////////////////////////////////////////////////////////
-// The cache listens for these messages to purge junk resources proactively.
-struct GrResourceInvalidatedMessage {
- GrContentKey fKey;
-};
-
bool GrIsBitmapInCache(const GrContext*, const SkBitmap&, const GrTextureParams*);
GrTexture* GrRefCachedBitmapTexture(GrContext*, const SkBitmap&, const GrTextureParams*);
diff --git a/src/core/SkMessageBus.h b/src/core/SkMessageBus.h
index a005c3b9df..b25ab80798 100644
--- a/src/core/SkMessageBus.h
+++ b/src/core/SkMessageBus.h
@@ -9,6 +9,7 @@
#define SkMessageBus_DEFINED
#include "SkLazyPtr.h"
+#include "SkTArray.h"
#include "SkTDArray.h"
#include "SkThread.h"
#include "SkTypes.h"
@@ -25,10 +26,10 @@ public:
~Inbox();
// Overwrite out with all the messages we've received since the last call. Threadsafe.
- void poll(SkTDArray<Message>* out);
+ void poll(SkTArray<Message>* out);
private:
- SkTDArray<Message> fMessages;
+ SkTArray<Message> fMessages;
SkMutex fMessagesMutex;
friend class SkMessageBus;
@@ -82,15 +83,15 @@ SkMessageBus<Message>::Inbox::~Inbox() {
template<typename Message>
void SkMessageBus<Message>::Inbox::receive(const Message& m) {
SkAutoMutexAcquire lock(fMessagesMutex);
- fMessages.push(m);
+ fMessages.push_back(m);
}
template<typename Message>
-void SkMessageBus<Message>::Inbox::poll(SkTDArray<Message>* messages) {
+void SkMessageBus<Message>::Inbox::poll(SkTArray<Message>* messages) {
SkASSERT(messages);
messages->reset();
SkAutoMutexAcquire lock(fMessagesMutex);
- messages->swap(fMessages);
+ fMessages.swap(messages);
}
// ----------------------- Implementation of SkMessageBus -----------------------
diff --git a/src/gpu/GrGpuResource.cpp b/src/gpu/GrGpuResource.cpp
index 6d250e4820..7fb5559362 100644
--- a/src/gpu/GrGpuResource.cpp
+++ b/src/gpu/GrGpuResource.cpp
@@ -82,9 +82,16 @@ void GrGpuResource::didChangeGpuMemorySize() const {
get_resource_cache2(fGpu)->resourceAccess().didChangeGpuMemorySize(this, oldSize);
}
+void GrGpuResource::removeContentKey() {
+ SkASSERT(fContentKey.isValid());
+ get_resource_cache2(fGpu)->resourceAccess().willRemoveContentKey(this);
+ fContentKey.reset();
+}
+
bool GrGpuResource::setContentKey(const GrContentKey& key) {
// Currently this can only be called once and can't be called when the resource is scratch.
SkASSERT(this->internalHasRef());
+ SkASSERT(key.isValid());
// Wrapped and uncached resources can never have a content key.
if (!this->cacheAccess().isBudgeted()) {
diff --git a/src/gpu/GrGpuResourceCacheAccess.h b/src/gpu/GrGpuResourceCacheAccess.h
index 867252d783..6c99d08e46 100644
--- a/src/gpu/GrGpuResourceCacheAccess.h
+++ b/src/gpu/GrGpuResourceCacheAccess.h
@@ -28,6 +28,8 @@ public:
return fResource->setContentKey(contentKey);
}
+ void removeContentKey() { return fResource->removeContentKey(); }
+
/**
* Is the resource currently cached as scratch? This means it is cached, has a valid scratch
* key, and does not have a content key.
diff --git a/src/gpu/GrLayerCache.cpp b/src/gpu/GrLayerCache.cpp
index 8f6a69bcf5..1e09d0e92d 100644
--- a/src/gpu/GrLayerCache.cpp
+++ b/src/gpu/GrLayerCache.cpp
@@ -470,7 +470,7 @@ void GrLayerCache::purgeAll() {
#endif
void GrLayerCache::processDeletedPictures() {
- SkTDArray<SkPicture::DeletionMessage> deletedPictures;
+ SkTArray<SkPicture::DeletionMessage> deletedPictures;
fPictDeletionInbox.poll(&deletedPictures);
for (int i = 0; i < deletedPictures.count(); i++) {
diff --git a/src/gpu/GrResourceCache2.cpp b/src/gpu/GrResourceCache2.cpp
index 84a8d48cbc..c1656593b5 100644
--- a/src/gpu/GrResourceCache2.cpp
+++ b/src/gpu/GrResourceCache2.cpp
@@ -14,7 +14,7 @@
#include "SkGr.h"
#include "SkMessageBus.h"
-DECLARE_SKMESSAGEBUS_MESSAGE(GrResourceInvalidatedMessage);
+DECLARE_SKMESSAGEBUS_MESSAGE(GrContentKeyInvalidatedMessage);
//////////////////////////////////////////////////////////////////////////////
@@ -221,6 +221,13 @@ void GrResourceCache2::willRemoveScratchKey(const GrGpuResource* resource) {
fScratchMap.remove(resource->cacheAccess().getScratchKey(), resource);
}
+void GrResourceCache2::willRemoveContentKey(const GrGpuResource* resource) {
+ // Someone has a ref to this resource in order to invalidate it. When the ref count reaches
+ // zero we will get a notifyPurgable() and figure out what to do with it.
+ SkASSERT(resource->getContentKey().isValid());
+ fContentHash.remove(resource->getContentKey());
+}
+
bool GrResourceCache2::didSetContentKey(GrGpuResource* resource) {
SkASSERT(!fPurging);
SkASSERT(resource);
@@ -406,6 +413,17 @@ void GrResourceCache2::purgeAllUnlocked() {
this->validate();
}
+void GrResourceCache2::processInvalidContentKeys(
+ const SkTArray<GrContentKeyInvalidatedMessage>& msgs) {
+ for (int i = 0; i < msgs.count(); ++i) {
+ GrGpuResource* resource = this->findAndRefContentResource(msgs[i].key());
+ if (resource) {
+ resource->cacheAccess().removeContentKey();
+ resource->unref(); // will call notifyPurgeable, if it is indeed now purgeable.
+ }
+ }
+}
+
#ifdef SK_DEBUG
void GrResourceCache2::validate() const {
// Reduce the frequency of validations for large resource counts.
diff --git a/src/gpu/GrResourceCache2.h b/src/gpu/GrResourceCache2.h
index 4f21db979b..e844f11e6a 100644
--- a/src/gpu/GrResourceCache2.h
+++ b/src/gpu/GrResourceCache2.h
@@ -12,7 +12,9 @@
#include "GrGpuResource.h"
#include "GrGpuResourceCacheAccess.h"
#include "GrResourceKey.h"
+#include "SkMessageBus.h"
#include "SkRefCnt.h"
+#include "SkTArray.h"
#include "SkTInternalLList.h"
#include "SkTMultiMap.h"
@@ -128,6 +130,20 @@ public:
return SkToBool(fContentHash.find(contentKey));
}
+ /** Purges resources to become under budget and processes resources with invalidated content
+ keys. */
+ void purgeAsNeeded() {
+ SkTArray<GrContentKeyInvalidatedMessage> invalidKeyMsgs;
+ fInvalidContentKeyInbox.poll(&invalidKeyMsgs);
+ if (invalidKeyMsgs.count()) {
+ this->processInvalidContentKeys(invalidKeyMsgs);
+ }
+ if (fPurging || (fBudgetedCount <= fMaxCount && fBudgetedBytes <= fMaxBytes)) {
+ return;
+ }
+ this->internalPurgeAsNeeded();
+ }
+
/** Purges all resources that don't have external owners. */
void purgeAllUnlocked();
@@ -161,18 +177,13 @@ private:
void didChangeGpuMemorySize(const GrGpuResource*, size_t oldSize);
bool didSetContentKey(GrGpuResource*);
void willRemoveScratchKey(const GrGpuResource*);
+ void willRemoveContentKey(const GrGpuResource*);
void didChangeBudgetStatus(GrGpuResource*);
void makeResourceMRU(GrGpuResource*);
/// @}
- void purgeAsNeeded() {
- if (fPurging || (fBudgetedCount <= fMaxCount && fBudgetedBytes <= fMaxBytes)) {
- return;
- }
- this->internalPurgeAsNeeded();
- }
-
void internalPurgeAsNeeded();
+ void processInvalidContentKeys(const SkTArray<GrContentKeyInvalidatedMessage>&);
#ifdef SK_DEBUG
bool isInCache(const GrGpuResource* r) const { return fResources.isInList(r); }
@@ -205,6 +216,8 @@ private:
typedef SkTInternalLList<GrGpuResource> ResourceList;
+ typedef SkMessageBus<GrContentKeyInvalidatedMessage>::Inbox InvalidContentKeyInbox;
+
ResourceList fResources;
// This map holds all resources that can be used as scratch resources.
ScratchMap fScratchMap;
@@ -237,6 +250,8 @@ private:
PFOverBudgetCB fOverBudgetCB;
void* fOverBudgetData;
+ InvalidContentKeyInbox fInvalidContentKeyInbox;
+
};
class GrResourceCache2::ResourceAccess {
@@ -278,7 +293,14 @@ private:
bool didSetContentKey(GrGpuResource* resource) { return fCache->didSetContentKey(resource); }
/**
- * Called by GrGpuResources when the remove their scratch key.
+ * Called by a GrGpuResource when it removes its content key.
+ */
+ void willRemoveContentKey(GrGpuResource* resource) {
+ return fCache->willRemoveContentKey(resource);
+ }
+
+ /**
+ * Called by a GrGpuResource when it removes its scratch key.
*/
void willRemoveScratchKey(const GrGpuResource* resource) {
fCache->willRemoveScratchKey(resource);
diff --git a/src/gpu/SkGr.cpp b/src/gpu/SkGr.cpp
index 2209ea465a..9ee415ea14 100644
--- a/src/gpu/SkGr.cpp
+++ b/src/gpu/SkGr.cpp
@@ -106,22 +106,20 @@ static Stretch get_stretch_type(const GrContext* ctx, int width, int height,
return kNo_Stretch;
}
-static bool make_resize_key(const GrContentKey& origKey, Stretch stretch, GrContentKey* resizeKey) {
+static bool make_stretched_key(const GrContentKey& origKey, Stretch stretch,
+ GrContentKey* stretchedKey) {
if (origKey.isValid() && kNo_Stretch != stretch) {
static const GrContentKey::Domain kDomain = GrContentKey::GenerateDomain();
- GrContentKey::Builder builder(resizeKey, origKey, kDomain, 1);
+ GrContentKey::Builder builder(stretchedKey, origKey, kDomain, 1);
builder[0] = stretch;
builder.finish();
return true;
}
- SkASSERT(!resizeKey->isValid());
+ SkASSERT(!stretchedKey->isValid());
return false;
}
-static void generate_bitmap_keys(const SkBitmap& bitmap,
- Stretch stretch,
- GrContentKey* key,
- GrContentKey* resizedKey) {
+static void make_unstretched_key(const SkBitmap& bitmap, GrContentKey* key) {
// Our id includes the offset, width, and height so that bitmaps created by extractSubset()
// are unique.
uint32_t genID = bitmap.getGenerationID();
@@ -135,10 +133,15 @@ static void generate_bitmap_keys(const SkBitmap& bitmap,
builder[1] = origin.fX;
builder[2] = origin.fY;
builder[3] = width | (height << 16);
- builder.finish();
+}
+static void make_bitmap_keys(const SkBitmap& bitmap,
+ Stretch stretch,
+ GrContentKey* key,
+ GrContentKey* stretchedKey) {
+ make_unstretched_key(bitmap, key);
if (kNo_Stretch != stretch) {
- make_resize_key(*key, stretch, resizedKey);
+ make_stretched_key(*key, stretch, stretchedKey);
}
}
@@ -153,34 +156,30 @@ static void generate_bitmap_texture_desc(const SkBitmap& bitmap, GrSurfaceDesc*
namespace {
// When the SkPixelRef genID changes, invalidate a corresponding GrResource described by key.
-class GrResourceInvalidator : public SkPixelRef::GenIDChangeListener {
+class BitmapInvalidator : public SkPixelRef::GenIDChangeListener {
public:
- explicit GrResourceInvalidator(const GrContentKey& key) : fKey(key) {}
+ explicit BitmapInvalidator(const GrContentKey& key) : fMsg(key) {}
private:
- GrContentKey fKey;
+ GrContentKeyInvalidatedMessage fMsg;
void onChange() SK_OVERRIDE {
- const GrResourceInvalidatedMessage message = { fKey };
- SkMessageBus<GrResourceInvalidatedMessage>::Post(message);
+ SkMessageBus<GrContentKeyInvalidatedMessage>::Post(fMsg);
}
};
} // namespace
-#if 0 // TODO: plug this back up
-static void add_genID_listener(const GrContentKey& key, SkPixelRef* pixelRef) {
- SkASSERT(pixelRef);
- pixelRef->addGenIDChangeListener(SkNEW_ARGS(GrResourceInvalidator, (key)));
-}
-#endif
static GrTexture* create_texture_for_bmp(GrContext* ctx,
const GrContentKey& optionalKey,
GrSurfaceDesc desc,
+ SkPixelRef* pixelRefForInvalidationNotification,
const void* pixels,
size_t rowBytes) {
GrTexture* result = ctx->createTexture(desc, true, pixels, rowBytes);
if (result && optionalKey.isValid()) {
+ BitmapInvalidator* listener = SkNEW_ARGS(BitmapInvalidator, (optionalKey));
+ pixelRefForInvalidationNotification->addGenIDChangeListener(listener);
SkAssertResult(ctx->addResourceToCache(optionalKey, result));
}
return result;
@@ -189,8 +188,9 @@ static GrTexture* create_texture_for_bmp(GrContext* ctx,
// creates a new texture that is the input texture scaled up to the next power of two in
// width or height. If optionalKey is valid it will be set on the new texture. stretch
// controls whether the scaling is done using nearest or bilerp filtering.
-GrTexture* resize_texture(GrTexture* inputTexture, Stretch stretch,
- const GrContentKey& optionalKey) {
+GrTexture* stretch_texture_to_next_pot(GrTexture* inputTexture, Stretch stretch,
+ SkPixelRef* pixelRef,
+ const GrContentKey& optionalKey) {
SkASSERT(kNo_Stretch != stretch);
GrContext* context = inputTexture->getContext();
@@ -228,9 +228,9 @@ GrTexture* resize_texture(GrTexture* inputTexture, Stretch stretch,
}
}
- GrTexture* resized = create_texture_for_bmp(context, optionalKey, rtDesc, NULL, 0);
+ GrTexture* stretched = create_texture_for_bmp(context, optionalKey, rtDesc, pixelRef, NULL, 0);
- if (!resized) {
+ if (!stretched) {
return NULL;
}
GrPaint paint;
@@ -245,11 +245,11 @@ GrTexture* resize_texture(GrTexture* inputTexture, Stretch stretch,
SkRect rect = SkRect::MakeWH(SkIntToScalar(rtDesc.fWidth), SkIntToScalar(rtDesc.fHeight));
SkRect localRect = SkRect::MakeWH(1.f, 1.f);
- GrContext::AutoRenderTarget autoRT(context, resized->asRenderTarget());
+ GrContext::AutoRenderTarget autoRT(context, stretched->asRenderTarget());
GrContext::AutoClip ac(context, GrContext::AutoClip::kWideOpen_InitialClip);
context->drawNonAARectToRect(paint, SkMatrix::I(), rect, localRect);
- return resized;
+ return stretched;
}
#ifndef SK_IGNORE_ETC1_SUPPORT
@@ -298,7 +298,7 @@ static GrTexture *load_etc1_texture(GrContext* ctx, const GrContentKey& optional
return NULL;
}
- return create_texture_for_bmp(ctx, optionalKey, desc, bytes, 0);
+ return create_texture_for_bmp(ctx, optionalKey, desc, bm.pixelRef(), bytes, 0);
}
#endif // SK_IGNORE_ETC1_SUPPORT
@@ -381,7 +381,7 @@ static GrTexture* load_yuv_texture(GrContext* ctx, const GrContentKey& optionalK
kRenderTarget_GrSurfaceFlag |
kNoStencil_GrSurfaceFlag;
- GrTexture* result = create_texture_for_bmp(ctx, optionalKey, rtDesc, NULL, 0);
+ GrTexture* result = create_texture_for_bmp(ctx, optionalKey, rtDesc, pixelRef, NULL, 0);
if (!result) {
return NULL;
}
@@ -422,7 +422,8 @@ static GrTexture* create_unstretched_bitmap_texture(GrContext* ctx,
// our compressed data will be trimmed, so pass width() for its
// "rowBytes", since they are the same now.
- return create_texture_for_bmp(ctx, optionalKey, desc, storage.get(), bitmap->width());
+ return create_texture_for_bmp(ctx, optionalKey, desc, origBitmap.pixelRef(),
+ storage.get(), bitmap->width());
} else {
origBitmap.copyTo(&tmpBitmap, kN32_SkColorType);
// now bitmap points to our temp, which has been promoted to 32bits
@@ -458,7 +459,8 @@ static GrTexture* create_unstretched_bitmap_texture(GrContext* ctx,
return NULL;
}
- return create_texture_for_bmp(ctx, optionalKey, desc, bitmap->getPixels(), bitmap->rowBytes());
+ return create_texture_for_bmp(ctx, optionalKey, desc, origBitmap.pixelRef(),
+ bitmap->getPixels(), bitmap->rowBytes());
}
static GrTexture* create_bitmap_texture(GrContext* ctx,
@@ -478,8 +480,9 @@ static GrTexture* create_bitmap_texture(GrContext* ctx,
return NULL;
}
}
- GrTexture* resized = resize_texture(unstretched, stretch, stretchedKey);
- return resized;
+ GrTexture* stretched = stretch_texture_to_next_pot(unstretched, stretch, bmp.pixelRef(),
+ stretchedKey);
+ return stretched;
}
return create_unstretched_bitmap_texture(ctx, bmp, unstretchedKey);
@@ -505,9 +508,9 @@ bool GrIsBitmapInCache(const GrContext* ctx,
if (!key.isValid()) {
return false;
}
- GrContentKey resizedKey;
- make_resize_key(key, stretch, &resizedKey);
- return ctx->isResourceInCache(resizedKey);
+ GrContentKey stretchedKey;
+ make_stretched_key(key, stretch, &stretchedKey);
+ return ctx->isResourceInCache(stretchedKey);
}
// We don't cache volatile bitmaps
@@ -515,9 +518,9 @@ bool GrIsBitmapInCache(const GrContext* ctx,
return false;
}
- GrContentKey key, resizedKey;
- generate_bitmap_keys(bitmap, stretch, &key, &resizedKey);
- return ctx->isResourceInCache((kNo_Stretch == stretch) ? key : resizedKey);
+ GrContentKey key, stretchedKey;
+ make_bitmap_keys(bitmap, stretch, &key, &stretchedKey);
+ return ctx->isResourceInCache((kNo_Stretch == stretch) ? key : stretchedKey);
}
GrTexture* GrRefCachedBitmapTexture(GrContext* ctx,
@@ -531,26 +534,26 @@ GrTexture* GrRefCachedBitmapTexture(GrContext* ctx,
if (kNo_Stretch == stretch) {
return SkRef(result);
}
- GrContentKey resizedKey;
+ GrContentKey stretchedKey;
// Don't create a key for the resized version if the bmp is volatile.
if (!bitmap.isVolatile()) {
const GrContentKey& key = result->getContentKey();
if (key.isValid()) {
- make_resize_key(key, stretch, &resizedKey);
- GrTexture* stretched = ctx->findAndRefCachedTexture(resizedKey);
+ make_stretched_key(key, stretch, &stretchedKey);
+ GrTexture* stretched = ctx->findAndRefCachedTexture(stretchedKey);
if (stretched) {
return stretched;
}
}
}
- return resize_texture(result, stretch, resizedKey);
+ return stretch_texture_to_next_pot(result, stretch, bitmap.pixelRef(), stretchedKey);
}
GrContentKey key, resizedKey;
if (!bitmap.isVolatile()) {
// If the bitmap isn't changing try to find a cached copy first.
- generate_bitmap_keys(bitmap, stretch, &key, &resizedKey);
+ make_bitmap_keys(bitmap, stretch, &key, &resizedKey);
result = ctx->findAndRefCachedTexture(resizedKey.isValid() ? resizedKey : key);
if (result) {
diff --git a/tests/MessageBusTest.cpp b/tests/MessageBusTest.cpp
index f7a02b2254..163addf8f0 100644
--- a/tests/MessageBusTest.cpp
+++ b/tests/MessageBusTest.cpp
@@ -25,7 +25,7 @@ DEF_TEST(MessageBus, r) {
SkMessageBus<TestMessage>::Post(m2);
// Make sure we got two.
- SkTDArray<TestMessage> messages;
+ SkTArray<TestMessage> messages;
inbox1.poll(&messages);
REPORTER_ASSERT(r, 2 == messages.count());
REPORTER_ASSERT(r, 5 == messages[0].x);
diff --git a/tests/ResourceCacheTest.cpp b/tests/ResourceCacheTest.cpp
index 7b10716e68..7a3355f162 100644
--- a/tests/ResourceCacheTest.cpp
+++ b/tests/ResourceCacheTest.cpp
@@ -68,13 +68,13 @@ public:
SK_DECLARE_INST_COUNT(TestResource);
/** Property that distinctly categorizes the resource.
* For example, textures have width, height, ... */
- enum SimulatedProperty { kProperty1_SimulatedProperty, kProperty2_SimulatedProperty };
+ enum SimulatedProperty { kA_SimulatedProperty, kB_SimulatedProperty };
TestResource(GrGpu* gpu, size_t size, GrGpuResource::LifeCycle lifeCycle)
: INHERITED(gpu, lifeCycle)
, fToDelete(NULL)
, fSize(size)
- , fProperty(kProperty1_SimulatedProperty) {
+ , fProperty(kA_SimulatedProperty) {
++fNumAlive;
this->registerWithCache();
}
@@ -83,7 +83,7 @@ public:
: INHERITED(gpu, lifeCycle)
, fToDelete(NULL)
, fSize(kDefaultSize)
- , fProperty(kProperty1_SimulatedProperty) {
+ , fProperty(kA_SimulatedProperty) {
++fNumAlive;
this->registerWithCache();
}
@@ -92,14 +92,12 @@ public:
: INHERITED(gpu, kCached_LifeCycle)
, fToDelete(NULL)
, fSize(kDefaultSize)
- , fProperty(kProperty1_SimulatedProperty) {
+ , fProperty(kA_SimulatedProperty) {
++fNumAlive;
this->registerWithCache();
}
- static TestResource* CreateScratchTestResource(GrGpu* gpu,
- SimulatedProperty property,
- bool cached = true) {
+ static TestResource* CreateScratch(GrGpu* gpu, SimulatedProperty property, bool cached = true) {
return SkNEW_ARGS(TestResource, (gpu, property, cached, kScratchConstructor));
}
@@ -241,8 +239,7 @@ static void test_budgeting(skiatest::Reporter* reporter) {
// Create a scratch, a content, and a wrapped resource
TestResource* scratch =
- TestResource::CreateScratchTestResource(context->getGpu(),
- TestResource::kProperty2_SimulatedProperty);
+ TestResource::CreateScratch(context->getGpu(), TestResource::kB_SimulatedProperty);
scratch->setSize(10);
TestResource* content = SkNEW_ARGS(TestResource, (context->getGpu()));
content->setSize(11);
@@ -331,8 +328,7 @@ static void test_unbudgeted(skiatest::Reporter* reporter) {
TestResource* unbudgeted;
// A large uncached or wrapped resource shouldn't evict anything.
- scratch = TestResource::CreateScratchTestResource(context->getGpu(),
- TestResource::kProperty2_SimulatedProperty);
+ scratch = TestResource::CreateScratch(context->getGpu(), TestResource::kB_SimulatedProperty);
scratch->setSize(10);
scratch->unref();
REPORTER_ASSERT(reporter, 1 == cache2->getResourceCount());
@@ -389,10 +385,9 @@ static void test_unbudgeted_to_scratch(skiatest::Reporter* reporter) {
GrResourceCache2* cache2 = mock.cache();
TestResource* resource =
- TestResource::CreateScratchTestResource(context->getGpu(),
- TestResource::kProperty1_SimulatedProperty, false);
+ TestResource::CreateScratch(context->getGpu(), TestResource::kA_SimulatedProperty, false);
GrScratchKey key;
- TestResource::ComputeScratchKey(TestResource::kProperty1_SimulatedProperty, &key);
+ TestResource::ComputeScratchKey(TestResource::kA_SimulatedProperty, &key);
size_t size = resource->gpuMemorySize();
for (int i = 0; i < 2; ++i) {
@@ -449,21 +444,19 @@ static void test_duplicate_scratch_key(skiatest::Reporter* reporter) {
GrResourceCache2* cache2 = mock.cache();
// Create two resources that have the same scratch key.
- TestResource* a =
- TestResource::CreateScratchTestResource(context->getGpu(),
- TestResource::kProperty2_SimulatedProperty);
- TestResource* b =
- TestResource::CreateScratchTestResource(context->getGpu(),
- TestResource::kProperty2_SimulatedProperty);
+ TestResource* a = TestResource::CreateScratch(context->getGpu(),
+ TestResource::kB_SimulatedProperty);
+ TestResource* b = TestResource::CreateScratch(context->getGpu(),
+ TestResource::kB_SimulatedProperty);
a->setSize(11);
b->setSize(12);
GrScratchKey scratchKey1;
- TestResource::ComputeScratchKey(TestResource::kProperty1_SimulatedProperty, &scratchKey1);
+ TestResource::ComputeScratchKey(TestResource::kA_SimulatedProperty, &scratchKey1);
// Check for negative case consistency. (leaks upon test failure.)
REPORTER_ASSERT(reporter, NULL == cache2->findAndRefScratchResource(scratchKey1));
GrScratchKey scratchKey;
- TestResource::ComputeScratchKey(TestResource::kProperty2_SimulatedProperty, &scratchKey);
+ TestResource::ComputeScratchKey(TestResource::kB_SimulatedProperty, &scratchKey);
// Scratch resources are registered with GrResourceCache2 just by existing. There are 2.
REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
@@ -496,24 +489,22 @@ static void test_remove_scratch_key(skiatest::Reporter* reporter) {
GrResourceCache2* cache2 = mock.cache();
// Create two resources that have the same scratch key.
- TestResource* a =
- TestResource::CreateScratchTestResource(context->getGpu(),
- TestResource::kProperty2_SimulatedProperty);
- TestResource* b =
- TestResource::CreateScratchTestResource(context->getGpu(),
- TestResource::kProperty2_SimulatedProperty);
+ TestResource* a = TestResource::CreateScratch(context->getGpu(),
+ TestResource::kB_SimulatedProperty);
+ TestResource* b = TestResource::CreateScratch(context->getGpu(),
+ TestResource::kB_SimulatedProperty);
a->unref();
b->unref();
GrScratchKey scratchKey;
// Ensure that scratch key lookup is correct for negative case.
- TestResource::ComputeScratchKey(TestResource::kProperty1_SimulatedProperty, &scratchKey);
+ TestResource::ComputeScratchKey(TestResource::kA_SimulatedProperty, &scratchKey);
// (following leaks upon test failure).
REPORTER_ASSERT(reporter, cache2->findAndRefScratchResource(scratchKey) == NULL);
// Scratch resources are registered with GrResourceCache2 just by existing. There are 2.
- TestResource::ComputeScratchKey(TestResource::kProperty2_SimulatedProperty, &scratchKey);
+ TestResource::ComputeScratchKey(TestResource::kB_SimulatedProperty, &scratchKey);
REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
SkDEBUGCODE(REPORTER_ASSERT(reporter, 2 == cache2->countScratchEntriesForKey(scratchKey));)
REPORTER_ASSERT(reporter, 2 == cache2->getResourceCount());
@@ -558,21 +549,19 @@ static void test_scratch_key_consistency(skiatest::Reporter* reporter) {
GrResourceCache2* cache2 = mock.cache();
// Create two resources that have the same scratch key.
- TestResource* a =
- TestResource::CreateScratchTestResource(context->getGpu(),
- TestResource::kProperty2_SimulatedProperty);
- TestResource* b =
- TestResource::CreateScratchTestResource(context->getGpu(),
- TestResource::kProperty2_SimulatedProperty);
+ TestResource* a = TestResource::CreateScratch(context->getGpu(),
+ TestResource::kB_SimulatedProperty);
+ TestResource* b = TestResource::CreateScratch(context->getGpu(),
+ TestResource::kB_SimulatedProperty);
a->unref();
b->unref();
GrScratchKey scratchKey;
// Ensure that scratch key comparison and assignment is consistent.
GrScratchKey scratchKey1;
- TestResource::ComputeScratchKey(TestResource::kProperty1_SimulatedProperty, &scratchKey1);
+ TestResource::ComputeScratchKey(TestResource::kA_SimulatedProperty, &scratchKey1);
GrScratchKey scratchKey2;
- TestResource::ComputeScratchKey(TestResource::kProperty2_SimulatedProperty, &scratchKey2);
+ TestResource::ComputeScratchKey(TestResource::kB_SimulatedProperty, &scratchKey2);
REPORTER_ASSERT(reporter, scratchKey1.size() == TestResource::ExpectedScratchKeySize());
REPORTER_ASSERT(reporter, scratchKey1 != scratchKey2);
REPORTER_ASSERT(reporter, scratchKey2 != scratchKey1);
@@ -590,12 +579,12 @@ static void test_scratch_key_consistency(skiatest::Reporter* reporter) {
REPORTER_ASSERT(reporter, scratchKey == scratchKey2);
// Ensure that scratch key lookup is correct for negative case.
- TestResource::ComputeScratchKey(TestResource::kProperty1_SimulatedProperty, &scratchKey);
+ TestResource::ComputeScratchKey(TestResource::kA_SimulatedProperty, &scratchKey);
// (following leaks upon test failure).
REPORTER_ASSERT(reporter, cache2->findAndRefScratchResource(scratchKey) == NULL);
// Find the first resource with a scratch key and a copy of a scratch key.
- TestResource::ComputeScratchKey(TestResource::kProperty2_SimulatedProperty, &scratchKey);
+ TestResource::ComputeScratchKey(TestResource::kB_SimulatedProperty, &scratchKey);
GrGpuResource* find = cache2->findAndRefScratchResource(scratchKey);
REPORTER_ASSERT(reporter, find != NULL);
find->unref();
@@ -670,48 +659,62 @@ static void test_purge_invalidated(skiatest::Reporter* reporter) {
make_content_key<0>(&key2, 2);
make_content_key<0>(&key3, 3);
- // Add three resources to the cache.
+ // Add three resources to the cache. Only c is usable as scratch.
TestResource* a = SkNEW_ARGS(TestResource, (context->getGpu()));
TestResource* b = SkNEW_ARGS(TestResource, (context->getGpu()));
- TestResource* c = SkNEW_ARGS(TestResource, (context->getGpu()));
+ TestResource* c = TestResource::CreateScratch(context->getGpu(),
+ TestResource::kA_SimulatedProperty);
a->cacheAccess().setContentKey(key1);
b->cacheAccess().setContentKey(key2);
c->cacheAccess().setContentKey(key3);
a->unref();
- b->unref();
+ // hold b until *after* the message is sent.
c->unref();
REPORTER_ASSERT(reporter, cache2->hasContentKey(key1));
REPORTER_ASSERT(reporter, cache2->hasContentKey(key2));
REPORTER_ASSERT(reporter, cache2->hasContentKey(key3));
-
- // Invalidate two of the three, they should be purged and destroyed.
REPORTER_ASSERT(reporter, 3 == TestResource::NumAlive());
- const GrResourceInvalidatedMessage msg1 = { key1 };
- SkMessageBus<GrResourceInvalidatedMessage>::Post(msg1);
- const GrResourceInvalidatedMessage msg2 = { key2 };
- SkMessageBus<GrResourceInvalidatedMessage>::Post(msg2);
-#if 0 // Disabled until reimplemented in GrResourceCache2.
+
+ typedef GrContentKeyInvalidatedMessage Msg;
+ typedef SkMessageBus<GrContentKeyInvalidatedMessage> Bus;
+
+ // Invalidate two of the three, they should be purged and no longer accessible via their keys.
+ Bus::Post(Msg(key1));
+ Bus::Post(Msg(key2));
cache2->purgeAsNeeded();
- REPORTER_ASSERT(reporter, 1 == TestResource::NumAlive());
+ // a should be deleted now, but we still have a ref on b.
REPORTER_ASSERT(reporter, !cache2->hasContentKey(key1));
REPORTER_ASSERT(reporter, !cache2->hasContentKey(key2));
+ REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
REPORTER_ASSERT(reporter, cache2->hasContentKey(key3));
-#endif
// Invalidate the third.
- const GrResourceInvalidatedMessage msg3 = { key3 };
- SkMessageBus<GrResourceInvalidatedMessage>::Post(msg3);
-#if 0 // Disabled until reimplemented in GrResourceCache2.
+ Bus::Post(Msg(key3));
cache2->purgeAsNeeded();
- REPORTER_ASSERT(reporter, 0 == TestResource::NumAlive());
+ // we still have a ref on b, c should be recycled as scratch.
+ REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
REPORTER_ASSERT(reporter, !cache2->hasContentKey(key3));
-#endif
+ // make b purgeable. It should be immediately deleted since it has no key.
+ b->unref();
+ REPORTER_ASSERT(reporter, 1 == TestResource::NumAlive());
+
+ // Make sure we actually get to c via it's scratch key, before we say goodbye.
+ GrScratchKey scratchKey;
+ TestResource::ComputeScratchKey(TestResource::kA_SimulatedProperty, &scratchKey);
+ GrGpuResource* scratch = cache2->findAndRefScratchResource(scratchKey);
+ REPORTER_ASSERT(reporter, scratch == c);
+ SkSafeUnref(scratch);
+
+ // Get rid of c.
cache2->purgeAllUnlocked();
+ scratch = cache2->findAndRefScratchResource(scratchKey);
REPORTER_ASSERT(reporter, 0 == TestResource::NumAlive());
REPORTER_ASSERT(reporter, 0 == cache2->getResourceCount());
REPORTER_ASSERT(reporter, 0 == cache2->getResourceBytes());
+ REPORTER_ASSERT(reporter, !scratch);
+ SkSafeUnref(scratch);
}
static void test_cache_chained_purge(skiatest::Reporter* reporter) {