When a bitmap is texture-backed, change SkBitmap::copyTo() to do a deep
copy of the texels in VRAM rather than a readback and re-upload.  This
gives a 3-10X speedup on recursive canvas-to-canvas draws.

N.B.:  This introduces a new GM test, which will need new baselines.



git-svn-id: http://skia.googlecode.com/svn/trunk@2790 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/include/core/SkBitmap.h b/include/core/SkBitmap.h
index ae56739..f280a24 100644
--- a/include/core/SkBitmap.h
+++ b/include/core/SkBitmap.h
@@ -462,19 +462,29 @@
     */
     bool extractSubset(SkBitmap* dst, const SkIRect& subset) const;
 
-    /** Makes a deep copy of this bitmap, respecting the requested config.
-        Returns false if either there is an error (i.e. the src does not have
-        pixels) or the request cannot be satisfied (e.g. the src has per-pixel
-        alpha, and the requested config does not support alpha).
-        @param dst The bitmap to be sized and allocated
-        @param c The desired config for dst
-        @param allocator Allocator used to allocate the pixelref for the dst
-                         bitmap. If this is null, the standard HeapAllocator
-                         will be used.
-        @return true if the copy could be made.
-    */
+    /** Makes a deep copy of this bitmap, respecting the requested config,
+     *  and allocating the dst pixels on the cpu.
+     *  Returns false if either there is an error (i.e. the src does not have
+     *  pixels) or the request cannot be satisfied (e.g. the src has per-pixel
+     *  alpha, and the requested config does not support alpha).
+     *  @param dst The bitmap to be sized and allocated
+     *  @param c The desired config for dst
+     *  @param allocator Allocator used to allocate the pixelref for the dst
+     *                   bitmap. If this is null, the standard HeapAllocator
+     *                   will be used.
+     *  @return true if the copy could be made.
+     */
     bool copyTo(SkBitmap* dst, Config c, Allocator* allocator = NULL) const;
 
+    /** Makes a deep copy of this bitmap, respecting the requested config, and
+     *  with custom allocation logic that will keep the copied pixels
+     *  in the same domain as the source: If the src pixels are allocated for
+     *  the cpu, then so will the dst. If the src pixels are allocated on the
+     *  gpu (typically as a texture), the it will do the same for the dst.
+     *  If the request cannot be fulfilled, returns false and dst is unmodified.
+     */
+    bool deepCopyTo(SkBitmap* dst, Config c) const;
+
     /** Returns true if this bitmap can be deep copied into the requested config
         by calling copyTo().
      */
diff --git a/include/core/SkPixelRef.h b/include/core/SkPixelRef.h
index 7e21a43..374868e 100644
--- a/include/core/SkPixelRef.h
+++ b/include/core/SkPixelRef.h
@@ -10,10 +10,10 @@
 #ifndef SkPixelRef_DEFINED
 #define SkPixelRef_DEFINED
 
+#include "SkBitmap.h"
 #include "SkRefCnt.h"
 #include "SkString.h"
 
-class SkBitmap;
 class SkColorTable;
 struct SkIRect;
 class SkMutex;
@@ -117,6 +117,12 @@
 
     bool readPixels(SkBitmap* dst, const SkIRect* subset = NULL);
 
+    /** Makes a deep copy of this PixelRef, respecting the requested config.
+        Returns NULL if either there is an error (e.g. the destination could
+        not be created with the given config), or this PixelRef does not 
+        support deep copies.  */
+    virtual SkPixelRef* deepCopy(SkBitmap::Config config) { return NULL; }
+
     // serialization
 
     typedef SkPixelRef* (*Factory)(SkFlattenableReadBuffer&);
diff --git a/include/gpu/GrContext.h b/include/gpu/GrContext.h
index bc52159..5b48c0b 100644
--- a/include/gpu/GrContext.h
+++ b/include/gpu/GrContext.h
@@ -548,6 +548,12 @@
                                          config, buffer, rowBytes, 0);
     }
     /**
+     * Copies all texels from one texture to another.
+     * @param src           the texture to copy from.
+     * @param dst           the render target to copy to.
+     */
+    void copyTexture(GrTexture* src, GrRenderTarget* dst);
+    /**
      * Applies a 1D convolution kernel in the X direction to a rectangle of
      * pixels from a given texture.
      * @param texture         the texture to read from
diff --git a/include/gpu/SkGrTexturePixelRef.h b/include/gpu/SkGrTexturePixelRef.h
index 1df10cb..720f130 100644
--- a/include/gpu/SkGrTexturePixelRef.h
+++ b/include/gpu/SkGrTexturePixelRef.h
@@ -52,6 +52,9 @@
     // override from SkPixelRef
     virtual bool onReadPixels(SkBitmap* dst, const SkIRect* subset);
 
+    // override from SkPixelRef
+    virtual SkPixelRef* deepCopy(SkBitmap::Config dstConfig) SK_OVERRIDE;
+
 private:
     GrTexture*  fTexture;
     typedef SkROLockPixelsPixelRef INHERITED;
@@ -72,6 +75,9 @@
     // override from SkPixelRef
     virtual bool onReadPixels(SkBitmap* dst, const SkIRect* subset);
 
+    // override from SkPixelRef
+    virtual SkPixelRef* deepCopy(SkBitmap::Config dstConfig) SK_OVERRIDE;
+
 private:
     GrRenderTarget*  fRenderTarget;
     typedef SkROLockPixelsPixelRef INHERITED;