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
18a74ce853c824c5ae30e219ddf46a61d91cc0ab2amtkleinstruct SimpleFlatController : public SkFlatController {
19a74ce853c824c5ae30e219ddf46a61d91cc0ab2amtklein    SimpleFlatController() : SkFlatController() {}
20391e318b3d31669ecef5306cb279618c121e45afmtklein    ~SimpleFlatController() { fAllocations.freeAll(); }
2136352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void* allocThrow(size_t bytes) override {
22391e318b3d31669ecef5306cb279618c121e45afmtklein        fAllocations.push(sk_malloc_throw(bytes));
23391e318b3d31669ecef5306cb279618c121e45afmtklein        return fAllocations.top();
24391e318b3d31669ecef5306cb279618c121e45afmtklein    }
2536352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void unalloc(void*) override { }
26a74ce853c824c5ae30e219ddf46a61d91cc0ab2amtklein    void setBitmapStorage(SkBitmapHeap* h) { this->setBitmapHeap(h); }
27391e318b3d31669ecef5306cb279618c121e45afmtkleinprivate:
28391e318b3d31669ecef5306cb279618c121e45afmtklein    SkTDArray<void*> fAllocations;
29a74ce853c824c5ae30e219ddf46a61d91cc0ab2amtklein};
30a74ce853c824c5ae30e219ddf46a61d91cc0ab2amtklein
3107adb6359fd137ccb633b2c64ee2287c8edfd701commit-bot@chromium.orgstruct SkShaderTraits {
32186c0ccac25229534ec6fb84726043083304d4d1commit-bot@chromium.org    static void Flatten(SkWriteBuffer& buffer, const SkShader& shader) {
3307adb6359fd137ccb633b2c64ee2287c8edfd701commit-bot@chromium.org        buffer.writeFlattenable(&shader);
34013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com    }
35013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com};
3607adb6359fd137ccb633b2c64ee2287c8edfd701commit-bot@chromium.orgtypedef SkFlatDictionary<SkShader, SkShaderTraits> FlatDictionary;
37013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com
38013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.comclass SkBitmapHeapTester {
39013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.compublic:
40013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com    static int32_t GetRefCount(const SkBitmapHeapEntry* entry) {
41013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com        return entry->fRefCount;
42013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com    }
43013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com};
44013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com
45e4fafb146e85cdfcf9d5418597b6818aa0754adatfarina@chromium.orgDEF_TEST(BitmapHeap, reporter) {
46013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com    // Create a bitmap shader.
47013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com    SkBitmap bm;
48fa9e5fa42a555712fb7a29d08d2ae2bdef0ed68ecommit-bot@chromium.org    bm.allocN32Pixels(2, 2);
49013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com    bm.eraseColor(SK_ColorRED);
50013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com    uint32_t* pixel = bm.getAddr32(1,0);
51013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com    *pixel = SK_ColorBLUE;
52013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com
53013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com    SkShader* bitmapShader = SkShader::CreateBitmapShader(bm, SkShader::kRepeat_TileMode,
54013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com                                                          SkShader::kRepeat_TileMode);
55013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com    SkAutoTUnref<SkShader> aur(bitmapShader);
56013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com
57013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com    // Flatten, storing it in the bitmap heap.
58013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com    SkBitmapHeap heap(1, 1);
59a74ce853c824c5ae30e219ddf46a61d91cc0ab2amtklein    SimpleFlatController controller;
60013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com    controller.setBitmapStorage(&heap);
61013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com    FlatDictionary dictionary(&controller);
62013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com
63013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com    // Dictionary and heap start off empty.
64013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com    REPORTER_ASSERT(reporter, heap.count() == 0);
65013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com    REPORTER_ASSERT(reporter, dictionary.count() == 0);
66013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com
67013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com    heap.deferAddingOwners();
68013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com    int index = dictionary.find(*bitmapShader);
69013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com    heap.endAddingOwnersDeferral(true);
70013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com
71013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com    // The dictionary and heap should now each have one entry.
72013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com    REPORTER_ASSERT(reporter, 1 == index);
73013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com    REPORTER_ASSERT(reporter, heap.count() == 1);
74013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com    REPORTER_ASSERT(reporter, dictionary.count() == 1);
75013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com
76013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com    // The bitmap entry's refcount should be 1, then 0 after release.
77013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com    SkBitmapHeapEntry* entry = heap.getEntry(0);
78013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com    REPORTER_ASSERT(reporter, SkBitmapHeapTester::GetRefCount(entry) == 1);
79013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com
80013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com    entry->releaseRef();
81013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com    REPORTER_ASSERT(reporter, SkBitmapHeapTester::GetRefCount(entry) == 0);
82013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com
83013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com    // Now clear out the heap, after which it should be empty.
84013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com    heap.freeMemoryIfPossible(~0U);
85013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com    REPORTER_ASSERT(reporter, heap.count() == 0);
86013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com
87013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com    // Now attempt to flatten the shader again.
88013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com    heap.deferAddingOwners();
89013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com    index = dictionary.find(*bitmapShader);
90013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com    heap.endAddingOwnersDeferral(false);
91013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com
92013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com    // The dictionary should report the same index since the new entry is identical.
93013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com    // The bitmap heap should contain the bitmap, but with no references.
94013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com    REPORTER_ASSERT(reporter, 1 == index);
95013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com    REPORTER_ASSERT(reporter, heap.count() == 1);
96013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com    REPORTER_ASSERT(reporter, SkBitmapHeapTester::GetRefCount(heap.getEntry(0)) == 0);
97013c5d9107a4abd50e879ca66cf60b0c3a8256d4scroggo@google.com}
98