BitmapHolder::BitmapHolder(SkReader32* reader, uint32_t op32, SkGPipeState* state) { const unsigned flags = state->getFlags(); const unsigned index = DrawOp_unpackData(op32); if (shouldFlattenBitmaps(flags)) { fHeapEntry = NULL; fBitmap = state->getBitmap(index); } else { SkBitmapHeapEntry* entry = state->getSharedHeap()->getEntry(index); if (SkToBool(flags & SkGPipeWriter::kSimultaneousReaders_Flag)) { // Make a shallow copy for thread safety. Each thread will point to the same SkPixelRef, // which is thread safe. fBitmapStorage = *entry->getBitmap(); fBitmap = &fBitmapStorage; // Release the ref on the bitmap now, since we made our own copy. entry->releaseRef(); fHeapEntry = NULL; } else { SkASSERT(!shouldFlattenBitmaps(flags)); SkASSERT(!SkToBool(flags & SkGPipeWriter::kSimultaneousReaders_Flag)); fHeapEntry = entry; fBitmap = fHeapEntry->getBitmap(); } } }
static void TestBitmapHeap(skiatest::Reporter* reporter) { // Create a bitmap shader. SkBitmap bm; bm.setConfig(SkBitmap::kARGB_8888_Config, 2, 2); bm.allocPixels(); bm.eraseColor(SK_ColorRED); uint32_t* pixel = bm.getAddr32(1,0); *pixel = SK_ColorBLUE; SkShader* bitmapShader = SkShader::CreateBitmapShader(bm, SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode); SkAutoTUnref<SkShader> aur(bitmapShader); // Flatten, storing it in the bitmap heap. SkBitmapHeap heap(1, 1); SkChunkFlatController controller(1024); controller.setBitmapStorage(&heap); FlatDictionary dictionary(&controller); // Dictionary and heap start off empty. REPORTER_ASSERT(reporter, heap.count() == 0); REPORTER_ASSERT(reporter, dictionary.count() == 0); heap.deferAddingOwners(); int index = dictionary.find(*bitmapShader); heap.endAddingOwnersDeferral(true); // The dictionary and heap should now each have one entry. REPORTER_ASSERT(reporter, 1 == index); REPORTER_ASSERT(reporter, heap.count() == 1); REPORTER_ASSERT(reporter, dictionary.count() == 1); // The bitmap entry's refcount should be 1, then 0 after release. SkBitmapHeapEntry* entry = heap.getEntry(0); REPORTER_ASSERT(reporter, SkBitmapHeapTester::GetRefCount(entry) == 1); entry->releaseRef(); REPORTER_ASSERT(reporter, SkBitmapHeapTester::GetRefCount(entry) == 0); // Now clear out the heap, after which it should be empty. heap.freeMemoryIfPossible(~0U); REPORTER_ASSERT(reporter, heap.count() == 0); // Now attempt to flatten the shader again. heap.deferAddingOwners(); index = dictionary.find(*bitmapShader); heap.endAddingOwnersDeferral(false); // The dictionary should report the same index since the new entry is identical. // The bitmap heap should contain the bitmap, but with no references. REPORTER_ASSERT(reporter, 1 == index); REPORTER_ASSERT(reporter, heap.count() == 1); REPORTER_ASSERT(reporter, SkBitmapHeapTester::GetRefCount(heap.getEntry(0)) == 0); }