X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Fthird_party%2Fskia%2Fsrc%2Fgpu%2FGrLayerCache.h;h=f027a26cbcab40bf4acf747538790714faf75a3a;hb=4a1a0bdd01eef90b0826a0e761d3379d3715c10f;hp=a957e78013e05e3acabafac6821dfa4cc9cd46d5;hpb=b1be5ca53587d23e7aeb77b26861fdc0a181ffd8;p=platform%2Fframework%2Fweb%2Fcrosswalk.git diff --git a/src/third_party/skia/src/gpu/GrLayerCache.h b/src/third_party/skia/src/gpu/GrLayerCache.h index a957e78..f027a26 100644 --- a/src/third_party/skia/src/gpu/GrLayerCache.h +++ b/src/third_party/skia/src/gpu/GrLayerCache.h @@ -8,113 +8,242 @@ #ifndef GrLayerCache_DEFINED #define GrLayerCache_DEFINED -#include "GrAllocPool.h" -#include "GrTHashTable.h" +#include "GrAtlas.h" #include "GrPictureUtils.h" #include "GrRect.h" +#include "SkChecksum.h" +#include "SkTDynamicHash.h" +#include "SkMessageBus.h" -class GrAtlasMgr; -class GrGpu; -class GrPlot; class SkPicture; -// GrAtlasLocation captures an atlased item's position in the atlas. This -// means the plot in which it resides and its bounds inside the plot. -// TODO: Make GrGlyph use one of these? -class GrAtlasLocation { -public: - GrAtlasLocation() : fPlot(NULL) {} +// The layer cache listens for these messages to purge picture-related resources. +struct GrPictureDeletedMessage { + uint32_t pictureID; +}; - void set(GrPlot* plot, const GrIRect16& bounds) { - fPlot = plot; - fBounds = bounds; - } +// 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: + // 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); } - const GrPlot* plot() const { - return fPlot; - } + // GrPictureInfo proper + GrPictureInfo(uint32_t pictureID) : fPictureID(pictureID) { } - const GrIRect16& bounds() const { - return fBounds; - } + const uint32_t fPictureID; -private: - GrPlot* fPlot; - GrIRect16 fBounds; // only valid is fPlot != NULL + GrAtlas::ClientPlotUsage fPlotUsage; }; // GrCachedLayer encapsulates the caching information for a single saveLayer. // -// Atlased layers get a ref to their atlas GrTexture and their GrAtlasLocation -// is filled in. -// In this case GrCachedLayer is roughly equivalent to a GrGlyph in the font -// caching system. -// -// Non-atlased layers get a ref to the GrTexture in which they reside. -// TODO: can we easily reuse the empty space in the non-atlased GrTexture's? +// 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: - uint32_t pictureID() const { return fPictureID; } - int layerID() const { return fLayerID; } - - void init(uint32_t pictureID, int layerID) { - fPictureID = pictureID; - fLayerID = layerID; - fTexture = NULL; - fLocation.set(NULL, GrIRect16::MakeEmpty()); - } + // For SkTDynamicHash + struct Key { + Key(uint32_t pictureID, int start, int stop, const SkMatrix& ctm) + : fPictureID(pictureID) + , fStart(start) + , fStop(stop) + , fCTM(ctm) { + fCTM.getType(); // force initialization of type so hashes match + + // Key needs to be tightly packed. + GR_STATIC_ASSERT(sizeof(Key) == sizeof(uint32_t) + 2 * sizeof(int) + + 9 * sizeof(SkScalar) + sizeof(uint32_t)); + } - // This call takes over the caller's ref - void setTexture(GrTexture* texture) { - if (NULL != fTexture) { - fTexture->unref(); + bool operator==(const Key& other) const { + return fPictureID == other.fPictureID && + fStart == other.fStart && + fStop == other.fStop && + fCTM.cheapEqualTo(other.fCTM); } - fTexture = texture; // just take over caller's ref + uint32_t pictureID() const { return fPictureID; } + int start() const { return fStart; } + int stop() const { return fStop; } + const SkMatrix& ctm() const { return fCTM; } + + private: + // ID of the picture of which this layer is a part + const uint32_t fPictureID; + // The range of commands in the picture this layer represents + const int fStart; + const int fStop; + // The CTM applied to this layer in the picture + SkMatrix fCTM; + }; + + static const Key& GetKey(const GrCachedLayer& layer) { return layer.fKey; } + static uint32_t Hash(const Key& key) { + return SkChecksum::Murmur3(reinterpret_cast(&key), sizeof(Key)); + } + + // GrCachedLayer proper + GrCachedLayer(uint32_t pictureID, int start, int stop, const SkMatrix& ctm) + : fKey(pictureID, start, stop, ctm) + , fTexture(NULL) + , fRect(GrIRect16::MakeEmpty()) + , fPlot(NULL) + , fLocked(false) { + SkASSERT(SK_InvalidGenID != pictureID && start >= 0 && stop >= 0); + } + + ~GrCachedLayer() { + SkSafeUnref(fTexture); } - GrTexture* getTexture() { return fTexture; } + + uint32_t pictureID() const { return fKey.pictureID(); } + int start() const { return fKey.start(); } + int stop() const { return fKey.stop(); } + const SkMatrix& ctm() const { return fKey.ctm(); } + + void setTexture(GrTexture* texture, const GrIRect16& rect) { + SkRefCnt_SafeAssign(fTexture, texture); + fRect = rect; + } + GrTexture* texture() { return fTexture; } + const GrIRect16& rect() const { return fRect; } + + void setPlot(GrPlot* plot) { + SkASSERT(NULL == fPlot); + fPlot = plot; + } + GrPlot* plot() { return fPlot; } + + bool isAtlased() const { return NULL != fPlot; } + + void setLocked(bool locked) { fLocked = locked; } + bool locked() const { return fLocked; } + + SkDEBUGCODE(const GrPlot* plot() const { return fPlot; }) + SkDEBUGCODE(void validate(const GrTexture* backingTexture) const;) private: - uint32_t fPictureID; - // fLayerID is only valid when fPicture != kInvalidGenID in which case it - // is the index of this layer in the picture (one of 0 .. #layers). - int fLayerID; + const Key fKey; // fTexture is a ref on the atlasing texture for atlased layers and a - // ref on a GrTexture for non-atlased textures. In both cases, if this is - // non-NULL, that means that the texture is locked in the texture cache. + // ref on a GrTexture for non-atlased textures. GrTexture* fTexture; - GrAtlasLocation fLocation; // only valid if the layer is atlased + // 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 NULL. + GrIRect16 fRect; + + // For atlased layers, fPlot stores the atlas plot in which the layer rests. + // It is always NULL for non-atlased layers. + GrPlot* fPlot; + + // For non-atlased layers 'fLocked' should always match "NULL != 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; }; // 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 GrTexture atlas only has one GrAtlasMgr (for 8888) +// Unlike the GrFontCache, the GrTexture atlas only has one GrAtlas (for 8888) // and one GrPlot (for the entire atlas). As such, the GrLayerCache // roughly combines the functionality of the GrFontCache and GrTextStrike // classes. class GrLayerCache { public: - GrLayerCache(GrGpu*); + GrLayerCache(GrContext*); ~GrLayerCache(); + // As a cache, the GrLayerCache can be ordered to free up all its cached + // elements by the GrContext void freeAll(); - GrCachedLayer* findLayerOrCreate(const SkPicture* picture, int id); + GrCachedLayer* findLayer(const SkPicture* picture, int start, int stop, const SkMatrix& ctm); + GrCachedLayer* findLayerOrCreate(const SkPicture* picture, + int start, int stop, + const SkMatrix& ctm); + + // Inform the cache that layer's cached image is now required. Return true + // if it was found in the ResourceCache and doesn't need to be regenerated. + // If false is returned the caller should (re)render the layer into the + // newly acquired texture. + bool lock(GrCachedLayer* layer, const GrTextureDesc& desc); + + // Inform the cache that layer's cached image is not currently required + void unlock(GrCachedLayer* layer); + + // Setup to be notified when 'picture' is deleted + void trackPicture(const SkPicture* picture); + + // Cleanup after any SkPicture deletions + void processDeletedPictures(); + + SkDEBUGCODE(void validate() const;) private: - SkAutoTUnref fGpu; - SkAutoTDelete fAtlasMgr; // TODO: could lazily allocate + 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; - class PictureLayerKey; - GrTHashTable fLayerHash; - GrTAllocPool fLayerPool; + GrContext* fContext; // pointer back to owning context + SkAutoTDelete fAtlas; // TODO: could lazily allocate + + // 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 fPictureHash; + + SkTDynamicHash fLayerHash; + + SkMessageBus::Inbox fPictDeletionInbox; + + SkAutoTUnref fDeletionListener; + + // 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]; + + void initAtlas(); + GrCachedLayer* createLayer(const SkPicture* picture, int start, int stop, const SkMatrix& ctm); + + // Remove all the layers (and unlock any resources) associated with 'pictureID' + void purge(uint32_t pictureID); + + static bool PlausiblyAtlasable(int width, int height) { + return width <= kPlotWidth && height <= kPlotHeight; + } - void init(); - GrCachedLayer* createLayer(const SkPicture* picture, int id); + // Try to find a purgeable plot and clear it out. Return true if a plot + // was purged; false otherwise. + bool purgePlot(); + // for testing + friend class TestingAccess; + int numLayers() const { return fLayerHash.count(); } }; #endif