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

#include "SkBitmap.h"
#include "SkBitmapHeap.h"
#include "SkColor.h"
#include "SkFlattenable.h"
#include "SkWriteBuffer.h"
#include "SkPictureFlat.h"
#include "SkRefCnt.h"
#include "SkShader.h"
#include "Test.h"

struct SimpleFlatController : public SkFlatController {
    SimpleFlatController() : SkFlatController() {}
    ~SimpleFlatController() { fAllocations.freeAll(); }
    virtual void* allocThrow(size_t bytes) SK_OVERRIDE {
        fAllocations.push(sk_malloc_throw(bytes));
        return fAllocations.top();
    }
    virtual void unalloc(void*) SK_OVERRIDE { }
    void setBitmapStorage(SkBitmapHeap* h) { this->setBitmapHeap(h); }
private:
    SkTDArray<void*> fAllocations;
};

struct SkShaderTraits {
    static void Flatten(SkWriteBuffer& buffer, const SkShader& shader) {
        buffer.writeFlattenable(&shader);
    }
};
typedef SkFlatDictionary<SkShader, SkShaderTraits> FlatDictionary;

class SkBitmapHeapTester {
public:
    static int32_t GetRefCount(const SkBitmapHeapEntry* entry) {
        return entry->fRefCount;
    }
};

DEF_TEST(BitmapHeap, reporter) {
    // Create a bitmap shader.
    SkBitmap bm;
    bm.allocN32Pixels(2, 2);
    bm.eraseColor(SK_ColorRED);
    uint32_t* pixel = bm.getAddr32(1,0);
    *pixel = SK_ColorBLUE;

    SkShader* bitmapShader = SkShader::CreateBitmapShader(bm, SkShader::kRepeat_TileMode,
                                                          SkShader::kRepeat_TileMode);
    SkAutoTUnref<SkShader> aur(bitmapShader);

    // Flatten, storing it in the bitmap heap.
    SkBitmapHeap heap(1, 1);
    SimpleFlatController controller;
    controller.setBitmapStorage(&heap);
    FlatDictionary dictionary(&controller);

    // Dictionary and heap start off empty.
    REPORTER_ASSERT(reporter, heap.count() == 0);
    REPORTER_ASSERT(reporter, dictionary.count() == 0);

    heap.deferAddingOwners();
    int index = dictionary.find(*bitmapShader);
    heap.endAddingOwnersDeferral(true);

    // The dictionary and heap should now each have one entry.
    REPORTER_ASSERT(reporter, 1 == index);
    REPORTER_ASSERT(reporter, heap.count() == 1);
    REPORTER_ASSERT(reporter, dictionary.count() == 1);

    // The bitmap entry's refcount should be 1, then 0 after release.
    SkBitmapHeapEntry* entry = heap.getEntry(0);
    REPORTER_ASSERT(reporter, SkBitmapHeapTester::GetRefCount(entry) == 1);

    entry->releaseRef();
    REPORTER_ASSERT(reporter, SkBitmapHeapTester::GetRefCount(entry) == 0);

    // Now clear out the heap, after which it should be empty.
    heap.freeMemoryIfPossible(~0U);
    REPORTER_ASSERT(reporter, heap.count() == 0);

    // Now attempt to flatten the shader again.
    heap.deferAddingOwners();
    index = dictionary.find(*bitmapShader);
    heap.endAddingOwnersDeferral(false);

    // The dictionary should report the same index since the new entry is identical.
    // The bitmap heap should contain the bitmap, but with no references.
    REPORTER_ASSERT(reporter, 1 == index);
    REPORTER_ASSERT(reporter, heap.count() == 1);
    REPORTER_ASSERT(reporter, SkBitmapHeapTester::GetRefCount(heap.getEntry(0)) == 0);
}
