/*
 * 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 "GrGradientBitmapCache.h"

#include "SkMalloc.h"
#include "SkFloatBits.h"
#include "SkHalf.h"
#include "SkTemplates.h"

#include <functional>

struct GrGradientBitmapCache::Entry {
    Entry*      fPrev;
    Entry*      fNext;

    void*       fBuffer;
    size_t      fSize;
    SkBitmap    fBitmap;

    Entry(const void* buffer, size_t size, const SkBitmap& bm)
            : fPrev(nullptr),
              fNext(nullptr),
              fBitmap(bm) {
        fBuffer = sk_malloc_throw(size);
        fSize = size;
        memcpy(fBuffer, buffer, size);
    }

    ~Entry() { sk_free(fBuffer); }

    bool equals(const void* buffer, size_t size) const {
        return (fSize == size) && !memcmp(fBuffer, buffer, size);
    }
};

GrGradientBitmapCache::GrGradientBitmapCache(int max, int res)
        : fMaxEntries(max)
        , fResolution(res) {
    fEntryCount = 0;
    fHead = fTail = nullptr;

    this->validate();
}

GrGradientBitmapCache::~GrGradientBitmapCache() {
    this->validate();

    Entry* entry = fHead;
    while (entry) {
        Entry* next = entry->fNext;
        delete entry;
        entry = next;
    }
}

GrGradientBitmapCache::Entry* GrGradientBitmapCache::release(Entry* entry) const {
    if (entry->fPrev) {
        SkASSERT(fHead != entry);
        entry->fPrev->fNext = entry->fNext;
    } else {
        SkASSERT(fHead == entry);
        fHead = entry->fNext;
    }
    if (entry->fNext) {
        SkASSERT(fTail != entry);
        entry->fNext->fPrev = entry->fPrev;
    } else {
        SkASSERT(fTail == entry);
        fTail = entry->fPrev;
    }
    return entry;
}

void GrGradientBitmapCache::attachToHead(Entry* entry) const {
    entry->fPrev = nullptr;
    entry->fNext = fHead;
    if (fHead) {
        fHead->fPrev = entry;
    } else {
        fTail = entry;
    }
    fHead = entry;
}

bool GrGradientBitmapCache::find(const void* buffer, size_t size, SkBitmap* bm) const {
    AutoValidate av(this);

    Entry* entry = fHead;
    while (entry) {
        if (entry->equals(buffer, size)) {
            if (bm) {
                *bm = entry->fBitmap;
            }
            // move to the head of our list, so we purge it last
            this->release(entry);
            this->attachToHead(entry);
            return true;
        }
        entry = entry->fNext;
    }
    return false;
}

void GrGradientBitmapCache::add(const void* buffer, size_t len, const SkBitmap& bm) {
    AutoValidate av(this);

    if (fEntryCount == fMaxEntries) {
        SkASSERT(fTail);
        delete this->release(fTail);
        fEntryCount -= 1;
    }

    Entry* entry = new Entry(buffer, len, bm);
    this->attachToHead(entry);
    fEntryCount += 1;
}

///////////////////////////////////////////////////////////////////////////////


void GrGradientBitmapCache::fillGradient(const SkPMColor4f* colors, const SkScalar* positions,
                                         int count, SkColorType colorType, SkBitmap* bitmap) {
    SkHalf* pixelsF16 = reinterpret_cast<SkHalf*>(bitmap->getPixels());
    uint32_t* pixels32 = reinterpret_cast<uint32_t*>(bitmap->getPixels());

    typedef std::function<void(const Sk4f&, int)> pixelWriteFn_t;

    pixelWriteFn_t writeF16Pixel = [&](const Sk4f& x, int index) {
        Sk4h c = SkFloatToHalf_finite_ftz(x);
        pixelsF16[4*index+0] = c[0];
        pixelsF16[4*index+1] = c[1];
        pixelsF16[4*index+2] = c[2];
        pixelsF16[4*index+3] = c[3];
    };
    pixelWriteFn_t write8888Pixel = [&](const Sk4f& c, int index) {
        pixels32[index] = Sk4f_toL32(c);
    };

    pixelWriteFn_t writePixel =
            (colorType == kRGBA_F16_SkColorType) ? writeF16Pixel : write8888Pixel;

    int prevIndex = 0;
    for (int i = 1; i < count; i++) {
        // Historically, stops have been mapped to [0, 256], with 256 then nudged to the next
        // smaller value, then truncate for the texture index. This seems to produce the best
        // results for some common distributions, so we preserve the behavior.
        int nextIndex = SkTMin(positions[i] * fResolution,
                               SkIntToScalar(fResolution - 1));

        if (nextIndex > prevIndex) {
            Sk4f          c0 = Sk4f::Load(colors[i - 1].vec()),
                          c1 = Sk4f::Load(colors[i    ].vec());

            Sk4f step = Sk4f(1.0f / static_cast<float>(nextIndex - prevIndex));
            Sk4f delta = (c1 - c0) * step;

            for (int curIndex = prevIndex; curIndex <= nextIndex; ++curIndex) {
                writePixel(c0, curIndex);
                c0 += delta;
            }
        }
        prevIndex = nextIndex;
    }
    SkASSERT(prevIndex == fResolution - 1);
}

void GrGradientBitmapCache::getGradient(const SkPMColor4f* colors, const SkScalar* positions,
        int count, SkColorType colorType, SkAlphaType alphaType, SkBitmap* bitmap) {
    // build our key: [numColors + colors[] + positions[] + alphaType + colorType ]
    static_assert(sizeof(SkPMColor4f) % sizeof(int32_t) == 0, "");
    const int colorsAsIntCount = count * sizeof(SkPMColor4f) / sizeof(int32_t);
    int keyCount = 1 + colorsAsIntCount + 1 + 1;
    if (count > 2) {
        keyCount += count - 1;
    }

    SkAutoSTMalloc<64, int32_t> storage(keyCount);
    int32_t* buffer = storage.get();

    *buffer++ = count;
    memcpy(buffer, colors, count * sizeof(SkPMColor4f));
    buffer += colorsAsIntCount;
    if (count > 2) {
        for (int i = 1; i < count; i++) {
            *buffer++ = SkFloat2Bits(positions[i]);
        }
    }
    *buffer++ = static_cast<int32_t>(alphaType);
    *buffer++ = static_cast<int32_t>(colorType);
    SkASSERT(buffer - storage.get() == keyCount);

    ///////////////////////////////////

    // acquire lock for checking/adding to cache
    SkAutoExclusive ama(fMutex);
    size_t size = keyCount * sizeof(int32_t);
    if (!this->find(storage.get(), size, bitmap)) {
        SkImageInfo info = SkImageInfo::Make(fResolution, 1, colorType, alphaType);
        bitmap->allocPixels(info);
        GrGradientBitmapCache::fillGradient(colors, positions, count, colorType, bitmap);
        bitmap->setImmutable();
        this->add(storage.get(), size, *bitmap);
    }
}

///////////////////////////////////////////////////////////////////////////////

#ifdef SK_DEBUG

void GrGradientBitmapCache::validate() const {
    SkASSERT(fEntryCount >= 0 && fEntryCount <= fMaxEntries);

    if (fEntryCount > 0) {
        SkASSERT(nullptr == fHead->fPrev);
        SkASSERT(nullptr == fTail->fNext);

        if (fEntryCount == 1) {
            SkASSERT(fHead == fTail);
        } else {
            SkASSERT(fHead != fTail);
        }

        Entry* entry = fHead;
        int count = 0;
        while (entry) {
            count += 1;
            entry = entry->fNext;
        }
        SkASSERT(count == fEntryCount);

        entry = fTail;
        while (entry) {
            count -= 1;
            entry = entry->fPrev;
        }
        SkASSERT(0 == count);
    } else {
        SkASSERT(nullptr == fHead);
        SkASSERT(nullptr == fTail);
    }
}

#endif
