aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu
diff options
context:
space:
mode:
authorGravatar robertphillips@google.com <robertphillips@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-06-22 12:41:43 +0000
committerGravatar robertphillips@google.com <robertphillips@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-06-22 12:41:43 +0000
commit15c0fea699b25343fe6f49668a5632866e1a0306 (patch)
tree0616bf4168b4d98e02ae7cabf95623ef7ccb4fa5 /src/gpu
parent5e2412983183f9c4075a795278f3ca4ffee0ed79 (diff)
AutoScratchTexture can now release its texture and it will return to the texture cache when freed
Diffstat (limited to 'src/gpu')
-rw-r--r--src/gpu/GrContext.cpp18
-rw-r--r--src/gpu/GrResourceCache.cpp33
-rw-r--r--src/gpu/GrResourceCache.h26
-rw-r--r--src/gpu/GrSoftwarePathRenderer.cpp5
-rw-r--r--src/gpu/GrTexture.cpp29
5 files changed, 101 insertions, 10 deletions
diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp
index 1fda26ba03..fc2b143c60 100644
--- a/src/gpu/GrContext.cpp
+++ b/src/gpu/GrContext.cpp
@@ -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) {
diff --git a/src/gpu/GrResourceCache.cpp b/src/gpu/GrResourceCache.cpp
index 6a6c16697a..8c939714d3 100644
--- a/src/gpu/GrResourceCache.cpp
+++ b/src/gpu/GrResourceCache.cpp
@@ -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()) {
diff --git a/src/gpu/GrResourceCache.h b/src/gpu/GrResourceCache.h
index ca7ca10a46..ba5ea4ee3d 100644
--- a/src/gpu/GrResourceCache.h
+++ b/src/gpu/GrResourceCache.h
@@ -231,15 +231,26 @@ 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);
+
};
///////////////////////////////////////////////////////////////////////////////
diff --git a/src/gpu/GrSoftwarePathRenderer.cpp b/src/gpu/GrSoftwarePathRenderer.cpp
index 72ad543121..bfad6dfb69 100644
--- a/src/gpu/GrSoftwarePathRenderer.cpp
+++ b/src/gpu/GrSoftwarePathRenderer.cpp
@@ -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;
diff --git a/src/gpu/GrTexture.cpp b/src/gpu/GrTexture.cpp
index 67ce62913e..19dc32220d 100644
--- a/src/gpu/GrTexture.cpp
+++ b/src/gpu/GrTexture.cpp
@@ -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();