From fdb9b212a8590204e99d49d08b8b9bf19f0b2f67 Mon Sep 17 00:00:00 2001 From: "tomhudson@google.com" Date: Mon, 13 Aug 2012 18:20:14 +0000 Subject: [PATCH] Revert r5063 until unit tests can be fixed. git-svn-id: http://skia.googlecode.com/svn/trunk@5067 2bbb7eff-a529-9590-31e7-b0007b416f81 --- src/core/SkBitmapHeap.cpp | 147 ++++++++++++-------------------- src/core/SkBitmapHeap.h | 86 +++++++++---------- src/pipe/SkGPipeRead.cpp | 3 +- src/pipe/SkGPipeWrite.cpp | 172 +++++++++++++++++++++----------------- 4 files changed, 190 insertions(+), 218 deletions(-) diff --git a/src/core/SkBitmapHeap.cpp b/src/core/SkBitmapHeap.cpp index d9b338a415..924264bf5c 100644 --- a/src/core/SkBitmapHeap.cpp +++ b/src/core/SkBitmapHeap.cpp @@ -15,7 +15,9 @@ SkBitmapHeapEntry::SkBitmapHeapEntry() : fSlot(-1) , fRefCount(0) - , fBytesAllocated(0) { + , fBytesAllocated(0) + , fMoreRecentlyUsed(NULL) + , fLessRecentlyUsed(NULL) { } SkBitmapHeapEntry::~SkBitmapHeapEntry() { @@ -35,30 +37,6 @@ void SkBitmapHeapEntry::addReferences(int count) { /////////////////////////////////////////////////////////////////////////////// -int SkBitmapHeap::LookupEntry::Compare(const SkBitmapHeap::LookupEntry *a, - const SkBitmapHeap::LookupEntry *b) { - if (a->fGenerationId < b->fGenerationId) { - return -1; - } else if (a->fGenerationId > b->fGenerationId) { - return 1; - } else if (a->fPixelOffset < b->fPixelOffset) { - return -1; - } else if (a->fPixelOffset > b->fPixelOffset) { - return 1; - } else if (a->fWidth < b->fWidth) { - return -1; - } else if (a->fWidth > b->fWidth) { - return 1; - } else if (a->fHeight < b->fHeight) { - return -1; - } else if (a->fHeight > b->fHeight) { - return 1; - } - return 0; -} - -/////////////////////////////////////////////////////////////////////////////// - SkBitmapHeap::SkBitmapHeap(int32_t preferredSize, int32_t ownerCount) : INHERITED() , fExternalStorage(NULL) @@ -114,35 +92,27 @@ SkTRefArray* SkBitmapHeap::extractBitmaps() const { return array; } -void SkBitmapHeap::removeFromLRU(SkBitmapHeap::LookupEntry* entry) { - if (fMostRecentlyUsed == entry) { - fMostRecentlyUsed = entry->fLessRecentlyUsed; - if (NULL == fMostRecentlyUsed) { - SkASSERT(fLeastRecentlyUsed == entry); - fLeastRecentlyUsed = NULL; - } else { - fMostRecentlyUsed->fMoreRecentlyUsed = NULL; - } - } else { - // Remove entry from its prior place, and make sure to cover the hole. - if (fLeastRecentlyUsed == entry) { - SkASSERT(entry->fMoreRecentlyUsed != NULL); - fLeastRecentlyUsed = entry->fMoreRecentlyUsed; - } - // Since we have already considered the case where entry is the most recently used, it must - // have a more recently used at this point. +// We just "used" the entry. Update our LRU accordingly +void SkBitmapHeap::setMostRecentlyUsed(SkBitmapHeapEntry* entry) { + SkASSERT(entry != NULL); + if (entry == fMostRecentlyUsed) { + return; + } + // Remove info from its prior place, and make sure to cover the hole. + if (fLeastRecentlyUsed == entry) { SkASSERT(entry->fMoreRecentlyUsed != NULL); + fLeastRecentlyUsed = entry->fMoreRecentlyUsed; + } + if (entry->fMoreRecentlyUsed != NULL) { + SkASSERT(fMostRecentlyUsed != entry); entry->fMoreRecentlyUsed->fLessRecentlyUsed = entry->fLessRecentlyUsed; - - if (entry->fLessRecentlyUsed != NULL) { - SkASSERT(fLeastRecentlyUsed != entry); - entry->fLessRecentlyUsed->fMoreRecentlyUsed = entry->fMoreRecentlyUsed; - } + } + if (entry->fLessRecentlyUsed != NULL) { + SkASSERT(fLeastRecentlyUsed != entry); + entry->fLessRecentlyUsed->fMoreRecentlyUsed = entry->fMoreRecentlyUsed; } entry->fMoreRecentlyUsed = NULL; -} - -void SkBitmapHeap::appendToLRU(SkBitmapHeap::LookupEntry* entry) { + // Set up the head and tail pointers properly. if (fMostRecentlyUsed != NULL) { SkASSERT(NULL == fMostRecentlyUsed->fMoreRecentlyUsed); fMostRecentlyUsed->fMoreRecentlyUsed = entry; @@ -155,20 +125,19 @@ void SkBitmapHeap::appendToLRU(SkBitmapHeap::LookupEntry* entry) { } // iterate through our LRU cache and try to find an entry to evict -SkBitmapHeap::LookupEntry* SkBitmapHeap::findEntryToReplace(const SkBitmap& replacement) { +SkBitmapHeapEntry* SkBitmapHeap::findEntryToReplace(const SkBitmap& replacement) { SkASSERT(fPreferredCount != UNLIMITED_SIZE); SkASSERT(fStorage.count() >= fPreferredCount); - SkBitmapHeap::LookupEntry* iter = fLeastRecentlyUsed; + SkBitmapHeapEntry* iter = fLeastRecentlyUsed; while (iter != NULL) { - SkBitmapHeapEntry* heapEntry = fStorage[iter->fStorageSlot]; - if (heapEntry->fRefCount > 0) { + if (iter->fRefCount > 0) { // If the least recently used bitmap has not been unreferenced // by its owner, then according to our LRU specifications a more // recently used one can not have used all it's references yet either. return NULL; } - if (replacement.getGenerationID() == iter->fGenerationId) { + if (replacement.pixelRef() && replacement.pixelRef() == iter->fBitmap.pixelRef()) { // Do not replace a bitmap with a new one using the same // pixel ref. Instead look for a different one that will // potentially free up more space. @@ -184,22 +153,21 @@ size_t SkBitmapHeap::freeMemoryIfPossible(size_t bytesToFree) { if (UNLIMITED_SIZE == fPreferredCount) { return 0; } - LookupEntry* iter = fLeastRecentlyUsed; + SkBitmapHeapEntry* iter = fLeastRecentlyUsed; size_t origBytesAllocated = fBytesAllocated; // Purge starting from LRU until a non-evictable bitmap is found or until // everything is evicted. - while (iter != NULL) { - SkBitmapHeapEntry* heapEntry = fStorage[iter->fStorageSlot]; - if (heapEntry->fRefCount > 0) { - break; - } - LookupEntry* next = iter->fMoreRecentlyUsed; - this->removeEntryFromLookupTable(iter); + while (iter && 0 == iter->fRefCount) { + SkBitmapHeapEntry* next = iter->fMoreRecentlyUsed; + this->removeEntryFromLookupTable(*iter); // Free the pixel memory. removeEntryFromLookupTable already reduced // fBytesAllocated properly. - heapEntry->fBitmap.reset(); + iter->fBitmap.reset(); // Add to list of unused slots which can be reused in the future. - fUnusedSlots.push(heapEntry->fSlot); + fUnusedSlots.push(iter->fSlot); + // Remove its LRU pointers, so that it does not pretend it is already in + // the list the next time it is used. + iter->fMoreRecentlyUsed = iter->fLessRecentlyUsed = NULL; iter = next; if (origBytesAllocated - fBytesAllocated >= bytesToFree) { break; @@ -225,17 +193,17 @@ size_t SkBitmapHeap::freeMemoryIfPossible(size_t bytesToFree) { } int SkBitmapHeap::findInLookupTable(const LookupEntry& indexEntry, SkBitmapHeapEntry** entry) { - int index = SkTSearch((const LookupEntry**)fLookupTable.begin(), + int index = SkTSearch(fLookupTable.begin(), fLookupTable.count(), - &indexEntry, sizeof(void*), LookupEntry::Compare); + indexEntry, sizeof(indexEntry)); if (index < 0) { // insert ourselves into the bitmapIndex index = ~index; - *fLookupTable.insert(index) = SkNEW_ARGS(LookupEntry, (indexEntry)); + fLookupTable.insert(index, 1, &indexEntry); } else if (entry != NULL) { // populate the entry if needed - *entry = fStorage[fLookupTable[index]->fStorageSlot]; + *entry = fStorage[fLookupTable[index].fStorageSlot]; } return index; @@ -261,16 +229,19 @@ bool SkBitmapHeap::copyBitmap(const SkBitmap& originalBitmap, SkBitmap& copiedBi return true; } -int SkBitmapHeap::removeEntryFromLookupTable(LookupEntry* entry) { +int SkBitmapHeap::removeEntryFromLookupTable(const SkBitmapHeapEntry& entry) { // remove the bitmap index for the deleted entry SkDEBUGCODE(int count = fLookupTable.count();) - int index = this->findInLookupTable(*entry, NULL); + // FIXME: If copying bitmaps retained the generation ID, we could + // just grab the generation ID from entry.fBitmap + LookupEntry key(entry.fBitmap, entry.fGenerationID); + int index = this->findInLookupTable(key, NULL); // Verify that findInLookupTable found an existing entry rather than adding // a new entry to the lookup table. SkASSERT(count == fLookupTable.count()); - SkDELETE(fLookupTable[index]); + fLookupTable.remove(index); - fBytesAllocated -= fStorage[entry->fStorageSlot]->fBytesAllocated; + fBytesAllocated -= entry.fBytesAllocated; return index; } @@ -278,17 +249,13 @@ int32_t SkBitmapHeap::insert(const SkBitmap& originalBitmap) { SkBitmapHeapEntry* entry = NULL; int searchIndex = this->findInLookupTable(LookupEntry(originalBitmap), &entry); + // check to see if we already had a copy of the bitmap in the heap if (entry) { - // Already had a copy of the bitmap in the heap. if (fOwnerCount != IGNORE_OWNERS) { entry->addReferences(fOwnerCount); } if (fPreferredCount != UNLIMITED_SIZE) { - LookupEntry* lookupEntry = fLookupTable[searchIndex]; - if (lookupEntry != fMostRecentlyUsed) { - this->removeFromLRU(lookupEntry); - this->appendToLRU(lookupEntry); - } + this->setMostRecentlyUsed(entry); } return entry->fSlot; } @@ -296,13 +263,10 @@ int32_t SkBitmapHeap::insert(const SkBitmap& originalBitmap) { // decide if we need to evict an existing heap entry or create a new one if (fPreferredCount != UNLIMITED_SIZE && fStorage.count() >= fPreferredCount) { // iterate through our LRU cache and try to find an entry to evict - LookupEntry* lookupEntry = this->findEntryToReplace(originalBitmap); - if (lookupEntry != NULL) { - // we found an entry to evict - entry = fStorage[lookupEntry->fStorageSlot]; - // Remove it from the LRU. The new entry will be added to the LRU later. - this->removeFromLRU(lookupEntry); - int index = this->removeEntryFromLookupTable(lookupEntry); + entry = this->findEntryToReplace(originalBitmap); + // we found an entry to evict + if (entry) { + int index = this->removeEntryFromLookupTable(*entry); // update the current search index now that we have removed one if (index < searchIndex) { @@ -336,7 +300,6 @@ int32_t SkBitmapHeap::insert(const SkBitmap& originalBitmap) { // if the copy failed then we must abort if (!copySucceeded) { // delete the index - SkDELETE(fLookupTable[searchIndex]); fLookupTable.remove(searchIndex); // If entry is the last slot in storage, it is safe to delete it. if (fStorage.count() - 1 == entry->fSlot) { @@ -344,16 +307,14 @@ int32_t SkBitmapHeap::insert(const SkBitmap& originalBitmap) { fStorage.remove(entry->fSlot); fBytesAllocated -= sizeof(SkBitmapHeapEntry); SkDELETE(entry); - } else { - fUnusedSlots.push(entry->fSlot); } return INVALID_SLOT; } // update the index with the appropriate slot in the heap - fLookupTable[searchIndex]->fStorageSlot = entry->fSlot; + fLookupTable[searchIndex].fStorageSlot = entry->fSlot; - // compute the space taken by this entry + // compute the space taken by the this entry // TODO if there is a shared pixel ref don't count it // If the SkBitmap does not share an SkPixelRef with an SkBitmap already // in the SharedHeap, also include the size of its pixels. @@ -362,11 +323,13 @@ int32_t SkBitmapHeap::insert(const SkBitmap& originalBitmap) { // add the bytes from this entry to the total count fBytesAllocated += entry->fBytesAllocated; + entry->fGenerationID = originalBitmap.getGenerationID(); + if (fOwnerCount != IGNORE_OWNERS) { entry->addReferences(fOwnerCount); } if (fPreferredCount != UNLIMITED_SIZE) { - this->appendToLRU(fLookupTable[searchIndex]); + this->setMostRecentlyUsed(entry); } return entry->fSlot; } diff --git a/src/core/SkBitmapHeap.h b/src/core/SkBitmapHeap.h index 71c340539f..3c00b5211b 100644 --- a/src/core/SkBitmapHeap.h +++ b/src/core/SkBitmapHeap.h @@ -39,12 +39,16 @@ private: int32_t fSlot; int32_t fRefCount; + uint32_t fGenerationID; SkBitmap fBitmap; // Keep track of the bytes allocated for this bitmap. When replacing the // bitmap or removing this HeapEntry we know how much memory has been // reclaimed. size_t fBytesAllocated; + // TODO: Generalize the LRU caching mechanism + SkBitmapHeapEntry* fMoreRecentlyUsed; + SkBitmapHeapEntry* fLessRecentlyUsed; friend class SkBitmapHeap; }; @@ -172,8 +176,7 @@ public: * Returns a count of the number of items currently in the heap */ int count() const { - SkASSERT(fExternalStorage != NULL || - fStorage.count() - fUnusedSlots.count() == fLookupTable.count()); + SkASSERT(fExternalStorage != NULL || fStorage.count() == fLookupTable.count()); return fLookupTable.count(); } @@ -194,39 +197,43 @@ public: private: struct LookupEntry { - LookupEntry(const SkBitmap& bm) - : fGenerationId(bm.getGenerationID()) - , fPixelOffset(bm.pixelRefOffset()) - , fWidth(bm.width()) - , fHeight(bm.height()) - , fMoreRecentlyUsed(NULL) - , fLessRecentlyUsed(NULL){} - - const uint32_t fGenerationId; // SkPixelRef GenerationID. - const size_t fPixelOffset; - const uint32_t fWidth; - const uint32_t fHeight; - - // TODO: Generalize the LRU caching mechanism - LookupEntry* fMoreRecentlyUsed; - LookupEntry* fLessRecentlyUsed; + LookupEntry(const SkBitmap& bm, uint32_t genId = 0) { + fGenerationId = 0 == genId ? bm.getGenerationID() : genId; + fPixelOffset = bm.pixelRefOffset(); + fWidth = bm.width(); + fHeight = bm.height(); + } + uint32_t fGenerationId; // SkPixelRef GenerationID. + size_t fPixelOffset; + uint32_t fWidth; + uint32_t fHeight; uint32_t fStorageSlot; // slot of corresponding bitmap in fStorage. - /** - * Compare two LookupEntry pointers, returning -1, 0, 1 for sorting. - */ - static int Compare(const LookupEntry* a, const LookupEntry* b); + bool operator < (const LookupEntry& other) const { + if (this->fGenerationId != other.fGenerationId) { + return this->fGenerationId < other.fGenerationId; + } else if(this->fPixelOffset != other.fPixelOffset) { + return this->fPixelOffset < other.fPixelOffset; + } else if(this->fWidth != other.fWidth) { + return this->fWidth < other.fWidth; + } else { + return this->fHeight < other.fHeight; + } + } + bool operator != (const LookupEntry& other) const { + return this->fGenerationId != other.fGenerationId + || this->fPixelOffset != other.fPixelOffset + || this->fWidth != other.fWidth + || this->fHeight != other.fHeight; + } }; /** - * Remove the entry from the lookup table. Also deletes the entry pointed - * to by the table. Therefore, if a pointer to that one was passed in, the - * pointer should no longer be used, since the object to which it points has - * been deleted. + * Remove the entry from the lookup table. * @return The index in the lookup table of the entry before removal. */ - int removeEntryFromLookupTable(LookupEntry*); + int removeEntryFromLookupTable(const SkBitmapHeapEntry&); /** * Searches for the bitmap in the lookup table and returns the bitmaps index within the table. @@ -238,27 +245,12 @@ private: */ int findInLookupTable(const LookupEntry& key, SkBitmapHeapEntry** entry); - LookupEntry* findEntryToReplace(const SkBitmap& replacement); + SkBitmapHeapEntry* findEntryToReplace(const SkBitmap& replacement); bool copyBitmap(const SkBitmap& originalBitmap, SkBitmap& copiedBitmap); - - /** - * Remove a LookupEntry from the LRU, in preparation for either deleting or appending as most - * recent. Points the LookupEntry's old neighbors at each other, and sets fLeastRecentlyUsed - * (if there is still an entry left). Sets LookupEntry's fMoreRecentlyUsed to NULL and leaves - * its fLessRecentlyUsed unmodified. - */ - void removeFromLRU(LookupEntry* entry); - - /** - * Append a LookupEntry to the end of the LRU cache, marking it as the most - * recently used. Assumes that the LookupEntry is already in fLookupTable, - * but is not in the LRU cache. If it is in the cache, removeFromLRU should - * be called first. - */ - void appendToLRU(LookupEntry*); + void setMostRecentlyUsed(SkBitmapHeapEntry* entry); // searchable index that maps to entries in the heap - SkTDArray fLookupTable; + SkTDArray fLookupTable; // heap storage SkTDArray fStorage; @@ -267,8 +259,8 @@ private: SkTDArray fUnusedSlots; ExternalStorage* fExternalStorage; - LookupEntry* fMostRecentlyUsed; - LookupEntry* fLeastRecentlyUsed; + SkBitmapHeapEntry* fMostRecentlyUsed; + SkBitmapHeapEntry* fLeastRecentlyUsed; const int32_t fPreferredCount; const int32_t fOwnerCount; diff --git a/src/pipe/SkGPipeRead.cpp b/src/pipe/SkGPipeRead.cpp index 3655107229..e6013db49e 100644 --- a/src/pipe/SkGPipeRead.cpp +++ b/src/pipe/SkGPipeRead.cpp @@ -113,6 +113,7 @@ public: } void addBitmap(int index) { + index--; SkBitmap* bm; if(fBitmaps.count() == index) { bm = SkNEW(SkBitmap); @@ -124,7 +125,7 @@ public: } SkBitmap* getBitmap(unsigned index) { - return fBitmaps[index]; + return fBitmaps[index - 1]; } void setSharedHeap(SkBitmapHeap* heap) { diff --git a/src/pipe/SkGPipeWrite.cpp b/src/pipe/SkGPipeWrite.cpp index fbb67bedec..128a458c9e 100644 --- a/src/pipe/SkGPipeWrite.cpp +++ b/src/pipe/SkGPipeWrite.cpp @@ -163,15 +163,6 @@ public: if (this->needOpBytes()) { this->writeOp(kDone_DrawOp); this->doNotify(); - if (shouldFlattenBitmaps(fFlags)) { - // In this case, a BitmapShuttle is reffed by the SharedHeap - // and refs this canvas. Unref the SharedHeap to end the - // circular reference. When shouldFlattenBitmaps is false, - // there is no circular reference, so the SharedHeap can be - // safely unreffed in the destructor. - fSharedHeap->unref(); - fSharedHeap = NULL; - } } fDone = true; } @@ -181,6 +172,11 @@ public: size_t freeMemoryIfPossible(size_t bytesToFree); size_t storageAllocatedForRecording() { + // FIXME: This can be removed once fSharedHeap is used by cross process + // case. + if (NULL == fSharedHeap) { + return 0; + } return fSharedHeap->bytesAllocated(); } @@ -235,11 +231,6 @@ public: const SkPaint&) SK_OVERRIDE; virtual void drawData(const void*, size_t) SK_OVERRIDE; - /** - * Flatten an SkBitmap to send to the reader, where it will be referenced - * according to slot. - */ - bool shuttleBitmap(const SkBitmap&, int32_t slot); private: enum { kNoSaveLayer = -1, @@ -252,7 +243,7 @@ private: size_t fBlockSize; // amount allocated for writer size_t fBytesNotified; bool fDone; - const uint32_t fFlags; + uint32_t fFlags; SkRefCntSet fTypefaceSet; @@ -282,15 +273,27 @@ private: // if a new SkFlatData was added when in cross process mode void flattenFactoryNames(); + // These are only used when in cross process, but with no shared address + // space, so bitmaps are flattened. + FlattenableHeap fBitmapHeap; + SkBitmapDictionary fBitmapDictionary; + int flattenToIndex(const SkBitmap&); + FlattenableHeap fFlattenableHeap; FlatDictionary fFlatDictionary; int fCurrFlatIndex[kCount_PaintFlats]; int flattenToIndex(SkFlattenable* obj, PaintFlats); - // Common code used by drawBitmap*. Behaves differently depending on the - // type of SkBitmapHeap being used, which is determined by the flags used. - bool commonDrawBitmap(const SkBitmap& bm, DrawOps op, unsigned flags, - size_t opBytesNeeded, const SkPaint* paint); + // Common code used by drawBitmap* when flattening. + bool commonDrawBitmapFlatten(const SkBitmap& bm, DrawOps op, unsigned flags, + size_t opBytesNeeded, const SkPaint* paint); + // Common code used by drawBitmap* when storing in the heap. + bool commonDrawBitmapHeap(const SkBitmap& bm, DrawOps op, unsigned flags, + size_t opBytesNeeded, const SkPaint* paint); + // Convenience type for function pointer + typedef bool (SkGPipeCanvas::*BitmapCommonFunction)(const SkBitmap&, + DrawOps, unsigned, + size_t, const SkPaint*); SkPaint fPaint; void writePaint(const SkPaint&); @@ -318,20 +321,23 @@ void SkGPipeCanvas::flattenFactoryNames() { } } -bool SkGPipeCanvas::shuttleBitmap(const SkBitmap& bm, int32_t slot) { +int SkGPipeCanvas::flattenToIndex(const SkBitmap & bitmap) { SkASSERT(shouldFlattenBitmaps(fFlags)); - SkOrderedWriteBuffer buffer(1024); - buffer.setNamedFactoryRecorder(fFactorySet); - bm.flatten(buffer); - this->flattenFactoryNames(); - uint32_t size = buffer.size(); - if (this->needOpBytes(size)) { - this->writeOp(kDef_Bitmap_DrawOp, 0, slot); - void* dst = static_cast(fWriter.reserve(size)); - buffer.writeToMemory(dst); - return true; + uint32_t flags = SkFlattenableWriteBuffer::kCrossProcess_Flag; + bool added, replaced; + const SkFlatData* flat = fBitmapDictionary.findAndReplace( + bitmap, flags, fBitmapHeap.flatToReplace(), &added, &replaced); + + int index = flat->index(); + if (added) { + this->flattenFactoryNames(); + size_t flatSize = flat->flatSize(); + if (this->needOpBytes(flatSize)) { + this->writeOp(kDef_Bitmap_DrawOp, 0, index); + fWriter.write(flat->data(), flatSize); + } } - return false; + return index; } // return 0 for NULL (or unflattenable obj), or index-base-1 @@ -371,24 +377,6 @@ int SkGPipeCanvas::flattenToIndex(SkFlattenable* obj, PaintFlats paintflat) { /////////////////////////////////////////////////////////////////////////////// -/** - * If SkBitmaps are to be flattened to send to the reader, this class is - * provided to the SkBitmapHeap to tell the SkGPipeCanvas to do so. - */ -class BitmapShuttle : public SkBitmapHeap::ExternalStorage { -public: - BitmapShuttle(SkGPipeCanvas*); - - ~BitmapShuttle(); - - virtual bool insert(const SkBitmap& bitmap, int32_t slot) SK_OVERRIDE; - -private: - SkGPipeCanvas* fCanvas; -}; - -/////////////////////////////////////////////////////////////////////////////// - #define MIN_BLOCK_SIZE (16 * 1024) #define BITMAPS_TO_KEEP 5 #define FLATTENABLES_TO_KEEP 10 @@ -398,6 +386,8 @@ SkGPipeCanvas::SkGPipeCanvas(SkGPipeController* controller, : fFactorySet(isCrossProcess(flags) ? SkNEW(SkNamedFactorySet) : NULL) , fWriter(*writer) , fFlags(flags) +, fBitmapHeap(BITMAPS_TO_KEEP, fFactorySet) +, fBitmapDictionary(&fBitmapHeap) , fFlattenableHeap(FLATTENABLES_TO_KEEP, fFactorySet) , fFlatDictionary(&fFlattenableHeap) { fController = controller; @@ -421,12 +411,10 @@ SkGPipeCanvas::SkGPipeCanvas(SkGPipeController* controller, } if (shouldFlattenBitmaps(flags)) { - BitmapShuttle* shuttle = SkNEW_ARGS(BitmapShuttle, (this)); - fSharedHeap = SkNEW_ARGS(SkBitmapHeap, (shuttle, BITMAPS_TO_KEEP)); - shuttle->unref(); + // TODO: Use the shared heap for cross process case as well. + fSharedHeap = NULL; } else { - fSharedHeap = SkNEW_ARGS(SkBitmapHeap, - (BITMAPS_TO_KEEP, controller->numberOfReaders())); + fSharedHeap = SkNEW_ARGS(SkBitmapHeap, (5, controller->numberOfReaders())); if (this->needOpBytes(sizeof(void*))) { this->writeOp(kShareHeap_DrawOp); fWriter.writePtr(static_cast(fSharedHeap)); @@ -438,6 +426,8 @@ SkGPipeCanvas::SkGPipeCanvas(SkGPipeController* controller, SkGPipeCanvas::~SkGPipeCanvas() { this->finish(); SkSafeUnref(fFactorySet); + // FIXME: This can be changed to unref() once fSharedHeap is used by cross + // process case. SkSafeUnref(fSharedHeap); } @@ -692,10 +682,26 @@ void SkGPipeCanvas::drawPath(const SkPath& path, const SkPaint& paint) { } } -bool SkGPipeCanvas::commonDrawBitmap(const SkBitmap& bm, DrawOps op, - unsigned flags, - size_t opBytesNeeded, - const SkPaint* paint) { +bool SkGPipeCanvas::commonDrawBitmapFlatten(const SkBitmap& bm, DrawOps op, + unsigned flags, + size_t opBytesNeeded, + const SkPaint* paint) { + if (paint != NULL) { + flags |= kDrawBitmap_HasPaint_DrawOpsFlag; + this->writePaint(*paint); + } + int bitmapIndex = this->flattenToIndex(bm); + if (this->needOpBytes(opBytesNeeded)) { + this->writeOp(op, flags, bitmapIndex); + return true; + } + return false; +} + +bool SkGPipeCanvas::commonDrawBitmapHeap(const SkBitmap& bm, DrawOps op, + unsigned flags, + size_t opBytesNeeded, + const SkPaint* paint) { int32_t bitmapIndex = fSharedHeap->insert(bm); if (SkBitmapHeap::INVALID_SLOT == bitmapIndex) { return false; @@ -716,7 +722,11 @@ void SkGPipeCanvas::drawBitmap(const SkBitmap& bm, SkScalar left, SkScalar top, NOTIFY_SETUP(this); size_t opBytesNeeded = sizeof(SkScalar) * 2; - if (this->commonDrawBitmap(bm, kDrawBitmap_DrawOp, 0, opBytesNeeded, paint)) { + BitmapCommonFunction bitmapCommon = shouldFlattenBitmaps(fFlags) ? + &SkGPipeCanvas::commonDrawBitmapFlatten : + &SkGPipeCanvas::commonDrawBitmapHeap; + + if ((*this.*bitmapCommon)(bm, kDrawBitmap_DrawOp, 0, opBytesNeeded, paint)) { fWriter.writeScalar(left); fWriter.writeScalar(top); } @@ -734,8 +744,12 @@ void SkGPipeCanvas::drawBitmapRect(const SkBitmap& bm, const SkIRect* src, } else { flags = 0; } + + BitmapCommonFunction bitmapCommon = shouldFlattenBitmaps(fFlags) ? + &SkGPipeCanvas::commonDrawBitmapFlatten : + &SkGPipeCanvas::commonDrawBitmapHeap; - if (this->commonDrawBitmap(bm, kDrawBitmapRect_DrawOp, flags, opBytesNeeded, paint)) { + if ((*this.*bitmapCommon)(bm, kDrawBitmapRect_DrawOp, flags, opBytesNeeded, paint)) { if (hasSrc) { fWriter.write32(src->fLeft); fWriter.write32(src->fTop); @@ -751,7 +765,11 @@ void SkGPipeCanvas::drawBitmapMatrix(const SkBitmap& bm, const SkMatrix& matrix, NOTIFY_SETUP(this); size_t opBytesNeeded = matrix.writeToMemory(NULL); - if (this->commonDrawBitmap(bm, kDrawBitmapMatrix_DrawOp, 0, opBytesNeeded, paint)) { + BitmapCommonFunction bitmapCommon = shouldFlattenBitmaps(fFlags) ? + &SkGPipeCanvas::commonDrawBitmapFlatten : + &SkGPipeCanvas::commonDrawBitmapHeap; + + if ((*this.*bitmapCommon)(bm, kDrawBitmapMatrix_DrawOp, 0, opBytesNeeded, paint)) { fWriter.writeMatrix(matrix); } } @@ -761,7 +779,11 @@ void SkGPipeCanvas::drawBitmapNine(const SkBitmap& bm, const SkIRect& center, NOTIFY_SETUP(this); size_t opBytesNeeded = sizeof(int32_t) * 4 + sizeof(SkRect); - if (this->commonDrawBitmap(bm, kDrawBitmapNine_DrawOp, 0, opBytesNeeded, paint)) { + BitmapCommonFunction bitmapCommon = shouldFlattenBitmaps(fFlags) ? + &SkGPipeCanvas::commonDrawBitmapFlatten : + &SkGPipeCanvas::commonDrawBitmapHeap; + + if ((*this.*bitmapCommon)(bm, kDrawBitmapNine_DrawOp, 0, opBytesNeeded, paint)) { fWriter.write32(center.fLeft); fWriter.write32(center.fTop); fWriter.write32(center.fRight); @@ -775,7 +797,11 @@ void SkGPipeCanvas::drawSprite(const SkBitmap& bm, int left, int top, NOTIFY_SETUP(this); size_t opBytesNeeded = sizeof(int32_t) * 2; - if (this->commonDrawBitmap(bm, kDrawSprite_DrawOp, 0, opBytesNeeded, paint)) { + BitmapCommonFunction bitmapCommon = shouldFlattenBitmaps(fFlags) ? + &SkGPipeCanvas::commonDrawBitmapFlatten : + &SkGPipeCanvas::commonDrawBitmapHeap; + + if ((*this.*bitmapCommon)(bm, kDrawSprite_DrawOp, 0, opBytesNeeded, paint)) { fWriter.write32(left); fWriter.write32(top); } @@ -934,6 +960,11 @@ void SkGPipeCanvas::flushRecording(bool detachCurrentBlock) { } size_t SkGPipeCanvas::freeMemoryIfPossible(size_t bytesToFree) { + // FIXME: This can be removed once fSharedHeap is used by cross process + // case. + if (NULL == fSharedHeap) { + return 0; + } return fSharedHeap->freeMemoryIfPossible(bytesToFree); } @@ -1114,18 +1145,3 @@ size_t SkGPipeWriter::storageAllocatedForRecording() const { return NULL == fCanvas ? 0 : fCanvas->storageAllocatedForRecording(); } -/////////////////////////////////////////////////////////////////////////////// - -BitmapShuttle::BitmapShuttle(SkGPipeCanvas* canvas) { - SkASSERT(canvas != NULL); - fCanvas = canvas; - fCanvas->ref(); -} - -BitmapShuttle::~BitmapShuttle() { - fCanvas->unref(); -} - -bool BitmapShuttle::insert(const SkBitmap& bitmap, int32_t slot) { - return fCanvas->shuttleBitmap(bitmap, slot); -}