AutoScratchTexture can now release its texture and it will return to the texture cache when freed
http://codereview.appspot.com/6262043/ git-svn-id: http://skia.googlecode.com/svn/trunk@4301 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
parent
5e24129831
commit
15c0fea699
@ -18,7 +18,6 @@
|
||||
|
||||
struct SkIRect;
|
||||
struct SkRect;
|
||||
class SkColorTable;
|
||||
class SkPaint;
|
||||
class SkPixelRef;
|
||||
class SkRegion;
|
||||
|
@ -80,7 +80,10 @@ private:
|
||||
#endif
|
||||
SkDELETE(this);
|
||||
}
|
||||
|
||||
friend class SkWeakRefCnt;
|
||||
friend class GrTexture; // to allow GrTexture's internal_dispose to
|
||||
// call SkRefCnt's & directly set fRefCnt (to 1)
|
||||
|
||||
mutable int32_t fRefCnt;
|
||||
|
||||
|
@ -100,10 +100,10 @@ public:
|
||||
}
|
||||
GrTexture* texture() const;
|
||||
void reset() { fEntry = NULL; }
|
||||
GrResourceEntry* cacheEntry() { return fEntry; }
|
||||
private:
|
||||
explicit TextureCacheEntry(GrResourceEntry* entry) { fEntry = entry; }
|
||||
void set(GrResourceEntry* entry) { fEntry = entry; }
|
||||
GrResourceEntry* cacheEntry() { return fEntry; }
|
||||
GrResourceEntry* fEntry;
|
||||
friend class GrContext;
|
||||
};
|
||||
@ -174,7 +174,7 @@ public:
|
||||
* Returns a texture matching the desc. It's contents are unknown. Subsequent
|
||||
* requests with the same descriptor are not guaranteed to return the same
|
||||
* texture. The same texture is guaranteed not be returned again until it is
|
||||
* unlocked. Must call be balanced with an unlockTexture() call.
|
||||
* unlocked. Call must be balanced with an unlockTexture() call.
|
||||
*
|
||||
* Textures created by createAndLockTexture() hide the complications of
|
||||
* tiling non-power-of-two textures on APIs that don't support this (e.g.
|
||||
@ -191,6 +191,11 @@ public:
|
||||
*/
|
||||
void unlockTexture(TextureCacheEntry entry);
|
||||
|
||||
/**
|
||||
* Free any data associated with the provided entry in the texture cache
|
||||
*/
|
||||
void freeEntry(TextureCacheEntry entry);
|
||||
|
||||
/**
|
||||
* Creates a texture that is outside the cache. Does not count against
|
||||
* cache's budget.
|
||||
@ -772,6 +777,14 @@ private:
|
||||
static int PaintStageVertexLayoutBits(
|
||||
const GrPaint& paint,
|
||||
const bool hasTexCoords[GrPaint::kTotalStages]);
|
||||
|
||||
// Needed so GrTexture's returnToCache helper function can call
|
||||
// addExistingTextureToCache
|
||||
friend class GrTexture;
|
||||
|
||||
// Add an existing texture to the texture cache. This is intended solely
|
||||
// for use with textures released from an GrAutoScratchTexture.
|
||||
void addExistingTextureToCache(GrTexture* texture);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -837,12 +850,39 @@ public:
|
||||
}
|
||||
|
||||
void reset() {
|
||||
if (NULL != fContext) {
|
||||
if (NULL != fContext && NULL != fEntry.cacheEntry()) {
|
||||
fContext->unlockTexture(fEntry);
|
||||
fEntry.reset();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* When detaching a texture we do not unlock it in the texture cache but
|
||||
* we do set the returnToCache flag. In this way the texture remains
|
||||
* "locked" in the texture cache until it is freed and recycled in
|
||||
* GrTexture::internal_dispose. In reality, the texture has been removed
|
||||
* from the cache (because this is in AutoScratchTexture) and by not
|
||||
* calling unlockTexture we simply don't re-add it. It will be reattached
|
||||
* in GrTexture::internal_dispose.
|
||||
*
|
||||
* Note that the caller is assumed to accept and manage the ref to the
|
||||
* returned texture.
|
||||
*/
|
||||
GrTexture* detach() {
|
||||
GrTexture* temp = this->texture();
|
||||
|
||||
GrAssert(1 == temp->getRefCnt());
|
||||
|
||||
// freeEntry will remove the texture cache's ref
|
||||
temp->ref();
|
||||
fContext->freeEntry(fEntry);
|
||||
fEntry.reset();
|
||||
|
||||
temp->setFlag((GrTextureFlags) GrTexture::kReturnToCache_FlagBit);
|
||||
GrAssert(1 == temp->getRefCnt());
|
||||
return temp;
|
||||
}
|
||||
|
||||
GrTexture* set(GrContext* context,
|
||||
const GrTextureDesc& desc,
|
||||
GrContext::ScratchTexMatch match =
|
||||
|
@ -32,6 +32,29 @@ public:
|
||||
SK_DECLARE_INST_COUNT(GrTexture)
|
||||
|
||||
// from GrResource
|
||||
/**
|
||||
* Informational texture flags
|
||||
*/
|
||||
enum FlagBits {
|
||||
kFirstBit = (kLastPublic_GrTextureFlagBit << 1),
|
||||
|
||||
/**
|
||||
* This texture should be returned to the texture cache when
|
||||
* it is no longer reffed
|
||||
*/
|
||||
kReturnToCache_FlagBit = kFirstBit,
|
||||
};
|
||||
|
||||
void setFlag(GrTextureFlags flags) {
|
||||
fDesc.fFlags = fDesc.fFlags | flags;
|
||||
}
|
||||
void resetFlag(GrTextureFlags flags) {
|
||||
fDesc.fFlags = fDesc.fFlags & ~flags;
|
||||
}
|
||||
bool isSetFlag(GrTextureFlags flags) const {
|
||||
return 0 != (fDesc.fFlags & flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* Approximate number of bytes used by the texture
|
||||
*/
|
||||
@ -162,11 +185,8 @@ protected:
|
||||
}
|
||||
|
||||
// GrResource overrides
|
||||
virtual void onRelease() {
|
||||
this->releaseRenderTarget();
|
||||
}
|
||||
|
||||
virtual void onAbandon();
|
||||
virtual void onRelease() SK_OVERRIDE;
|
||||
virtual void onAbandon() SK_OVERRIDE;
|
||||
|
||||
void validateDesc() const;
|
||||
|
||||
@ -176,6 +196,8 @@ private:
|
||||
int fShiftFixedX;
|
||||
int fShiftFixedY;
|
||||
|
||||
virtual void internal_dispose() const SK_OVERRIDE;
|
||||
|
||||
typedef GrSurface INHERITED;
|
||||
};
|
||||
|
||||
|
@ -454,6 +454,9 @@ enum GrTextureFlags {
|
||||
* Hint that the CPU may modify this texture after creation.
|
||||
*/
|
||||
kDynamicUpdate_GrTextureFlagBit = 0x4,
|
||||
|
||||
kDummy_GrTextureFlagBit,
|
||||
kLastPublic_GrTextureFlagBit = kDummy_GrTextureFlagBit-1,
|
||||
};
|
||||
|
||||
GR_MAKE_BITFIELD_OPS(GrTextureFlags)
|
||||
|
@ -520,6 +520,18 @@ GrContext::TextureCacheEntry GrContext::lockScratchTexture(
|
||||
return TextureCacheEntry(entry);
|
||||
}
|
||||
|
||||
void GrContext::addExistingTextureToCache(GrTexture* texture) {
|
||||
|
||||
if (NULL == texture) {
|
||||
return;
|
||||
}
|
||||
|
||||
GrResourceKey key = GrTexture::ComputeKey(fGpu, NULL,
|
||||
texture->desc(),
|
||||
true);
|
||||
fTextureCache->attach(key, texture);
|
||||
}
|
||||
|
||||
void GrContext::unlockTexture(TextureCacheEntry entry) {
|
||||
ASSERT_OWNED_RESOURCE(entry.texture());
|
||||
// If this is a scratch texture we detached it from the cache
|
||||
@ -532,6 +544,12 @@ void GrContext::unlockTexture(TextureCacheEntry entry) {
|
||||
}
|
||||
}
|
||||
|
||||
void GrContext::freeEntry(TextureCacheEntry entry) {
|
||||
ASSERT_OWNED_RESOURCE(entry.texture());
|
||||
|
||||
fTextureCache->freeEntry(entry.cacheEntry());
|
||||
}
|
||||
|
||||
GrTexture* GrContext::createUncachedTexture(const GrTextureDesc& descIn,
|
||||
void* srcData,
|
||||
size_t rowBytes) {
|
||||
|
@ -81,6 +81,9 @@ void GrResourceCache::internalDetach(GrResourceEntry* entry,
|
||||
--fUnlockedEntryCount;
|
||||
}
|
||||
|
||||
entry->fPrev = NULL;
|
||||
entry->fNext = NULL;
|
||||
|
||||
// update our stats
|
||||
if (clientDetach) {
|
||||
fClientDetachedCount += 1;
|
||||
@ -165,8 +168,9 @@ bool GrResourceCache::hasKey(const GrResourceKey& key) const {
|
||||
return NULL != fCache.find(key);
|
||||
}
|
||||
|
||||
GrResourceEntry* GrResourceCache::createAndLock(const GrResourceKey& key,
|
||||
GrResource* resource) {
|
||||
GrResourceEntry* GrResourceCache::create(const GrResourceKey& key,
|
||||
GrResource* resource,
|
||||
bool lock) {
|
||||
// we don't expect to create new resources during a purge. In theory
|
||||
// this could cause purgeAsNeeded() into an infinite loop (e.g.
|
||||
// each resource destroyed creates and locks 2 resources and
|
||||
@ -176,9 +180,11 @@ GrResourceEntry* GrResourceCache::createAndLock(const GrResourceKey& key,
|
||||
|
||||
GrResourceEntry* entry = new GrResourceEntry(key, resource);
|
||||
|
||||
// mark the entry as "busy" so it doesn't get purged
|
||||
// do this before attach for locked count tracking
|
||||
entry->lock();
|
||||
if (lock) {
|
||||
// mark the entry as "busy" so it doesn't get purged
|
||||
// do this before attach for locked count tracking
|
||||
entry->lock();
|
||||
}
|
||||
|
||||
this->attachToHead(entry, false);
|
||||
fCache.insert(key, entry);
|
||||
@ -192,12 +198,27 @@ GrResourceEntry* GrResourceCache::createAndLock(const GrResourceKey& key,
|
||||
return entry;
|
||||
}
|
||||
|
||||
GrResourceEntry* GrResourceCache::createAndLock(const GrResourceKey& key,
|
||||
GrResource* resource) {
|
||||
return this->create(key, resource, true);
|
||||
}
|
||||
|
||||
void GrResourceCache::attach(const GrResourceKey& key,
|
||||
GrResource* resource) {
|
||||
this->create(key, resource, false);
|
||||
}
|
||||
|
||||
void GrResourceCache::detach(GrResourceEntry* entry) {
|
||||
GrAutoResourceCacheValidate atcv(this);
|
||||
internalDetach(entry, true);
|
||||
this->internalDetach(entry, true);
|
||||
fCache.remove(entry->fKey, entry);
|
||||
}
|
||||
|
||||
void GrResourceCache::freeEntry(GrResourceEntry* entry) {
|
||||
GrAssert(NULL == entry->fNext && NULL == entry->fPrev);
|
||||
delete entry;
|
||||
}
|
||||
|
||||
void GrResourceCache::reattachAndUnlock(GrResourceEntry* entry) {
|
||||
GrAutoResourceCacheValidate atcv(this);
|
||||
if (entry->resource()->isValid()) {
|
||||
|
@ -231,14 +231,25 @@ public:
|
||||
GrResourceEntry* findAndLock(const GrResourceKey&, LockType style);
|
||||
|
||||
/**
|
||||
* Create a new entry, based on the specified key and resource, and return
|
||||
* its "locked" entry.
|
||||
* Create a new cache entry, based on the provided key and resource, and
|
||||
* return it.
|
||||
*
|
||||
* Ownership of the resource is transferred to the Entry, which will
|
||||
* unref() it when we are purged or deleted.
|
||||
* Ownership of the resource is transferred to the resource cache,
|
||||
* which will unref() it when it is purged or deleted.
|
||||
*/
|
||||
GrResourceEntry* createAndLock(const GrResourceKey&, GrResource*);
|
||||
|
||||
/**
|
||||
* Create a new cache entry, based on the provided key and resource.
|
||||
*
|
||||
* Ownership of the resource is transferred to the resource cache,
|
||||
* which will unref() it when it is purged or deleted.
|
||||
*
|
||||
* Currently this entry point is only intended for textures "detached"
|
||||
* from an AutoScratchTexture object.
|
||||
*/
|
||||
void attach(const GrResourceKey& key, GrResource* resource);
|
||||
|
||||
/**
|
||||
* Determines if the cache contains an entry matching a key. If a matching
|
||||
* entry exists but was detached then it will not be found.
|
||||
@ -253,6 +264,8 @@ public:
|
||||
*/
|
||||
void detach(GrResourceEntry*);
|
||||
|
||||
void freeEntry(GrResourceEntry* entry);
|
||||
|
||||
/**
|
||||
* Reattaches a resource to the cache and unlocks it. Allows it to be found
|
||||
* by a subsequent findAndLock or be purged (provided its lock count is
|
||||
@ -298,6 +311,11 @@ private:
|
||||
|
||||
// prevents recursive purging
|
||||
bool fPurging;
|
||||
|
||||
GrResourceEntry* create(const GrResourceKey& key,
|
||||
GrResource* resource,
|
||||
bool lock);
|
||||
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -336,7 +336,11 @@ bool GrSoftwarePathRenderer::onDrawPath(const SkPath& path,
|
||||
if (sw_draw_path_to_mask_texture(path, pathBounds,
|
||||
fill, fContext,
|
||||
translate, &ast, antiAlias)) {
|
||||
#if 1
|
||||
GrTexture* texture = ast.texture();
|
||||
#else
|
||||
SkAutoTUnref<GrTexture> texture(ast.detach());
|
||||
#endif
|
||||
GrAssert(NULL != texture);
|
||||
GrDrawTarget::AutoDeviceCoordDraw adcd(target, stageMask);
|
||||
enum {
|
||||
@ -351,6 +355,7 @@ bool GrSoftwarePathRenderer::onDrawPath(const SkPath& path,
|
||||
GrScalar h = GrIntToScalar(pathBounds.height());
|
||||
GrRect maskRect = GrRect::MakeWH(w / texture->width(),
|
||||
h / texture->height());
|
||||
|
||||
const GrRect* srcRects[GrDrawState::kNumStages] = {NULL};
|
||||
srcRects[kPathMaskStage] = &maskRect;
|
||||
stageMask |= 1 << kPathMaskStage;
|
||||
|
@ -16,6 +16,30 @@
|
||||
|
||||
SK_DEFINE_INST_COUNT(GrTexture)
|
||||
|
||||
/**
|
||||
* This method allows us to interrupt the normal deletion process and place
|
||||
* textures back in the texture cache when their ref count goes to zero.
|
||||
*/
|
||||
void GrTexture::internal_dispose() const {
|
||||
|
||||
if (this->isSetFlag((GrTextureFlags) kReturnToCache_FlagBit) &&
|
||||
NULL != this->INHERITED::getContext()) {
|
||||
GrTexture* nonConstThis = const_cast<GrTexture *>(this);
|
||||
this->fRefCnt = 1; // restore ref count to initial setting
|
||||
|
||||
nonConstThis->resetFlag((GrTextureFlags) kReturnToCache_FlagBit);
|
||||
nonConstThis->INHERITED::getContext()->addExistingTextureToCache(nonConstThis);
|
||||
|
||||
// Note: this next assert is only correct for the texture cache's
|
||||
// current single threaded usage. If we ever start accessing it via
|
||||
// threads it isn't guaranteed to be correct.
|
||||
GrAssert(1 == this->INHERITED::getRefCnt());
|
||||
return;
|
||||
}
|
||||
|
||||
this->INHERITED::internal_dispose();
|
||||
}
|
||||
|
||||
bool GrTexture::readPixels(int left, int top, int width, int height,
|
||||
GrPixelConfig config, void* buffer,
|
||||
size_t rowBytes) {
|
||||
@ -59,6 +83,11 @@ void GrTexture::releaseRenderTarget() {
|
||||
}
|
||||
}
|
||||
|
||||
void GrTexture::onRelease() {
|
||||
GrAssert(!this->isSetFlag((GrTextureFlags) kReturnToCache_FlagBit));
|
||||
this->releaseRenderTarget();
|
||||
}
|
||||
|
||||
void GrTexture::onAbandon() {
|
||||
if (NULL != fRenderTarget) {
|
||||
fRenderTarget->abandon();
|
||||
|
Loading…
Reference in New Issue
Block a user