scroggo@google.com | 013c5d9 | 2012-11-16 20:34:37 +0000 | [diff] [blame] | 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" |
commit-bot@chromium.org | 8b0e8ac | 2014-01-30 18:58:24 +0000 | [diff] [blame] | 12 | #include "SkWriteBuffer.h" |
scroggo@google.com | 013c5d9 | 2012-11-16 20:34:37 +0000 | [diff] [blame] | 13 | #include "SkPictureFlat.h" |
| 14 | #include "SkRefCnt.h" |
| 15 | #include "SkShader.h" |
| 16 | #include "Test.h" |
| 17 | |
mtklein | a74ce85 | 2014-11-12 09:19:02 -0800 | [diff] [blame] | 18 | struct SimpleFlatController : public SkFlatController { |
| 19 | SimpleFlatController() : SkFlatController() {} |
mtklein | 391e318 | 2014-11-12 10:09:10 -0800 | [diff] [blame] | 20 | ~SimpleFlatController() { fAllocations.freeAll(); } |
mtklein | 72c9faa | 2015-01-09 10:06:39 -0800 | [diff] [blame] | 21 | void* allocThrow(size_t bytes) SK_OVERRIDE { |
mtklein | 391e318 | 2014-11-12 10:09:10 -0800 | [diff] [blame] | 22 | fAllocations.push(sk_malloc_throw(bytes)); |
| 23 | return fAllocations.top(); |
| 24 | } |
mtklein | 72c9faa | 2015-01-09 10:06:39 -0800 | [diff] [blame] | 25 | void unalloc(void*) SK_OVERRIDE { } |
mtklein | a74ce85 | 2014-11-12 09:19:02 -0800 | [diff] [blame] | 26 | void setBitmapStorage(SkBitmapHeap* h) { this->setBitmapHeap(h); } |
mtklein | 391e318 | 2014-11-12 10:09:10 -0800 | [diff] [blame] | 27 | private: |
| 28 | SkTDArray<void*> fAllocations; |
mtklein | a74ce85 | 2014-11-12 09:19:02 -0800 | [diff] [blame] | 29 | }; |
| 30 | |
commit-bot@chromium.org | 07adb63 | 2014-01-02 22:20:49 +0000 | [diff] [blame] | 31 | struct SkShaderTraits { |
commit-bot@chromium.org | 186c0cc | 2014-02-18 16:15:05 +0000 | [diff] [blame] | 32 | static void Flatten(SkWriteBuffer& buffer, const SkShader& shader) { |
commit-bot@chromium.org | 07adb63 | 2014-01-02 22:20:49 +0000 | [diff] [blame] | 33 | buffer.writeFlattenable(&shader); |
scroggo@google.com | 013c5d9 | 2012-11-16 20:34:37 +0000 | [diff] [blame] | 34 | } |
| 35 | }; |
commit-bot@chromium.org | 07adb63 | 2014-01-02 22:20:49 +0000 | [diff] [blame] | 36 | typedef SkFlatDictionary<SkShader, SkShaderTraits> FlatDictionary; |
scroggo@google.com | 013c5d9 | 2012-11-16 20:34:37 +0000 | [diff] [blame] | 37 | |
| 38 | class SkBitmapHeapTester { |
scroggo@google.com | 013c5d9 | 2012-11-16 20:34:37 +0000 | [diff] [blame] | 39 | public: |
| 40 | static int32_t GetRefCount(const SkBitmapHeapEntry* entry) { |
| 41 | return entry->fRefCount; |
| 42 | } |
| 43 | }; |
| 44 | |
tfarina@chromium.org | e4fafb1 | 2013-12-12 21:11:12 +0000 | [diff] [blame] | 45 | DEF_TEST(BitmapHeap, reporter) { |
scroggo@google.com | 013c5d9 | 2012-11-16 20:34:37 +0000 | [diff] [blame] | 46 | // Create a bitmap shader. |
| 47 | SkBitmap bm; |
commit-bot@chromium.org | fa9e5fa | 2014-02-13 22:00:04 +0000 | [diff] [blame] | 48 | bm.allocN32Pixels(2, 2); |
scroggo@google.com | 013c5d9 | 2012-11-16 20:34:37 +0000 | [diff] [blame] | 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); |
mtklein | a74ce85 | 2014-11-12 09:19:02 -0800 | [diff] [blame] | 59 | SimpleFlatController controller; |
scroggo@google.com | 013c5d9 | 2012-11-16 20:34:37 +0000 | [diff] [blame] | 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 | } |