Remove SkBitmapHeap and SkBitmapHeapReader. They're unused.
BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1938033002 Review-Url: https://codereview.chromium.org/1938033002
This commit is contained in:
parent
db1adf5989
commit
444f1ba1b7
@ -33,8 +33,6 @@
|
|||||||
'<(skia_src_path)/core/SkBitmapController.cpp',
|
'<(skia_src_path)/core/SkBitmapController.cpp',
|
||||||
'<(skia_src_path)/core/SkBitmapDevice.cpp',
|
'<(skia_src_path)/core/SkBitmapDevice.cpp',
|
||||||
'<(skia_src_path)/core/SkBitmapFilter.h',
|
'<(skia_src_path)/core/SkBitmapFilter.h',
|
||||||
'<(skia_src_path)/core/SkBitmapHeap.cpp',
|
|
||||||
'<(skia_src_path)/core/SkBitmapHeap.h',
|
|
||||||
'<(skia_src_path)/core/SkBitmapProcShader.cpp',
|
'<(skia_src_path)/core/SkBitmapProcShader.cpp',
|
||||||
'<(skia_src_path)/core/SkBitmapProcShader.h',
|
'<(skia_src_path)/core/SkBitmapProcShader.h',
|
||||||
'<(skia_src_path)/core/SkBitmapProcState.cpp',
|
'<(skia_src_path)/core/SkBitmapProcState.cpp',
|
||||||
|
@ -19,7 +19,6 @@
|
|||||||
#include "../private/SkTHash.h"
|
#include "../private/SkTHash.h"
|
||||||
|
|
||||||
class SkBitmap;
|
class SkBitmap;
|
||||||
class SkBitmapHeap;
|
|
||||||
class SkFactorySet;
|
class SkFactorySet;
|
||||||
class SkFlattenable;
|
class SkFlattenable;
|
||||||
class SkRefCntSet;
|
class SkRefCntSet;
|
||||||
@ -79,15 +78,6 @@ public:
|
|||||||
SkRefCntSet* getTypefaceRecorder() const { return fTFSet; }
|
SkRefCntSet* getTypefaceRecorder() const { return fTFSet; }
|
||||||
SkRefCntSet* setTypefaceRecorder(SkRefCntSet*);
|
SkRefCntSet* setTypefaceRecorder(SkRefCntSet*);
|
||||||
|
|
||||||
/**
|
|
||||||
* Set an SkBitmapHeap to store bitmaps rather than flattening.
|
|
||||||
*
|
|
||||||
* Incompatible with an SkPixelSerializer. If an SkPixelSerializer is set,
|
|
||||||
* setting an SkBitmapHeap will set the SkPixelSerializer to NULL in release
|
|
||||||
* and crash in debug.
|
|
||||||
*/
|
|
||||||
void setBitmapHeap(SkBitmapHeap*);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set an SkPixelSerializer to store an encoded representation of pixels,
|
* Set an SkPixelSerializer to store an encoded representation of pixels,
|
||||||
* e.g. SkBitmaps.
|
* e.g. SkBitmaps.
|
||||||
@ -95,9 +85,6 @@ public:
|
|||||||
* Calls ref() on the serializer.
|
* Calls ref() on the serializer.
|
||||||
*
|
*
|
||||||
* TODO: Encode SkImage pixels as well.
|
* TODO: Encode SkImage pixels as well.
|
||||||
*
|
|
||||||
* Incompatible with the SkBitmapHeap. If an encoder is set fBitmapHeap will
|
|
||||||
* be set to NULL in release and crash in debug.
|
|
||||||
*/
|
*/
|
||||||
void setPixelSerializer(SkPixelSerializer*);
|
void setPixelSerializer(SkPixelSerializer*);
|
||||||
SkPixelSerializer* getPixelSerializer() const { return fPixelSerializer; }
|
SkPixelSerializer* getPixelSerializer() const { return fPixelSerializer; }
|
||||||
@ -107,7 +94,6 @@ private:
|
|||||||
SkFactorySet* fFactorySet;
|
SkFactorySet* fFactorySet;
|
||||||
SkWriter32 fWriter;
|
SkWriter32 fWriter;
|
||||||
|
|
||||||
SkBitmapHeap* fBitmapHeap;
|
|
||||||
SkRefCntSet* fTFSet;
|
SkRefCntSet* fTFSet;
|
||||||
|
|
||||||
SkAutoTUnref<SkPixelSerializer> fPixelSerializer;
|
SkAutoTUnref<SkPixelSerializer> fPixelSerializer;
|
||||||
|
@ -1,391 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2012 Google Inc.
|
|
||||||
*
|
|
||||||
* Use of this source code is governed by a BSD-style license that can be
|
|
||||||
* found in the LICENSE file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "SkBitmapHeap.h"
|
|
||||||
#include "SkBitmap.h"
|
|
||||||
#include "SkTSearch.h"
|
|
||||||
|
|
||||||
SkBitmapHeapEntry::SkBitmapHeapEntry()
|
|
||||||
: fSlot(-1)
|
|
||||||
, fRefCount(0)
|
|
||||||
, fBytesAllocated(0) {
|
|
||||||
}
|
|
||||||
|
|
||||||
SkBitmapHeapEntry::~SkBitmapHeapEntry() {
|
|
||||||
SkASSERT(0 == fRefCount);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SkBitmapHeapEntry::addReferences(int count) {
|
|
||||||
if (0 == fRefCount) {
|
|
||||||
// If there are no current owners then the heap manager
|
|
||||||
// will be the only one able to modify it, so it does not
|
|
||||||
// need to be an atomic operation.
|
|
||||||
fRefCount = count;
|
|
||||||
} else {
|
|
||||||
sk_atomic_add(&fRefCount, count);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
static bool operator<(const SkIPoint& a, const SkIPoint& b) {
|
|
||||||
return *(const int64_t*)&a < *(const int64_t*)&b;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool operator>(const SkIPoint& a, const SkIPoint& b) {
|
|
||||||
return *(const int64_t*)&a > *(const int64_t*)&b;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SkBitmapHeap::LookupEntry::Less(const SkBitmapHeap::LookupEntry& a,
|
|
||||||
const SkBitmapHeap::LookupEntry& b) {
|
|
||||||
if (a.fGenerationId < b.fGenerationId) {
|
|
||||||
return true;
|
|
||||||
} else if (a.fGenerationId > b.fGenerationId) {
|
|
||||||
return false;
|
|
||||||
} else if (a.fPixelOrigin < b.fPixelOrigin) {
|
|
||||||
return true;
|
|
||||||
} else if (a.fPixelOrigin > b.fPixelOrigin) {
|
|
||||||
return false;
|
|
||||||
} else if (a.fWidth < b.fWidth) {
|
|
||||||
return true;
|
|
||||||
} else if (a.fWidth > b.fWidth) {
|
|
||||||
return false;
|
|
||||||
} else if (a.fHeight < b.fHeight) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
SkBitmapHeap::SkBitmapHeap(int32_t preferredSize, int32_t ownerCount)
|
|
||||||
: INHERITED()
|
|
||||||
, fExternalStorage(nullptr)
|
|
||||||
, fMostRecentlyUsed(nullptr)
|
|
||||||
, fLeastRecentlyUsed(nullptr)
|
|
||||||
, fPreferredCount(preferredSize)
|
|
||||||
, fOwnerCount(ownerCount)
|
|
||||||
, fBytesAllocated(0)
|
|
||||||
, fDeferAddingOwners(false) {
|
|
||||||
}
|
|
||||||
|
|
||||||
SkBitmapHeap::SkBitmapHeap(ExternalStorage* storage, int32_t preferredSize)
|
|
||||||
: INHERITED()
|
|
||||||
, fExternalStorage(storage)
|
|
||||||
, fMostRecentlyUsed(nullptr)
|
|
||||||
, fLeastRecentlyUsed(nullptr)
|
|
||||||
, fPreferredCount(preferredSize)
|
|
||||||
, fOwnerCount(IGNORE_OWNERS)
|
|
||||||
, fBytesAllocated(0)
|
|
||||||
, fDeferAddingOwners(false) {
|
|
||||||
SkSafeRef(storage);
|
|
||||||
}
|
|
||||||
|
|
||||||
SkBitmapHeap::~SkBitmapHeap() {
|
|
||||||
SkDEBUGCODE(
|
|
||||||
for (int i = 0; i < fStorage.count(); i++) {
|
|
||||||
bool unused = false;
|
|
||||||
for (int j = 0; j < fUnusedSlots.count(); j++) {
|
|
||||||
if (fUnusedSlots[j] == fStorage[i]->fSlot) {
|
|
||||||
unused = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!unused) {
|
|
||||||
fBytesAllocated -= fStorage[i]->fBytesAllocated;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fBytesAllocated -= (fStorage.count() * sizeof(SkBitmapHeapEntry));
|
|
||||||
)
|
|
||||||
SkASSERT(0 == fBytesAllocated);
|
|
||||||
fStorage.deleteAll();
|
|
||||||
SkSafeUnref(fExternalStorage);
|
|
||||||
fLookupTable.deleteAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
void SkBitmapHeap::removeFromLRU(SkBitmapHeap::LookupEntry* entry) {
|
|
||||||
if (fMostRecentlyUsed == entry) {
|
|
||||||
fMostRecentlyUsed = entry->fLessRecentlyUsed;
|
|
||||||
if (nullptr == fMostRecentlyUsed) {
|
|
||||||
SkASSERT(fLeastRecentlyUsed == entry);
|
|
||||||
fLeastRecentlyUsed = nullptr;
|
|
||||||
} else {
|
|
||||||
fMostRecentlyUsed->fMoreRecentlyUsed = nullptr;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Remove entry from its prior place, and make sure to cover the hole.
|
|
||||||
if (fLeastRecentlyUsed == entry) {
|
|
||||||
SkASSERT(entry->fMoreRecentlyUsed != nullptr);
|
|
||||||
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.
|
|
||||||
SkASSERT(entry->fMoreRecentlyUsed != nullptr);
|
|
||||||
entry->fMoreRecentlyUsed->fLessRecentlyUsed = entry->fLessRecentlyUsed;
|
|
||||||
|
|
||||||
if (entry->fLessRecentlyUsed != nullptr) {
|
|
||||||
SkASSERT(fLeastRecentlyUsed != entry);
|
|
||||||
entry->fLessRecentlyUsed->fMoreRecentlyUsed = entry->fMoreRecentlyUsed;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
entry->fMoreRecentlyUsed = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SkBitmapHeap::appendToLRU(SkBitmapHeap::LookupEntry* entry) {
|
|
||||||
if (fMostRecentlyUsed != nullptr) {
|
|
||||||
SkASSERT(nullptr == fMostRecentlyUsed->fMoreRecentlyUsed);
|
|
||||||
fMostRecentlyUsed->fMoreRecentlyUsed = entry;
|
|
||||||
entry->fLessRecentlyUsed = fMostRecentlyUsed;
|
|
||||||
}
|
|
||||||
fMostRecentlyUsed = entry;
|
|
||||||
if (nullptr == fLeastRecentlyUsed) {
|
|
||||||
fLeastRecentlyUsed = entry;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// iterate through our LRU cache and try to find an entry to evict
|
|
||||||
SkBitmapHeap::LookupEntry* SkBitmapHeap::findEntryToReplace(const SkBitmap& replacement) {
|
|
||||||
SkASSERT(fPreferredCount != UNLIMITED_SIZE);
|
|
||||||
SkASSERT(fStorage.count() >= fPreferredCount);
|
|
||||||
|
|
||||||
SkBitmapHeap::LookupEntry* iter = fLeastRecentlyUsed;
|
|
||||||
while (iter != nullptr) {
|
|
||||||
SkBitmapHeapEntry* heapEntry = fStorage[iter->fStorageSlot];
|
|
||||||
if (heapEntry->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 its references yet either.
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
if (replacement.getGenerationID() == iter->fGenerationId) {
|
|
||||||
// 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.
|
|
||||||
iter = iter->fMoreRecentlyUsed;
|
|
||||||
} else {
|
|
||||||
return iter;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t SkBitmapHeap::freeMemoryIfPossible(size_t bytesToFree) {
|
|
||||||
if (UNLIMITED_SIZE == fPreferredCount) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
LookupEntry* iter = fLeastRecentlyUsed;
|
|
||||||
size_t origBytesAllocated = fBytesAllocated;
|
|
||||||
// Purge starting from LRU until a non-evictable bitmap is found or until
|
|
||||||
// everything is evicted.
|
|
||||||
while (iter != nullptr) {
|
|
||||||
SkBitmapHeapEntry* heapEntry = fStorage[iter->fStorageSlot];
|
|
||||||
if (heapEntry->fRefCount > 0) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
LookupEntry* next = iter->fMoreRecentlyUsed;
|
|
||||||
this->removeEntryFromLookupTable(iter);
|
|
||||||
// Free the pixel memory. removeEntryFromLookupTable already reduced
|
|
||||||
// fBytesAllocated properly.
|
|
||||||
heapEntry->fBitmap.reset();
|
|
||||||
// Add to list of unused slots which can be reused in the future.
|
|
||||||
fUnusedSlots.push(heapEntry->fSlot);
|
|
||||||
iter = next;
|
|
||||||
if (origBytesAllocated - fBytesAllocated >= bytesToFree) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fLeastRecentlyUsed != iter) {
|
|
||||||
// There was at least one eviction.
|
|
||||||
fLeastRecentlyUsed = iter;
|
|
||||||
if (nullptr == fLeastRecentlyUsed) {
|
|
||||||
// Everything was evicted
|
|
||||||
fMostRecentlyUsed = nullptr;
|
|
||||||
fBytesAllocated -= (fStorage.count() * sizeof(SkBitmapHeapEntry));
|
|
||||||
fStorage.deleteAll();
|
|
||||||
fUnusedSlots.reset();
|
|
||||||
SkASSERT(0 == fBytesAllocated);
|
|
||||||
} else {
|
|
||||||
fLeastRecentlyUsed->fLessRecentlyUsed = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return origBytesAllocated - fBytesAllocated;
|
|
||||||
}
|
|
||||||
|
|
||||||
int SkBitmapHeap::findInLookupTable(const LookupEntry& indexEntry, SkBitmapHeapEntry** entry) {
|
|
||||||
int index = SkTSearch<const LookupEntry, LookupEntry::Less>(
|
|
||||||
(const LookupEntry**)fLookupTable.begin(),
|
|
||||||
fLookupTable.count(),
|
|
||||||
&indexEntry, sizeof(void*));
|
|
||||||
|
|
||||||
if (index < 0) {
|
|
||||||
// insert ourselves into the bitmapIndex
|
|
||||||
index = ~index;
|
|
||||||
*fLookupTable.insert(index) = new LookupEntry(indexEntry);
|
|
||||||
} else if (entry != nullptr) {
|
|
||||||
// populate the entry if needed
|
|
||||||
*entry = fStorage[fLookupTable[index]->fStorageSlot];
|
|
||||||
}
|
|
||||||
|
|
||||||
return index;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SkBitmapHeap::copyBitmap(const SkBitmap& originalBitmap, SkBitmap& copiedBitmap) {
|
|
||||||
SkASSERT(!fExternalStorage);
|
|
||||||
|
|
||||||
// If the bitmap is mutable, we need to do a deep copy, since the
|
|
||||||
// caller may modify it afterwards.
|
|
||||||
if (originalBitmap.isImmutable()) {
|
|
||||||
copiedBitmap = originalBitmap;
|
|
||||||
// TODO if we have the pixel ref in the heap we could pass it here to avoid a potential deep copy
|
|
||||||
// else if (sharedPixelRef != nullptr) {
|
|
||||||
// copiedBitmap = orig;
|
|
||||||
// copiedBitmap.setPixelRef(sharedPixelRef, originalBitmap.pixelRefOffset());
|
|
||||||
} else if (originalBitmap.empty()) {
|
|
||||||
copiedBitmap.reset();
|
|
||||||
} else if (!originalBitmap.deepCopyTo(&copiedBitmap)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
copiedBitmap.setImmutable();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
int SkBitmapHeap::removeEntryFromLookupTable(LookupEntry* entry) {
|
|
||||||
// remove the bitmap index for the deleted entry
|
|
||||||
SkDEBUGCODE(int count = fLookupTable.count();)
|
|
||||||
int index = this->findInLookupTable(*entry, nullptr);
|
|
||||||
// Verify that findInLookupTable found an existing entry rather than adding
|
|
||||||
// a new entry to the lookup table.
|
|
||||||
SkASSERT(count == fLookupTable.count());
|
|
||||||
fBytesAllocated -= fStorage[entry->fStorageSlot]->fBytesAllocated;
|
|
||||||
delete fLookupTable[index];
|
|
||||||
fLookupTable.remove(index);
|
|
||||||
return index;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t SkBitmapHeap::insert(const SkBitmap& originalBitmap) {
|
|
||||||
SkBitmapHeapEntry* entry = nullptr;
|
|
||||||
int searchIndex = this->findInLookupTable(LookupEntry(originalBitmap), &entry);
|
|
||||||
|
|
||||||
if (entry) {
|
|
||||||
// Already had a copy of the bitmap in the heap.
|
|
||||||
if (fOwnerCount != IGNORE_OWNERS) {
|
|
||||||
if (fDeferAddingOwners) {
|
|
||||||
*fDeferredEntries.append() = entry->fSlot;
|
|
||||||
} else {
|
|
||||||
entry->addReferences(fOwnerCount);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (fPreferredCount != UNLIMITED_SIZE) {
|
|
||||||
LookupEntry* lookupEntry = fLookupTable[searchIndex];
|
|
||||||
if (lookupEntry != fMostRecentlyUsed) {
|
|
||||||
this->removeFromLRU(lookupEntry);
|
|
||||||
this->appendToLRU(lookupEntry);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return entry->fSlot;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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 != nullptr) {
|
|
||||||
// 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);
|
|
||||||
|
|
||||||
// update the current search index now that we have removed one
|
|
||||||
if (index < searchIndex) {
|
|
||||||
searchIndex--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// if we didn't have an entry yet we need to create one
|
|
||||||
if (!entry) {
|
|
||||||
if (fPreferredCount != UNLIMITED_SIZE && fUnusedSlots.count() > 0) {
|
|
||||||
int slot;
|
|
||||||
fUnusedSlots.pop(&slot);
|
|
||||||
entry = fStorage[slot];
|
|
||||||
} else {
|
|
||||||
entry = new SkBitmapHeapEntry;
|
|
||||||
fStorage.append(1, &entry);
|
|
||||||
entry->fSlot = fStorage.count() - 1;
|
|
||||||
fBytesAllocated += sizeof(SkBitmapHeapEntry);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// create a copy of the bitmap
|
|
||||||
bool copySucceeded;
|
|
||||||
if (fExternalStorage) {
|
|
||||||
copySucceeded = fExternalStorage->insert(originalBitmap, entry->fSlot);
|
|
||||||
} else {
|
|
||||||
copySucceeded = copyBitmap(originalBitmap, entry->fBitmap);
|
|
||||||
}
|
|
||||||
|
|
||||||
// if the copy failed then we must abort
|
|
||||||
if (!copySucceeded) {
|
|
||||||
// delete the index
|
|
||||||
delete 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) {
|
|
||||||
// free the slot
|
|
||||||
fStorage.remove(entry->fSlot);
|
|
||||||
fBytesAllocated -= sizeof(SkBitmapHeapEntry);
|
|
||||||
delete entry;
|
|
||||||
} else {
|
|
||||||
fUnusedSlots.push(entry->fSlot);
|
|
||||||
}
|
|
||||||
return INVALID_SLOT;
|
|
||||||
}
|
|
||||||
|
|
||||||
// update the index with the appropriate slot in the heap
|
|
||||||
fLookupTable[searchIndex]->fStorageSlot = entry->fSlot;
|
|
||||||
|
|
||||||
// compute the space taken by 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.
|
|
||||||
entry->fBytesAllocated = originalBitmap.getSize();
|
|
||||||
|
|
||||||
// add the bytes from this entry to the total count
|
|
||||||
fBytesAllocated += entry->fBytesAllocated;
|
|
||||||
|
|
||||||
if (fOwnerCount != IGNORE_OWNERS) {
|
|
||||||
if (fDeferAddingOwners) {
|
|
||||||
*fDeferredEntries.append() = entry->fSlot;
|
|
||||||
} else {
|
|
||||||
entry->addReferences(fOwnerCount);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (fPreferredCount != UNLIMITED_SIZE) {
|
|
||||||
this->appendToLRU(fLookupTable[searchIndex]);
|
|
||||||
}
|
|
||||||
return entry->fSlot;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SkBitmapHeap::deferAddingOwners() {
|
|
||||||
fDeferAddingOwners = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SkBitmapHeap::endAddingOwnersDeferral(bool add) {
|
|
||||||
if (add) {
|
|
||||||
for (int i = 0; i < fDeferredEntries.count(); i++) {
|
|
||||||
SkASSERT(fOwnerCount != IGNORE_OWNERS);
|
|
||||||
SkBitmapHeapEntry* heapEntry = this->getEntry(fDeferredEntries[i]);
|
|
||||||
SkASSERT(heapEntry != nullptr);
|
|
||||||
heapEntry->addReferences(fOwnerCount);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fDeferAddingOwners = false;
|
|
||||||
fDeferredEntries.reset();
|
|
||||||
}
|
|
@ -1,299 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2012 Google Inc.
|
|
||||||
*
|
|
||||||
* Use of this source code is governed by a BSD-style license that can be
|
|
||||||
* found in the LICENSE file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef SkBitmapHeap_DEFINED
|
|
||||||
#define SkBitmapHeap_DEFINED
|
|
||||||
|
|
||||||
#include "SkAtomics.h"
|
|
||||||
#include "SkBitmap.h"
|
|
||||||
#include "SkPoint.h"
|
|
||||||
#include "SkRefCnt.h"
|
|
||||||
#include "SkTDArray.h"
|
|
||||||
#include "SkTypes.h"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* SkBitmapHeapEntry provides users of SkBitmapHeap (using internal storage) with a means to...
|
|
||||||
* (1) get access a bitmap in the heap
|
|
||||||
* (2) indicate they are done with bitmap by releasing their reference (if they were an owner).
|
|
||||||
*/
|
|
||||||
class SkBitmapHeapEntry : SkNoncopyable {
|
|
||||||
public:
|
|
||||||
~SkBitmapHeapEntry();
|
|
||||||
|
|
||||||
int32_t getSlot() { return fSlot; }
|
|
||||||
|
|
||||||
SkBitmap* getBitmap() { return &fBitmap; }
|
|
||||||
|
|
||||||
void releaseRef() {
|
|
||||||
sk_atomic_dec(&fRefCount);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
SkBitmapHeapEntry();
|
|
||||||
|
|
||||||
void addReferences(int count);
|
|
||||||
|
|
||||||
int32_t fSlot;
|
|
||||||
int32_t fRefCount;
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
friend class SkBitmapHeap;
|
|
||||||
friend class SkBitmapHeapTester;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
class SkBitmapHeapReader : public SkRefCnt {
|
|
||||||
public:
|
|
||||||
|
|
||||||
|
|
||||||
SkBitmapHeapReader() : INHERITED() {}
|
|
||||||
virtual SkBitmap* getBitmap(int32_t slot) const = 0;
|
|
||||||
virtual void releaseRef(int32_t slot) = 0;
|
|
||||||
private:
|
|
||||||
typedef SkRefCnt INHERITED;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* TODO: stores immutable bitmaps into a heap
|
|
||||||
*/
|
|
||||||
class SkBitmapHeap : public SkBitmapHeapReader {
|
|
||||||
public:
|
|
||||||
class ExternalStorage : public SkRefCnt {
|
|
||||||
public:
|
|
||||||
|
|
||||||
|
|
||||||
virtual bool insert(const SkBitmap& bitmap, int32_t slot) = 0;
|
|
||||||
|
|
||||||
private:
|
|
||||||
typedef SkRefCnt INHERITED;
|
|
||||||
};
|
|
||||||
|
|
||||||
static const int32_t UNLIMITED_SIZE = -1;
|
|
||||||
static const int32_t IGNORE_OWNERS = -1;
|
|
||||||
static const int32_t INVALID_SLOT = -1;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs a heap that is responsible for allocating and managing its own storage. In the
|
|
||||||
* case where we choose to allow the heap to grow indefinitely (i.e. UNLIMITED_SIZE) we
|
|
||||||
* guarantee that once allocated in the heap a bitmap's index in the heap is immutable.
|
|
||||||
* Otherwise we guarantee the bitmaps placement in the heap until its owner count goes to zero.
|
|
||||||
*
|
|
||||||
* @param preferredSize Specifies the preferred maximum number of bitmaps to store. This is
|
|
||||||
* not a hard limit as it can grow larger if the number of bitmaps in the heap with active
|
|
||||||
* owners exceeds this limit.
|
|
||||||
* @param ownerCount The number of owners to assign to each inserted bitmap. NOTE: while a
|
|
||||||
* bitmap in the heap has a least one owner it can't be removed.
|
|
||||||
*/
|
|
||||||
SkBitmapHeap(int32_t preferredSize = UNLIMITED_SIZE, int32_t ownerCount = IGNORE_OWNERS);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs a heap that defers the responsibility of storing the bitmaps to an external
|
|
||||||
* function. This is especially useful if the bitmaps will be used in a separate process as the
|
|
||||||
* external storage can ensure the data is properly shuttled to the appropriate processes.
|
|
||||||
*
|
|
||||||
* Our LRU implementation assumes that inserts into the external storage are consumed in the
|
|
||||||
* order that they are inserted (i.e. SkPipe). This ensures that we don't need to query the
|
|
||||||
* external storage to see if a slot in the heap is eligible to be overwritten.
|
|
||||||
*
|
|
||||||
* @param externalStorage The class responsible for storing the bitmaps inserted into the heap
|
|
||||||
* @param heapSize The maximum size of the heap. Because of the sequential limitation imposed
|
|
||||||
* by our LRU implementation we can guarantee that the heap will never grow beyond this size.
|
|
||||||
*/
|
|
||||||
SkBitmapHeap(ExternalStorage* externalStorage, int32_t heapSize = UNLIMITED_SIZE);
|
|
||||||
|
|
||||||
virtual ~SkBitmapHeap();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves the bitmap from the specified slot in the heap
|
|
||||||
*
|
|
||||||
* @return The bitmap located at that slot or nullptr if external storage is being used.
|
|
||||||
*/
|
|
||||||
SkBitmap* getBitmap(int32_t slot) const override {
|
|
||||||
SkASSERT(fExternalStorage == nullptr);
|
|
||||||
SkBitmapHeapEntry* entry = getEntry(slot);
|
|
||||||
if (entry) {
|
|
||||||
return &entry->fBitmap;
|
|
||||||
}
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves the bitmap from the specified slot in the heap
|
|
||||||
*
|
|
||||||
* @return The bitmap located at that slot or nullptr if external storage is being used.
|
|
||||||
*/
|
|
||||||
void releaseRef(int32_t slot) override {
|
|
||||||
SkASSERT(fExternalStorage == nullptr);
|
|
||||||
if (fOwnerCount != IGNORE_OWNERS) {
|
|
||||||
SkBitmapHeapEntry* entry = getEntry(slot);
|
|
||||||
if (entry) {
|
|
||||||
entry->releaseRef();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Inserts a bitmap into the heap. The stored version of bitmap is guaranteed to be immutable
|
|
||||||
* and is not dependent on the lifecycle of the provided bitmap.
|
|
||||||
*
|
|
||||||
* @param bitmap the bitmap to be inserted into the heap
|
|
||||||
* @return the slot in the heap where the bitmap is stored or INVALID_SLOT if the bitmap could
|
|
||||||
* not be added to the heap. If it was added the slot will remain valid...
|
|
||||||
* (1) indefinitely if no owner count has been specified.
|
|
||||||
* (2) until all owners have called releaseRef on the appropriate SkBitmapHeapEntry*
|
|
||||||
*/
|
|
||||||
int32_t insert(const SkBitmap& bitmap);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves an entry from the heap at a given slot.
|
|
||||||
*
|
|
||||||
* @param slot the slot in the heap where a bitmap was stored.
|
|
||||||
* @return a SkBitmapHeapEntry that wraps the bitmap or nullptr if external storage is used.
|
|
||||||
*/
|
|
||||||
SkBitmapHeapEntry* getEntry(int32_t slot) const {
|
|
||||||
SkASSERT(slot <= fStorage.count());
|
|
||||||
if (fExternalStorage != nullptr) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
return fStorage[slot];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a count of the number of items currently in the heap
|
|
||||||
*/
|
|
||||||
int count() const {
|
|
||||||
SkASSERT(fExternalStorage != nullptr ||
|
|
||||||
fStorage.count() - fUnusedSlots.count() == fLookupTable.count());
|
|
||||||
return fLookupTable.count();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the total number of bytes allocated by the bitmaps in the heap
|
|
||||||
*/
|
|
||||||
size_t bytesAllocated() const {
|
|
||||||
return fBytesAllocated;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Attempt to reduce the storage allocated.
|
|
||||||
* @param bytesToFree minimum number of bytes that should be attempted to
|
|
||||||
* be freed.
|
|
||||||
* @return number of bytes actually freed.
|
|
||||||
*/
|
|
||||||
size_t freeMemoryIfPossible(size_t bytesToFree);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Defer any increments of owner counts until endAddingOwnersDeferral is called. So if an
|
|
||||||
* existing SkBitmap is inserted into the SkBitmapHeap, its corresponding SkBitmapHeapEntry will
|
|
||||||
* not have addReferences called on it, and the client does not need to make a corresponding
|
|
||||||
* call to releaseRef. Only meaningful if this SkBitmapHeap was created with an owner count not
|
|
||||||
* equal to IGNORE_OWNERS.
|
|
||||||
*/
|
|
||||||
void deferAddingOwners();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Resume adding references when duplicate SkBitmaps are inserted.
|
|
||||||
* @param add If true, add references to the SkBitmapHeapEntrys whose SkBitmaps were re-inserted
|
|
||||||
* while deferring.
|
|
||||||
*/
|
|
||||||
void endAddingOwnersDeferral(bool add);
|
|
||||||
|
|
||||||
private:
|
|
||||||
struct LookupEntry {
|
|
||||||
LookupEntry(const SkBitmap& bm)
|
|
||||||
: fGenerationId(bm.getGenerationID())
|
|
||||||
, fPixelOrigin(bm.pixelRefOrigin())
|
|
||||||
, fWidth(bm.width())
|
|
||||||
, fHeight(bm.height())
|
|
||||||
, fMoreRecentlyUsed(nullptr)
|
|
||||||
, fLessRecentlyUsed(nullptr){}
|
|
||||||
|
|
||||||
const uint32_t fGenerationId; // SkPixelRef GenerationID.
|
|
||||||
const SkIPoint fPixelOrigin;
|
|
||||||
const uint32_t fWidth;
|
|
||||||
const uint32_t fHeight;
|
|
||||||
|
|
||||||
// TODO: Generalize the LRU caching mechanism
|
|
||||||
LookupEntry* fMoreRecentlyUsed;
|
|
||||||
LookupEntry* fLessRecentlyUsed;
|
|
||||||
|
|
||||||
uint32_t fStorageSlot; // slot of corresponding bitmap in fStorage.
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Compare two LookupEntry pointers for sorting and searching.
|
|
||||||
*/
|
|
||||||
static bool Less(const LookupEntry& a, const LookupEntry& b);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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.
|
|
||||||
* @return The index in the lookup table of the entry before removal.
|
|
||||||
*/
|
|
||||||
int removeEntryFromLookupTable(LookupEntry*);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Searches for the bitmap in the lookup table and returns the bitmaps index within the table.
|
|
||||||
* If the bitmap was not already in the table it is added.
|
|
||||||
*
|
|
||||||
* @param key The key to search the lookup table, created from a bitmap.
|
|
||||||
* @param entry A pointer to a SkBitmapHeapEntry* that if non-null AND the bitmap is found
|
|
||||||
* in the lookup table is populated with the entry from the heap storage.
|
|
||||||
*/
|
|
||||||
int findInLookupTable(const LookupEntry& key, SkBitmapHeapEntry** entry);
|
|
||||||
|
|
||||||
LookupEntry* 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 nullptr 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*);
|
|
||||||
|
|
||||||
// searchable index that maps to entries in the heap
|
|
||||||
SkTDArray<LookupEntry*> fLookupTable;
|
|
||||||
|
|
||||||
// heap storage
|
|
||||||
SkTDArray<SkBitmapHeapEntry*> fStorage;
|
|
||||||
// Used to mark slots in fStorage as deleted without actually deleting
|
|
||||||
// the slot so as not to mess up the numbering.
|
|
||||||
SkTDArray<int> fUnusedSlots;
|
|
||||||
ExternalStorage* fExternalStorage;
|
|
||||||
|
|
||||||
LookupEntry* fMostRecentlyUsed;
|
|
||||||
LookupEntry* fLeastRecentlyUsed;
|
|
||||||
|
|
||||||
const int32_t fPreferredCount;
|
|
||||||
const int32_t fOwnerCount;
|
|
||||||
size_t fBytesAllocated;
|
|
||||||
|
|
||||||
bool fDeferAddingOwners;
|
|
||||||
SkTDArray<int> fDeferredEntries;
|
|
||||||
|
|
||||||
typedef SkBitmapHeapReader INHERITED;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // SkBitmapHeap_DEFINED
|
|
@ -153,10 +153,6 @@ private:
|
|||||||
bool parseBufferTag(SkReadBuffer&, uint32_t tag, uint32_t size);
|
bool parseBufferTag(SkReadBuffer&, uint32_t tag, uint32_t size);
|
||||||
void flattenToBuffer(SkWriteBuffer&) const;
|
void flattenToBuffer(SkWriteBuffer&) const;
|
||||||
|
|
||||||
// Only used by getBitmap() if the passed in index is SkBitmapHeap::INVALID_SLOT. This empty
|
|
||||||
// bitmap allows playback to draw nothing and move on.
|
|
||||||
SkBitmap fBadBitmap;
|
|
||||||
|
|
||||||
SkTArray<SkBitmap> fBitmaps;
|
SkTArray<SkBitmap> fBitmaps;
|
||||||
SkTArray<SkPaint> fPaints;
|
SkTArray<SkPaint> fPaints;
|
||||||
SkTArray<SkPath> fPaths;
|
SkTArray<SkPath> fPaths;
|
||||||
|
@ -8,7 +8,6 @@
|
|||||||
#define SkPictureFlat_DEFINED
|
#define SkPictureFlat_DEFINED
|
||||||
|
|
||||||
|
|
||||||
#include "SkBitmapHeap.h"
|
|
||||||
#include "SkChecksum.h"
|
#include "SkChecksum.h"
|
||||||
#include "SkChunkAlloc.h"
|
#include "SkChunkAlloc.h"
|
||||||
#include "SkReadBuffer.h"
|
#include "SkReadBuffer.h"
|
||||||
|
@ -27,7 +27,6 @@ SkReadBuffer::SkReadBuffer() {
|
|||||||
fVersion = 0;
|
fVersion = 0;
|
||||||
fMemoryPtr = nullptr;
|
fMemoryPtr = nullptr;
|
||||||
|
|
||||||
fBitmapStorage = nullptr;
|
|
||||||
fTFArray = nullptr;
|
fTFArray = nullptr;
|
||||||
fTFCount = 0;
|
fTFCount = 0;
|
||||||
|
|
||||||
@ -45,7 +44,6 @@ SkReadBuffer::SkReadBuffer(const void* data, size_t size) {
|
|||||||
fReader.setMemory(data, size);
|
fReader.setMemory(data, size);
|
||||||
fMemoryPtr = nullptr;
|
fMemoryPtr = nullptr;
|
||||||
|
|
||||||
fBitmapStorage = nullptr;
|
|
||||||
fTFArray = nullptr;
|
fTFArray = nullptr;
|
||||||
fTFCount = 0;
|
fTFCount = 0;
|
||||||
|
|
||||||
@ -65,7 +63,6 @@ SkReadBuffer::SkReadBuffer(SkStream* stream) {
|
|||||||
stream->read(fMemoryPtr, length);
|
stream->read(fMemoryPtr, length);
|
||||||
fReader.setMemory(fMemoryPtr, length);
|
fReader.setMemory(fMemoryPtr, length);
|
||||||
|
|
||||||
fBitmapStorage = nullptr;
|
|
||||||
fTFArray = nullptr;
|
fTFArray = nullptr;
|
||||||
fTFCount = 0;
|
fTFCount = 0;
|
||||||
|
|
||||||
@ -79,7 +76,6 @@ SkReadBuffer::SkReadBuffer(SkStream* stream) {
|
|||||||
|
|
||||||
SkReadBuffer::~SkReadBuffer() {
|
SkReadBuffer::~SkReadBuffer() {
|
||||||
sk_free(fMemoryPtr);
|
sk_free(fMemoryPtr);
|
||||||
SkSafeUnref(fBitmapStorage);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SkReadBuffer::readBool() {
|
bool SkReadBuffer::readBool() {
|
||||||
@ -186,25 +182,15 @@ uint32_t SkReadBuffer::getArrayCount() {
|
|||||||
bool SkReadBuffer::readBitmap(SkBitmap* bitmap) {
|
bool SkReadBuffer::readBitmap(SkBitmap* bitmap) {
|
||||||
const int width = this->readInt();
|
const int width = this->readInt();
|
||||||
const int height = this->readInt();
|
const int height = this->readInt();
|
||||||
|
|
||||||
// The writer stored a boolean value to determine whether an SkBitmapHeap was used during
|
// The writer stored a boolean value to determine whether an SkBitmapHeap was used during
|
||||||
// writing.
|
// writing. That feature is deprecated.
|
||||||
if (this->readBool()) {
|
if (this->readBool()) {
|
||||||
// An SkBitmapHeap was used for writing. Read the index from the stream and find the
|
this->readUInt(); // Bitmap index
|
||||||
// corresponding SkBitmap in fBitmapStorage.
|
this->readUInt(); // Bitmap generation ID
|
||||||
const uint32_t index = this->readUInt();
|
SkErrorInternals::SetError(kParseError_SkError, "SkWriteBuffer::writeBitmap "
|
||||||
this->readUInt(); // bitmap generation ID (see SkWriteBuffer::writeBitmap)
|
"stored the SkBitmap in an SkBitmapHeap, but "
|
||||||
if (fBitmapStorage) {
|
"that feature is no longer supported.");
|
||||||
*bitmap = *fBitmapStorage->getBitmap(index);
|
|
||||||
fBitmapStorage->releaseRef(index);
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
// The bitmap was stored in a heap, but there is no way to access it. Set an error and
|
|
||||||
// fall through to use a place holder bitmap.
|
|
||||||
SkErrorInternals::SetError(kParseError_SkError, "SkWriteBuffer::writeBitmap "
|
|
||||||
"stored the SkBitmap in an SkBitmapHeap, but "
|
|
||||||
"SkReadBuffer has no SkBitmapHeapReader to "
|
|
||||||
"retrieve the SkBitmap.");
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// The writer stored false, meaning the SkBitmap was not stored in an SkBitmapHeap.
|
// The writer stored false, meaning the SkBitmap was not stored in an SkBitmapHeap.
|
||||||
const size_t length = this->readUInt();
|
const size_t length = this->readUInt();
|
||||||
|
@ -8,7 +8,6 @@
|
|||||||
#ifndef SkReadBuffer_DEFINED
|
#ifndef SkReadBuffer_DEFINED
|
||||||
#define SkReadBuffer_DEFINED
|
#define SkReadBuffer_DEFINED
|
||||||
|
|
||||||
#include "SkBitmapHeap.h"
|
|
||||||
#include "SkColorFilter.h"
|
#include "SkColorFilter.h"
|
||||||
#include "SkData.h"
|
#include "SkData.h"
|
||||||
#include "SkDrawLooper.h"
|
#include "SkDrawLooper.h"
|
||||||
@ -176,10 +175,6 @@ public:
|
|||||||
|
|
||||||
virtual SkTypeface* readTypeface();
|
virtual SkTypeface* readTypeface();
|
||||||
|
|
||||||
void setBitmapStorage(SkBitmapHeapReader* bitmapStorage) {
|
|
||||||
SkRefCnt_SafeAssign(fBitmapStorage, bitmapStorage);
|
|
||||||
}
|
|
||||||
|
|
||||||
void setTypefaceArray(SkTypeface* array[], int count) {
|
void setTypefaceArray(SkTypeface* array[], int count) {
|
||||||
fTFArray = array;
|
fTFArray = array;
|
||||||
fTFCount = count;
|
fTFCount = count;
|
||||||
@ -255,7 +250,6 @@ private:
|
|||||||
|
|
||||||
void* fMemoryPtr;
|
void* fMemoryPtr;
|
||||||
|
|
||||||
SkBitmapHeapReader* fBitmapStorage;
|
|
||||||
SkTypeface** fTFArray;
|
SkTypeface** fTFArray;
|
||||||
int fTFCount;
|
int fTFCount;
|
||||||
|
|
||||||
|
@ -9,7 +9,6 @@
|
|||||||
#define SkValidatingReadBuffer_DEFINED
|
#define SkValidatingReadBuffer_DEFINED
|
||||||
|
|
||||||
#include "SkRefCnt.h"
|
#include "SkRefCnt.h"
|
||||||
#include "SkBitmapHeap.h"
|
|
||||||
#include "SkReadBuffer.h"
|
#include "SkReadBuffer.h"
|
||||||
#include "SkWriteBuffer.h"
|
#include "SkWriteBuffer.h"
|
||||||
#include "SkPath.h"
|
#include "SkPath.h"
|
||||||
|
@ -7,7 +7,6 @@
|
|||||||
|
|
||||||
#include "SkWriteBuffer.h"
|
#include "SkWriteBuffer.h"
|
||||||
#include "SkBitmap.h"
|
#include "SkBitmap.h"
|
||||||
#include "SkBitmapHeap.h"
|
|
||||||
#include "SkData.h"
|
#include "SkData.h"
|
||||||
#include "SkPixelRef.h"
|
#include "SkPixelRef.h"
|
||||||
#include "SkPtrRecorder.h"
|
#include "SkPtrRecorder.h"
|
||||||
@ -17,7 +16,6 @@
|
|||||||
SkWriteBuffer::SkWriteBuffer(uint32_t flags)
|
SkWriteBuffer::SkWriteBuffer(uint32_t flags)
|
||||||
: fFlags(flags)
|
: fFlags(flags)
|
||||||
, fFactorySet(nullptr)
|
, fFactorySet(nullptr)
|
||||||
, fBitmapHeap(nullptr)
|
|
||||||
, fTFSet(nullptr) {
|
, fTFSet(nullptr) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -25,13 +23,11 @@ SkWriteBuffer::SkWriteBuffer(void* storage, size_t storageSize, uint32_t flags)
|
|||||||
: fFlags(flags)
|
: fFlags(flags)
|
||||||
, fFactorySet(nullptr)
|
, fFactorySet(nullptr)
|
||||||
, fWriter(storage, storageSize)
|
, fWriter(storage, storageSize)
|
||||||
, fBitmapHeap(nullptr)
|
|
||||||
, fTFSet(nullptr) {
|
, fTFSet(nullptr) {
|
||||||
}
|
}
|
||||||
|
|
||||||
SkWriteBuffer::~SkWriteBuffer() {
|
SkWriteBuffer::~SkWriteBuffer() {
|
||||||
SkSafeUnref(fFactorySet);
|
SkSafeUnref(fFactorySet);
|
||||||
SkSafeUnref(fBitmapHeap);
|
|
||||||
SkSafeUnref(fTFSet);
|
SkSafeUnref(fTFSet);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -139,32 +135,15 @@ void SkWriteBuffer::writeBitmap(const SkBitmap& bitmap) {
|
|||||||
this->writeInt(bitmap.width());
|
this->writeInt(bitmap.width());
|
||||||
this->writeInt(bitmap.height());
|
this->writeInt(bitmap.height());
|
||||||
|
|
||||||
// Record information about the bitmap in one of three ways, in order of priority:
|
// Record information about the bitmap in one of two ways, in order of priority:
|
||||||
// 1. If there is an SkBitmapHeap, store it in the heap. The client can avoid serializing the
|
// 1. If there is a function for encoding bitmaps, use it to write an encoded version of the
|
||||||
// bitmap entirely or serialize it later as desired. A boolean value of true will be written
|
|
||||||
// to the stream to signify that a heap was used.
|
|
||||||
// 2. If there is a function for encoding bitmaps, use it to write an encoded version of the
|
|
||||||
// bitmap. After writing a boolean value of false, signifying that a heap was not used, write
|
// bitmap. After writing a boolean value of false, signifying that a heap was not used, write
|
||||||
// the size of the encoded data. A non-zero size signifies that encoded data was written.
|
// the size of the encoded data. A non-zero size signifies that encoded data was written.
|
||||||
// 3. Call SkBitmap::flatten. After writing a boolean value of false, signifying that a heap was
|
// 2. Call SkBitmap::flatten. After writing a boolean value of false, signifying that a heap was
|
||||||
// not used, write a zero to signify that the data was not encoded.
|
// not used, write a zero to signify that the data was not encoded.
|
||||||
bool useBitmapHeap = fBitmapHeap != nullptr;
|
|
||||||
// Write a bool: true if the SkBitmapHeap is to be used, in which case the reader must use an
|
// Write a bool to indicate that we did not use an SkBitmapHeap. That feature is deprecated.
|
||||||
// SkBitmapHeapReader to read the SkBitmap. False if the bitmap was serialized another way.
|
this->writeBool(false);
|
||||||
this->writeBool(useBitmapHeap);
|
|
||||||
if (useBitmapHeap) {
|
|
||||||
SkASSERT(nullptr == fPixelSerializer);
|
|
||||||
int32_t slot = fBitmapHeap->insert(bitmap);
|
|
||||||
fWriter.write32(slot);
|
|
||||||
// crbug.com/155875
|
|
||||||
// The generation ID is not required information. We write it to prevent collisions
|
|
||||||
// in SkFlatDictionary. It is possible to get a collision when a previously
|
|
||||||
// unflattened (i.e. stale) instance of a similar flattenable is in the dictionary
|
|
||||||
// and the instance currently being written is re-using the same slot from the
|
|
||||||
// bitmap heap.
|
|
||||||
fWriter.write32(bitmap.getGenerationID());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
SkPixelRef* pixelRef = bitmap.pixelRef();
|
SkPixelRef* pixelRef = bitmap.pixelRef();
|
||||||
if (pixelRef) {
|
if (pixelRef) {
|
||||||
@ -183,7 +162,6 @@ void SkWriteBuffer::writeBitmap(const SkBitmap& bitmap) {
|
|||||||
// see if the caller wants to manually encode
|
// see if the caller wants to manually encode
|
||||||
SkAutoPixmapUnlock result;
|
SkAutoPixmapUnlock result;
|
||||||
if (fPixelSerializer && bitmap.requestLock(&result)) {
|
if (fPixelSerializer && bitmap.requestLock(&result)) {
|
||||||
SkASSERT(nullptr == fBitmapHeap);
|
|
||||||
SkAutoDataUnref data(fPixelSerializer->encode(result.pixmap()));
|
SkAutoDataUnref data(fPixelSerializer->encode(result.pixmap()));
|
||||||
if (data.get() != nullptr) {
|
if (data.get() != nullptr) {
|
||||||
// if we have to "encode" the bitmap, then we assume there is no
|
// if we have to "encode" the bitmap, then we assume there is no
|
||||||
@ -229,21 +207,10 @@ SkRefCntSet* SkWriteBuffer::setTypefaceRecorder(SkRefCntSet* rec) {
|
|||||||
return rec;
|
return rec;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SkWriteBuffer::setBitmapHeap(SkBitmapHeap* bitmapHeap) {
|
|
||||||
SkRefCnt_SafeAssign(fBitmapHeap, bitmapHeap);
|
|
||||||
if (bitmapHeap != nullptr) {
|
|
||||||
SkASSERT(nullptr == fPixelSerializer);
|
|
||||||
fPixelSerializer.reset(nullptr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SkWriteBuffer::setPixelSerializer(SkPixelSerializer* serializer) {
|
void SkWriteBuffer::setPixelSerializer(SkPixelSerializer* serializer) {
|
||||||
fPixelSerializer.reset(serializer);
|
fPixelSerializer.reset(serializer);
|
||||||
if (serializer) {
|
if (serializer) {
|
||||||
serializer->ref();
|
serializer->ref();
|
||||||
SkASSERT(nullptr == fBitmapHeap);
|
|
||||||
SkSafeUnref(fBitmapHeap);
|
|
||||||
fBitmapHeap = nullptr;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user