diff options
Diffstat (limited to 'src/gpu/GrLayerCache.h')
-rw-r--r-- | src/gpu/GrLayerCache.h | 432 |
1 files changed, 0 insertions, 432 deletions
diff --git a/src/gpu/GrLayerCache.h b/src/gpu/GrLayerCache.h deleted file mode 100644 index 2fa927197b..0000000000 --- a/src/gpu/GrLayerCache.h +++ /dev/null @@ -1,432 +0,0 @@ -/* - * Copyright 2014 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#ifndef GrLayerCache_DEFINED -#define GrLayerCache_DEFINED - - -#include "GrLayerAtlas.h" -#include "GrTexture.h" -#include "GrRect.h" - -#include "SkChecksum.h" -#include "SkImageFilter.h" -#include "SkMessageBus.h" -#include "SkPaint.h" -#include "SkPicture.h" -#include "SkTDynamicHash.h" - -// Set to 0 to disable caching of hoisted layers -#define GR_CACHE_HOISTED_LAYERS 0 - -// GrPictureInfo stores the atlas plots used by a single picture. A single -// plot may be used to store layers from multiple pictures. -struct GrPictureInfo { -public: - static const int kNumPlots = 4; - - // for SkTDynamicHash - just use the pictureID as the hash key - static const uint32_t& GetKey(const GrPictureInfo& pictInfo) { return pictInfo.fPictureID; } - static uint32_t Hash(const uint32_t& key) { return SkChecksum::Mix(key); } - - // GrPictureInfo proper - GrPictureInfo(uint32_t pictureID) - : fPictureID(pictureID) - , fPlotUsage(kNumPlots) { -#if !GR_CACHE_HOISTED_LAYERS - memset(fPlotUses, 0, sizeof(fPlotUses)); -#endif - } - -#if !GR_CACHE_HOISTED_LAYERS - void incPlotUsage(int plotID) { - SkASSERT(plotID < kNumPlots); - fPlotUses[plotID]++; - } - - void decPlotUsage(int plotID) { - SkASSERT(plotID < kNumPlots); - SkASSERT(fPlotUses[plotID] > 0); - fPlotUses[plotID]--; - } - - int plotUsage(int plotID) const { - SkASSERT(plotID < kNumPlots); - return fPlotUses[plotID]; - } -#endif - - const uint32_t fPictureID; - GrLayerAtlas::ClientPlotUsage fPlotUsage; - -#if !GR_CACHE_HOISTED_LAYERS -private: - int fPlotUses[kNumPlots]; -#endif -}; - -// GrCachedLayer encapsulates the caching information for a single saveLayer. -// -// Atlased layers get a ref to the backing GrTexture while non-atlased layers -// get a ref to the GrTexture in which they reside. In both cases 'fRect' -// contains the layer's extent in its texture. -// Atlased layers also get a pointer to the plot in which they reside. -// For non-atlased layers, the lock field just corresponds to locking in -// the resource cache. For atlased layers, it implements an additional level -// of locking to allow atlased layers to be reused multiple times. -struct GrCachedLayer { -public: - // For SkTDynamicHash - struct Key { - Key(uint32_t pictureID, const SkMatrix& initialMat, - const int* key, int keySize, bool copyKey = false) - : fKeySize(keySize) - , fFreeKey(copyKey) { - fIDMatrix.fPictureID = pictureID; - fIDMatrix.fInitialMat = initialMat; - fIDMatrix.fInitialMat.getType(); // force initialization of type so hashes match - - if (copyKey) { - int* tempKey = new int[keySize]; - memcpy(tempKey, key, keySize*sizeof(int)); - fKey = tempKey; - } else { - fKey = key; - } - - // The pictureID/matrix portion needs to be tightly packed. - GR_STATIC_ASSERT(sizeof(IDMatrix) == sizeof(uint32_t)+ // pictureID - 9 * sizeof(SkScalar) + sizeof(uint32_t)); // matrix - } - - ~Key() { - if (fFreeKey) { - delete[] fKey; - } - } - - bool operator==(const Key& other) const { - if (fKeySize != other.fKeySize) { - return false; - } - return fIDMatrix.fPictureID == other.fIDMatrix.fPictureID && - fIDMatrix.fInitialMat.cheapEqualTo(other.fIDMatrix.fInitialMat) && - !memcmp(fKey, other.fKey, fKeySize * sizeof(int)); - } - - uint32_t pictureID() const { return fIDMatrix.fPictureID; } - - // TODO: remove these when GrCachedLayer & ReplacementInfo fuse - const int* key() const { SkASSERT(fFreeKey); return fKey; } - int keySize() const { SkASSERT(fFreeKey); return fKeySize; } - - uint32_t hash() const { - uint32_t hash = SkChecksum::Murmur3(reinterpret_cast<const uint32_t*>(fKey), - fKeySize * sizeof(int)); - return SkChecksum::Murmur3(reinterpret_cast<const uint32_t*>(&fIDMatrix), - sizeof(IDMatrix), hash); - } - - private: - struct IDMatrix { - // ID of the picture of which this layer is a part - uint32_t fPictureID; - // The initial matrix passed into drawPicture - SkMatrix fInitialMat; - } fIDMatrix; - - const int* fKey; - const int fKeySize; - bool fFreeKey; - }; - - static const Key& GetKey(const GrCachedLayer& layer) { return layer.fKey; } - static uint32_t Hash(const Key& key) { return key.hash(); } - - // GrCachedLayer proper - GrCachedLayer(uint32_t pictureID, - int start, - int stop, - const SkIRect& srcIR, - const SkIRect& dstIR, - const SkMatrix& ctm, - const int* key, - int keySize, - const SkPaint* paint) - : fKey(pictureID, ctm, key, keySize, true) - , fStart(start) - , fStop(stop) - , fSrcIR(srcIR) - , fDstIR(dstIR) - , fOffset(SkIPoint::Make(0, 0)) - , fPaint(paint ? new SkPaint(*paint) : nullptr) - , fFilter(nullptr) - , fTexture(nullptr) - , fAtlased(false) - , fRect(SkIRect::MakeEmpty()) - , fPlot(nullptr) - , fUses(0) - , fLocked(false) { - SkASSERT(SK_InvalidGenID != pictureID); - - if (fPaint) { - if (fPaint->getImageFilter()) { - fFilter = SkSafeRef(fPaint->getImageFilter()); - fPaint->setImageFilter(nullptr); - } - } - } - - ~GrCachedLayer() { - if (!fAtlased) { - SkSafeUnref(fTexture); - } - SkSafeUnref(fFilter); - delete fPaint; - } - - uint32_t pictureID() const { return fKey.pictureID(); } - // TODO: remove these when GrCachedLayer & ReplacementInfo fuse - const int* key() const { return fKey.key(); } - int keySize() const { return fKey.keySize(); } - - int start() const { return fStart; } - // TODO: make bound debug only - const SkIRect& srcIR() const { return fSrcIR; } - const SkIRect& dstIR() const { return fDstIR; } - int stop() const { return fStop; } - void setTexture(GrTexture* texture, const SkIRect& rect, bool atlased) { - if (texture && !atlased) { - texture->ref(); // non-atlased textures carry a ref - } - if (fTexture && !fAtlased) { - fTexture->unref(); // non-atlased textures carry a ref - } - fTexture = texture; - fAtlased = atlased; - fRect = rect; - if (!fTexture) { - fLocked = false; - } - } - GrTexture* texture() { return fTexture; } - const SkPaint* paint() const { return fPaint; } - const SkImageFilter* filter() const { return fFilter; } - const SkIRect& rect() const { return fRect; } - - void setOffset(const SkIPoint& offset) { fOffset = offset; } - const SkIPoint& offset() const { return fOffset; } - - void setPlot(GrLayerAtlas::Plot* plot) { - SkASSERT(nullptr == plot || nullptr == fPlot); - fPlot = plot; - } - GrLayerAtlas::Plot* plot() { return fPlot; } - - bool isAtlased() const { SkASSERT(fAtlased == SkToBool(fPlot)); return fAtlased; } - - void setLocked(bool locked) { fLocked = locked; } - bool locked() const { return fLocked; } - - SkDEBUGCODE(const GrLayerAtlas::Plot* plot() const { return fPlot; }) - SkDEBUGCODE(void validate(const GrTexture* backingTexture) const;) - -private: - const Key fKey; - - // The "saveLayer" operation index of the cached layer - const int fStart; - // The final "restore" operation index of the cached layer - const int fStop; - - // The layer's src rect (i.e., the portion of the source scene required - // for filtering). - const SkIRect fSrcIR; - // The layer's dest rect (i.e., where it will land in device space) - const SkIRect fDstIR; - // Offset sometimes required by image filters - SkIPoint fOffset; - - // The paint used when dropping the layer down into the owning canvas. - // Can be nullptr. This class makes a copy for itself. - SkPaint* fPaint; - - // The imagefilter that needs to be applied to the layer prior to it being - // composited with the rest of the scene. - const SkImageFilter* fFilter; - - // fTexture is a ref on the atlasing texture for atlased layers and a - // ref on a GrTexture for non-atlased textures. - GrTexture* fTexture; - - // true if this layer is in the atlas (and 'fTexture' doesn't carry a ref) - // and false if the layer is a free floater (and carries a ref). - bool fAtlased; - - // For both atlased and non-atlased layers 'fRect' contains the bound of - // the layer in whichever texture it resides. It is empty when 'fTexture' - // is nullptr. - SkIRect fRect; - - // For atlased layers, fPlot stores the atlas plot in which the layer rests. - // It is always nullptr for non-atlased layers. - GrLayerAtlas::Plot* fPlot; - - // The number of actively hoisted layers using this cached image (e.g., - // extant GrHoistedLayers pointing at this object). This object will - // be unlocked when the use count reaches 0. - int fUses; - - // For non-atlased layers 'fLocked' should always match "fTexture". - // (i.e., if there is a texture it is locked). - // For atlased layers, 'fLocked' is true if the layer is in a plot and - // actively required for rendering. If the layer is in a plot but not - // actively required for rendering, then 'fLocked' is false. If the - // layer isn't in a plot then is can never be locked. - bool fLocked; - - void addUse() { ++fUses; } - void removeUse() { SkASSERT(fUses > 0); --fUses; } - int uses() const { return fUses; } - - friend class GrLayerCache; // for access to usage methods - friend class TestingAccess; // for testing -}; - -// The GrLayerCache caches pre-computed saveLayers for later rendering. -// Non-atlased layers are stored in their own GrTexture while the atlased -// layers share a single GrTexture. -// Unlike the GrFontCache, the GrLayerCache only has one atlas (for 8888). -// As such, the GrLayerCache roughly combines the functionality of the -// GrFontCache and GrTextStrike classes. -class GrLayerCache { -public: - GrLayerCache(GrContext*); - ~GrLayerCache(); - - // As a cache, the GrLayerCache can be ordered to free up all its cached - // elements by the GrContext - void freeAll(); - - GrCachedLayer* findLayer(uint32_t pictureID, const SkMatrix& ctm, - const int* key, int keySize); - GrCachedLayer* findLayerOrCreate(uint32_t pictureID, - int start, int stop, - const SkIRect& srcIR, - const SkIRect& dstIR, - const SkMatrix& initialMat, - const int* key, int keySize, - const SkPaint* paint); - - // Attempt to place 'layer' in the atlas. Return true on success; false on failure. - // When true is returned, 'needsRendering' will indicate if the layer must be (re)drawn. - // Additionally, the GPU resources will be locked. - bool tryToAtlas(GrCachedLayer* layer, const GrSurfaceDesc& desc, bool* needsRendering); - - // Attempt to lock the GPU resources required for a layer. Return true on success; - // false on failure. When true is returned 'needsRendering' will indicate if the - // layer must be (re)drawn. - // Note that atlased layers should already have been locked and rendered so only - // free floating layers will have 'needsRendering' set. - // Currently, this path always uses a new scratch texture for non-Atlased layers - // and (thus) doesn't cache anything. This can yield a lot of re-rendering. - // TODO: allow rediscovery of free-floating layers that are still in the resource cache. - bool lock(GrCachedLayer* layer, const GrSurfaceDesc& desc, bool* needsRendering); - - // addUse is just here to keep the API symmetric - void addUse(GrCachedLayer* layer) { layer->addUse(); } - void removeUse(GrCachedLayer* layer) { - layer->removeUse(); - if (layer->uses() == 0) { - // If no one cares about the layer allow it to be recycled. - this->unlock(layer); - } - } - - // Cleanup after any SkPicture deletions - void processDeletedPictures(); - - SkDEBUGCODE(void validate() const;) - -#ifdef SK_DEBUG - void writeLayersToDisk(const SkString& dirName); -#endif - - static bool PlausiblyAtlasable(int width, int height) { - return width <= kPlotWidth && height <= kPlotHeight; - } - - void begin(); - void end(); - -#if !GR_CACHE_HOISTED_LAYERS - void purgeAll(); -#endif - -private: - static const int kAtlasTextureWidth = 1024; - static const int kAtlasTextureHeight = 1024; - - static const int kNumPlotsX = 2; - static const int kNumPlotsY = 2; - - static const int kPlotWidth = kAtlasTextureWidth / kNumPlotsX; - static const int kPlotHeight = kAtlasTextureHeight / kNumPlotsY; - - GrContext* fContext; // pointer back to owning context - SkAutoTDelete<GrLayerAtlas> fAtlas; // lazily allocated - - // We cache this information here (rather then, say, on the owning picture) - // because we want to be able to clean it up as needed (e.g., if a picture - // is leaked and never cleans itself up we still want to be able to - // remove the GrPictureInfo once its layers are purged from all the atlas - // plots). - SkTDynamicHash<GrPictureInfo, uint32_t> fPictureHash; - - SkTDynamicHash<GrCachedLayer, GrCachedLayer::Key> fLayerHash; - - SkMessageBus<SkPicture::DeletionMessage>::Inbox fPictDeletionInbox; - - // This implements a plot-centric locking mechanism (since the atlas - // backing texture is always locked). Each layer that is locked (i.e., - // needed for the current rendering) in a plot increments the plot lock - // count for that plot. Similarly, once a rendering is complete all the - // layers used in it decrement the lock count for the used plots. - // Plots with a 0 lock count are open for recycling/purging. - int fPlotLocks[kNumPlotsX * kNumPlotsY]; - - // Inform the cache that layer's cached image is not currently required - void unlock(GrCachedLayer* layer); - - void initAtlas(); - GrCachedLayer* createLayer(uint32_t pictureID, int start, int stop, - const SkIRect& srcIR, const SkIRect& dstIR, - const SkMatrix& initialMat, - const int* key, int keySize, - const SkPaint* paint); - - // Remove all the layers (and unlock any resources) associated with 'pictureID' - void purge(uint32_t pictureID); - - void purgePlot(GrLayerAtlas::Plot* plot); - - // Either purge all un-locked plots or just one. Return true if >= 1 plot - // was purged; false otherwise. - bool purgePlots(bool justOne); - - void incPlotLock(int plotIdx) { ++fPlotLocks[plotIdx]; } - void decPlotLock(int plotIdx) { - SkASSERT(fPlotLocks[plotIdx] > 0); - --fPlotLocks[plotIdx]; - } - - // for testing - friend class TestingAccess; - int numLayers() const { return fLayerHash.count(); } -}; - -#endif |