aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu/GrLayerCache.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/gpu/GrLayerCache.h')
-rw-r--r--src/gpu/GrLayerCache.h432
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