Remove SkGpuDevice::fTexture, use new pixel ref class name

Review URL: https://codereview.appspot.com/6474068/


git-svn-id: http://skia.googlecode.com/svn/trunk@5307 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
bsalomon@google.com 2012-08-28 12:34:17 +00:00
Родитель 97af1a64ae
Коммит a292112154
8 изменённых файлов: 94 добавлений и 80 удалений

Просмотреть файл

@ -95,6 +95,9 @@ public:
return NULL == fHead && NULL == fTail; return NULL == fHead && NULL == fTail;
} }
T* head() { return fHead; }
T* tail() { return fTail; }
class Iter { class Iter {
public: public:
enum IterStart { enum IterStart {

Просмотреть файл

@ -76,6 +76,8 @@ protected:
virtual void onRelease() = 0; virtual void onRelease() = 0;
virtual void onAbandon() = 0; virtual void onAbandon() = 0;
bool isInCache() const { return NULL != fCacheEntry; }
private: private:
friend class GrGpu; // GrGpu manages list of resources. friend class GrGpu; // GrGpu manages list of resources.

Просмотреть файл

@ -132,9 +132,8 @@ private:
GrClipData fClipData; GrClipData fClipData;
// state for our offscreen render-target // state for our offscreen render-target
// TODO: remove 'fCached' and let fTexture automatically return to the cache // TODO: remove 'fCached' and automatically return to the cache
bool fCached; // is fTexture in the cache bool fCached; // is fRenderTarget->asTexture() in the cache
GrTexture* fTexture;
GrRenderTarget* fRenderTarget; GrRenderTarget* fRenderTarget;
bool fNeedClear; bool fNeedClear;
bool fNeedPrepareRenderTarget; bool fNeedPrepareRenderTarget;

Просмотреть файл

@ -136,7 +136,7 @@ void GrContext::contextDestroyed() {
fAARectRenderer->reset(); fAARectRenderer->reset();
fTextureCache->removeAll(); fTextureCache->purgeAllUnlocked();
fFontCache->freeAll(); fFontCache->freeAll();
fGpu->markContextDirty(); fGpu->markContextDirty();
} }
@ -152,7 +152,7 @@ void GrContext::freeGpuResources() {
fAARectRenderer->reset(); fAARectRenderer->reset();
fTextureCache->removeAll(); fTextureCache->purgeAllUnlocked();
fFontCache->freeAll(); fFontCache->freeAll();
// a path renderer may be holding onto resources // a path renderer may be holding onto resources
GrSafeSetNull(fPathRendererChain); GrSafeSetNull(fPathRendererChain);

Просмотреть файл

@ -35,6 +35,36 @@ void GrResourceEntry::validate() const {
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
class GrResourceCache::Key {
typedef GrResourceEntry T;
const GrResourceKey& fKey;
public:
Key(const GrResourceKey& key) : fKey(key) {}
uint32_t getHash() const { return fKey.hashIndex(); }
static bool LT(const T& entry, const Key& key) {
return entry.key() < key.fKey;
}
static bool EQ(const T& entry, const Key& key) {
return entry.key() == key.fKey;
}
#if GR_DEBUG
static uint32_t GetHash(const T& entry) {
return entry.key().hashIndex();
}
static bool LT(const T& a, const T& b) {
return a.key() < b.key();
}
static bool EQ(const T& a, const T& b) {
return a.key() == b.key();
}
#endif
};
///////////////////////////////////////////////////////////////////////////////
GrResourceCache::GrResourceCache(int maxCount, size_t maxBytes) : GrResourceCache::GrResourceCache(int maxCount, size_t maxBytes) :
fMaxCount(maxCount), fMaxCount(maxCount),
fMaxBytes(maxBytes) { fMaxBytes(maxBytes) {
@ -58,7 +88,20 @@ GrResourceCache::GrResourceCache(int maxCount, size_t maxBytes) :
GrResourceCache::~GrResourceCache() { GrResourceCache::~GrResourceCache() {
GrAutoResourceCacheValidate atcv(this); GrAutoResourceCacheValidate atcv(this);
this->removeAll(); EntryList::Iter iter;
// Unlike the removeAll, here we really remove everything, including locked resources.
while (GrResourceEntry* entry = fList.head()) {
GrAutoResourceCacheValidate atcv(this);
// remove from our cache
fCache.remove(entry->fKey, entry);
// remove from our llist
this->internalDetach(entry, false);
delete entry;
}
} }
void GrResourceCache::getLimits(int* maxResources, size_t* maxResourceBytes) const{ void GrResourceCache::getLimits(int* maxResources, size_t* maxResourceBytes) const{
@ -141,34 +184,6 @@ void GrResourceCache::attachToHead(GrResourceEntry* entry,
} }
} }
class GrResourceCache::Key {
typedef GrResourceEntry T;
const GrResourceKey& fKey;
public:
Key(const GrResourceKey& key) : fKey(key) {}
uint32_t getHash() const { return fKey.hashIndex(); }
static bool LT(const T& entry, const Key& key) {
return entry.key() < key.fKey;
}
static bool EQ(const T& entry, const Key& key) {
return entry.key() == key.fKey;
}
#if GR_DEBUG
static uint32_t GetHash(const T& entry) {
return entry.key().hashIndex();
}
static bool LT(const T& a, const T& b) {
return a.key() < b.key();
}
static bool EQ(const T& a, const T& b) {
return a.key() == b.key();
}
#endif
};
GrResource* GrResourceCache::findAndLock(const GrResourceKey& key, GrResource* GrResourceCache::findAndLock(const GrResourceKey& key,
LockType type) { LockType type) {
GrAutoResourceCacheValidate atcv(this); GrAutoResourceCacheValidate atcv(this);
@ -310,14 +325,13 @@ void GrResourceCache::purgeAsNeeded() {
fPurging = true; fPurging = true;
bool withinBudget = false; bool withinBudget = false;
do { do {
SkTDLinkedList<GrResourceEntry>::Iter iter; EntryList::Iter iter;
// Note: the following code relies on the fact that the // Note: the following code relies on the fact that the
// doubly linked list doesn't invalidate its data/pointers // doubly linked list doesn't invalidate its data/pointers
// outside of the specific area where a deletion occurs (e.g., // outside of the specific area where a deletion occurs (e.g.,
// in internalDetach) // in internalDetach)
GrResourceEntry* entry = iter.init(fList, GrResourceEntry* entry = iter.init(fList, EntryList::Iter::kTail_IterStart);
SkTDLinkedList<GrResourceEntry>::Iter::kTail_IterStart);
while (entry && fUnlockedEntryCount) { while (entry && fUnlockedEntryCount) {
GrAutoResourceCacheValidate atcv(this); GrAutoResourceCacheValidate atcv(this);
@ -350,7 +364,7 @@ void GrResourceCache::purgeAsNeeded() {
} }
} }
void GrResourceCache::removeAll() { void GrResourceCache::purgeAllUnlocked() {
GrAutoResourceCacheValidate atcv(this); GrAutoResourceCacheValidate atcv(this);
// we can have one GrResource holding a lock on another // we can have one GrResource holding a lock on another
@ -384,14 +398,13 @@ void GrResourceCache::removeAll() {
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
#if GR_DEBUG #if GR_DEBUG
size_t GrResourceCache::countBytes(const SkTDLinkedList<GrResourceEntry>& list) { size_t GrResourceCache::countBytes(const EntryList& list) {
size_t bytes = 0; size_t bytes = 0;
SkTDLinkedList<GrResourceEntry>::Iter iter; EntryList::Iter iter;
const GrResourceEntry* entry = iter.init( const GrResourceEntry* entry = iter.init(const_cast<EntryList&>(list),
const_cast<SkTDLinkedList<GrResourceEntry>&>(list), EntryList::Iter::kTail_IterStart);
SkTDLinkedList<GrResourceEntry>::Iter::kTail_IterStart);
for ( ; NULL != entry; entry = iter.prev()) { for ( ; NULL != entry; entry = iter.prev()) {
bytes += entry->resource()->sizeInBytes(); bytes += entry->resource()->sizeInBytes();
@ -417,11 +430,10 @@ void GrResourceCache::validate() const {
int count = 0; int count = 0;
int unlockCount = 0; int unlockCount = 0;
SkTDLinkedList<GrResourceEntry>::Iter iter; EntryList::Iter iter;
const GrResourceEntry* entry = iter.init( const GrResourceEntry* entry = iter.init(const_cast<EntryList&>(fList),
const_cast<SkTDLinkedList<GrResourceEntry>&>(fList), EntryList::Iter::kHead_IterStart);
SkTDLinkedList<GrResourceEntry>::Iter::kHead_IterStart);
for ( ; NULL != entry; entry = iter.next()) { for ( ; NULL != entry; entry = iter.next()) {
entry->validate(); entry->validate();

Просмотреть файл

@ -264,12 +264,15 @@ public:
void makeNonExclusive(GrResourceEntry* entry); void makeNonExclusive(GrResourceEntry* entry);
/** /**
* When done with an entry, call unlock(entry) on it, which returns it to * When done with an entry, call unlock(entry) on it, which returns it to
* a purgable state. * a purgable state.
*/ */
void unlock(GrResourceEntry*); void unlock(GrResourceEntry*);
void removeAll(); /**
* Removes every resource in the cache that isn't locked.
*/
void purgeAllUnlocked();
#if GR_DEBUG #if GR_DEBUG
void validate() const; void validate() const;
@ -289,11 +292,12 @@ private:
GrTHashTable<GrResourceEntry, Key, 8> fCache; GrTHashTable<GrResourceEntry, Key, 8> fCache;
// manage the dlink list // manage the dlink list
SkTDLinkedList<GrResourceEntry> fList; typedef SkTDLinkedList<GrResourceEntry> EntryList;
EntryList fList;
#if GR_DEBUG #if GR_DEBUG
// These objects cannot be returned by a search // These objects cannot be returned by a search
SkTDLinkedList<GrResourceEntry> fExclusiveList; EntryList fExclusiveList;
#endif #endif
// our budget, used in purgeAsNeeded() // our budget, used in purgeAsNeeded()

Просмотреть файл

@ -41,7 +41,6 @@ void GrStencilBuffer::onRelease() {
this->unlockInCache(); this->unlockInCache();
// we shouldn't be deleted here because some RT still has a ref on us. // we shouldn't be deleted here because some RT still has a ref on us.
} }
fHoldingLock = false;
} }
void GrStencilBuffer::onAbandon() { void GrStencilBuffer::onAbandon() {
@ -50,12 +49,13 @@ void GrStencilBuffer::onAbandon() {
} }
void GrStencilBuffer::unlockInCache() { void GrStencilBuffer::unlockInCache() {
if (fHoldingLock) { if (fHoldingLock && this->isInCache()) {
GrGpu* gpu = this->getGpu(); GrGpu* gpu = this->getGpu();
if (NULL != gpu) { if (NULL != gpu) {
GrAssert(NULL != gpu->getContext()); GrAssert(NULL != gpu->getContext());
gpu->getContext()->unlockStencilBuffer(this); gpu->getContext()->unlockStencilBuffer(this);
} }
fHoldingLock = false;
} }
} }

Просмотреть файл

@ -189,28 +189,23 @@ void SkGpuDevice::initFromRenderTarget(GrContext* context,
fContext->ref(); fContext->ref();
fCached = false; fCached = false;
fTexture = NULL;
fRenderTarget = NULL; fRenderTarget = NULL;
fNeedClear = false; fNeedClear = false;
GrAssert(NULL != renderTarget); GrAssert(NULL != renderTarget);
fRenderTarget = renderTarget; fRenderTarget = renderTarget;
fRenderTarget->ref(); fRenderTarget->ref();
// if this RT is also a texture, hold a ref on it
fTexture = fRenderTarget->asTexture();
SkSafeRef(fTexture);
// Create a pixel ref for the underlying SkBitmap. We prefer a texture pixel // Hold onto to the texture in the pixel ref (if there is one) because the texture holds a ref
// ref to a render target pixel reft. The pixel ref may get ref'ed outside // on the RT but not vice-versa.
// the device via accessBitmap. This external ref may outlive the device. // TODO: Remove this trickery once we figure out how to make SkGrPixelRef do this without
// Since textures own their render targets (but not vice-versa) we // busting chrome (for a currently unknown reason).
// are ensuring that both objects will live as long as the pixel ref. GrSurface* surface = fRenderTarget->asTexture();
SkPixelRef* pr; if (NULL == surface) {
if (fTexture) { surface = fRenderTarget;
pr = SkNEW_ARGS(SkGrTexturePixelRef, (fTexture));
} else {
pr = SkNEW_ARGS(SkGrRenderTargetPixelRef, (fRenderTarget));
} }
SkPixelRef* pr = SkNEW_ARGS(SkGrPixelRef, (surface));
this->setPixelRef(pr, 0)->unref(); this->setPixelRef(pr, 0)->unref();
} }
@ -227,7 +222,6 @@ SkGpuDevice::SkGpuDevice(GrContext* context,
fContext->ref(); fContext->ref();
fCached = false; fCached = false;
fTexture = NULL;
fRenderTarget = NULL; fRenderTarget = NULL;
fNeedClear = false; fNeedClear = false;
@ -243,16 +237,16 @@ SkGpuDevice::SkGpuDevice(GrContext* context,
desc.fHeight = height; desc.fHeight = height;
desc.fConfig = SkBitmapConfig2GrPixelConfig(bm.config()); desc.fConfig = SkBitmapConfig2GrPixelConfig(bm.config());
fTexture = fContext->createUncachedTexture(desc, NULL, 0); SkAutoTUnref<GrTexture> texture(fContext->createUncachedTexture(desc, NULL, 0));
if (NULL != fTexture) { if (NULL != texture) {
fRenderTarget = fTexture->asRenderTarget(); fRenderTarget = texture->asRenderTarget();
fRenderTarget->ref(); fRenderTarget->ref();
GrAssert(NULL != fRenderTarget); GrAssert(NULL != fRenderTarget);
// wrap the bitmap with a pixelref to expose our texture // wrap the bitmap with a pixelref to expose our texture
SkGrTexturePixelRef* pr = SkNEW_ARGS(SkGrTexturePixelRef, (fTexture)); SkGrPixelRef* pr = SkNEW_ARGS(SkGrPixelRef, (texture));
this->setPixelRef(pr, 0)->unref(); this->setPixelRef(pr, 0)->unref();
} else { } else {
GrPrintf("--- failed to create gpu-offscreen [%d %d]\n", GrPrintf("--- failed to create gpu-offscreen [%d %d]\n",
@ -270,12 +264,11 @@ SkGpuDevice::~SkGpuDevice() {
// This call gives the context a chance to relinquish it // This call gives the context a chance to relinquish it
fContext->setRenderTarget(NULL); fContext->setRenderTarget(NULL);
SkSafeUnref(fTexture); GrTexture* texture = fRenderTarget->asTexture();
SkSafeUnref(fRenderTarget); if (NULL != texture && fCached) {
if (NULL != fTexture && fCached) { fContext->unlockTexture(texture);
GrAssert(fRenderTarget == fTexture->asRenderTarget());
fContext->unlockTexture(fTexture);
} }
SkSafeUnref(fRenderTarget);
fContext->unref(); fContext->unref();
} }
@ -485,9 +478,10 @@ SkGpuRenderTarget* SkGpuDevice::accessRenderTarget() {
} }
bool SkGpuDevice::bindDeviceAsTexture(GrPaint* paint) { bool SkGpuDevice::bindDeviceAsTexture(GrPaint* paint) {
if (NULL != fTexture) { GrTexture* texture = fRenderTarget->asTexture();
if (NULL != texture) {
paint->textureSampler(kBitmapTextureIdx)->setCustomStage( paint->textureSampler(kBitmapTextureIdx)->setCustomStage(
SkNEW_ARGS(GrSingleTextureEffect, (fTexture)))->unref(); SkNEW_ARGS(GrSingleTextureEffect, (texture)))->unref();
return true; return true;
} }
return false; return false;