Make "priv" classes for GrTexure and GrSurface.

R=robertphillips@google.com, egdaniel@google.com, joshualitt@google.com

Author: bsalomon@google.com

Review URL: https://codereview.chromium.org/596053002
diff --git a/bench/GrResourceCacheBench.cpp b/bench/GrResourceCacheBench.cpp
index d86ccf4..234a626 100644
--- a/bench/GrResourceCacheBench.cpp
+++ b/bench/GrResourceCacheBench.cpp
@@ -14,6 +14,7 @@
 #include "GrResourceCache.h"
 #include "GrStencilBuffer.h"
 #include "GrTexture.h"
+#include "GrTexturePriv.h"
 #include "SkCanvas.h"
 
 enum {
@@ -62,7 +63,7 @@
     }
 
     static GrResourceKey ComputeKey(const GrTextureDesc& desc) {
-        return GrTextureImpl::ComputeScratchKey(desc);
+        return GrTexturePriv::ComputeScratchKey(desc);
     }
 
     int fID;
diff --git a/gyp/gpu.gypi b/gyp/gpu.gypi
index ec7ced4..ad4a40c 100644
--- a/gyp/gpu.gypi
+++ b/gyp/gpu.gypi
@@ -149,6 +149,7 @@
       '<(skia_src_path)/gpu/GrSWMaskHelper.h',
       '<(skia_src_path)/gpu/GrSoftwarePathRenderer.cpp',
       '<(skia_src_path)/gpu/GrSoftwarePathRenderer.h',
+      '<(skia_src_path)/gpu/GrSurfacePriv.h',
       '<(skia_src_path)/gpu/GrSurface.cpp',
       '<(skia_src_path)/gpu/GrTemplates.h',
       '<(skia_src_path)/gpu/GrTextContext.cpp',
@@ -157,6 +158,7 @@
       '<(skia_src_path)/gpu/GrTextStrike.h',
       '<(skia_src_path)/gpu/GrTextStrike_impl.h',
       '<(skia_src_path)/gpu/GrTexture.cpp',
+      '<(skia_src_path)/gpu/GrTexturePriv.h',
       '<(skia_src_path)/gpu/GrTextureAccess.cpp',
       '<(skia_src_path)/gpu/GrVertexBuffer.h',
 
diff --git a/include/gpu/GrContext.h b/include/gpu/GrContext.h
index 45cd599..366fba9 100644
--- a/include/gpu/GrContext.h
+++ b/include/gpu/GrContext.h
@@ -1082,7 +1082,7 @@
  * Gets and locks a scratch texture from a descriptor using either exact or approximate criteria.
  * Unlocks texture in the destructor.
  */
