1013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com/*
2013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com * Copyright 2012 Google Inc.
3013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com *
4013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com * Use of this source code is governed by a BSD-style license that can be
5013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com * found in the LICENSE file.
6013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com */
7013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com
8013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com#include "SkBitmap.h"
9013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com#include "SkBitmapHeap.h"
10013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com#include "SkColor.h"
11013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com#include "SkFlattenable.h"
128b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#include "SkWriteBuffer.h"
13013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com#include "SkPictureFlat.h"
14013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com#include "SkRefCnt.h"
15013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com#include "SkShader.h"
16013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com#include "Test.h"
17013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com
1807adb6359fd137ccb633b2c64ee2287c8edfd701commit-bot@chromium.orgstruct SkShaderTraits {
19186c0ccac25229534ec6fb84726043083304d4d1commit-bot@chromium.org    static void Flatten(SkWriteBuffer& buffer, const SkShader& shader) {
2007adb6359fd137ccb633b2c64ee2287c8edfd701commit-bot@chromium.org        buffer.writeFlattenable(&shader);
21013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com    }
22013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com};
2307adb6359fd137ccb633b2c64ee2287c8edfd701commit-bot@chromium.orgtypedef SkFlatDictionary<SkShader, SkShaderTraits> FlatDictionary;
24013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com
25013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.comclass SkBitmapHeapTester {
26013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com
27013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.compublic:
28013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com    static int32_t GetRefCount(const SkBitmapHeapEntry* entry) {
29013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com        return entry->fRefCount;
30013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com    }
31013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com};
32013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com
33e4fafb146e85cdfcf9d5418597b6818aa0754adatfarina@chromium.orgDEF_TEST(BitmapHeap, reporter) {
34013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com    // Create a bitmap shader.
35013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com    SkBitmap bm;
36fa9e5fa42a555712fb7a29d08d2ae2bdef0ed68ecommit-bot@chromium.org    bm.allocN32Pixels(2, 2);
37013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com    bm.eraseColor(SK_ColorRED);
38013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com    uint32_t* pixel = bm.getAddr32(1,0);
39013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com    *pixel = SK_ColorBLUE;
40013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com
41013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com    SkShader* bitmapShader = SkShader::CreateBitmapShader(bm, SkShader::kRepeat_TileMode,
42013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com                                                          SkShader::kRepeat_TileMode);
43013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com    SkAutoTUnref<SkShader> aur(bitmapShader);
44013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com
45013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com    // Flatten, storing it in the bitmap heap.
46013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com    SkBitmapHeap heap(1, 1);
47013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com    SkChunkFlatController controller(1024);
48013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com    controller.setBitmapStorage(&heap);
49013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com    FlatDictionary dictionary(&controller);
50013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com
51013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com    // Dictionary and heap start off empty.
52013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com    REPORTER_ASSERT(reporter, heap.count() == 0);
53013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com    REPORTER_ASSERT(reporter, dictionary.count() == 0);
54013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com
55013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com    heap.deferAddingOwners();
56013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com    int index = dictionary.find(*bitmapShader);
57013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com    heap.endAddingOwnersDeferral(true);
58013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com
59013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com    // The dictionary and heap should now each have one entry.
60013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com    REPORTER_ASSERT(reporter, 1 == index);
61013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com    REPORTER_ASSERT(reporter, heap.count() == 1);
62013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com    REPORTER_ASSERT(reporter, dictionary.count() == 1);
63013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com
64013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com    // The bitmap entry's refcount should be 1, then 0 after release.
65013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com    SkBitmapHeapEntry* entry = heap.getEntry(0);
66013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com    REPORTER_ASSERT(reporter, SkBitmapHeapTester::GetRefCount(entry) == 1);
67013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com
68013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com    entry->releaseRef();
69013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com    REPORTER_ASSERT(reporter, SkBitmapHeapTester::GetRefCount(entry) == 0);
70013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com
71013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com    // Now clear out the heap, after which it should be empty.
72013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com    heap.freeMemoryIfPossible(~0U);
73013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com    REPORTER_ASSERT(reporter, heap.count() == 0);
74013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com
75013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com    // Now attempt to flatten the shader again.
76013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com    heap.deferAddingOwners();
77013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com    index = dictionary.find(*bitmapShader);
78013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com    heap.endAddingOwnersDeferral(false);
79013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com
80013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com    // The dictionary should report the same index since the new entry is identical.
81013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com    // The bitmap heap should contain the bitmap, but with no references.
82013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com    REPORTER_ASSERT(reporter, 1 == index);
83013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com    REPORTER_ASSERT(reporter, heap.count() == 1);
84013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com    REPORTER_ASSERT(reporter, SkBitmapHeapTester::GetRefCount(heap.getEntry(0)) == 0);
85013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com}
86