Make GrTextureCache into a generic GrResource cache. Also some GrContext texture interface cleanup.

http://codereview.appspot.com/4815055/


git-svn-id: http://skia.googlecode.com/svn/trunk@1965 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/gpu/include/GrContext.h b/gpu/include/GrContext.h
index 0f69e0b..c7a87da 100644
--- a/gpu/include/GrContext.h
+++ b/gpu/include/GrContext.h
@@ -18,16 +18,18 @@
 #define GrContext_DEFINED
 
 #include "GrClip.h"
-#include "GrTextureCache.h"
 #include "GrPaint.h"
 #include "GrPathRenderer.h"
 
 class GrFontCache;
 class GrGpu;
 struct GrGpuStats;
-class GrVertexBufferAllocPool;
 class GrIndexBufferAllocPool;
 class GrInOrderDrawBuffer;
+class GrResourceEntry;
+class GrResourceCache;
+class GrVertexBufferAllocPool;
+
 
 class GR_API GrContext : public GrRefCnt {
 public:
@@ -82,54 +84,92 @@
     // Textures
 
     /**
-     *  Search for an entry with the same Key. If found, "lock" it and return it.
-     *  If not found, return null.
+     * Token that refers to an entry in the texture cache. Returned by
+     * functions that lock textures. Passed to unlockTexture.
      */
-    GrTextureEntry* findAndLockTexture(GrTextureKey*,
-                                       const GrSamplerState&);
+    class TextureCacheEntry {
+    public:
+        TextureCacheEntry() : fEntry(NULL) {}
+        TextureCacheEntry(const TextureCacheEntry& e) : fEntry(e.fEntry) {}
+        TextureCacheEntry& operator= (const TextureCacheEntry& e) {
+            fEntry = e.fEntry;
+            return *this;
+        }
+        GrTexture* texture() const;
+        void reset() { fEntry = NULL; }
+    private:
+        explicit TextureCacheEntry(GrResourceEntry* entry) { fEntry = entry; }
+        void set(GrResourceEntry* entry) { fEntry = entry; }
+        GrResourceEntry* cacheEntry() { return fEntry; }
+        GrResourceEntry* fEntry;
+        friend class GrContext;
+    };
 
+    /**
+     * Key generated by client. Should be a unique key on the texture data.
+     * Does not need to consider that width and height of the texture. Two
+     * textures with the same TextureKey but different bounds will not collide.
+     */
+    typedef uint64_t TextureKey;
+
+    /**
+     *  Search for an entry based on key and dimensions. If found, "lock" it and
+     *  return it. The entry's texture() function will return NULL if not found.
+     *  Must call be balanced with an unlockTexture() call.
+     */
+    TextureCacheEntry findAndLockTexture(TextureKey key,
+                                         int width,
+                                         int height,
+                                         const GrSamplerState&);
 
     /**
      *  Create a new entry, based on the specified key and texture, and return
-     *  its "locked" entry.
-     *
-     *  Ownership of the texture is transferred to the Entry, which will unref()
-     *  it when we are purged or deleted.
+     *  its "locked" entry. Must call be balanced with an unlockTexture() call.
      */
-    GrTextureEntry* createAndLockTexture(GrTextureKey* key,
-                                         const GrSamplerState&,
-                                         const GrTextureDesc&,
-                                         void* srcData, size_t rowBytes);
+    TextureCacheEntry createAndLockTexture(TextureKey key,
+                                           const GrSamplerState&,
+                                           const GrTextureDesc&,
+                                           void* srcData, size_t rowBytes);
+
+    /**
+     * Enum that determines how closely a returned scratch texture must match
+     * a provided GrTextureDesc.
+     */
+    enum ScratchTexMatch {
+        /**
+         * Finds a texture that exactly matches the descriptor.
+         */
+        kExact_ScratchTexMatch,
+        /**
+         * Finds a texture that approximately matches the descriptor. Will be
+         * at least as large in width and height as desc specifies. If desc
+         * specifies that texture is a render target then result will be a
+         * render target. If desc specifies a render target and doesn't set the
+         * no stencil flag then result will have a stencil. Format and aa level
+         * will always match.
+         */
+        kApprox_ScratchTexMatch
+    };
 
     /**
      * 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.
+     * unlocked. Must call 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. 
-     * unextended GLES2). Tiling a npot texture created by lockKeylessTexture on
+     * unextended GLES2). Tiling a npot texture created by lockScratchTexture on
      * such an API will create gaps in the tiling pattern. This includes clamp
      * mode. (This may be addressed in a future update.)
      */
-    GrTextureEntry* lockKeylessTexture(const GrTextureDesc& desc);
-
-    /**
-     * Finds a texture that approximately matches the descriptor. Will be
-     * at least as large in width and height as desc specifies. If desc
-     * specifies that texture is a render target then result will be a
-     * render target. If desc specifies a render target and doesn't set the
-     * no stencil flag then result will have a stencil. Format and aa level
-     * will always match.
-     */
-    GrTextureEntry* findApproximateKeylessTexture(const GrTextureDesc& desc);
+    TextureCacheEntry lockScratchTexture(const GrTextureDesc& desc, ScratchTexMatch match);
 
     /**
      *  When done with an entry, call unlockTexture(entry) on it, which returns
      *  it to the cache, where it may be purged.
      */
-    void unlockTexture(GrTextureEntry* entry);
+    void unlockTexture(TextureCacheEntry entry);
 
     /**
      * Creates a texture that is outside the cache. Does not count against
@@ -195,9 +235,6 @@
     ///////////////////////////////////////////////////////////////////////////
     // Platform Surfaces
 
-    // GrContext provides an interface for wrapping externally created textures
-    // and rendertargets in their Gr-equivalents.
-
     /**
      * Wraps an existing 3D API surface in a GrObject. desc.fFlags determines
      * the type of object returned. If kIsTexture is set the returned object
@@ -213,6 +250,7 @@
      *         on failure.
      */
     GrResource* createPlatformSurface(const GrPlatformSurfaceDesc& desc);
+
     /**
      * Reads the current target object (e.g. FBO or IDirect3DSurface9*) and
      * viewport state from the underlying 3D API and wraps it in a
@@ -559,9 +597,9 @@
     };
     DrawCategory fLastDrawCategory;
 
-    GrGpu*          fGpu;
-    GrTextureCache* fTextureCache;
-    GrFontCache*    fFontCache;
+    GrGpu*              fGpu;
+    GrResourceCache*    fTextureCache;
+    GrFontCache*        fFontCache;
 
     GrPathRenderer*         fCustomPathRenderer;
     GrDefaultPathRenderer   fDefaultPathRenderer;
@@ -597,10 +635,6 @@
 
     static void SetPaint(const GrPaint& paint, GrDrawTarget* target);
 
-    bool finalizeTextureKey(GrTextureKey*, 
-                            const GrSamplerState&,
-                            bool keyless) const;
-
     GrDrawTarget* prepareToDraw(const GrPaint& paint, DrawCategory drawType);
 
     void drawClipIntoStencil();
@@ -680,24 +714,54 @@
 };
 
 /**
- * Unlocks a texture entry when this goes out of scope.  Entry may be NULL.
+ * Gets and locks a scratch texture from a descriptor using
+ * either exact or approximate criteria. Unlocks texture in
+ * the destructor.
  */
-class GrAutoUnlockTextureEntry : ::GrNoncopyable {
+class GrAutoScratchTexture : ::GrNoncopyable {
 public:
-    GrAutoUnlockTextureEntry(GrContext* context, GrTextureEntry* entry)
-      : fContext(context)
-      , fEntry(entry) {
+    GrAutoScratchTexture()
+        : fContext(NULL) {
     }
-    ~GrAutoUnlockTextureEntry() {
-        if (fContext && fEntry) {
+
+    GrAutoScratchTexture(GrContext* context,
+                         const GrTextureDesc& desc,
+                         GrContext::ScratchTexMatch match =
+                            GrContext::kApprox_ScratchTexMatch)
+      : fContext(NULL) {
+      this->set(context, desc, match);
+    }
+    
+    ~GrAutoScratchTexture() {
+        if (NULL != fContext) {
             fContext->unlockTexture(fEntry);
         }
     }
 
-    GrTexture* texture() { return fEntry->texture(); }
+    GrTexture* set(GrContext* context,
+                   const GrTextureDesc& desc,
+                   GrContext::ScratchTexMatch match =
+                        GrContext::kApprox_ScratchTexMatch) {
+        if (NULL != fContext) {
+            fContext->unlockTexture(fEntry);
+        }
+        fContext = context;
+        if (NULL != fContext) {
+            fEntry = fContext->lockScratchTexture(desc, match);
+            GrTexture* ret = fEntry.texture();
+            if (NULL == ret) {
+                fContext = NULL;
+            }
+            return ret;
+        } else {
+            return NULL;
+        }
+    }
+
+    GrTexture* texture() { return fEntry.texture(); }
 private:
-    GrContext*      fContext;
-    GrTextureEntry* fEntry;
+    GrContext*                    fContext;
+    GrContext::TextureCacheEntry  fEntry;
 };
 
 #endif