diff options
author | bsalomon <bsalomon@google.com> | 2015-02-06 11:54:28 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-02-06 11:54:28 -0800 |
commit | 23e619cf462b2a8a500f3ca750e099f79601f508 (patch) | |
tree | ee448aaed72aa80f035a8b7b2ec285cd8aadfd2b | |
parent | d0423587ac56ae84d3f1eb796d5c1e2dfba9646e (diff) |
Reimplement gpu message bus for invalidated bitmap gen IDs
Review URL: https://codereview.chromium.org/902873002
-rw-r--r-- | include/core/SkTArray.h | 27 | ||||
-rw-r--r-- | include/gpu/GrGpuResource.h | 1 | ||||
-rw-r--r-- | include/gpu/GrResourceKey.h | 15 | ||||
-rw-r--r-- | include/gpu/SkGr.h | 5 | ||||
-rw-r--r-- | src/core/SkMessageBus.h | 11 | ||||
-rw-r--r-- | src/gpu/GrGpuResource.cpp | 7 | ||||
-rw-r--r-- | src/gpu/GrGpuResourceCacheAccess.h | 2 | ||||
-rw-r--r-- | src/gpu/GrLayerCache.cpp | 2 | ||||
-rw-r--r-- | src/gpu/GrResourceCache2.cpp | 20 | ||||
-rw-r--r-- | src/gpu/GrResourceCache2.h | 38 | ||||
-rw-r--r-- | src/gpu/SkGr.cpp | 89 | ||||
-rw-r--r-- | tests/MessageBusTest.cpp | 2 | ||||
-rw-r--r-- | tests/ResourceCacheTest.cpp | 117 |
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) { |