-class GrAutoScratchTexture : public ::SkNoncopyable {
+class SK_API GrAutoScratchTexture : public ::SkNoncopyable {
 public:
     GrAutoScratchTexture()
         : fContext(NULL)
@@ -1121,24 +1121,7 @@
      * Note that the caller is assumed to accept and manage the ref to the
      * returned texture.
      */
-    GrTexture* detach() {
-        if (NULL == fTexture) {
-            return NULL;
-        }
-        GrTexture* texture = fTexture;
-        fTexture = NULL;
-
-        // This GrAutoScratchTexture has a ref from lockAndRefScratchTexture, which we give up now.
-        // The cache also has a ref which we are lending to the caller of detach(). When the caller
-        // lets go of the ref and the ref count goes to 0 internal_dispose will see this flag is
-        // set and re-ref the texture, thereby restoring the cache's ref.
-        SkASSERT(!texture->unique());
-        texture->impl()->setFlag((GrTextureFlags) GrTextureImpl::kReturnToCache_FlagBit);
-        texture->unref();
-        SkASSERT(texture->getCacheEntry());
-
-        return texture;
-    }
+    GrTexture* detach();
 
     GrTexture* set(GrContext* context,
                    const GrTextureDesc& desc,
diff --git a/include/gpu/GrSurface.h b/include/gpu/GrSurface.h
index 24eb39a..23311a2 100644
--- a/include/gpu/GrSurface.h
+++ b/include/gpu/GrSurface.h
@@ -11,11 +11,12 @@
 
 #include "GrTypes.h"
 #include "GrGpuResource.h"
+#include "SkImageInfo.h"
 #include "SkRect.h"
 
-class GrTexture;
 class GrRenderTarget;
-struct SkImageInfo;
+class GrSurfacePriv;
+class GrTexture;
 
 class GrSurface : public GrGpuResource {
 public:
@@ -59,8 +60,6 @@
      */
     const GrTextureDesc& desc() const { return fDesc; }
 
-    SkImageInfo info() const;
-
     /**
      * @return the texture associated with the surface, may be NULL.
      */
@@ -74,22 +73,6 @@
     virtual const GrRenderTarget* asRenderTarget() const = 0;
 
     /**
-     * Checks whether this GrSurface refers to the same GPU object as other. This
-     * catches the case where a GrTexture and GrRenderTarget refer to the same
-     * GPU memory.
-     */
-    bool isSameAs(const GrSurface* other) const {
-        const GrRenderTarget* thisRT = this->asRenderTarget();
-        if (thisRT) {
-            return thisRT == other->asRenderTarget();
-        } else {
-            const GrTexture* thisTex = this->asTexture();
-            SkASSERT(thisTex); // We must be one or the other
-            return thisTex == other->asTexture();
-        }
-    }
-
-    /**
      * Reads a rectangle of pixels from the surface.
      * @param left          left edge of the rectangle to read (inclusive)
      * @param top           top edge of the rectangle to read (inclusive)
@@ -129,17 +112,22 @@
                              size_t rowBytes = 0,
                              uint32_t pixelOpsFlags = 0) = 0;
 
-    /**
-     * Write the contents of the surface to a PNG. Returns true if successful.
-     * @param filename      Full path to desired file
-     */
-    bool savePixels(const char* filename);
+    /** Access methods that are only to be used within Skia code. */
+    inline GrSurfacePriv surfacePriv();
+    inline const GrSurfacePriv surfacePriv() const;
 
+protected:
+    // Methods made available via GrSurfacePriv
+    SkImageInfo info() const;
+    bool savePixels(const char* filename);
     bool hasPendingRead() const;
     bool hasPendingWrite() const;
     bool hasPendingIO() const;
+    bool isSameAs(const GrSurface* other) const;
 
-protected:
+    // Provides access to methods that should be public within Skia code.
+    friend class GrSurfacePriv;
+
     GrSurface(GrGpu* gpu, bool isWrapped, const GrTextureDesc& desc)
     : INHERITED(gpu, isWrapped)
     , fDesc(desc) {
@@ -151,4 +139,4 @@
     typedef GrGpuResource INHERITED;
 };
 
-#endif // GrSurface_DEFINED
+#endif
diff --git a/include/gpu/GrTexture.h b/include/gpu/GrTexture.h
index 06ba2e4..8bdff34 100644
--- a/include/gpu/GrTexture.h
+++ b/include/gpu/GrTexture.h
@@ -16,7 +16,7 @@
 
 class GrResourceKey;
 class GrTextureParams;
-class GrTextureImpl;
+class GrTexturePriv;
 
 class GrTexture : public GrSurface {
 public:
@@ -44,19 +44,6 @@
     virtual const GrRenderTarget* asRenderTarget() const SK_OVERRIDE { return fRenderTarget.get(); }
 
     /**
-     * Convert from texels to normalized texture coords for POT textures only. Please don't add
-     * new callsites for these functions. They are slated for removal.
-     */
-    SkFixed normalizeFixedX(SkFixed x) const {
-        SkASSERT(SkIsPow2(fDesc.fWidth));
-        return x >> fShiftFixedX;
-    }
-    SkFixed normalizeFixedY(SkFixed y) const {
-        SkASSERT(SkIsPow2(fDesc.fHeight));
-        return y >> fShiftFixedY;
-    }
-
-    /**
      *  Return the native ID or handle to the texture, depending on the
      *  platform. e.g. on OpenGL, return the texture ID.
      */
@@ -67,11 +54,9 @@
      * changed externally to Skia.
      */
     virtual void textureParamsModified() = 0;
-    SK_ATTR_DEPRECATED("Renamed to textureParamsModified.")
-    void invalidateCachedState() { this->textureParamsModified(); }
 
     /**
-     * Informational texture flags. This will be moved to the private GrTextureImpl class soon.
+     * Informational texture flags. This will be removed soon.
      */
     enum FlagBits {
         kFirstBit = (kLastPublic_GrTextureFlagBit << 1),
@@ -94,21 +79,16 @@
     }
 #endif
 
-    GrTextureImpl* impl() { return reinterpret_cast<GrTextureImpl*>(this); }
-    const GrTextureImpl* impl() const { return reinterpret_cast<const GrTextureImpl*>(this); }
+    /** Access methods that are only to be used within Skia code. */
+    inline GrTexturePriv texturePriv();
+    inline const GrTexturePriv texturePriv() const;
 
 protected:
     // A texture refs its rt representation but not vice-versa. It is up to
     // the subclass constructor to initialize this pointer.
     SkAutoTUnref<GrRenderTarget> fRenderTarget;
 
-    GrTexture(GrGpu* gpu, bool isWrapped, const GrTextureDesc& desc)
-    : INHERITED(gpu, isWrapped, desc)
-    , fRenderTarget(NULL) {
-        // only make sense if alloc size is pow2
-        fShiftFixedX = 31 - SkCLZ(fDesc.fWidth);
-        fShiftFixedY = 31 - SkCLZ(fDesc.fHeight);
-    }
+    GrTexture(GrGpu* gpu, bool isWrapped, const GrTextureDesc& desc);
 
     virtual ~GrTexture();
 
@@ -121,60 +101,23 @@
 private:
     void abandonReleaseCommon();
     virtual void internal_dispose() const SK_OVERRIDE;
-
-    // these two shift a fixed-point value into normalized coordinates
-    // for this texture if the texture is power of two sized.
-    int                 fShiftFixedX;
-    int                 fShiftFixedY;
-
-    typedef GrSurface INHERITED;
-};
-
-class GrTextureImpl : public GrTexture {
-public:
-    SK_DECLARE_INST_COUNT(GrTextureImpl)
-
-    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);
-    }
-
     void dirtyMipMaps(bool mipMapsDirty);
 
-    bool mipMapsAreDirty() const {
-        return kValid_MipMapsStatus != fMipMapsStatus;
-    }
-
-    bool hasMipMaps() const {
-        return kNotAllocated_MipMapsStatus != fMipMapsStatus;
-    }
-
-    static GrResourceKey ComputeKey(const GrGpu* gpu,
-                                    const GrTextureParams* params,
-                                    const GrTextureDesc& desc,
-                                    const GrCacheID& cacheID);
-    static GrResourceKey ComputeScratchKey(const GrTextureDesc& desc);
-    static bool NeedsResizing(const GrResourceKey& key);
-    static bool NeedsBilerp(const GrResourceKey& key);
-
-protected:
-    GrTextureImpl(GrGpu* gpu, bool isWrapped, const GrTextureDesc& desc);
-
-private:
     enum MipMapsStatus {
         kNotAllocated_MipMapsStatus,
         kAllocated_MipMapsStatus,
         kValid_MipMapsStatus
     };
 
-    MipMapsStatus       fMipMapsStatus;
+    MipMapsStatus   fMipMapsStatus;
+    // These two shift a fixed-point value into normalized coordinates	
+    // for this texture if the texture is power of two sized.
+    int             fShiftFixedX;
+    int             fShiftFixedY;
 
-    typedef GrTexture INHERITED;
+    friend class GrTexturePriv;
+
+    typedef GrSurface INHERITED;
 };
 
 /**
diff --git a/src/gpu/GrBitmapTextContext.cpp b/src/gpu/GrBitmapTextContext.cpp
index 0f6d1b6..422a7e0 100755
--- a/src/gpu/GrBitmapTextContext.cpp
+++ b/src/gpu/GrBitmapTextContext.cpp
@@ -11,20 +11,21 @@
 #include "GrFontScaler.h"
 #include "GrIndexBuffer.h"
 #include "GrStrokeInfo.h"
+#include "GrTexturePriv.h"
 #include "GrTextStrike.h"
 #include "GrTextStrike_impl.h"
-#include "SkColorPriv.h"
-#include "SkPath.h"
-#include "SkRTConf.h"
-#include "SkStrokeRec.h"
 #include "effects/GrCustomCoordsTextureEffect.h"
 
 #include "SkAutoKern.h"
+#include "SkColorPriv.h"
 #include "SkDraw.h"
 #include "SkDrawProcs.h"
 #include "SkGlyphCache.h"
 #include "SkGpuDevice.h"
 #include "SkGr.h"
+#include "SkPath.h"
+#include "SkRTConf.h"
+#include "SkStrokeRec.h"
 #include "SkTextMapStateProc.h"
 
 SK_CONF_DECLARE(bool, c_DumpFontCache, "gpu.dumpFontCache", false,
@@ -588,10 +589,10 @@
     // The texture coords are last in both the with and without color vertex layouts.
     SkPoint* textureCoords = reinterpret_cast<SkPoint*>(
             reinterpret_cast<intptr_t>(positions) + vertSize  - sizeof(SkPoint));
-    textureCoords->setRectFan(SkFixedToFloat(texture->normalizeFixedX(tx)),
-                              SkFixedToFloat(texture->normalizeFixedY(ty)),
-                              SkFixedToFloat(texture->normalizeFixedX(tx + width)),
-                              SkFixedToFloat(texture->normalizeFixedY(ty + height)),
+    textureCoords->setRectFan(SkFixedToFloat(texture->texturePriv().normalizeFixedX(tx)),
+                              SkFixedToFloat(texture->texturePriv().normalizeFixedY(ty)),
+                              SkFixedToFloat(texture->texturePriv().normalizeFixedX(tx + width)),
+                              SkFixedToFloat(texture->texturePriv().normalizeFixedY(ty + height)),
                               vertSize);
     if (useColorVerts) {
         if (0xFF == GrColorUnpackA(fPaint.getColor())) {
diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp
index d55aed9..46a5576 100755
--- a/src/gpu/GrContext.cpp
+++ b/src/gpu/GrContext.cpp
@@ -30,7 +30,9 @@
 #include "GrStencilBuffer.h"
 #include "GrStencilAndCoverTextContext.h"
 #include "GrStrokeInfo.h"
+#include "GrSurfacePriv.h"
 #include "GrTextStrike.h"
+#include "GrTexturePriv.h"
 #include "GrTraceMarker.h"
 #include "GrTracing.h"
 #include "SkDashPathPriv.h"
@@ -68,6 +70,25 @@
 
 #define ASSERT_OWNED_RESOURCE(R) SkASSERT(!(R) || (R)->getContext() == this)
 
+GrTexture* GrAutoScratchTexture::detach() {
+    if (NULL == fTexture) {
+        return NULL;
+    }
+    GrTexture* texture = fTexture;
+    fTexture = NULL;
+
+    // This GrAutoScratchTexture has a ref from lockAndRefScratchTexture, which we give up now.
+    // The cache also has a ref which we are lending to the caller of detach(). When the caller
+    // lets go of the ref and the ref count goes to 0 internal_dispose will see this flag is
+    // set and re-ref the texture, thereby restoring the cache's ref.
+    SkASSERT(!texture->unique());
+    texture->texturePriv().setFlag((GrTextureFlags) GrTexture::kReturnToCache_FlagBit);
+    texture->unref();
+    SkASSERT(texture->getCacheEntry());
+
+    return texture;
+}
+
 // Glorified typedef to avoid including GrDrawState.h in GrContext.h
 class GrContext::AutoRestoreEffects : public GrDrawState::AutoRestoreEffects {};
 
@@ -262,7 +283,7 @@
 GrTexture* GrContext::findAndRefTexture(const GrTextureDesc& desc,
                                         const GrCacheID& cacheID,
                                         const GrTextureParams* params) {
-    GrResourceKey resourceKey = GrTextureImpl::ComputeKey(fGpu, params, desc, cacheID);
+    GrResourceKey resourceKey = GrTexturePriv::ComputeKey(fGpu, params, desc, cacheID);
     GrGpuResource* resource = fResourceCache->find(resourceKey);
     SkSafeRef(resource);
     return static_cast<GrTexture*>(resource);
@@ -271,7 +292,7 @@
 bool GrContext::isTextureInCache(const GrTextureDesc& desc,
                                  const GrCacheID& cacheID,
                                  const GrTextureParams* params) const {
-    GrResourceKey resourceKey = GrTextureImpl::ComputeKey(fGpu, params, desc, cacheID);
+    GrResourceKey resourceKey = GrTexturePriv::ComputeKey(fGpu, params, desc, cacheID);
     return fResourceCache->hasKey(resourceKey);
 }
 
@@ -410,16 +431,16 @@
                                     const void* srcData,
                                     size_t rowBytes,
                                     GrResourceKey* cacheKey) {
-    GrResourceKey resourceKey = GrTextureImpl::ComputeKey(fGpu, params, desc, cacheID);
+    GrResourceKey resourceKey = GrTexturePriv::ComputeKey(fGpu, params, desc, cacheID);
 
     GrTexture* texture;
-    if (GrTextureImpl::NeedsResizing(resourceKey)) {
+    if (GrTexturePriv::NeedsResizing(resourceKey)) {
         // We do not know how to resize compressed textures.
         SkASSERT(!GrPixelConfigIsCompressed(desc.fConfig));
 
         texture = this->createResizedTexture(desc, cacheID,
                                              srcData, rowBytes,
-                                             GrTextureImpl::NeedsBilerp(resourceKey));
+                                             GrTexturePriv::NeedsBilerp(resourceKey));
     } else {
         texture = fGpu->createTexture(desc, srcData, rowBytes);
     }
@@ -443,7 +464,7 @@
                                          const GrTextureDesc& desc) {
     GrTexture* texture = gpu->createTexture(desc, NULL, 0);
     if (texture) {
-        GrResourceKey key = GrTextureImpl::ComputeScratchKey(texture->desc());
+        GrResourceKey key = GrTexturePriv::ComputeScratchKey(texture->desc());
         // Adding a resource could put us overbudget. Try to free up the
         // necessary space before adding it.
         resourceCache->purgeAsNeeded(1, texture->gpuMemorySize());
@@ -483,7 +504,7 @@
     int origHeight = desc.fHeight;
 
     do {
-        GrResourceKey key = GrTextureImpl::ComputeScratchKey(desc);
+        GrResourceKey key = GrTexturePriv::ComputeScratchKey(desc);
         // Ensure we have exclusive access to the texture so future 'find' calls don't return it
         resource = fResourceCache->find(key, GrResourceCache::kHide_OwnershipFlag);
         if (resource) {
@@ -578,7 +599,7 @@
             // Instead, give up the cache's ref and leave the decision up to
             // addExistingTextureToCache once its ref count reaches 0. For
             // this to work we need to leave it in the exclusive list.
-            texture->impl()->setFlag((GrTextureFlags) GrTextureImpl::kReturnToCache_FlagBit);
+            texture->texturePriv().setFlag((GrTextureFlags) GrTexture::kReturnToCache_FlagBit);
             // Give up the cache's ref to the texture
             texture->unref();
         }
@@ -1347,7 +1368,7 @@
         }
     }
 
-    if (!(kDontFlush_PixelOpsFlag & flags) && texture->hasPendingIO()) {
+    if (!(kDontFlush_PixelOpsFlag & flags) && texture->surfacePriv().hasPendingIO()) {
         this->flush();
     }
 
@@ -1418,7 +1439,7 @@
         }
     }
 
-    if (!(kDontFlush_PixelOpsFlag & flags) && target->hasPendingWrite()) {
+    if (!(kDontFlush_PixelOpsFlag & flags) && target->surfacePriv().hasPendingWrite()) {
         this->flush();
     }
 
diff --git a/src/gpu/GrDistanceFieldTextContext.cpp b/src/gpu/GrDistanceFieldTextContext.cpp
index e2bd6e9..07e9a2e 100755
--- a/src/gpu/GrDistanceFieldTextContext.cpp
+++ b/src/gpu/GrDistanceFieldTextContext.cpp
@@ -7,18 +7,20 @@
 
 #include "GrDistanceFieldTextContext.h"
 #include "GrAtlas.h"
-#include "SkColorFilter.h"
 #include "GrDrawTarget.h"
 #include "GrDrawTargetCaps.h"
 #include "GrFontScaler.h"
-#include "SkGlyphCache.h"
 #include "GrGpu.h"
 #include "GrIndexBuffer.h"
 #include "GrStrokeInfo.h"
+#include "GrTexturePriv.h"
 #include "GrTextStrike.h"
 #include "GrTextStrike_impl.h"
+
+#include "SkColorFilter.h"
 #include "SkDistanceFieldGen.h"
 #include "SkDraw.h"
+#include "SkGlyphCache.h"
 #include "SkGpuDevice.h"
 #include "SkPath.h"
 #include "SkRTConf.h"
@@ -423,10 +425,10 @@
     // The texture coords are last in both the with and without color vertex layouts.
     SkPoint* textureCoords = reinterpret_cast<SkPoint*>(
             reinterpret_cast<intptr_t>(positions) + vertSize  - sizeof(SkPoint));
-    textureCoords->setRectFan(SkFixedToFloat(texture->normalizeFixedX(tx)),
-                              SkFixedToFloat(texture->normalizeFixedY(ty)),
-                              SkFixedToFloat(texture->normalizeFixedX(tx + tw)),
-                              SkFixedToFloat(texture->normalizeFixedY(ty + th)),
+    textureCoords->setRectFan(SkFixedToFloat(texture->texturePriv().normalizeFixedX(tx)),
+                              SkFixedToFloat(texture->texturePriv().normalizeFixedY(ty)),
+                              SkFixedToFloat(texture->texturePriv().normalizeFixedX(tx + tw)),
+                              SkFixedToFloat(texture->texturePriv().normalizeFixedY(ty + th)),
                               vertSize);
     if (useColorVerts) {
         if (0xFF == GrColorUnpackA(fPaint.getColor())) {
diff --git a/src/gpu/GrDrawTarget.cpp b/src/gpu/GrDrawTarget.cpp
index eb89915..d8848bc 100644
--- a/src/gpu/GrDrawTarget.cpp
+++ b/src/gpu/GrDrawTarget.cpp
@@ -13,6 +13,7 @@
 #include "GrDrawTargetCaps.h"
 #include "GrPath.h"
 #include "GrRenderTarget.h"
+#include "GrSurfacePriv.h"
 #include "GrTemplates.h"
 #include "GrTexture.h"
 #include "GrVertexBuffer.h"
@@ -964,7 +965,7 @@
     SkASSERT(dstPoint.fX + srcRect.width() <= dst->width() &&
              dstPoint.fY + srcRect.height() <= dst->height());
 
-    return !dst->isSameAs(src) && dst->asRenderTarget() && src->asTexture();
+    return !dst->surfacePriv().isSameAs(src) && dst->asRenderTarget() && src->asTexture();
 }
 
 bool GrDrawTarget::onCopySurface(GrSurface* dst,
diff --git a/src/gpu/GrSurface.cpp b/src/gpu/GrSurface.cpp
index d15cbdf..37fd73f 100644
--- a/src/gpu/GrSurface.cpp
+++ b/src/gpu/GrSurface.cpp
@@ -6,6 +6,7 @@
  */
 
 #include "GrSurface.h"
+#include "GrSurfacePriv.h"
 
 #include "SkBitmap.h"
 #include "SkGr.h"
@@ -20,14 +21,16 @@
     return SkImageInfo::Make(this->width(), this->height(), colorType, kPremul_SkAlphaType);
 }
 
+// TODO: This should probably be a non-member helper function. It might only be needed in
+// debug or developer builds.
 bool GrSurface::savePixels(const char* filename) {
     SkBitmap bm;
     if (!bm.tryAllocPixels(SkImageInfo::MakeN32Premul(this->width(), this->height()))) {
         return false;
     }
 
-    bool result = readPixels(0, 0, this->width(), this->height(), kSkia8888_GrPixelConfig,
-                             bm.getPixels());
+    bool result = this->readPixels(0, 0, this->width(), this->height(), kSkia8888_GrPixelConfig,
+                                   bm.getPixels());
     if (!result) {
         SkDebugf("------ failed to read pixels for %s\n", filename);
         return false;
@@ -80,3 +83,14 @@
     }
     return false;
 }
+
+bool GrSurface::isSameAs(const GrSurface* other) const {
+    const GrRenderTarget* thisRT = this->asRenderTarget();
+    if (thisRT) {
+        return thisRT == other->asRenderTarget();
+    } else {
+        const GrTexture* thisTex = this->asTexture();
+        SkASSERT(thisTex); // We must be one or the other
+        return thisTex == other->asTexture();
+    }
+}
diff --git a/src/gpu/GrSurfacePriv.h b/src/gpu/GrSurfacePriv.h
new file mode 100644
index 0000000..3203671
--- /dev/null
+++ b/src/gpu/GrSurfacePriv.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrSurfacePriv_DEFINED
+#define GrSurfacePriv_DEFINED
+
+#include "GrSurface.h"
+
+/** Class that adds methods to GrSurface that are only intended for use internal to Skia.
+    This class is purely a privileged window into GrSurface. It should never have additional data
+    members or virtual methods.
+    Non-static methods that are not trivial inlines should be spring-boarded (e.g. declared and
+    implemented privately in GrSurface with a inline public method here). */
+class GrSurfacePriv {
+public:
+    /**
+     * Derive a SkImageInfo from the surface's descriptor. This is lossy as ImageInfo has fields not
+     * known to GrSurface (e.g. alphaType).
+     */
+    SkImageInfo info() const { return fSurface->info(); }
+
+    /**
+     * Checks whether this GrSurface refers to the same GPU object as other. This
+     * catches the case where a GrTexture and GrRenderTarget refer to the same
+     * GPU memory.
+     */
+    bool isSameAs(const GrSurface* other) const { return fSurface->isSameAs(other); }
+
+    /**
+     * Write the contents of the surface to a PNG. Returns true if successful.
+     * @param filename      Full path to desired file
+     */
+    bool savePixels(const char* filename) { return fSurface->savePixels(filename); }
+
+    bool hasPendingRead() const { return fSurface->hasPendingRead(); }
+    bool hasPendingWrite() const { return fSurface->hasPendingWrite(); }
+    bool hasPendingIO() const { return fSurface->hasPendingIO(); }
+
+private:
+    GrSurfacePriv(GrSurface* surface) : fSurface(surface) { }
+    GrSurfacePriv(const GrSurfacePriv& that) : fSurface(that.fSurface) { }
+    GrSurfacePriv& operator=(const GrSurface&); // unimpl
+
+    // No taking addresses of this type.
+    const GrSurfacePriv* operator&() const;
+    GrSurfacePriv* operator&();
+
+    GrSurface* fSurface;
+
+    friend class GrSurface; // to construct/copy this type.
+};
+
+inline GrSurfacePriv GrSurface::surfacePriv() { return GrSurfacePriv(this); }
+
+inline const GrSurfacePriv GrSurface::surfacePriv() const {
+    return GrSurfacePriv(const_cast<GrSurface*>(this));
+}
+
+#endif
diff --git a/src/gpu/GrTextStrike.cpp b/src/gpu/GrTextStrike.cpp
index fa97f73..8ae10cc 100644
--- a/src/gpu/GrTextStrike.cpp
+++ b/src/gpu/GrTextStrike.cpp
@@ -7,6 +7,7 @@
 
 #include "GrGpu.h"
 #include "GrRectanizer.h"
+#include "GrSurfacePriv.h"
 #include "GrTextStrike.h"
 #include "GrTextStrike_impl.h"
 #include "SkString.h"
@@ -206,7 +207,7 @@
 #else
                 filename.printf("fontcache_%d%d.png", gDumpCount, i);
 #endif
-                texture->savePixels(filename.c_str());
+                texture->surfacePriv().savePixels(filename.c_str());
             }
         }
     }
