зеркало из https://github.com/mozilla/moz-skia.git
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:
Родитель
97af1a64ae
Коммит
a292112154
|
@ -95,6 +95,9 @@ public:
|
|||
return NULL == fHead && NULL == fTail;
|
||||
}
|
||||
|
||||
T* head() { return fHead; }
|
||||
T* tail() { return fTail; }
|
||||
|
||||
class Iter {
|
||||
public:
|
||||
enum IterStart {
|
||||
|
|
|
@ -76,6 +76,8 @@ protected:
|
|||
virtual void onRelease() = 0;
|
||||
virtual void onAbandon() = 0;
|
||||
|
||||
bool isInCache() const { return NULL != fCacheEntry; }
|
||||
|
||||
private:
|
||||
|
||||
friend class GrGpu; // GrGpu manages list of resources.
|
||||
|
|
|
@ -132,9 +132,8 @@ private:
|
|||
GrClipData fClipData;
|
||||
|
||||
// state for our offscreen render-target
|
||||
// TODO: remove 'fCached' and let fTexture automatically return to the cache
|
||||
bool fCached; // is fTexture in the cache
|
||||
GrTexture* fTexture;
|
||||
// TODO: remove 'fCached' and automatically return to the cache
|
||||
bool fCached; // is fRenderTarget->asTexture() in the cache
|
||||
GrRenderTarget* fRenderTarget;
|
||||
bool fNeedClear;
|
||||
bool fNeedPrepareRenderTarget;
|
||||
|
|
|
@ -136,7 +136,7 @@ void GrContext::contextDestroyed() {
|
|||
|
||||
fAARectRenderer->reset();
|
||||
|
||||
fTextureCache->removeAll();
|
||||
fTextureCache->purgeAllUnlocked();
|
||||
fFontCache->freeAll();
|
||||
fGpu->markContextDirty();
|
||||
}
|
||||
|
@ -152,7 +152,7 @@ void GrContext::freeGpuResources() {
|
|||
|
||||
fAARectRenderer->reset();
|
||||
|
||||
fTextureCache->removeAll();
|
||||
fTextureCache->purgeAllUnlocked();
|
||||
fFontCache->freeAll();
|
||||
// a path renderer may be holding onto resources
|
||||
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) :
|
||||
fMaxCount(maxCount),
|
||||
fMaxBytes(maxBytes) {
|
||||
|
@ -58,7 +88,20 @@ GrResourceCache::GrResourceCache(int maxCount, size_t maxBytes) :
|
|||
GrResourceCache::~GrResourceCache() {
|
||||
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{
|
||||
|
@ -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,
|
||||
LockType type) {
|
||||
GrAutoResourceCacheValidate atcv(this);
|
||||
|
@ -310,14 +325,13 @@ void GrResourceCache::purgeAsNeeded() {
|
|||
fPurging = true;
|
||||
bool withinBudget = false;
|
||||
do {
|
||||
SkTDLinkedList<GrResourceEntry>::Iter iter;
|
||||
EntryList::Iter iter;
|
||||
|
||||
// Note: the following code relies on the fact that the
|
||||
// doubly linked list doesn't invalidate its data/pointers
|
||||
// outside of the specific area where a deletion occurs (e.g.,
|
||||
// in internalDetach)
|
||||
GrResourceEntry* entry = iter.init(fList,
|
||||
SkTDLinkedList<GrResourceEntry>::Iter::kTail_IterStart);
|
||||
GrResourceEntry* entry = iter.init(fList, EntryList::Iter::kTail_IterStart);
|
||||
|
||||
while (entry && fUnlockedEntryCount) {
|
||||
GrAutoResourceCacheValidate atcv(this);
|
||||
|
@ -350,7 +364,7 @@ void GrResourceCache::purgeAsNeeded() {
|
|||
}
|
||||
}
|
||||
|
||||
void GrResourceCache::removeAll() {
|
||||
void GrResourceCache::purgeAllUnlocked() {
|
||||
GrAutoResourceCacheValidate atcv(this);
|
||||
|
||||
// we can have one GrResource holding a lock on another
|
||||
|
@ -384,14 +398,13 @@ void GrResourceCache::removeAll() {
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if GR_DEBUG
|
||||
size_t GrResourceCache::countBytes(const SkTDLinkedList<GrResourceEntry>& list) {
|
||||
size_t GrResourceCache::countBytes(const EntryList& list) {
|
||||
size_t bytes = 0;
|
||||
|
||||
SkTDLinkedList<GrResourceEntry>::Iter iter;
|
||||
EntryList::Iter iter;
|
||||
|
||||
const GrResourceEntry* entry = iter.init(
|
||||
const_cast<SkTDLinkedList<GrResourceEntry>&>(list),
|
||||
SkTDLinkedList<GrResourceEntry>::Iter::kTail_IterStart);
|
||||
const GrResourceEntry* entry = iter.init(const_cast<EntryList&>(list),
|
||||
EntryList::Iter::kTail_IterStart);
|
||||
|
||||
for ( ; NULL != entry; entry = iter.prev()) {
|
||||
bytes += entry->resource()->sizeInBytes();
|
||||
|
@ -417,11 +430,10 @@ void GrResourceCache::validate() const {
|
|||
int count = 0;
|
||||
int unlockCount = 0;
|
||||
|
||||
SkTDLinkedList<GrResourceEntry>::Iter iter;
|
||||
EntryList::Iter iter;
|
||||
|
||||
const GrResourceEntry* entry = iter.init(
|
||||
const_cast<SkTDLinkedList<GrResourceEntry>&>(fList),
|
||||
SkTDLinkedList<GrResourceEntry>::Iter::kHead_IterStart);
|
||||
const GrResourceEntry* entry = iter.init(const_cast<EntryList&>(fList),
|
||||
EntryList::Iter::kHead_IterStart);
|
||||
|
||||
for ( ; NULL != entry; entry = iter.next()) {
|
||||
entry->validate();
|
||||
|
|
|
@ -264,12 +264,15 @@ public:
|
|||
void makeNonExclusive(GrResourceEntry* entry);
|
||||
|
||||
/**
|
||||
* When done with an entry, call unlock(entry) on it, which returns it to
|
||||
* a purgable state.
|
||||
* When done with an entry, call unlock(entry) on it, which returns it to
|
||||
* a purgable state.
|
||||
*/
|
||||
void unlock(GrResourceEntry*);
|
||||
|
||||
void removeAll();
|
||||
/**
|
||||
* Removes every resource in the cache that isn't locked.
|
||||
*/
|
||||
void purgeAllUnlocked();
|
||||
|
||||
#if GR_DEBUG
|
||||
void validate() const;
|
||||
|
@ -289,11 +292,12 @@ private:
|
|||
GrTHashTable<GrResourceEntry, Key, 8> fCache;
|
||||
|
||||
// manage the dlink list
|
||||
SkTDLinkedList<GrResourceEntry> fList;
|
||||
typedef SkTDLinkedList<GrResourceEntry> EntryList;
|
||||
EntryList fList;
|
||||
|
||||
#if GR_DEBUG
|
||||
// These objects cannot be returned by a search
|
||||
SkTDLinkedList<GrResourceEntry> fExclusiveList;
|
||||
EntryList fExclusiveList;
|
||||
#endif
|
||||
|
||||
// our budget, used in purgeAsNeeded()
|
||||
|
|
|
@ -41,7 +41,6 @@ void GrStencilBuffer::onRelease() {
|
|||
this->unlockInCache();
|
||||
// we shouldn't be deleted here because some RT still has a ref on us.
|
||||
}
|
||||
fHoldingLock = false;
|
||||
}
|
||||
|
||||
void GrStencilBuffer::onAbandon() {
|
||||
|
@ -50,12 +49,13 @@ void GrStencilBuffer::onAbandon() {
|
|||
}
|
||||
|
||||
void GrStencilBuffer::unlockInCache() {
|
||||
if (fHoldingLock) {
|
||||
if (fHoldingLock && this->isInCache()) {
|
||||
GrGpu* gpu = this->getGpu();
|
||||
if (NULL != gpu) {
|
||||
GrAssert(NULL != gpu->getContext());
|
||||
gpu->getContext()->unlockStencilBuffer(this);
|
||||
}
|
||||
fHoldingLock = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -189,28 +189,23 @@ void SkGpuDevice::initFromRenderTarget(GrContext* context,
|
|||
fContext->ref();
|
||||
|
||||
fCached = false;
|
||||
fTexture = NULL;
|
||||
fRenderTarget = NULL;
|
||||
fNeedClear = false;
|
||||
|
||||
GrAssert(NULL != renderTarget);
|
||||
fRenderTarget = renderTarget;
|
||||
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
|
||||
// ref to a render target pixel reft. The pixel ref may get ref'ed outside
|
||||
// the device via accessBitmap. This external ref may outlive the device.
|
||||
// Since textures own their render targets (but not vice-versa) we
|
||||
// are ensuring that both objects will live as long as the pixel ref.
|
||||
SkPixelRef* pr;
|
||||
if (fTexture) {
|
||||
pr = SkNEW_ARGS(SkGrTexturePixelRef, (fTexture));
|
||||
} else {
|
||||
pr = SkNEW_ARGS(SkGrRenderTargetPixelRef, (fRenderTarget));
|
||||
// Hold onto to the texture in the pixel ref (if there is one) because the texture holds a ref
|
||||
// on the RT but not vice-versa.
|
||||
// TODO: Remove this trickery once we figure out how to make SkGrPixelRef do this without
|
||||
// busting chrome (for a currently unknown reason).
|
||||
GrSurface* surface = fRenderTarget->asTexture();
|
||||
if (NULL == surface) {
|
||||
surface = fRenderTarget;
|
||||
}
|
||||
SkPixelRef* pr = SkNEW_ARGS(SkGrPixelRef, (surface));
|
||||
|
||||
this->setPixelRef(pr, 0)->unref();
|
||||
}
|
||||
|
||||
|
@ -227,7 +222,6 @@ SkGpuDevice::SkGpuDevice(GrContext* context,
|
|||
fContext->ref();
|
||||
|
||||
fCached = false;
|
||||
fTexture = NULL;
|
||||
fRenderTarget = NULL;
|
||||
fNeedClear = false;
|
||||
|
||||
|
@ -243,16 +237,16 @@ SkGpuDevice::SkGpuDevice(GrContext* context,
|
|||
desc.fHeight = height;
|
||||
desc.fConfig = SkBitmapConfig2GrPixelConfig(bm.config());
|
||||
|
||||
fTexture = fContext->createUncachedTexture(desc, NULL, 0);
|
||||
SkAutoTUnref<GrTexture> texture(fContext->createUncachedTexture(desc, NULL, 0));
|
||||
|
||||
if (NULL != fTexture) {
|
||||
fRenderTarget = fTexture->asRenderTarget();
|
||||
if (NULL != texture) {
|
||||
fRenderTarget = texture->asRenderTarget();
|
||||
fRenderTarget->ref();
|
||||
|
||||
GrAssert(NULL != fRenderTarget);
|
||||
|
||||
// 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();
|
||||
} else {
|
||||
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
|
||||
fContext->setRenderTarget(NULL);
|
||||
|
||||
SkSafeUnref(fTexture);
|
||||
SkSafeUnref(fRenderTarget);
|
||||
if (NULL != fTexture && fCached) {
|
||||
GrAssert(fRenderTarget == fTexture->asRenderTarget());
|
||||
fContext->unlockTexture(fTexture);
|
||||
GrTexture* texture = fRenderTarget->asTexture();
|
||||
if (NULL != texture && fCached) {
|
||||
fContext->unlockTexture(texture);
|
||||
}
|
||||
SkSafeUnref(fRenderTarget);
|
||||
fContext->unref();
|
||||
}
|
||||
|
||||
|
@ -485,9 +478,10 @@ SkGpuRenderTarget* SkGpuDevice::accessRenderTarget() {
|
|||
}
|
||||
|
||||
bool SkGpuDevice::bindDeviceAsTexture(GrPaint* paint) {
|
||||
if (NULL != fTexture) {
|
||||
GrTexture* texture = fRenderTarget->asTexture();
|
||||
if (NULL != texture) {
|
||||
paint->textureSampler(kBitmapTextureIdx)->setCustomStage(
|
||||
SkNEW_ARGS(GrSingleTextureEffect, (fTexture)))->unref();
|
||||
SkNEW_ARGS(GrSingleTextureEffect, (texture)))->unref();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
Загрузка…
Ссылка в новой задаче