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