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/SkBitmapDevice.cpp',
|
||||
'<(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.h',
|
||||
'<(skia_src_path)/core/SkBitmapProcState.cpp',
|
||||
|
@ -19,7 +19,6 @@
|
||||
#include "../private/SkTHash.h"
|
||||
|
||||
class SkBitmap;
|
||||
class SkBitmapHeap;
|
||||
class SkFactorySet;
|
||||
class SkFlattenable;
|
||||
class SkRefCntSet;
|
||||
@ -79,15 +78,6 @@ public:
|
||||
SkRefCntSet* getTypefaceRecorder() const { return fTFSet; }
|
||||
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,
|
||||
* e.g. SkBitmaps.
|
||||
@ -95,9 +85,6 @@ public:
|
||||
* Calls ref() on the serializer.
|
||||
*
|
||||
* 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*);
|
||||
SkPixelSerializer* getPixelSerializer() const { return fPixelSerializer; }
|
||||
@ -107,7 +94,6 @@ private:
|
||||
SkFactorySet* fFactorySet;
|
||||
SkWriter32 fWriter;
|
||||
|
||||
SkBitmapHeap* fBitmapHeap;
|
||||
SkRefCntSet* fTFSet;
|
||||
|
||||
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);
|
||||
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<SkPaint> fPaints;
|
||||
SkTArray<SkPath> fPaths;
|
||||
|
@ -8,7 +8,6 @@
|
||||
#define SkPictureFlat_DEFINED
|
||||
|
||||
|
||||
#include "SkBitmapHeap.h"
|
||||
#include "SkChecksum.h"
|
||||
#include "SkChunkAlloc.h"
|
||||
#include "SkReadBuffer.h"
|
||||
|
@ -27,7 +27,6 @@ SkReadBuffer::SkReadBuffer() {
|
||||
fVersion = 0;
|
||||
fMemoryPtr = nullptr;
|
||||
|
||||
fBitmapStorage = nullptr;
|
||||
fTFArray = nullptr;
|
||||
fTFCount = 0;
|
||||
|
||||
@ -45,7 +44,6 @@ SkReadBuffer::SkReadBuffer(const void* data, size_t size) {
|
||||
fReader.setMemory(data, size);
|
||||
fMemoryPtr = nullptr;
|
||||
|
||||
fBitmapStorage = nullptr;
|
||||
fTFArray = nullptr;
|
||||
fTFCount = 0;
|
||||
|
||||
@ -65,7 +63,6 @@ SkReadBuffer::SkReadBuffer(SkStream* stream) {
|
||||
stream->read(fMemoryPtr, length);
|
||||
fReader.setMemory(fMemoryPtr, length);
|
||||
|
||||
fBitmapStorage = nullptr;
|
||||
fTFArray = nullptr;
|
||||
fTFCount = 0;
|
||||
|
||||
@ -79,7 +76,6 @@ SkReadBuffer::SkReadBuffer(SkStream* stream) {
|
||||
|
||||
SkReadBuffer::~SkReadBuffer() {
|
||||
sk_free(fMemoryPtr);
|
||||
SkSafeUnref(fBitmapStorage);
|
||||
}
|
||||
|
||||
bool SkReadBuffer::readBool() {
|
||||
@ -186,25 +182,15 @@ uint32_t SkReadBuffer::getArrayCount() {
|
||||
bool SkReadBuffer::readBitmap(SkBitmap* bitmap) {
|
||||
const int width = this->readInt();
|
||||
const int height = this->readInt();
|
||||
|
||||
// The writer stored a boolean value to determine whether an SkBitmapHeap was used during
|
||||
// writing.
|
||||
// writing. That feature is deprecated.
|
||||
if (this->readBool()) {
|
||||
// An SkBitmapHeap was used for writing. Read the index from the stream and find the
|
||||
// corresponding SkBitmap in fBitmapStorage.
|
||||
const uint32_t index = this->readUInt();
|
||||
this->readUInt(); // bitmap generation ID (see SkWriteBuffer::writeBitmap)
|
||||
if (fBitmapStorage) {
|
||||
*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.");
|
||||
}
|
||||
this->readUInt(); // Bitmap index
|
||||
this->readUInt(); // Bitmap generation ID
|
||||
SkErrorInternals::SetError(kParseError_SkError, "SkWriteBuffer::writeBitmap "
|
||||
"stored the SkBitmap in an SkBitmapHeap, but "
|
||||
"that feature is no longer supported.");
|
||||
} else {
|
||||
// The writer stored false, meaning the SkBitmap was not stored in an SkBitmapHeap.
|
||||
const size_t length = this->readUInt();
|
||||
|
@ -8,7 +8,6 @@
|
||||
#ifndef SkReadBuffer_DEFINED
|
||||
#define SkReadBuffer_DEFINED
|
||||
|
||||
#include "SkBitmapHeap.h"
|
||||
#include "SkColorFilter.h"
|
||||
#include "SkData.h"
|
||||
#include "SkDrawLooper.h"
|
||||
@ -176,10 +175,6 @@ public:
|
||||
|
||||
virtual SkTypeface* readTypeface();
|
||||
|
||||
void setBitmapStorage(SkBitmapHeapReader* bitmapStorage) {
|
||||
SkRefCnt_SafeAssign(fBitmapStorage, bitmapStorage);
|
||||
}
|
||||
|
||||
void setTypefaceArray(SkTypeface* array[], int count) {
|
||||
fTFArray = array;
|
||||
fTFCount = count;
|
||||
@ -255,7 +250,6 @@ private:
|
||||
|
||||
void* fMemoryPtr;
|
||||
|
||||
SkBitmapHeapReader* fBitmapStorage;
|
||||
SkTypeface** fTFArray;
|
||||
int fTFCount;
|
||||
|
||||
|
@ -9,7 +9,6 @@
|
||||
#define SkValidatingReadBuffer_DEFINED
|
||||
|
||||
#include "SkRefCnt.h"
|
||||
#include "SkBitmapHeap.h"
|
||||
#include "SkReadBuffer.h"
|
||||
#include "SkWriteBuffer.h"
|
||||
#include "SkPath.h"
|
||||
|
@ -7,7 +7,6 @@
|
||||
|
||||
#include "SkWriteBuffer.h"
|
||||
#include "SkBitmap.h"
|
||||
#include "SkBitmapHeap.h"
|
||||
#include "SkData.h"
|
||||
#include "SkPixelRef.h"
|
||||
#include "SkPtrRecorder.h"
|
||||
@ -17,7 +16,6 @@
|
||||
SkWriteBuffer::SkWriteBuffer(uint32_t flags)
|
||||
: fFlags(flags)
|
||||
, fFactorySet(nullptr)
|
||||
, fBitmapHeap(nullptr)
|
||||
, fTFSet(nullptr) {
|
||||
}
|
||||
|
||||
@ -25,13 +23,11 @@ SkWriteBuffer::SkWriteBuffer(void* storage, size_t storageSize, uint32_t flags)
|
||||
: fFlags(flags)
|
||||
, fFactorySet(nullptr)
|
||||
, fWriter(storage, storageSize)
|
||||
, fBitmapHeap(nullptr)
|
||||
, fTFSet(nullptr) {
|
||||
}
|
||||
|
||||
SkWriteBuffer::~SkWriteBuffer() {
|
||||
SkSafeUnref(fFactorySet);
|
||||
SkSafeUnref(fBitmapHeap);
|
||||
SkSafeUnref(fTFSet);
|
||||
}
|
||||
|
||||
@ -139,32 +135,15 @@ void SkWriteBuffer::writeBitmap(const SkBitmap& bitmap) {
|
||||
this->writeInt(bitmap.width());
|
||||
this->writeInt(bitmap.height());
|
||||
|
||||
// Record information about the bitmap in one of three ways, in order of priority:
|
||||
// 1. If there is an SkBitmapHeap, store it in the heap. The client can avoid serializing 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
|
||||
// Record information about the bitmap in one of two ways, in order of priority:
|
||||
// 1. 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
|
||||
// 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.
|
||||
bool useBitmapHeap = fBitmapHeap != nullptr;
|
||||
// Write a bool: true if the SkBitmapHeap is to be used, in which case the reader must use an
|
||||
// SkBitmapHeapReader to read the SkBitmap. False if the bitmap was serialized another way.
|
||||
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;
|
||||
}
|
||||
|
||||
// Write a bool to indicate that we did not use an SkBitmapHeap. That feature is deprecated.
|
||||
this->writeBool(false);
|
||||
|
||||
SkPixelRef* pixelRef = bitmap.pixelRef();
|
||||
if (pixelRef) {
|
||||
@ -183,7 +162,6 @@ void SkWriteBuffer::writeBitmap(const SkBitmap& bitmap) {
|
||||
// see if the caller wants to manually encode
|
||||
SkAutoPixmapUnlock result;
|
||||
if (fPixelSerializer && bitmap.requestLock(&result)) {
|
||||
SkASSERT(nullptr == fBitmapHeap);
|
||||
SkAutoDataUnref data(fPixelSerializer->encode(result.pixmap()));
|
||||
if (data.get() != nullptr) {
|
||||
// if we have to "encode" the bitmap, then we assume there is no
|
||||
@ -229,21 +207,10 @@ SkRefCntSet* SkWriteBuffer::setTypefaceRecorder(SkRefCntSet* 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) {
|
||||
fPixelSerializer.reset(serializer);
|
||||
if (serializer) {
|
||||
serializer->ref();
|
||||
SkASSERT(nullptr == fBitmapHeap);
|
||||
SkSafeUnref(fBitmapHeap);
|
||||
fBitmapHeap = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user