/*
 * Copyright 2018 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "src/gpu/ccpr/GrCCPathCache.h"

#include "include/private/SkNx.h"
#include "src/gpu/GrOnFlushResourceProvider.h"
#include "src/gpu/GrProxyProvider.h"

static constexpr int kMaxKeyDataCountU32 = 256;  // 1kB of uint32_t's.

DECLARE_SKMESSAGEBUS_MESSAGE(sk_sp<GrCCPathCache::Key>);

static inline uint32_t next_path_cache_id() {
    static std::atomic<uint32_t> gNextID(1);
    for (;;) {
        uint32_t id = gNextID.fetch_add(+1, std::memory_order_acquire);
        if (SK_InvalidUniqueID != id) {
            return id;
        }
    }
}

static inline bool SkShouldPostMessageToBus(
        const sk_sp<GrCCPathCache::Key>& key, uint32_t msgBusUniqueID) {
    return key->pathCacheUniqueID() == msgBusUniqueID;
}

// The maximum number of cache entries we allow in our own cache.
static constexpr int kMaxCacheCount = 1 << 16;


GrCCPathCache::MaskTransform::MaskTransform(const SkMatrix& m, SkIVector* shift)
        : fMatrix2x2{m.getScaleX(), m.getSkewX(), m.getSkewY(), m.getScaleY()} {
    SkASSERT(!m.hasPerspective());
    Sk2f translate = Sk2f(m.getTranslateX(), m.getTranslateY());
    Sk2f transFloor;
#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
    // On Android framework we pre-round view matrix translates to integers for better caching.
    transFloor = translate;
#else
    transFloor = translate.floor();
    (translate - transFloor).store(fSubpixelTranslate);
#endif
    shift->set((int)transFloor[0], (int)transFloor[1]);
    SkASSERT((float)shift->fX == transFloor[0]);  // Make sure transFloor had integer values.
    SkASSERT((float)shift->fY == transFloor[1]);
}

inline static bool fuzzy_equals(const GrCCPathCache::MaskTransform& a,
                                const GrCCPathCache::MaskTransform& b) {
    if ((Sk4f::Load(a.fMatrix2x2) != Sk4f::Load(b.fMatrix2x2)).anyTrue()) {
        return false;
    }
#ifndef SK_BUILD_FOR_ANDROID_FRAMEWORK
    if (((Sk2f::Load(a.fSubpixelTranslate) -
          Sk2f::Load(b.fSubpixelTranslate)).abs() > 1.f/256).anyTrue()) {
        return false;
    }
#endif
    return true;
}

sk_sp<GrCCPathCache::Key> GrCCPathCache::Key::Make(uint32_t pathCacheUniqueID,
                                                   int dataCountU32, const void* data) {
    void* memory = ::operator new (sizeof(Key) + dataCountU32 * sizeof(uint32_t));
    sk_sp<GrCCPathCache::Key> key(new (memory) Key(pathCacheUniqueID, dataCountU32));
    if (data) {
        memcpy(key->data(), data, key->dataSizeInBytes());
    }
    return key;
}

void GrCCPathCache::Key::operator delete(void* p) { ::operator delete(p); }

const uint32_t* GrCCPathCache::Key::data() const {
    // The shape key is a variable-length footer to the entry allocation.
    return reinterpret_cast<const uint32_t*>(reinterpret_cast<const char*>(this) + sizeof(Key));
}

uint32_t* GrCCPathCache::Key::data() {
    // The shape key is a variable-length footer to the entry allocation.
    return reinterpret_cast<uint32_t*>(reinterpret_cast<char*>(this) + sizeof(Key));
}

void GrCCPathCache::Key::changed() {
    // Our key's corresponding path was invalidated. Post a thread-safe eviction message.
    SkMessageBus<sk_sp<Key>>::Post(sk_ref_sp(this));
}

GrCCPathCache::GrCCPathCache(uint32_t contextUniqueID)
        : fContextUniqueID(contextUniqueID)
        , fInvalidatedKeysInbox(next_path_cache_id())
        , fScratchKey(Key::Make(fInvalidatedKeysInbox.uniqueID(), kMaxKeyDataCountU32)) {
}

GrCCPathCache::~GrCCPathCache() {
    while (!fLRU.isEmpty()) {
        this->evict(*fLRU.tail()->fCacheKey, fLRU.tail());
    }
    SkASSERT(0 == fHashTable.count());  // Ensure the hash table and LRU list were coherent.

    // Now take all the atlas textures we just invalidated and purge them from the GrResourceCache.
    // We just purge via message bus since we don't have any access to the resource cache right now.
    for (sk_sp<GrTextureProxy>& proxy : fInvalidatedProxies) {
        SkMessageBus<GrUniqueKeyInvalidatedMessage>::Post(
                GrUniqueKeyInvalidatedMessage(proxy->getUniqueKey(), fContextUniqueID));
    }
    for (const GrUniqueKey& key : fInvalidatedProxyUniqueKeys) {
        SkMessageBus<GrUniqueKeyInvalidatedMessage>::Post(
                GrUniqueKeyInvalidatedMessage(key, fContextUniqueID));
    }
}

namespace {

// Produces a key that accounts both for a shape's path geometry, as well as any stroke/style.
class WriteKeyHelper {
public:
    static constexpr int kStrokeWidthIdx = 0;
    static constexpr int kStrokeMiterIdx = 1;
    static constexpr int kStrokeCapJoinIdx = 2;
    static constexpr int kShapeUnstyledKeyIdx = 3;

    WriteKeyHelper(const GrStyledShape& shape) : fShapeUnstyledKeyCount(shape.unstyledKeySize()) {}

    // Returns the total number of uint32_t's to allocate for the key.
    int allocCountU32() const { return kShapeUnstyledKeyIdx + fShapeUnstyledKeyCount; }

    // Writes the key data to out[].
    void write(const GrStyledShape& shape, uint32_t* out) {
        // Stroke key.
        // We don't use GrStyle::WriteKey() because it does not account for hairlines.
        // http://skbug.com/8273
        SkASSERT(!shape.style().hasPathEffect());
        const SkStrokeRec& stroke = shape.style().strokeRec();
        if (stroke.isFillStyle()) {
            // Use a value for width that won't collide with a valid fp32 value >= 0.
            out[kStrokeWidthIdx] = ~0;
            out[kStrokeMiterIdx] = out[kStrokeCapJoinIdx] = 0;
        } else {
            float width = stroke.getWidth(), miterLimit = stroke.getMiter();
            memcpy(&out[kStrokeWidthIdx], &width, sizeof(float));
            memcpy(&out[kStrokeMiterIdx], &miterLimit, sizeof(float));
            out[kStrokeCapJoinIdx] = (stroke.getCap() << 16) | stroke.getJoin();
            static_assert(sizeof(out[kStrokeWidthIdx]) == sizeof(float));
        }

        // Shape unstyled key.
        shape.writeUnstyledKey(&out[kShapeUnstyledKeyIdx]);
    }

private:
    int fShapeUnstyledKeyCount;
};

}

GrCCPathCache::OnFlushEntryRef GrCCPathCache::find(
        GrOnFlushResourceProvider* onFlushRP, const GrStyledShape& shape,
        const SkIRect& clippedDrawBounds, const SkMatrix& viewMatrix, SkIVector* maskShift) {
    if (!shape.hasUnstyledKey()) {
        return OnFlushEntryRef();
    }

    WriteKeyHelper writeKeyHelper(shape);
    if (writeKeyHelper.allocCountU32() > kMaxKeyDataCountU32) {
        return OnFlushEntryRef();
    }

    SkASSERT(fScratchKey->unique());
    fScratchKey->resetDataCountU32(writeKeyHelper.allocCountU32());
    writeKeyHelper.write(shape, fScratchKey->data());

    MaskTransform m(viewMatrix, maskShift);
    GrCCPathCacheEntry* entry = nullptr;
    if (HashNode* node = fHashTable.find(*fScratchKey)) {
        entry = node->entry();
        SkASSERT(fLRU.isInList(entry));

        if (!fuzzy_equals(m, entry->fMaskTransform)) {
            // The path was reused with an incompatible matrix.
            if (entry->unique()) {
                // This entry is unique: recycle it instead of deleting and malloc-ing a new one.
                SkASSERT(0 == entry->fOnFlushRefCnt);  // Because we are unique.
                entry->fMaskTransform = m;
                entry->fHitCount = 0;
                entry->fHitRect = SkIRect::MakeEmpty();
                entry->releaseCachedAtlas(this);
            } else {
                this->evict(*fScratchKey);
                entry = nullptr;
            }
        }
    }

    if (!entry) {
        if (fHashTable.count() >= kMaxCacheCount) {
            SkDEBUGCODE(HashNode* node = fHashTable.find(*fLRU.tail()->fCacheKey));
            SkASSERT(node && node->entry() == fLRU.tail());
            this->evict(*fLRU.tail()->fCacheKey);  // We've exceeded our limit.
        }

        // Create a new entry in the cache.
        sk_sp<Key> permanentKey = Key::Make(fInvalidatedKeysInbox.uniqueID(),
                                            writeKeyHelper.allocCountU32(), fScratchKey->data());
        SkASSERT(*permanentKey == *fScratchKey);
        SkASSERT(!fHashTable.find(*permanentKey));
        entry = fHashTable.set(HashNode(this, std::move(permanentKey), m, shape))->entry();

        SkASSERT(fHashTable.count() <= kMaxCacheCount);
    } else {
        fLRU.remove(entry);  // Will be re-added at head.
    }

    SkDEBUGCODE(HashNode* node = fHashTable.find(*fScratchKey));
    SkASSERT(node && node->entry() == entry);
    fLRU.addToHead(entry);

    if (0 == entry->fOnFlushRefCnt) {
        // Only update the time stamp and hit count if we haven't seen this entry yet during the
        // current flush.
        entry->fTimestamp = this->quickPerFlushTimestamp();
        ++entry->fHitCount;

        if (entry->fCachedAtlas) {
            SkASSERT(SkToBool(entry->fCachedAtlas->peekOnFlushRefCnt()) ==
                     SkToBool(entry->fCachedAtlas->getOnFlushProxy()));
            if (!entry->fCachedAtlas->getOnFlushProxy()) {
                if (sk_sp<GrTextureProxy> onFlushProxy = onFlushRP->findOrCreateProxyByUniqueKey(
                            entry->fCachedAtlas->textureKey(), GrSurfaceProxy::UseAllocator::kNo)) {
                    entry->fCachedAtlas->setOnFlushProxy(std::move(onFlushProxy));
                }
            }
            if (!entry->fCachedAtlas->getOnFlushProxy()) {
                // Our atlas's backing texture got purged from the GrResourceCache. Release the
                // cached atlas.
                entry->releaseCachedAtlas(this);
            }
        }
    }
    entry->fHitRect.join(clippedDrawBounds.makeOffset(-*maskShift));
    SkASSERT(!entry->fCachedAtlas || entry->fCachedAtlas->getOnFlushProxy());
    return OnFlushEntryRef::OnFlushRef(entry);
}

void GrCCPathCache::evict(const GrCCPathCache::Key& key, GrCCPathCacheEntry* entry) {
    if (!entry) {
        HashNode* node = fHashTable.find(key);
        SkASSERT(node);
        entry = node->entry();
    }
    SkASSERT(*entry->fCacheKey == key);
    SkASSERT(!entry->hasBeenEvicted());
    entry->fCacheKey->markShouldDeregister();  // Unregister the path listener.
    entry->releaseCachedAtlas(this);
    fLRU.remove(entry);
    fHashTable.remove(key);
}

void GrCCPathCache::doPreFlushProcessing() {
    this->evictInvalidatedCacheKeys();

    // Mark the per-flush timestamp as needing to be updated with a newer clock reading.
    fPerFlushTimestamp = GrStdSteadyClock::time_point::min();
}

void GrCCPathCache::purgeEntriesOlderThan(GrProxyProvider* proxyProvider,
                                          const GrStdSteadyClock::time_point& purgeTime) {
    this->evictInvalidatedCacheKeys();

#ifdef SK_DEBUG
    auto lastTimestamp = (fLRU.isEmpty())
            ? GrStdSteadyClock::time_point::max()
            : fLRU.tail()->fTimestamp;
#endif

    // Evict every entry from our local path cache whose timestamp is older than purgeTime.
    while (!fLRU.isEmpty() && fLRU.tail()->fTimestamp < purgeTime) {
#ifdef SK_DEBUG
        // Verify that fLRU is sorted by timestamp.
        auto timestamp = fLRU.tail()->fTimestamp;
        SkASSERT(timestamp >= lastTimestamp);
        lastTimestamp = timestamp;
#endif
        this->evict(*fLRU.tail()->fCacheKey);
    }

    // Now take all the atlas textures we just invalidated and purge them from the GrResourceCache.
    this->purgeInvalidatedAtlasTextures(proxyProvider);
}

void GrCCPathCache::purgeInvalidatedAtlasTextures(GrOnFlushResourceProvider* onFlushRP) {
    for (sk_sp<GrTextureProxy>& proxy : fInvalidatedProxies) {
        onFlushRP->removeUniqueKeyFromProxy(proxy.get());
    }
    fInvalidatedProxies.reset();

    for (const GrUniqueKey& key : fInvalidatedProxyUniqueKeys) {
        onFlushRP->processInvalidUniqueKey(key);
    }
    fInvalidatedProxyUniqueKeys.reset();
}

void GrCCPathCache::purgeInvalidatedAtlasTextures(GrProxyProvider* proxyProvider) {
    for (sk_sp<GrTextureProxy>& proxy : fInvalidatedProxies) {
        proxyProvider->removeUniqueKeyFromProxy(proxy.get());
    }
    fInvalidatedProxies.reset();

    for (const GrUniqueKey& key : fInvalidatedProxyUniqueKeys) {
        proxyProvider->processInvalidUniqueKey(key, nullptr,
                                               GrProxyProvider::InvalidateGPUResource::kYes);
    }
    fInvalidatedProxyUniqueKeys.reset();
}

void GrCCPathCache::evictInvalidatedCacheKeys() {
    SkTArray<sk_sp<Key>> invalidatedKeys;
    fInvalidatedKeysInbox.poll(&invalidatedKeys);
    for (const sk_sp<Key>& key : invalidatedKeys) {
        bool isInCache = !key->shouldDeregister();  // Gets set upon exiting the cache.
        if (isInCache) {
            this->evict(*key);
        }
    }
}

GrCCPathCache::OnFlushEntryRef
GrCCPathCache::OnFlushEntryRef::OnFlushRef(GrCCPathCacheEntry* entry) {
    entry->ref();
    ++entry->fOnFlushRefCnt;
    if (entry->fCachedAtlas) {
        entry->fCachedAtlas->incrOnFlushRefCnt();
    }
    return OnFlushEntryRef(entry);
}

GrCCPathCache::OnFlushEntryRef::~OnFlushEntryRef() {
    if (!fEntry) {
        return;
    }
    --fEntry->fOnFlushRefCnt;
    SkASSERT(fEntry->fOnFlushRefCnt >= 0);
    if (fEntry->fCachedAtlas) {
        fEntry->fCachedAtlas->decrOnFlushRefCnt();
    }
    fEntry->unref();
}


void GrCCPathCacheEntry::setCoverageCountAtlas(
        GrOnFlushResourceProvider* onFlushRP, GrCCAtlas* atlas, const SkIVector& atlasOffset,
        const GrOctoBounds& octoBounds, const SkIRect& devIBounds, const SkIVector& maskShift) {
    SkASSERT(fOnFlushRefCnt > 0);
    SkASSERT(!fCachedAtlas);  // Otherwise we would need to call releaseCachedAtlas().

    if (this->hasBeenEvicted()) {
        // This entry will never be found in the path cache again. Don't bother trying to save an
        // atlas texture for it in the GrResourceCache.
        return;
    }

    fCachedAtlas = atlas->refOrMakeCachedAtlas(onFlushRP);
    fCachedAtlas->incrOnFlushRefCnt(fOnFlushRefCnt);
    fCachedAtlas->addPathPixels(devIBounds.height() * devIBounds.width());

    fAtlasOffset = atlasOffset + maskShift;

    fOctoBounds.setOffset(octoBounds, -maskShift.fX, -maskShift.fY);
    fDevIBounds = devIBounds.makeOffset(-maskShift);
}

GrCCPathCacheEntry::ReleaseAtlasResult GrCCPathCacheEntry::upgradeToLiteralCoverageAtlas(
        GrCCPathCache* pathCache, GrOnFlushResourceProvider* onFlushRP, GrCCAtlas* atlas,
        const SkIVector& newAtlasOffset) {
    SkASSERT(!this->hasBeenEvicted());
    SkASSERT(fOnFlushRefCnt > 0);
    SkASSERT(fCachedAtlas);
    SkASSERT(GrCCAtlas::CoverageType::kA8_LiteralCoverage != fCachedAtlas->coverageType());

    ReleaseAtlasResult releaseAtlasResult = this->releaseCachedAtlas(pathCache);

    fCachedAtlas = atlas->refOrMakeCachedAtlas(onFlushRP);
    fCachedAtlas->incrOnFlushRefCnt(fOnFlushRefCnt);
    fCachedAtlas->addPathPixels(this->height() * this->width());

    fAtlasOffset = newAtlasOffset;
    return releaseAtlasResult;
}

GrCCPathCacheEntry::ReleaseAtlasResult GrCCPathCacheEntry::releaseCachedAtlas(
        GrCCPathCache* pathCache) {
    ReleaseAtlasResult result = ReleaseAtlasResult::kNone;
    if (fCachedAtlas) {
        result = fCachedAtlas->invalidatePathPixels(pathCache, this->height() * this->width());
        if (fOnFlushRefCnt) {
            SkASSERT(fOnFlushRefCnt > 0);
            fCachedAtlas->decrOnFlushRefCnt(fOnFlushRefCnt);
        }
        fCachedAtlas = nullptr;
    }
    return result;
}

GrCCPathCacheEntry::ReleaseAtlasResult GrCCCachedAtlas::invalidatePathPixels(
        GrCCPathCache* pathCache, int numPixels) {
    // Mark the pixels invalid in the cached atlas texture.
    fNumInvalidatedPathPixels += numPixels;
    SkASSERT(fNumInvalidatedPathPixels <= fNumPathPixels);
    if (!fIsInvalidatedFromResourceCache && fNumInvalidatedPathPixels >= fNumPathPixels / 2) {
        // Too many invalidated pixels: purge the atlas texture from the resource cache.
        if (fOnFlushProxy) {
            // Don't clear (or std::move) fOnFlushProxy. Other path cache entries might still have a
            // reference on this atlas and expect to use our proxy during the current flush.
            // fOnFlushProxy will be cleared once fOnFlushRefCnt decrements to zero.
            pathCache->fInvalidatedProxies.push_back(fOnFlushProxy);
        } else {
            pathCache->fInvalidatedProxyUniqueKeys.push_back(fTextureKey);
        }
        fIsInvalidatedFromResourceCache = true;
        return ReleaseAtlasResult::kDidInvalidateFromCache;
    }
    return ReleaseAtlasResult::kNone;
}

void GrCCCachedAtlas::decrOnFlushRefCnt(int count) const {
    SkASSERT(count > 0);
    fOnFlushRefCnt -= count;
    SkASSERT(fOnFlushRefCnt >= 0);
    if (0 == fOnFlushRefCnt) {
        // Don't hold the actual proxy past the end of the current flush.
        SkASSERT(fOnFlushProxy);
        fOnFlushProxy = nullptr;
    }
}
