/*
 * 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
