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 18 struct SimpleFlatController : public SkFlatController { 19 SimpleFlatController() : SkFlatController() {} 20 ~SimpleFlatController() { fAllocations.freeAll(); } 21 void* allocThrow(size_t bytes) override { 22 fAllocations.push(sk_malloc_throw(bytes)); 23 return fAllocations.top(); 24 } 25 void unalloc(void*) override { } 26 void setBitmapStorage(SkBitmapHeap* h) { this->setBitmapHeap(h); } 27 private: 28 SkTDArray<void*> fAllocations; 29 }; 30 31 struct SkShaderTraits { 32 static void Flatten(SkWriteBuffer& buffer, const SkShader& shader) { 33 buffer.writeFlattenable(&shader); 34 } 35 }; 36 typedef SkFlatDictionary<SkShader, SkShaderTraits> FlatDictionary; 37 38 class SkBitmapHeapTester { 39 public: 40 static int32_t GetRefCount(const SkBitmapHeapEntry* entry) { 41 return entry->fRefCount; 42 } 43 }; 44 45 DEF_TEST(BitmapHeap, reporter) { 46 // Create a bitmap shader. 47 SkBitmap bm; 48 bm.allocN32Pixels(2, 2); 49 bm.eraseColor(SK_ColorRED); 50 uint32_t* pixel = bm.getAddr32(1,0); 51 *pixel = SK_ColorBLUE; 52 53 SkShader* bitmapShader = SkShader::CreateBitmapShader(bm, SkShader::kRepeat_TileMode, 54 SkShader::kRepeat_TileMode); 55 SkAutoTUnref<SkShader> aur(bitmapShader); 56 57 // Flatten, storing it in the bitmap heap. 58 SkBitmapHeap heap(1, 1); 59 SimpleFlatController controller; 60 controller.setBitmapStorage(&heap); 61 FlatDictionary dictionary(&controller); 62 63 // Dictionary and heap start off empty. 64 REPORTER_ASSERT(reporter, heap.count() == 0); 65 REPORTER_ASSERT(reporter, dictionary.count() == 0); 66 67 heap.deferAddingOwners(); 68 int index = dictionary.find(*bitmapShader); 69 heap.endAddingOwnersDeferral(true); 70 71 // The dictionary and heap should now each have one entry. 72 REPORTER_ASSERT(reporter, 1 == index); 73 REPORTER_ASSERT(reporter, heap.count() == 1); 74 REPORTER_ASSERT(reporter, dictionary.count() == 1); 75 76 // The bitmap entry's refcount should be 1, then 0 after release. 77 SkBitmapHeapEntry* entry = heap.getEntry(0); 78 REPORTER_ASSERT(reporter, SkBitmapHeapTester::GetRefCount(entry) == 1); 79 80 entry->releaseRef(); 81 REPORTER_ASSERT(reporter, SkBitmapHeapTester::GetRefCount(entry) == 0); 82 83 // Now clear out the heap, after which it should be empty. 84 heap.freeMemoryIfPossible(~0U); 85 REPORTER_ASSERT(reporter, heap.count() == 0); 86 87 // Now attempt to flatten the shader again. 88 heap.deferAddingOwners(); 89 index = dictionary.find(*bitmapShader); 90 heap.endAddingOwnersDeferral(false); 91 92 // The dictionary should report the same index since the new entry is identical. 93 // The bitmap heap should contain the bitmap, but with no references. 94 REPORTER_ASSERT(reporter, 1 == index); 95 REPORTER_ASSERT(reporter, heap.count() == 1); 96 REPORTER_ASSERT(reporter, SkBitmapHeapTester::GetRefCount(heap.getEntry(0)) == 0); 97 } 98