diff --git a/src/gpu/GrTexture.cpp b/src/gpu/GrTexture.cpp
index 667ddd1..e1188f9 100644
--- a/src/gpu/GrTexture.cpp
+++ b/src/gpu/GrTexture.cpp
@@ -7,13 +7,13 @@
  */
 
 
-#include "GrTexture.h"
-
 #include "GrContext.h"
 #include "GrDrawTargetCaps.h"
 #include "GrGpu.h"
 #include "GrRenderTarget.h"
 #include "GrResourceCache.h"
+#include "GrTexture.h"
+#include "GrTexturePriv.h"
 
 GrTexture::~GrTexture() {
     if (fRenderTarget.get()) {
@@ -26,12 +26,12 @@
  * textures back in the texture cache when their ref count goes to zero.
  */
 void GrTexture::internal_dispose() const {
-    if (this->impl()->isSetFlag((GrTextureFlags) GrTextureImpl::kReturnToCache_FlagBit) &&
+    if (this->texturePriv().isSetFlag((GrTextureFlags) GrTexture::kReturnToCache_FlagBit) &&
         this->INHERITED::getContext()) {
         GrTexture* nonConstThis = const_cast<GrTexture *>(this);
         this->ref(); // restore ref count to initial setting
 
-        nonConstThis->impl()->resetFlag((GrTextureFlags) GrTextureImpl::kReturnToCache_FlagBit);
+        nonConstThis->texturePriv().resetFlag((GrTextureFlags) kReturnToCache_FlagBit);
         nonConstThis->INHERITED::getContext()->addExistingTextureToCache(nonConstThis);
 
         // Note: "this" texture might be freed inside addExistingTextureToCache
@@ -42,10 +42,10 @@
     this->INHERITED::internal_dispose();
 }
 
-void GrTextureImpl::dirtyMipMaps(bool mipMapsDirty) {
+void GrTexture::dirtyMipMaps(bool mipMapsDirty) {
     if (mipMapsDirty) {
         if (kValid_MipMapsStatus == fMipMapsStatus) {
-            fMipMapsStatus = kAllocated_MipMapsStatus;
+           fMipMapsStatus = kAllocated_MipMapsStatus;
         }
     } else {
         const bool sizeChanged = kNotAllocated_MipMapsStatus == fMipMapsStatus;
@@ -66,7 +66,7 @@
         textureSize = (size_t) fDesc.fWidth * fDesc.fHeight * GrBytesPerPixel(fDesc.fConfig);
     }
 
-    if (this->impl()->hasMipMaps()) {
+    if (this->texturePriv().hasMipMaps()) {
         // We don't have to worry about the mipmaps being a different size than
         // we'd expect because we never change fDesc.fWidth/fHeight.
         textureSize *= 2;
@@ -107,17 +107,17 @@
     // After abandon() or release() the resource cache will be unreachable (getContext() == NULL).
     // So we readd the texture to the cache here so that it is removed from the exclusive list and
     // there is no longer an unref'ed ptr to the texture in the cache.
-    if (this->impl()->isSetFlag((GrTextureFlags)GrTextureImpl::kReturnToCache_FlagBit)) {
+    if (this->texturePriv().isSetFlag((GrTextureFlags)kReturnToCache_FlagBit)) {
         SkASSERT(!this->wasDestroyed());
         this->ref();  // restores the ref the resource cache gave up when it marked this exclusive.
-        this->impl()->resetFlag((GrTextureFlags) GrTextureImpl::kReturnToCache_FlagBit);
+        this->texturePriv().resetFlag((GrTextureFlags) kReturnToCache_FlagBit);
         this->getContext()->addExistingTextureToCache(this);
     }
 }
 
 void GrTexture::onRelease() {
     this->abandonReleaseCommon();
-    SkASSERT(!this->impl()->isSetFlag((GrTextureFlags) GrTextureImpl::kReturnToCache_FlagBit));
+    SkASSERT(!this->texturePriv().isSetFlag((GrTextureFlags) kReturnToCache_FlagBit));
     INHERITED::onRelease();
 }
 
@@ -207,13 +207,17 @@
 }
 
 //////////////////////////////////////////////////////////////////////////////
-GrTextureImpl::GrTextureImpl(GrGpu* gpu, bool isWrapped, const GrTextureDesc& desc)
+GrTexture::GrTexture(GrGpu* gpu, bool isWrapped, const GrTextureDesc& desc)
     : INHERITED(gpu, isWrapped, desc)
+    , fRenderTarget(NULL)
     , fMipMapsStatus(kNotAllocated_MipMapsStatus) {
-    this->setScratchKey(ComputeScratchKey(desc));
+    this->setScratchKey(GrTexturePriv::ComputeScratchKey(desc));
+    // only make sense if alloc size is pow2
+    fShiftFixedX = 31 - SkCLZ(fDesc.fWidth);
+    fShiftFixedY = 31 - SkCLZ(fDesc.fHeight);
 }
 
-GrResourceKey GrTextureImpl::ComputeKey(const GrGpu* gpu,
+GrResourceKey GrTexturePriv::ComputeKey(const GrGpu* gpu,
                                     const GrTextureParams* params,
                                     const GrTextureDesc& desc,
                                     const GrCacheID& cacheID) {
@@ -221,7 +225,7 @@
     return GrResourceKey(cacheID, texture_resource_type(), flags);
 }
 
-GrResourceKey GrTextureImpl::ComputeScratchKey(const GrTextureDesc& desc) {
+GrResourceKey GrTexturePriv::ComputeScratchKey(const GrTextureDesc& desc) {
     GrCacheID::Key idKey;
     // Instead of a client-provided key of the texture contents we create a key from the
     // descriptor.
@@ -240,10 +244,10 @@
     return GrResourceKey(cacheID, texture_resource_type(), 0);
 }
 
-bool GrTextureImpl::NeedsResizing(const GrResourceKey& key) {
+bool GrTexturePriv::NeedsResizing(const GrResourceKey& key) {
     return SkToBool(key.getResourceFlags() & kStretchToPOT_TextureFlag);
 }
 
-bool GrTextureImpl::NeedsBilerp(const GrResourceKey& key) {
+bool GrTexturePriv::NeedsBilerp(const GrResourceKey& key) {
     return SkToBool(key.getResourceFlags() & kBilerp_TextureFlag);
 }
diff --git a/src/gpu/GrTexturePriv.h b/src/gpu/GrTexturePriv.h
new file mode 100644
index 0000000..9a3e0e2
--- /dev/null
+++ b/src/gpu/GrTexturePriv.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrTexturePriv_DEFINED
+#define GrTexturePriv_DEFINED
+
+#include "GrTexture.h"
+
+/** Class that adds methods to GrTexture that are only intended for use internal to Skia.
+    This class is purely a privileged window into GrTexture. It should never have additional data
+    members or virtual methods.
+    Non-static methods that are not trivial inlines should be spring-boarded (e.g. declared and
+    implemented privately in GrTexture with a inline public method here). */
+class GrTexturePriv {
+public:
+    void setFlag(GrTextureFlags flags) {
+        fTexture->fDesc.fFlags = fTexture->fDesc.fFlags | flags;
+    }
+
+    void resetFlag(GrTextureFlags flags) {
+        fTexture->fDesc.fFlags = fTexture->fDesc.fFlags & ~flags;
+    }
+
+    bool isSetFlag(GrTextureFlags flags) const {
+        return 0 != (fTexture->fDesc.fFlags & flags);
+    }
+
+    void dirtyMipMaps(bool mipMapsDirty) { fTexture->dirtyMipMaps(mipMapsDirty); }
+
+    bool mipMapsAreDirty() const {
+        return GrTexture::kValid_MipMapsStatus != fTexture->fMipMapsStatus;
+    }
+
+    bool hasMipMaps() const {
+        return GrTexture::kNotAllocated_MipMapsStatus != fTexture->fMipMapsStatus;
+    }
+
+    static GrResourceKey ComputeKey(const GrGpu* gpu,
+                                    const GrTextureParams* params,
+                                    const GrTextureDesc& desc,
+                                    const GrCacheID& cacheID);
+    static GrResourceKey ComputeScratchKey(const GrTextureDesc& desc);
+    static bool NeedsResizing(const GrResourceKey& key);
+    static bool NeedsBilerp(const GrResourceKey& key);
+
+
+    // TODO: Move this logic and the shift values out of here and to the callers.
+    SkFixed normalizeFixedX(SkFixed x) const {
+        SkASSERT(SkIsPow2(fTexture->fDesc.fWidth));
+        return x >> fTexture->fShiftFixedX;
+    }
+
+    SkFixed normalizeFixedY(SkFixed y) const {
+        SkASSERT(SkIsPow2(fTexture->fDesc.fHeight));
+        return y >> fTexture->fShiftFixedY;
+    }
+
+private:
+    GrTexturePriv(GrTexture* texture) : fTexture(texture) { }
+    GrTexturePriv(const GrTexturePriv& that) : fTexture(that.fTexture) { }
+    GrTexturePriv& operator=(const GrTexturePriv&); // unimpl
+
+    // No taking addresses of this type.
+    const GrTexturePriv* operator&() const;
+    GrTexturePriv* operator&();
+
+    GrTexture* fTexture;
+        
+    friend class GrTexture; // to construct/copy this type.
+};
+
+inline GrTexturePriv GrTexture::texturePriv() { return GrTexturePriv(this); }
+
+inline const GrTexturePriv GrTexture::texturePriv () const {
+    return GrTexturePriv(const_cast<GrTexture*>(this));
+}
+
+#endif
diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
index 455a8ab..6eaed89 100644
--- a/src/gpu/SkGpuDevice.cpp
+++ b/src/gpu/SkGpuDevice.cpp
@@ -151,9 +151,10 @@
 
     fRenderTarget = SkRef(surface->asRenderTarget());
 
+    SkImageInfo info = surface->surfacePriv().info();
     SkPixelRef* pr = SkNEW_ARGS(SkGrPixelRef,
-                                (surface->info(), surface, SkToBool(flags & kCached_Flag)));
-    fLegacyBitmap.setInfo(surface->info());
+                                (info, surface, SkToBool(flags & kCached_Flag)));
+    fLegacyBitmap.setInfo(info);
     fLegacyBitmap.setPixelRef(pr)->unref();
 
     this->setPixelGeometry(props.pixelGeometry());
@@ -691,7 +692,7 @@
 
 SkBitmap wrap_texture(GrTexture* texture) {
     SkBitmap result;
-    result.setInfo(texture->info());
+    result.setInfo(texture->surfacePriv().info());
     result.setPixelRef(SkNEW_ARGS(SkGrPixelRef, (result.info(), texture)))->unref();
     return result;
 }
diff --git a/src/gpu/SkGpuDevice.h b/src/gpu/SkGpuDevice.h
index f19d2cb..285a737 100644
--- a/src/gpu/SkGpuDevice.h
+++ b/src/gpu/SkGpuDevice.h
@@ -17,6 +17,7 @@
 #include "SkPicture.h"
 #include "SkRegion.h"
 #include "GrContext.h"
+#include "GrSurfacePriv.h"
 
 struct SkDrawProcs;
 struct GrSkDrawProcs;
@@ -61,7 +62,7 @@
     virtual GrRenderTarget* accessRenderTarget() SK_OVERRIDE;
 
     virtual SkImageInfo imageInfo() const SK_OVERRIDE {
-        return fRenderTarget ? fRenderTarget->info() : SkImageInfo::MakeUnknown();
+        return fRenderTarget ? fRenderTarget->surfacePriv().info() : SkImageInfo::MakeUnknown();
     }
 
     virtual void clear(SkColor color) SK_OVERRIDE;
diff --git a/src/gpu/gl/GrGLTexture.h b/src/gpu/gl/GrGLTexture.h
index 23ae3fa..05acaa8 100644
--- a/src/gpu/gl/GrGLTexture.h
+++ b/src/gpu/gl/GrGLTexture.h
@@ -45,7 +45,7 @@
 ////////////////////////////////////////////////////////////////////////////////
 
 
-class GrGLTexture : public GrTextureImpl {
+class GrGLTexture : public GrTexture {
 
 public:
     struct TexParams {
@@ -105,7 +105,7 @@
               const Desc& textureDesc,
               const GrGLRenderTarget::Desc* rtDesc);
 
-    typedef GrTextureImpl INHERITED;
+    typedef GrTexture INHERITED;
 };
 
 #endif
diff --git a/src/gpu/gl/GrGpuGL.cpp b/src/gpu/gl/GrGpuGL.cpp
index be38511..8be1118 100644
--- a/src/gpu/gl/GrGpuGL.cpp
+++ b/src/gpu/gl/GrGpuGL.cpp
@@ -9,7 +9,9 @@
 #include "GrGpuGL.h"
 #include "GrGLStencilBuffer.h"
 #include "GrOptDrawState.h"
+#include "GrSurfacePriv.h"
 #include "GrTemplates.h"
+#include "GrTexturePriv.h"
 #include "GrTypes.h"
 #include "SkStrokeRec.h"
 #include "SkTemplates.h"
@@ -493,7 +495,7 @@
     }
 
     if (success) {
-        texture->impl()->dirtyMipMaps(true);
+        texture->texturePriv().dirtyMipMaps(true);
         return true;
     }
 
@@ -1731,7 +1733,7 @@
 
     GrTexture *texture = target->asTexture();
     if (texture) {
-        texture->impl()->dirtyMipMaps(true);
+        texture->texturePriv().dirtyMipMaps(true);
     }
 }
 
@@ -2053,9 +2055,9 @@
     newTexParams.fMagFilter = glMagFilterModes[filterMode];
 
     if (GrTextureParams::kMipMap_FilterMode == filterMode &&
-        texture->mipMapsAreDirty() && !GrPixelConfigIsCompressed(texture->config())) {
+        texture->texturePriv().mipMapsAreDirty() && !GrPixelConfigIsCompressed(texture->config())) {
         GL_CALL(GenerateMipmap(GR_GL_TEXTURE_2D));
-        texture->dirtyMipMaps(false);
+        texture->texturePriv().dirtyMipMaps(false);
     }
 
     newTexParams.fWrapS = tile_to_gl_wrap(params.getTileModeX());
@@ -2469,7 +2471,7 @@
         SkIRect dstRect = SkIRect::MakeXYWH(dstPoint.fX, dstPoint.fY,
                                             srcRect.width(), srcRect.height());
         bool selfOverlap = false;
-        if (dst->isSameAs(src)) {
+        if (dst->surfacePriv().isSameAs(src)) {
             selfOverlap = SkIRect::IntersectsNoEmptyCheck(dstRect, srcRect);
         }
 
@@ -2547,7 +2549,7 @@
         return true;
     }
     if (can_blit_framebuffer(dst, src, this)) {
-        if (dst->isSameAs(src)) {
+        if (dst->surfacePriv().isSameAs(src)) {
             SkIRect dstRect = SkIRect::MakeXYWH(dstPoint.fX, dstPoint.fY,
                                                 srcRect.width(), srcRect.height());
             if(!SkIRect::IntersectsNoEmptyCheck(dstRect, srcRect)) {
diff --git a/tests/GrSurfaceTest.cpp b/tests/GrSurfaceTest.cpp
index a2ed629..285e9e8 100644
--- a/tests/GrSurfaceTest.cpp
+++ b/tests/GrSurfaceTest.cpp
@@ -11,6 +11,7 @@
 #include "GrContextFactory.h"
 #include "GrRenderTarget.h"
 #include "GrTexture.h"
+#include "GrSurfacePriv.h"
 #include "SkTypes.h"
 #include "Test.h"
 
@@ -28,14 +29,14 @@
         desc.fFlags = kNone_GrTextureFlags;
         GrSurface* tex1 = context->createUncachedTexture(desc, NULL, 0);
 
-        REPORTER_ASSERT(reporter, texRT1->isSameAs(texRT1));
-        REPORTER_ASSERT(reporter, texRT1->isSameAs(texRT1->asRenderTarget()));
-        REPORTER_ASSERT(reporter, texRT1->asRenderTarget()->isSameAs(texRT1));
-        REPORTER_ASSERT(reporter, !texRT2->isSameAs(texRT1));
-        REPORTER_ASSERT(reporter, !texRT2->asRenderTarget()->isSameAs(texRT1));
-        REPORTER_ASSERT(reporter, !texRT2->isSameAs(texRT1->asRenderTarget()));
-        REPORTER_ASSERT(reporter, !texRT2->isSameAs(tex1));
-        REPORTER_ASSERT(reporter, !texRT2->asRenderTarget()->isSameAs(tex1));
+        REPORTER_ASSERT(reporter, texRT1->surfacePriv().isSameAs(texRT1));
+        REPORTER_ASSERT(reporter, texRT1->surfacePriv().isSameAs(texRT1->asRenderTarget()));
+        REPORTER_ASSERT(reporter, texRT1->asRenderTarget()->surfacePriv().isSameAs(texRT1));
+        REPORTER_ASSERT(reporter, !texRT2->surfacePriv().isSameAs(texRT1));
+        REPORTER_ASSERT(reporter, !texRT2->asRenderTarget()->surfacePriv().isSameAs(texRT1));
+        REPORTER_ASSERT(reporter, !texRT2->surfacePriv().isSameAs(texRT1->asRenderTarget()));
+        REPORTER_ASSERT(reporter, !texRT2->surfacePriv().isSameAs(tex1));
+        REPORTER_ASSERT(reporter, !texRT2->asRenderTarget()->surfacePriv().isSameAs(tex1));
 
         GrBackendTextureDesc backendDesc;
         backendDesc.fConfig = kSkia8888_GrPixelConfig;
@@ -45,11 +46,13 @@
         backendDesc.fSampleCnt = 0;
         backendDesc.fTextureHandle = 5;
         GrSurface* externalTexRT = context->wrapBackendTexture(backendDesc);
-        REPORTER_ASSERT(reporter, externalTexRT->isSameAs(externalTexRT));
-        REPORTER_ASSERT(reporter, externalTexRT->isSameAs(externalTexRT->asRenderTarget()));
-        REPORTER_ASSERT(reporter, externalTexRT->asRenderTarget()->isSameAs(externalTexRT));
-        REPORTER_ASSERT(reporter, !externalTexRT->isSameAs(texRT1));
-        REPORTER_ASSERT(reporter, !externalTexRT->asRenderTarget()->isSameAs(texRT1));
+        REPORTER_ASSERT(reporter, externalTexRT->surfacePriv().isSameAs(externalTexRT));
+        REPORTER_ASSERT(reporter,
+                        externalTexRT->surfacePriv().isSameAs(externalTexRT->asRenderTarget()));
+        REPORTER_ASSERT(reporter,
+                        externalTexRT->asRenderTarget()->surfacePriv().isSameAs(externalTexRT));
+        REPORTER_ASSERT(reporter, !externalTexRT->surfacePriv().isSameAs(texRT1));
+        REPORTER_ASSERT(reporter, !externalTexRT->asRenderTarget()->surfacePriv().isSameAs(texRT1));
 
         texRT1->unref();
         texRT2->unref();