Add lockKeylessTexture() for caching texture without a content key.

Review URL: http://codereview.appspot.com/4440065/




git-svn-id: http://skia.googlecode.com/svn/trunk@1172 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/gpu/src/GrContext.cpp b/gpu/src/GrContext.cpp
index 7cf0cca..75caa74 100644
--- a/gpu/src/GrContext.cpp
+++ b/gpu/src/GrContext.cpp
@@ -103,9 +103,46 @@
     fFontCache->freeAll();
 }
 
+////////////////////////////////////////////////////////////////////////////////
+
+
+enum {
+    kNPOTBit    = 0x1,
+    kFilterBit  = 0x2,
+    kKeylessBit = 0x4,
+};
+
+bool GrContext::finalizeTextureKey(GrTextureKey* key,
+                                   const GrSamplerState& sampler,
+                                   bool keyless) const {
+    uint32_t bits = 0;
+    uint16_t width = key->width();
+    uint16_t height = key->height();
+
+    if (!fGpu->npotTextureTileSupport()) {
+        bool isPow2 = GrIsPow2(width) && GrIsPow2(height);
+
+        bool tiled = (sampler.getWrapX() != GrSamplerState::kClamp_WrapMode) ||
+                     (sampler.getWrapY() != GrSamplerState::kClamp_WrapMode);
+
+        if (tiled && !isPow2) {
+            bits |= kNPOTBit;
+            if (sampler.isFilter()) {
+                bits |= kFilterBit;
+            }
+        }
+    }
+
+    if (keyless) {
+        bits |= kKeylessBit;
+    }
+    key->finalize(bits);
+    return 0 != bits;
+}
+
 GrTextureEntry* GrContext::findAndLockTexture(GrTextureKey* key,
                                               const GrSamplerState& sampler) {
-    finalizeTextureKey(key, sampler);
+    finalizeTextureKey(key, sampler, false);
     return fTextureCache->findAndLock(*key);
 }
 
@@ -138,7 +175,7 @@
 
 GrTextureEntry* GrContext::createAndLockTexture(GrTextureKey* key,
                                                 const GrSamplerState& sampler,
-                                                const GrGpu::TextureDesc& desc,
+                                                const GrTextureDesc& desc,
                                                 void* srcData, size_t rowBytes) {
     GrAssert(key->width() == desc.fWidth);
     GrAssert(key->height() == desc.fHeight);
@@ -148,7 +185,7 @@
 #endif
 
     GrTextureEntry* entry = NULL;
-    bool special = finalizeTextureKey(key, sampler);
+    bool special = finalizeTextureKey(key, sampler, false);
     if (special) {
         GrTextureEntry* clampEntry;
         GrTextureKey clampKey(*key);
@@ -163,9 +200,10 @@
                 return NULL;
             }
         }
-        GrGpu::TextureDesc rtDesc = desc;
-        rtDesc.fFlags |= GrGpu::kRenderTarget_TextureFlag |
-                         GrGpu::kNoStencil_TextureFlag;
+        GrTextureDesc rtDesc = desc;
+        rtDesc.fFlags =  rtDesc.fFlags |
+                         kRenderTarget_GrTextureFlagBit |
+                         kNoStencil_GrTextureFlagBit;
         rtDesc.fWidth  = GrNextPow2(GrMax<int>(desc.fWidth,
                                                fGpu->minRenderTargetWidth()));
         rtDesc.fHeight = GrNextPow2(GrMax<int>(desc.fHeight,
@@ -211,7 +249,7 @@
             // not. Either implement filtered stretch blit on CPU or just create
             // one when FBO case fails.
 
-            rtDesc.fFlags = 0;
+            rtDesc.fFlags = kNone_GrTextureFlags;
             // no longer need to clamp at min RT size.
             rtDesc.fWidth  = GrNextPow2(desc.fWidth);
             rtDesc.fHeight = GrNextPow2(desc.fHeight);
@@ -243,19 +281,37 @@
     return entry;
 }
 
+GrTextureEntry* GrContext::lockKeylessTexture(const GrTextureDesc& desc,
+                                              const GrSamplerState& state) {
+    uint32_t p0 = desc.fFormat;
+    uint32_t p1 = (desc.fAALevel << 16) | desc.fFlags;
+    GrTextureKey key(p0, p1, desc.fWidth, desc.fHeight);
+    this->finalizeTextureKey(&key, state, true);
+    GrTextureEntry* entry = fTextureCache->findAndLock(key);
+    if (NULL == entry) {
+        GrTexture* texture = fGpu->createTexture(desc, NULL, 0);
+        if (NULL != texture) {
+            entry = fTextureCache->createAndLock(key, texture);
+        }
+    }
+    // If the caller gives us the same desc/sampler twice we don't want
+    // to return the same texture the second time (unless it was previously
+    // released). So we detach the entry from the cache and reattach at release.
+    if (NULL != entry) {
+        fTextureCache->detach(entry);
+    }
+    return entry;
+}
+
 void GrContext::unlockTexture(GrTextureEntry* entry) {
-    fTextureCache->unlock(entry);
+    if (kKeylessBit & entry->key().getPrivateBits()) {
+        fTextureCache->reattachAndUnlock(entry);
+    } else {
+        fTextureCache->unlock(entry);
+    }
 }
 
-void GrContext::detachCachedTexture(GrTextureEntry* entry) {
-    fTextureCache->detach(entry);
-}
-
-void GrContext::reattachAndUnlockCachedTexture(GrTextureEntry* entry) {
-    fTextureCache->reattachAndUnlock(entry);
-}
-
-GrTexture* GrContext::createUncachedTexture(const GrGpu::TextureDesc& desc,
+GrTexture* GrContext::createUncachedTexture(const GrTextureDesc& desc,
                                             void* srcData,
                                             size_t rowBytes) {
     return fGpu->createTexture(desc, srcData, rowBytes);
@@ -935,8 +991,8 @@
     // TODO: when underlying api has a direct way to do this we should use it
     // (e.g. glDrawPixels on desktop GL).
 
-    const GrGpu::TextureDesc desc = {
-        0, GrGpu::kNone_AALevel, width, height, config
+    const GrTextureDesc desc = {
+        kNone_GrTextureFlags, kNone_GrAALevel, width, height, config
     };
     GrTexture* texture = fGpu->createTexture(desc, buffer, stride);
     if (NULL == texture) {
@@ -1123,28 +1179,6 @@
 #endif
 }
 
-bool GrContext::finalizeTextureKey(GrTextureKey* key,
-                                   const GrSamplerState& sampler) const {
-    uint32_t bits = 0;
-    uint16_t width = key->width();
-    uint16_t height = key->height();
-
-
-    if (!fGpu->npotTextureTileSupport()) {
-        bool isPow2 = GrIsPow2(width) && GrIsPow2(height);
-
-        bool tiled = (sampler.getWrapX() != GrSamplerState::kClamp_WrapMode) ||
-                     (sampler.getWrapY() != GrSamplerState::kClamp_WrapMode);
-
-        if (tiled && !isPow2) {
-            bits |= 1;
-            bits |= sampler.isFilter() ? 2 : 0;
-        }
-    }
-    key->finalize(bits);
-    return 0 != bits;
-}
-
 GrDrawTarget* GrContext::getTextTarget(const GrPaint& paint) {
     GrDrawTarget* target;
 #if DEFER_TEXT_RENDERING