1/*
2 * Copyright 2012 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "SkBitmap.h"
9#include "SkBitmapHeap.h"
10#include "SkColor.h"
11#include "SkFlattenable.h"
12#include "SkWriteBuffer.h"
13#include "SkPictureFlat.h"
14#include "SkRefCnt.h"
15#include "SkShader.h"
16#include "Test.h"
17
18struct SkShaderTraits {
19    static void Flatten(SkWriteBuffer& buffer, const SkShader& shader) {
20        buffer.writeFlattenable(&shader);
21    }
22};
23typedef SkFlatDictionary<SkShader, SkShaderTraits> FlatDictionary;
24
25class SkBitmapHeapTester {
26
27public:
28    static int32_t GetRefCount(const SkBitmapHeapEntry* entry) {
29        return entry->fRefCount;
30    }
31};
32
33DEF_TEST(BitmapHeap, reporter) {
34    // Create a bitmap shader.
35    SkBitmap bm;
36    bm.allocN32Pixels(2, 2);
37    bm.eraseColor(SK_ColorRED);
38    uint32_t* pixel = bm.getAddr32(1,0);
39    *pixel = SK_ColorBLUE;
40
41    SkShader* bitmapShader = SkShader::CreateBitmapShader(bm, SkShader::kRepeat_TileMode,
42                                                          SkShader::kRepeat_TileMode);
43    SkAutoTUnref<SkShader> aur(bitmapShader);
44
45    // Flatten, storing it in the bitmap heap.
46    SkBitmapHeap heap(1, 1);
47    SkChunkFlatController controller(1024);
48    controller.setBitmapStorage(&heap);
49    FlatDictionary dictionary(&controller);
50
51    // Dictionary and heap start off empty.
52    REPORTER_ASSERT(reporter, heap.count() == 0);
53    REPORTER_ASSERT(reporter, dictionary.count() == 0);
54
55    heap.deferAddingOwners();
56    int index = dictionary.find(*bitmapShader);
57    heap.endAddingOwnersDeferral(true);
58
59    // The dictionary and heap should now each have one entry.
60    REPORTER_ASSERT(reporter, 1 == index);
61    REPORTER_ASSERT(reporter, heap.count() == 1);
62    REPORTER_ASSERT(reporter, dictionary.count() == 1);
63
64    // The bitmap entry's refcount should be 1, then 0 after release.
65    SkBitmapHeapEntry* entry = heap.getEntry(0);
66    REPORTER_ASSERT(reporter, SkBitmapHeapTester::GetRefCount(entry) == 1);
67
68    entry->releaseRef();
69    REPORTER_ASSERT(reporter, SkBitmapHeapTester::GetRefCount(entry) == 0);
70
71    // Now clear out the heap, after which it should be empty.
72    heap.freeMemoryIfPossible(~0U);
73    REPORTER_ASSERT(reporter, heap.count() == 0);
74
75    // Now attempt to flatten the shader again.
76    heap.deferAddingOwners();
77    index = dictionary.find(*bitmapShader);
78    heap.endAddingOwnersDeferral(false);
79
80    // The dictionary should report the same index since the new entry is identical.
81    // The bitmap heap should contain the bitmap, but with no references.
82    REPORTER_ASSERT(reporter, 1 == index);
83    REPORTER_ASSERT(reporter, heap.count() == 1);
84    REPORTER_ASSERT(reporter, SkBitmapHeapTester::GetRefCount(heap.getEntry(0)) == 0);
85}
86