Make GrDrawTarget::Caps ref counted and GrGLCaps derive from it.

Also rename GrDrawTarget::getCaps() -> GrDrawTarget::caps().
Review URL: https://codereview.chromium.org/12843026

git-svn-id: http://skia.googlecode.com/svn/trunk@8364 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/gpu/GrAAConvexPathRenderer.cpp b/src/gpu/GrAAConvexPathRenderer.cpp
index ebf2ea9..b4509b3 100644
--- a/src/gpu/GrAAConvexPathRenderer.cpp
+++ b/src/gpu/GrAAConvexPathRenderer.cpp
@@ -432,7 +432,7 @@
                                          const SkStrokeRec& stroke,
                                          const GrDrawTarget* target,
                                          bool antiAlias) const {
-    return (target->getCaps().shaderDerivativeSupport() && antiAlias &&
+    return (target->caps()->shaderDerivativeSupport() && antiAlias &&
             stroke.isFillStyle() && !path.isInverseFillType() && path.isConvex());
 }
 
diff --git a/src/gpu/GrAAHairLinePathRenderer.cpp b/src/gpu/GrAAHairLinePathRenderer.cpp
index 783cadf..90ab128 100644
--- a/src/gpu/GrAAHairLinePathRenderer.cpp
+++ b/src/gpu/GrAAHairLinePathRenderer.cpp
@@ -565,7 +565,7 @@
 
     static const uint32_t gReqDerivMask = SkPath::kCubic_SegmentMask |
                                           SkPath::kQuad_SegmentMask;
-    if (!target->getCaps().shaderDerivativeSupport() &&
+    if (!target->caps()->shaderDerivativeSupport() &&
         (gReqDerivMask & path.getSegmentMasks())) {
         return false;
     }
diff --git a/src/gpu/GrBufferAllocPool.cpp b/src/gpu/GrBufferAllocPool.cpp
index 65d76c4..8d748b8 100644
--- a/src/gpu/GrBufferAllocPool.cpp
+++ b/src/gpu/GrBufferAllocPool.cpp
@@ -302,7 +302,7 @@
     //      threshold (since we don't expect it is likely that we will see more vertex data)
     //      b) If the hint is not set we lock if the buffer size is greater than the threshold.
     bool attemptLock = block.fBuffer->isCPUBacked();
-    if (!attemptLock && fGpu->getCaps().bufferLockSupport()) {
+    if (!attemptLock && fGpu->caps()->bufferLockSupport()) {
         if (fFrequentResetHint) {
             attemptLock = requestSize > GR_GEOM_BUFFER_LOCK_THRESHOLD;
         } else {
@@ -350,7 +350,7 @@
     GrAssert(flushSize <= buffer->sizeInBytes());
     VALIDATE(true);
 
-    if (fGpu->getCaps().bufferLockSupport() &&
+    if (fGpu->caps()->bufferLockSupport() &&
         flushSize > GR_GEOM_BUFFER_LOCK_THRESHOLD) {
         void* data = buffer->lock();
         if (NULL != data) {
diff --git a/src/gpu/GrClipMaskManager.cpp b/src/gpu/GrClipMaskManager.cpp
index 6415859..4626af8 100644
--- a/src/gpu/GrClipMaskManager.cpp
+++ b/src/gpu/GrClipMaskManager.cpp
@@ -824,8 +824,8 @@
         stencilBits = stencilBuffer->bits();
     }
 
-    GrAssert(fGpu->getCaps().stencilWrapOpsSupport() || !settings.usesWrapOp());
-    GrAssert(fGpu->getCaps().twoSidedStencilSupport() || !settings.isTwoSided());
+    GrAssert(fGpu->caps()->stencilWrapOpsSupport() || !settings.usesWrapOp());
+    GrAssert(fGpu->caps()->twoSidedStencilSupport() || !settings.isTwoSided());
     this->adjustStencilParams(&settings, clipMode, stencilBits);
     fGpu->setStencilSettings(settings);
 }
@@ -845,7 +845,7 @@
     unsigned int userBits = clipBit - 1;
 
     GrStencilSettings::Face face = GrStencilSettings::kFront_Face;
-    bool twoSided = fGpu->getCaps().twoSidedStencilSupport();
+    bool twoSided = fGpu->caps()->twoSidedStencilSupport();
 
     bool finished = false;
     while (!finished) {
diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp
index e2c41d1..0a2f01d 100644
--- a/src/gpu/GrContext.cpp
+++ b/src/gpu/GrContext.cpp
@@ -548,15 +548,15 @@
 }
 
 int GrContext::getMaxTextureSize() const {
-    return fGpu->getCaps().maxTextureSize();
+    return fGpu->caps()->maxTextureSize();
 }
 
 int GrContext::getMaxRenderTargetSize() const {
-    return fGpu->getCaps().maxRenderTargetSize();
+    return fGpu->caps()->maxRenderTargetSize();
 }
 
 int GrContext::getMaxSampleCount() const {
-    return fGpu->getCaps().maxSampleCount();
+    return fGpu->caps()->maxSampleCount();
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -573,8 +573,8 @@
 
 bool GrContext::supportsIndex8PixelConfig(const GrTextureParams* params,
                                           int width, int height) const {
-    const GrDrawTarget::Caps& caps = fGpu->getCaps();
-    if (!caps.eightBitPaletteSupport()) {
+    const GrDrawTarget::Caps* caps = fGpu->caps();
+    if (!caps->eightBitPaletteSupport()) {
         return false;
     }
 
@@ -582,7 +582,7 @@
 
     if (!isPow2) {
         bool tiled = NULL != params && params->isTiled();
-        if (tiled && !caps.npotTextureTileSupport()) {
+        if (tiled && !caps->npotTextureTileSupport()) {
             return false;
         }
     }
diff --git a/src/gpu/GrDrawTarget.cpp b/src/gpu/GrDrawTarget.cpp
index cd4d4d2..9f9c7d6 100644
--- a/src/gpu/GrDrawTarget.cpp
+++ b/src/gpu/GrDrawTarget.cpp
@@ -452,7 +452,7 @@
 void GrDrawTarget::stencilPath(const GrPath* path, const SkStrokeRec& stroke, SkPath::FillType fill) {
     // TODO: extract portions of checkDraw that are relevant to path stenciling.
     GrAssert(NULL != path);
-    GrAssert(fCaps.pathStencilingSupport());
+    GrAssert(this->caps()->pathStencilingSupport());
     GrAssert(!stroke.isHairlineStyle());
     GrAssert(!SkPath::IsInverseFillType(fill));
     this->onStencilPath(path, stroke, fill);
@@ -464,7 +464,7 @@
     // There is a conflict between using smooth lines and our use of premultiplied alpha. Smooth
     // lines tweak the incoming alpha value but not in a premul-alpha way. So we only use them when
     // our alpha is 0xff and tweaking the color for partial coverage is OK
-    if (!fCaps.hwAALineSupport() ||
+    if (!this->caps()->hwAALineSupport() ||
         !this->getDrawState().isHWAntialiasState()) {
         return false;
     }
@@ -476,7 +476,7 @@
 bool GrDrawTarget::canApplyCoverage() const {
     // we can correctly apply coverage if a) we have dual source blending
     // or b) one of our blend optimizations applies.
-    return this->getCaps().dualSourceBlendingSupport() ||
+    return this->caps()->dualSourceBlendingSupport() ||
            GrDrawState::kNone_BlendOpt != this->getDrawState().getBlendOpts(true);
 }
 
@@ -677,19 +677,59 @@
     target->setClip(&fReplacementClip);
 }
 
+///////////////////////////////////////////////////////////////////////////////
+
+SK_DEFINE_INST_COUNT(GrDrawTarget::Caps)
+
+void GrDrawTarget::Caps::reset() {
+    f8BitPaletteSupport = false;
+    fNPOTTextureTileSupport = false;
+    fTwoSidedStencilSupport = false;
+    fStencilWrapOpsSupport = false;
+    fHWAALineSupport = false;
+    fShaderDerivativeSupport = false;
+    fGeometryShaderSupport = false;
+    fDualSourceBlendingSupport = false;
+    fBufferLockSupport = false;
+    fPathStencilingSupport = false;
+
+    fMaxRenderTargetSize = 0;
+    fMaxTextureSize = 0;
+    fMaxSampleCount = 0;
+}
+
+GrDrawTarget::Caps& GrDrawTarget::Caps::operator=(const GrDrawTarget::Caps& other) {
+    f8BitPaletteSupport = other.f8BitPaletteSupport;
+    fNPOTTextureTileSupport = other.fNPOTTextureTileSupport;
+    fTwoSidedStencilSupport = other.fTwoSidedStencilSupport;
+    fStencilWrapOpsSupport = other.fStencilWrapOpsSupport;
+    fHWAALineSupport = other.fHWAALineSupport;
+    fShaderDerivativeSupport = other.fShaderDerivativeSupport;
+    fGeometryShaderSupport = other.fGeometryShaderSupport;
+    fDualSourceBlendingSupport = other.fDualSourceBlendingSupport;
+    fBufferLockSupport = other.fBufferLockSupport;
+    fPathStencilingSupport = other.fPathStencilingSupport;
+
+    fMaxRenderTargetSize = other.fMaxRenderTargetSize;
+    fMaxTextureSize = other.fMaxTextureSize;
+    fMaxSampleCount = other.fMaxSampleCount;
+
+    return *this;
+}
+
 void GrDrawTarget::Caps::print() const {
     static const char* gNY[] = {"NO", "YES"};
-    GrPrintf("8 Bit Palette Support       : %s\n", gNY[fInternals.f8BitPaletteSupport]);
-    GrPrintf("NPOT Texture Tile Support   : %s\n", gNY[fInternals.fNPOTTextureTileSupport]);
-    GrPrintf("Two Sided Stencil Support   : %s\n", gNY[fInternals.fTwoSidedStencilSupport]);
-    GrPrintf("Stencil Wrap Ops  Support   : %s\n", gNY[fInternals.fStencilWrapOpsSupport]);
-    GrPrintf("HW AA Lines Support         : %s\n", gNY[fInternals.fHWAALineSupport]);
-    GrPrintf("Shader Derivative Support   : %s\n", gNY[fInternals.fShaderDerivativeSupport]);
-    GrPrintf("Geometry Shader Support     : %s\n", gNY[fInternals.fGeometryShaderSupport]);
-    GrPrintf("FSAA Support                : %s\n", gNY[fInternals.fFSAASupport]);
-    GrPrintf("Dual Source Blending Support: %s\n", gNY[fInternals.fDualSourceBlendingSupport]);
-    GrPrintf("Buffer Lock Support         : %s\n", gNY[fInternals.fBufferLockSupport]);
-    GrPrintf("Path Stenciling Support     : %s\n", gNY[fInternals.fPathStencilingSupport]);
-    GrPrintf("Max Texture Size            : %d\n", fInternals.fMaxTextureSize);
-    GrPrintf("Max Render Target Size      : %d\n", fInternals.fMaxRenderTargetSize);
+    GrPrintf("8 Bit Palette Support       : %s\n", gNY[f8BitPaletteSupport]);
+    GrPrintf("NPOT Texture Tile Support   : %s\n", gNY[fNPOTTextureTileSupport]);
+    GrPrintf("Two Sided Stencil Support   : %s\n", gNY[fTwoSidedStencilSupport]);
+    GrPrintf("Stencil Wrap Ops  Support   : %s\n", gNY[fStencilWrapOpsSupport]);
+    GrPrintf("HW AA Lines Support         : %s\n", gNY[fHWAALineSupport]);
+    GrPrintf("Shader Derivative Support   : %s\n", gNY[fShaderDerivativeSupport]);
+    GrPrintf("Geometry Shader Support     : %s\n", gNY[fGeometryShaderSupport]);
+    GrPrintf("Dual Source Blending Support: %s\n", gNY[fDualSourceBlendingSupport]);
+    GrPrintf("Buffer Lock Support         : %s\n", gNY[fBufferLockSupport]);
+    GrPrintf("Path Stenciling Support     : %s\n", gNY[fPathStencilingSupport]);
+    GrPrintf("Max Texture Size            : %d\n", fMaxTextureSize);
+    GrPrintf("Max Render Target Size      : %d\n", fMaxRenderTargetSize);
+    GrPrintf("Max Sample Count            : %d\n", fMaxSampleCount);
 }
diff --git a/src/gpu/GrDrawTarget.h b/src/gpu/GrDrawTarget.h
index de8c5c4..68ba591 100644
--- a/src/gpu/GrDrawTarget.h
+++ b/src/gpu/GrDrawTarget.h
@@ -30,27 +30,6 @@
 
 class GrDrawTarget : public GrRefCnt {
 protected:
-    /** This helper class allows GrDrawTarget subclasses to set the caps values without having to be
-        made a friend of GrDrawTarget::Caps. */
-    class CapsInternals {
-    public:
-        bool f8BitPaletteSupport        : 1;
-        bool fNPOTTextureTileSupport    : 1;
-        bool fTwoSidedStencilSupport    : 1;
-        bool fStencilWrapOpsSupport     : 1;
-        bool fHWAALineSupport           : 1;
-        bool fShaderDerivativeSupport   : 1;
-        bool fGeometryShaderSupport     : 1;
-        bool fFSAASupport               : 1;
-        bool fDualSourceBlendingSupport : 1;
-        bool fBufferLockSupport         : 1;
-        bool fPathStencilingSupport     : 1;
-
-        int fMaxRenderTargetSize;
-        int fMaxTextureSize;
-        int fMaxSampleCount;
-    };
-
     class DrawInfo;
 
 public:
@@ -59,35 +38,50 @@
     /**
      * Represents the draw target capabilities.
      */
-    class Caps {
+    class Caps : public SkRefCnt {
     public:
-        Caps() { memset(this, 0, sizeof(Caps)); }
+        SK_DECLARE_INST_COUNT(Caps)
+
+        Caps() { this->reset(); }
         Caps(const Caps& c) { *this = c; }
-        Caps& operator= (const Caps& c) {
-            memcpy(this, &c, sizeof(Caps));
-            return *this;
-        }
-        void print() const;
+        Caps& operator= (const Caps& c);
 
-        bool eightBitPaletteSupport() const { return fInternals.f8BitPaletteSupport; }
-        bool npotTextureTileSupport() const { return fInternals.fNPOTTextureTileSupport; }
-        bool twoSidedStencilSupport() const { return fInternals.fTwoSidedStencilSupport; }
-        bool stencilWrapOpsSupport() const { return  fInternals.fStencilWrapOpsSupport; }
-        bool hwAALineSupport() const { return fInternals.fHWAALineSupport; }
-        bool shaderDerivativeSupport() const { return fInternals.fShaderDerivativeSupport; }
-        bool geometryShaderSupport() const { return fInternals.fGeometryShaderSupport; }
-        bool fsaaSupport() const { return fInternals.fFSAASupport; }
-        bool dualSourceBlendingSupport() const { return fInternals.fDualSourceBlendingSupport; }
-        bool bufferLockSupport() const { return fInternals.fBufferLockSupport; }
-        bool pathStencilingSupport() const { return fInternals.fPathStencilingSupport; }
+        virtual void reset();
+        virtual void print() const;
 
-        int maxRenderTargetSize() const { return fInternals.fMaxRenderTargetSize; }
-        int maxTextureSize() const { return fInternals.fMaxTextureSize; }
+        bool eightBitPaletteSupport() const { return f8BitPaletteSupport; }
+        bool npotTextureTileSupport() const { return fNPOTTextureTileSupport; }
+        bool twoSidedStencilSupport() const { return fTwoSidedStencilSupport; }
+        bool stencilWrapOpsSupport() const { return  fStencilWrapOpsSupport; }
+        bool hwAALineSupport() const { return fHWAALineSupport; }
+        bool shaderDerivativeSupport() const { return fShaderDerivativeSupport; }
+        bool geometryShaderSupport() const { return fGeometryShaderSupport; }
+        bool dualSourceBlendingSupport() const { return fDualSourceBlendingSupport; }
+        bool bufferLockSupport() const { return fBufferLockSupport; }
+        bool pathStencilingSupport() const { return fPathStencilingSupport; }
+
+        int maxRenderTargetSize() const { return fMaxRenderTargetSize; }
+        int maxTextureSize() const { return fMaxTextureSize; }
         // Will be 0 if MSAA is not supported
-        int maxSampleCount() const { return fInternals.fMaxSampleCount; }
-    private:
-        CapsInternals fInternals;
-        friend class GrDrawTarget; // to set values of fInternals
+        int maxSampleCount() const { return fMaxSampleCount; }
+    protected:
+
+        bool f8BitPaletteSupport        : 1;
+        bool fNPOTTextureTileSupport    : 1;
+        bool fTwoSidedStencilSupport    : 1;
+        bool fStencilWrapOpsSupport     : 1;
+        bool fHWAALineSupport           : 1;
+        bool fShaderDerivativeSupport   : 1;
+        bool fGeometryShaderSupport     : 1;
+        bool fDualSourceBlendingSupport : 1;
+        bool fBufferLockSupport         : 1;
+        bool fPathStencilingSupport     : 1;
+
+        int fMaxRenderTargetSize;
+        int fMaxTextureSize;
+        int fMaxSampleCount;
+
+        typedef SkRefCnt INHERITED;
     };
 
     ///////////////////////////////////////////////////////////////////////////
@@ -100,7 +94,7 @@
     /**
      * Gets the capabilities of the draw target.
      */
-    const Caps& getCaps() const { return fCaps; }
+    const Caps* caps() const { return fCaps.get(); }
 
     /**
      * Sets the current clip to the region specified by clip. All draws will be
@@ -652,9 +646,6 @@
     GrContext* getContext() { return fContext; }
     const GrContext* getContext() const { return fContext; }
 
-    // allows derived class to set the caps
-    CapsInternals* capsInternals() { return &fCaps.fInternals; }
-
     // A subclass may override this function if it wishes to be notified when the clip is changed.
     // The override should call INHERITED::clipWillBeSet().
     virtual void clipWillBeSet(const GrClipData* clipData);
@@ -673,7 +664,8 @@
         return this->getGeomSrc().fVertexSize;
     }
 
-    Caps fCaps;
+    // Subclass must initialize this in its constructor.
+    SkAutoTUnref<const Caps> fCaps;
 
     /**
      * Used to communicate draws to subclass's onDraw function.
diff --git a/src/gpu/GrGpu.cpp b/src/gpu/GrGpu.cpp
index b5cdc5c..ba7bedd 100644
--- a/src/gpu/GrGpu.cpp
+++ b/src/gpu/GrGpu.cpp
@@ -204,7 +204,7 @@
 }
 
 GrPath* GrGpu::createPath(const SkPath& path) {
-    GrAssert(fCaps.pathStencilingSupport());
+    GrAssert(this->caps()->pathStencilingSupport());
     this->handleDirtyContext();
     return this->onCreatePath(path);
 }
diff --git a/src/gpu/GrInOrderDrawBuffer.cpp b/src/gpu/GrInOrderDrawBuffer.cpp
index 6966858..2e86147 100644
--- a/src/gpu/GrInOrderDrawBuffer.cpp
+++ b/src/gpu/GrInOrderDrawBuffer.cpp
@@ -29,7 +29,7 @@
     , fFlushing(false) {
 
     fDstGpu->ref();
-    fCaps = fDstGpu->getCaps();
+    fCaps.reset(SkRef(fDstGpu->caps()));
 
     GrAssert(NULL != vertexPool);
     GrAssert(NULL != indexPool);
@@ -99,7 +99,7 @@
     // optimizations help determine whether coverage and color can be blended correctly when
     // dual-source blending isn't available. This comes into play when there is coverage. If colors
     // were a stage it could take a hint that every vertex's color will be opaque.
-    if (this->getCaps().dualSourceBlendingSupport() ||
+    if (this->caps()->dualSourceBlendingSupport() ||
         drawState->hasSolidCoverage(drawState->getAttribBindings())) {
         bindings |= GrDrawState::kColor_AttribBindingsBit;
         drawState->setAttribIndex(GrDrawState::kColor_AttribIndex, attribs.count());
diff --git a/src/gpu/GrPathRendererChain.cpp b/src/gpu/GrPathRendererChain.cpp
index 23f7576..3458841 100644
--- a/src/gpu/GrPathRendererChain.cpp
+++ b/src/gpu/GrPathRendererChain.cpp
@@ -79,8 +79,8 @@
 void GrPathRendererChain::init() {
     GrAssert(!fInit);
     GrGpu* gpu = fOwner->getGpu();
-    bool twoSided = gpu->getCaps().twoSidedStencilSupport();
-    bool wrapOp = gpu->getCaps().stencilWrapOpsSupport();
+    bool twoSided = gpu->caps()->twoSidedStencilSupport();
+    bool wrapOp = gpu->caps()->stencilWrapOpsSupport();
     GrPathRenderer::AddPathRenderers(fOwner, this);
     this->addPathRenderer(SkNEW_ARGS(GrDefaultPathRenderer,
                                      (twoSided, wrapOp)))->unref();
diff --git a/src/gpu/GrStencilAndCoverPathRenderer.cpp b/src/gpu/GrStencilAndCoverPathRenderer.cpp
index 44da3f9..04d7674 100644
--- a/src/gpu/GrStencilAndCoverPathRenderer.cpp
+++ b/src/gpu/GrStencilAndCoverPathRenderer.cpp
@@ -16,7 +16,7 @@
 GrPathRenderer* GrStencilAndCoverPathRenderer::Create(GrContext* context) {
     GrAssert(NULL != context);
     GrAssert(NULL != context->getGpu());
-    if (context->getGpu()->getCaps().pathStencilingSupport()) {
+    if (context->getGpu()->caps()->pathStencilingSupport()) {
         return SkNEW_ARGS(GrStencilAndCoverPathRenderer, (context->getGpu()));
     } else {
         return NULL;
@@ -24,7 +24,7 @@
 }
 
 GrStencilAndCoverPathRenderer::GrStencilAndCoverPathRenderer(GrGpu* gpu) {
-    GrAssert(gpu->getCaps().pathStencilingSupport());
+    GrAssert(gpu->caps()->pathStencilingSupport());
     fGpu = gpu;
     gpu->ref();
 }
diff --git a/src/gpu/GrTexture.cpp b/src/gpu/GrTexture.cpp
index 1e30661..479d7bb 100644
--- a/src/gpu/GrTexture.cpp
+++ b/src/gpu/GrTexture.cpp
@@ -136,7 +136,7 @@
                                                const GrTextureDesc& desc) {
     GrResourceKey::ResourceFlags flags = 0;
     bool tiled = NULL != params && params->isTiled();
-    if (tiled && !gpu->getCaps().npotTextureTileSupport()) {
+    if (tiled && !gpu->caps()->npotTextureTileSupport()) {
         if (!GrIsPow2(desc.fWidth) || !GrIsPow2(desc.fHeight)) {
             flags |= kStretchToPOT_TextureFlag;
             if (params->isBilerp()) {
diff --git a/src/gpu/gl/GrGLBufferImpl.cpp b/src/gpu/gl/GrGLBufferImpl.cpp
index 6867e13..0723bd2 100644
--- a/src/gpu/gl/GrGLBufferImpl.cpp
+++ b/src/gpu/gl/GrGLBufferImpl.cpp
@@ -74,7 +74,7 @@
     GrAssert(!this->isLocked());
     if (0 == fDesc.fID) {
         fLockPtr = fCPUData;
-    } else if (gpu->getCaps().bufferLockSupport()) {
+    } else if (gpu->caps()->bufferLockSupport()) {
         this->bind(gpu);
         // Let driver know it can discard the old data
         GL_CALL(gpu, BufferData(fBufferType,
@@ -92,7 +92,7 @@
     VALIDATE();
     GrAssert(this->isLocked());
     if (0 != fDesc.fID) {
-        GrAssert(gpu->getCaps().bufferLockSupport());
+        GrAssert(gpu->caps()->bufferLockSupport());
         this->bind(gpu);
         GL_CALL(gpu, UnmapBuffer(fBufferType));
     }
diff --git a/src/gpu/gl/GrGLCaps.cpp b/src/gpu/gl/GrGLCaps.cpp
index a115b5d..cf09506 100644
--- a/src/gpu/gl/GrGLCaps.cpp
+++ b/src/gpu/gl/GrGLCaps.cpp
@@ -10,11 +10,15 @@
 #include "GrGLContext.h"
 #include "SkTSearch.h"
 
+SK_DEFINE_INST_COUNT(GrGLCaps)
+
 GrGLCaps::GrGLCaps() {
     this->reset();
 }
 
 void GrGLCaps::reset() {
+    INHERITED::reset();
+
     fVerifiedColorConfigs.reset();
     fStencilFormats.reset();
     fStencilVerifiedColorConfigs.reset();
@@ -46,6 +50,7 @@
 }
 
 GrGLCaps& GrGLCaps::operator = (const GrGLCaps& caps) {
+    INHERITED::operator=(caps);
     fVerifiedColorConfigs = caps.fVerifiedColorConfigs;
     fStencilFormats = caps.fStencilFormats;
     fStencilVerifiedColorConfigs = caps.fStencilVerifiedColorConfigs;
@@ -85,6 +90,10 @@
     GrGLBinding binding = ctxInfo.binding();
     GrGLVersion version = ctxInfo.version();
 
+    /**************************************************************************
+     * Caps specific to GrGLCaps
+     **************************************************************************/
+
     if (kES2_GrGLBinding == binding) {
         GR_GL_GetIntegerv(gli, GR_GL_MAX_FRAGMENT_UNIFORM_VECTORS,
                           &fMaxFragmentUniformVectors);
@@ -194,6 +203,89 @@
 
     this->initFSAASupport(ctxInfo, gli);
     this->initStencilFormats(ctxInfo);
+
+    /**************************************************************************
+     * GrDrawTarget::Caps fields
+     **************************************************************************/
+    GrGLint maxTextureUnits;
+    // check FS and fixed-function texture unit limits
+    // we only use textures in the fragment stage currently.
+    // checks are > to make sure we have a spare unit.
+    GR_GL_GetIntegerv(gli, GR_GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextureUnits);
+    GrAssert(maxTextureUnits > GrDrawState::kNumStages);
+
+    GrGLint numFormats;
+    GR_GL_GetIntegerv(gli, GR_GL_NUM_COMPRESSED_TEXTURE_FORMATS, &numFormats);
+    SkAutoSTMalloc<10, GrGLint> formats(numFormats);
+    GR_GL_GetIntegerv(gli, GR_GL_COMPRESSED_TEXTURE_FORMATS, formats);
+    for (int i = 0; i < numFormats; ++i) {
+        if (formats[i] == GR_GL_PALETTE8_RGBA8) {
+            f8BitPaletteSupport = true;
+            break;
+        }
+    }
+
+    if (kDesktop_GrGLBinding == binding) {
+        // we could also look for GL_ATI_separate_stencil extension or
+        // GL_EXT_stencil_two_side but they use different function signatures
+        // than GL2.0+ (and than each other).
+        fTwoSidedStencilSupport = (ctxInfo.version() >= GR_GL_VER(2,0));
+        // supported on GL 1.4 and higher or by extension
+        fStencilWrapOpsSupport = (ctxInfo.version() >= GR_GL_VER(1,4)) ||
+                                  ctxInfo.hasExtension("GL_EXT_stencil_wrap");
+    } else {
+        // ES 2 has two sided stencil and stencil wrap
+        fTwoSidedStencilSupport = true;
+        fStencilWrapOpsSupport = true;
+    }
+
+    if (kDesktop_GrGLBinding == binding) {
+        fBufferLockSupport = true; // we require VBO support and the desktop VBO extension includes
+                                   // glMapBuffer.
+    } else {
+        fBufferLockSupport = ctxInfo.hasExtension("GL_OES_mapbuffer");
+    }
+
+    if (kDesktop_GrGLBinding == binding) {
+        if (ctxInfo.version() >= GR_GL_VER(2,0) ||
+            ctxInfo.hasExtension("GL_ARB_texture_non_power_of_two")) {
+            fNPOTTextureTileSupport = true;
+        } else {
+            fNPOTTextureTileSupport = false;
+        }
+    } else {
+        // Unextended ES2 supports NPOT textures with clamp_to_edge and non-mip filters only
+        fNPOTTextureTileSupport = ctxInfo.hasExtension("GL_OES_texture_npot");
+    }
+
+    fHWAALineSupport = (kDesktop_GrGLBinding == binding);
+
+    GR_GL_GetIntegerv(gli, GR_GL_MAX_TEXTURE_SIZE, &fMaxTextureSize);
+    GR_GL_GetIntegerv(gli, GR_GL_MAX_RENDERBUFFER_SIZE, &fMaxRenderTargetSize);
+    // Our render targets are always created with textures as the color
+    // attachment, hence this min:
+    fMaxRenderTargetSize = GrMin(fMaxTextureSize, fMaxRenderTargetSize);
+
+    fPathStencilingSupport = GR_GL_USE_NV_PATH_RENDERING &&
+                             ctxInfo.hasExtension("GL_NV_path_rendering");
+
+    // Enable supported shader-related caps
+    if (kDesktop_GrGLBinding == binding) {
+        fDualSourceBlendingSupport = ctxInfo.version() >= GR_GL_VER(3,3) ||
+                                     ctxInfo.hasExtension("GL_ARB_blend_func_extended");
+        fShaderDerivativeSupport = true;
+        // we don't support GL_ARB_geometry_shader4, just GL 3.2+ GS
+        fGeometryShaderSupport = ctxInfo.version() >= GR_GL_VER(3,2) &&
+                                 ctxInfo.glslGeneration() >= k150_GrGLSLGeneration;
+    } else {
+        fShaderDerivativeSupport = ctxInfo.hasExtension("GL_OES_standard_derivatives");
+    }
+
+    if (GrGLCaps::kImaginationES_MSFBOType == fMSFBOType) {
+        GR_GL_GetIntegerv(gli, GR_GL_MAX_SAMPLES_IMG, &fMaxSampleCount);
+    } else if (GrGLCaps::kNone_MSFBOType != fMSFBOType) {
+        GR_GL_GetIntegerv(gli, GR_GL_MAX_SAMPLES, &fMaxSampleCount);
+    }
 }
 
 bool GrGLCaps::readPixelsSupported(const GrGLInterface* intf,
@@ -411,6 +503,10 @@
 }
 
 void GrGLCaps::print() const {
+
+    INHERITED::print();
+
+    GrPrintf("--- GL-Specific ---\n");
     for (int i = 0; i < fStencilFormats.count(); ++i) {
         GrPrintf("Stencil Format %d, stencil bits: %02d, total bits: %02d\n",
                  i,
@@ -432,20 +528,25 @@
     };
     GrPrintf("MSAA Type: %s\n", gMSFBOExtStr[fMSFBOType]);
     GrPrintf("Max FS Uniform Vectors: %d\n", fMaxFragmentUniformVectors);
-    GrPrintf("Support RGBA8 Render Buffer: %s\n",
-             (fRGBA8RenderbufferSupport ? "YES": "NO"));
-    GrPrintf("BGRA is an internal format: %s\n",
-             (fBGRAIsInternalFormat ? "YES": "NO"));
-    GrPrintf("Support texture swizzle: %s\n",
-             (fTextureSwizzleSupport ? "YES": "NO"));
-    GrPrintf("Unpack Row length support: %s\n",
-             (fUnpackRowLengthSupport ? "YES": "NO"));
-    GrPrintf("Unpack Flip Y support: %s\n",
-             (fUnpackFlipYSupport ? "YES": "NO"));
-    GrPrintf("Pack Row length support: %s\n",
-             (fPackRowLengthSupport ? "YES": "NO"));
-    GrPrintf("Pack Flip Y support: %s\n",
-             (fPackFlipYSupport ? "YES": "NO"));
+    GrPrintf("Max Vertex Attributes: %d\n", fMaxVertexAttributes);
+    GrPrintf("Support RGBA8 Render Buffer: %s\n", (fRGBA8RenderbufferSupport ? "YES": "NO"));
+    GrPrintf("BGRA support: %s\n", (fBGRAFormatSupport ? "YES": "NO"));
+    GrPrintf("BGRA is an internal format: %s\n", (fBGRAIsInternalFormat ? "YES": "NO"));
+    GrPrintf("Support texture swizzle: %s\n", (fTextureSwizzleSupport ? "YES": "NO"));
+    GrPrintf("Unpack Row length support: %s\n", (fUnpackRowLengthSupport ? "YES": "NO"));
+    GrPrintf("Unpack Flip Y support: %s\n", (fUnpackFlipYSupport ? "YES": "NO"));
+    GrPrintf("Pack Row length support: %s\n", (fPackRowLengthSupport ? "YES": "NO"));
+    GrPrintf("Pack Flip Y support: %s\n", (fPackFlipYSupport ? "YES": "NO"));
+
+    GrPrintf("Texture Usage support: %s\n", (fTextureUsageSupport ? "YES": "NO"));
+    GrPrintf("Texture Storage support: %s\n", (fTexStorageSupport ? "YES": "NO"));
+    GrPrintf("GL_R support: %s\n", (fTextureRedSupport ? "YES": "NO"));
+    GrPrintf("GL_ARB_imaging support: %s\n", (fImagingSupport ? "YES": "NO"));
     GrPrintf("Two Format Limit: %s\n", (fTwoFormatLimit ? "YES": "NO"));
-    GrPrintf("Fragment coord conventions support: %s\n", (fFragCoordsConventionSupport ? "YES": "NO"));
+    GrPrintf("Fragment coord conventions support: %s\n",
+             (fFragCoordsConventionSupport ? "YES": "NO"));
+    GrPrintf("Vertex array object support: %s\n", (fVertexArrayObjectSupport ? "YES": "NO"));
+    GrPrintf("Use non-VBO for dynamic data: %s\n",
+             (fUseNonVBOVertexAndIndexDynamicData ? "YES" : "NO"));
+    GrPrintf("Core Profile: %s\n", (fIsCoreProfile ? "YES" : "NO"));
 }
diff --git a/src/gpu/gl/GrGLCaps.h b/src/gpu/gl/GrGLCaps.h
index 83f4650..d19c989 100644
--- a/src/gpu/gl/GrGLCaps.h
+++ b/src/gpu/gl/GrGLCaps.h
@@ -12,6 +12,7 @@
 #include "SkTArray.h"
 #include "SkTDArray.h"
 #include "GrGLStencilBuffer.h"
+#include "GrDrawTarget.h"
 
 class GrGLContextInfo;
 
@@ -20,8 +21,10 @@
  * version and the extensions string. It also tracks formats that have passed
  * the FBO completeness test.
  */
-class GrGLCaps {
+class GrGLCaps : public GrDrawTarget::Caps {
 public:
+    SK_DECLARE_INST_COUNT(GrGLCaps)
+
     typedef GrGLStencilBuffer::Format StencilFormat;
 
     /**
@@ -93,7 +96,7 @@
     /**
      * Resets the caps such that nothing is supported.
      */
-    void reset();
+    virtual void reset() SK_OVERRIDE;
 
     /**
      * Initializes the GrGLCaps to the set of features supported in the current
@@ -158,7 +161,7 @@
     /**
      * Prints the caps info using GrPrintf.
      */
-    void print() const;
+    virtual void print() const SK_OVERRIDE;
 
     /**
      * Gets an array of legal stencil formats. These formats are not guaranteed
@@ -308,6 +311,8 @@
     bool fVertexArrayObjectSupport : 1;
     bool fUseNonVBOVertexAndIndexDynamicData : 1;
     bool fIsCoreProfile : 1;
+
+    typedef GrDrawTarget::Caps INHERITED;
 };
 
 #endif
diff --git a/src/gpu/gl/GrGLContext.cpp b/src/gpu/gl/GrGLContext.cpp
index 0c3f0eb..d384b4e 100644
--- a/src/gpu/gl/GrGLContext.cpp
+++ b/src/gpu/gl/GrGLContext.cpp
@@ -14,7 +14,7 @@
     fGLSLGeneration = ctxInfo.fGLSLGeneration;
     fVendor = ctxInfo.fVendor;
     fExtensions = ctxInfo.fExtensions;
-    fGLCaps = ctxInfo.fGLCaps;
+    *fGLCaps = *ctxInfo.fGLCaps.get();
     return *this;
 }
 
@@ -36,7 +36,7 @@
             fGLSLGeneration = GrGetGLSLGeneration(fBindingInUse, interface);
 
             fVendor = GrGLGetVendor(interface);
-            fGLCaps.init(*this, interface);
+            fGLCaps->init(*this, interface);
             return true;
         }
     }
@@ -53,7 +53,7 @@
     fGLSLGeneration = static_cast<GrGLSLGeneration>(0);
     fVendor = kOther_GrGLVendor;
     fExtensions.reset();
-    fGLCaps.reset();
+    fGLCaps->reset();
 }
 
 ////////////////////////////////////////////////////////////////////////////////
diff --git a/src/gpu/gl/GrGLContext.h b/src/gpu/gl/GrGLContext.h
index 1091ab9..71b3861 100644
--- a/src/gpu/gl/GrGLContext.h
+++ b/src/gpu/gl/GrGLContext.h
@@ -26,7 +26,10 @@
     /**
      * Default constructor
      */
-    GrGLContextInfo() { this->reset(); }
+    GrGLContextInfo() {
+        fGLCaps.reset(SkNEW(GrGLCaps));
+        this->reset();
+    }
 
     /**
      * Copies a GrGLContextInfo
@@ -44,8 +47,8 @@
     GrGLVersion version() const { return fGLVersion; }
     GrGLSLGeneration glslGeneration() const { return fGLSLGeneration; }
     GrGLVendor vendor() const { return fVendor; }
-    const GrGLCaps& caps() const { return fGLCaps; }
-    GrGLCaps& caps() { return fGLCaps; }
+    const GrGLCaps* caps() const { return fGLCaps.get(); }
+    GrGLCaps* caps() { return fGLCaps; }
 
     /**
      * Checks for extension support using a cached copy of the GL_EXTENSIONS
@@ -65,12 +68,12 @@
 
 private:
 
-    GrGLBinding          fBindingInUse;
-    GrGLVersion          fGLVersion;
-    GrGLSLGeneration     fGLSLGeneration;
-    GrGLVendor           fVendor;
-    GrGLExtensions       fExtensions;
-    GrGLCaps             fGLCaps;
+    GrGLBinding             fBindingInUse;
+    GrGLVersion             fGLVersion;
+    GrGLSLGeneration        fGLSLGeneration;
+    GrGLVendor              fVendor;
+    GrGLExtensions          fExtensions;
+    SkAutoTUnref<GrGLCaps>  fGLCaps;
 };
 
 /**
diff --git a/src/gpu/gl/GrGLProgram.cpp b/src/gpu/gl/GrGLProgram.cpp
index 21729cd..3331468 100644
--- a/src/gpu/gl/GrGLProgram.cpp
+++ b/src/gpu/gl/GrGLProgram.cpp
@@ -149,7 +149,7 @@
     // other than pass through values from the VS to the FS anyway).
 #if GR_GL_EXPERIMENTAL_GS
 #if 0
-    desc->fExperimentalGS = gpu->getCaps().geometryShaderSupport();
+    desc->fExperimentalGS = gpu->caps().geometryShaderSupport();
 #else
     desc->fExperimentalGS = false;
 #endif
@@ -177,7 +177,7 @@
             desc->fFirstCoverageStage = firstCoverageStage;
         }
 
-        if (gpu->getCaps().dualSourceBlendingSupport() &&
+        if (gpu->caps()->dualSourceBlendingSupport() &&
             !(blendOpts & (GrDrawState::kEmitCoverage_BlendOptFlag |
                            GrDrawState::kCoverageAsAlpha_BlendOptFlag))) {
             if (kZero_GrBlendCoeff == dstCoeff) {
diff --git a/src/gpu/gl/GrGLShaderBuilder.cpp b/src/gpu/gl/GrGLShaderBuilder.cpp
index 1179626..3808402 100644
--- a/src/gpu/gl/GrGLShaderBuilder.cpp
+++ b/src/gpu/gl/GrGLShaderBuilder.cpp
@@ -158,7 +158,7 @@
                  sample_function_name(varyingType, fCtxInfo.glslGeneration()),
                  this->getUniformCStr(sampler.fSamplerUniform),
                  coordName);
-    append_swizzle(out, *sampler.textureAccess(), fCtxInfo.caps());
+    append_swizzle(out, *sampler.textureAccess(), *fCtxInfo.caps());
 }
 
 void GrGLShaderBuilder::appendTextureLookup(ShaderType type,
@@ -332,7 +332,7 @@
 
 const char* GrGLShaderBuilder::fragmentPosition() {
 #if 1
-    if (fCtxInfo.caps().fragCoordConventionsSupport()) {
+    if (fCtxInfo.caps()->fragCoordConventionsSupport()) {
         if (!fSetupFragPosition) {
             if (fCtxInfo.glslGeneration() < k150_GrGLSLGeneration) {
                 fFSHeader.append("#extension GL_ARB_fragment_coord_conventions: require\n");
diff --git a/src/gpu/gl/GrGpuGL.cpp b/src/gpu/gl/GrGpuGL.cpp
index e7d3a94..cf4acd5 100644
--- a/src/gpu/gl/GrGpuGL.cpp
+++ b/src/gpu/gl/GrGpuGL.cpp
@@ -153,9 +153,10 @@
 
     GrAssert(ctx.isInitialized());
 
+    fCaps.reset(SkRef(ctx.info().caps()));
+
     fillInConfigRenderableTable();
 
-    fPrintedCaps = false;
 
     GrGLClearErr(fGLContext.interface());
 
@@ -174,10 +175,9 @@
         GrPrintf("------ RENDERER %s\n", renderer);
         GrPrintf("------ VERSION %s\n",  version);
         GrPrintf("------ EXTENSIONS\n %s \n", ext);
+        ctx.info().caps()->print();
     }
 
-    this->initCaps();
-
     fProgramCache = SkNEW_ARGS(ProgramCache, (this->glContext()));
 
     GrAssert(this->glCaps().maxVertexAttributes() >= GrDrawState::kVertexAttribCnt);
@@ -209,92 +209,6 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 
-void GrGpuGL::initCaps() {
-    GrGLint maxTextureUnits;
-    // check FS and fixed-function texture unit limits
-    // we only use textures in the fragment stage currently.
-    // checks are > to make sure we have a spare unit.
-    const GrGLInterface* gl = this->glInterface();
-    GR_GL_GetIntegerv(gl, GR_GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextureUnits);
-    GrAssert(maxTextureUnits > GrDrawState::kNumStages);
-
-    CapsInternals* caps = this->capsInternals();
-
-    GrGLint numFormats;
-    GR_GL_GetIntegerv(gl, GR_GL_NUM_COMPRESSED_TEXTURE_FORMATS, &numFormats);
-    SkAutoSTMalloc<10, GrGLint> formats(numFormats);
-    GR_GL_GetIntegerv(gl, GR_GL_COMPRESSED_TEXTURE_FORMATS, formats);
-    for (int i = 0; i < numFormats; ++i) {
-        if (formats[i] == GR_GL_PALETTE8_RGBA8) {
-            caps->f8BitPaletteSupport = true;
-            break;
-        }
-    }
-
-    if (kDesktop_GrGLBinding == this->glBinding()) {
-        // we could also look for GL_ATI_separate_stencil extension or
-        // GL_EXT_stencil_two_side but they use different function signatures
-        // than GL2.0+ (and than each other).
-        caps->fTwoSidedStencilSupport = (this->glVersion() >= GR_GL_VER(2,0));
-        // supported on GL 1.4 and higher or by extension
-        caps->fStencilWrapOpsSupport = (this->glVersion() >= GR_GL_VER(1,4)) ||
-                                       this->hasExtension("GL_EXT_stencil_wrap");
-    } else {
-        // ES 2 has two sided stencil and stencil wrap
-        caps->fTwoSidedStencilSupport = true;
-        caps->fStencilWrapOpsSupport = true;
-    }
-
-    if (kDesktop_GrGLBinding == this->glBinding()) {
-        caps->fBufferLockSupport = true; // we require VBO support and the desktop VBO
-                                         // extension includes glMapBuffer.
-    } else {
-        caps->fBufferLockSupport = this->hasExtension("GL_OES_mapbuffer");
-    }
-
-    if (kDesktop_GrGLBinding == this->glBinding()) {
-        if (this->glVersion() >= GR_GL_VER(2,0) ||
-            this->hasExtension("GL_ARB_texture_non_power_of_two")) {
-            caps->fNPOTTextureTileSupport = true;
-        } else {
-            caps->fNPOTTextureTileSupport = false;
-        }
-    } else {
-        // Unextended ES2 supports NPOT textures with clamp_to_edge and non-mip filters only
-        caps->fNPOTTextureTileSupport = this->hasExtension("GL_OES_texture_npot");
-    }
-
-    caps->fHWAALineSupport = (kDesktop_GrGLBinding == this->glBinding());
-
-    GR_GL_GetIntegerv(gl, GR_GL_MAX_TEXTURE_SIZE, &caps->fMaxTextureSize);
-    GR_GL_GetIntegerv(gl, GR_GL_MAX_RENDERBUFFER_SIZE, &caps->fMaxRenderTargetSize);
-    // Our render targets are always created with textures as the color
-    // attachment, hence this min:
-    caps->fMaxRenderTargetSize = GrMin(caps->fMaxTextureSize, caps->fMaxRenderTargetSize);
-
-    caps->fFSAASupport = GrGLCaps::kNone_MSFBOType != this->glCaps().msFBOType();
-    caps->fPathStencilingSupport = GR_GL_USE_NV_PATH_RENDERING &&
-                                   this->hasExtension("GL_NV_path_rendering");
-
-    // Enable supported shader-related caps
-    if (kDesktop_GrGLBinding == this->glBinding()) {
-        caps->fDualSourceBlendingSupport = this->glVersion() >= GR_GL_VER(3,3) ||
-                                           this->hasExtension("GL_ARB_blend_func_extended");
-        caps->fShaderDerivativeSupport = true;
-        // we don't support GL_ARB_geometry_shader4, just GL 3.2+ GS
-        caps->fGeometryShaderSupport = this->glVersion() >= GR_GL_VER(3,2) &&
-                                       this->glslGeneration() >= k150_GrGLSLGeneration;
-    } else {
-        caps->fShaderDerivativeSupport = this->hasExtension("GL_OES_standard_derivatives");
-    }
-
-    if (GrGLCaps::kImaginationES_MSFBOType == this->glCaps().msFBOType()) {
-        GR_GL_GetIntegerv(this->glInterface(), GR_GL_MAX_SAMPLES_IMG, &caps->fMaxSampleCount);
-    } else if (GrGLCaps::kNone_MSFBOType != this->glCaps().msFBOType()) {
-        GR_GL_GetIntegerv(this->glInterface(), GR_GL_MAX_SAMPLES, &caps->fMaxSampleCount);
-    }
-}
-
 void GrGpuGL::fillInConfigRenderableTable() {
 
     // OpenGL < 3.0
@@ -399,11 +313,6 @@
 }
 
 void GrGpuGL::onResetContext() {
-    if (gPrintStartupSpew && !fPrintedCaps) {
-        fPrintedCaps = true;
-        this->getCaps().print();
-        this->glCaps().print();
-    }
 
     // we don't use the zb at all
     GL_CALL(Disable(GR_GL_DEPTH_TEST));
@@ -463,7 +372,7 @@
     fHWBoundRenderTarget = NULL;
 
     fHWPathStencilMatrixState.invalidate();
-    if (fCaps.pathStencilingSupport()) {
+    if (this->caps()->pathStencilingSupport()) {
         // we don't use the model view matrix.
         GL_CALL(MatrixMode(GR_GL_MODELVIEW));
         GL_CALL(LoadIdentity());
@@ -511,7 +420,7 @@
         return NULL;
     }
 
-    int maxSize = this->getCaps().maxTextureSize();
+    int maxSize = this->caps()->maxTextureSize();
     if (desc.fWidth > maxSize || desc.fHeight > maxSize) {
         return NULL;
     }
@@ -836,12 +745,12 @@
                                GrGLenum format,
                                int width, int height) {
     CLEAR_ERROR_BEFORE_ALLOC(ctx.interface());
-    GrAssert(GrGLCaps::kNone_MSFBOType != ctx.info().caps().msFBOType());
+    GrAssert(GrGLCaps::kNone_MSFBOType != ctx.info().caps()->msFBOType());
     bool created = false;
     if (GrGLCaps::kNVDesktop_CoverageAAType ==
-        ctx.info().caps().coverageAAType()) {
+        ctx.info().caps()->coverageAAType()) {
         const GrGLCaps::MSAACoverageMode& mode =
-            ctx.info().caps().getMSAACoverageMode(sampleCount);
+            ctx.info().caps()->getMSAACoverageMode(sampleCount);
         GL_ALLOC_CALL(ctx.interface(),
                       RenderbufferStorageMultisampleCoverage(GR_GL_RENDERBUFFER,
                                                         mode.fCoverageSampleCnt,
@@ -924,7 +833,7 @@
             if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
                 goto FAILED;
             }
-            fGLContext.info().caps().markConfigAsValidColorAttachment(desc->fConfig);
+            fGLContext.info().caps()->markConfigAsValidColorAttachment(desc->fConfig);
         }
     }
     GL_CALL(BindFramebuffer(GR_GL_FRAMEBUFFER, desc->fTexFBOID));
@@ -945,7 +854,7 @@
         if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
             goto FAILED;
         }
-        fGLContext.info().caps().markConfigAsValidColorAttachment(desc->fConfig);
+        fGLContext.info().caps()->markConfigAsValidColorAttachment(desc->fConfig);
     }
 
     return true;
@@ -990,7 +899,7 @@
         return return_null_texture();
     }
     // If the sample count exceeds the max then we clamp it.
-    glTexDesc.fSampleCnt = GrMin(desc.fSampleCnt, this->getCaps().maxSampleCount());
+    glTexDesc.fSampleCnt = GrMin(desc.fSampleCnt, this->caps()->maxSampleCount());
 
     glTexDesc.fFlags  = desc.fFlags;
     glTexDesc.fWidth  = desc.fWidth;
@@ -1006,8 +915,6 @@
 
     bool renderTarget = 0 != (desc.fFlags & kRenderTarget_GrTextureFlagBit);
 
-    const Caps& caps = this->getCaps();
-
     glTexDesc.fOrigin = resolve_origin(desc.fOrigin, renderTarget);
     glRTDesc.fOrigin = glTexDesc.fOrigin;
 
@@ -1019,8 +926,8 @@
     }
 
     if (renderTarget) {
-        if (glTexDesc.fWidth > caps.maxRenderTargetSize() ||
-            glTexDesc.fHeight > caps.maxRenderTargetSize()) {
+        int maxRTSize = this->caps()->maxRenderTargetSize();
+        if (glTexDesc.fWidth > maxRTSize || glTexDesc.fHeight > maxRTSize) {
             return return_null_texture();
         }
     }
@@ -1234,7 +1141,7 @@
                 }
                 return false;
             } else {
-                fGLContext.info().caps().markColorConfigAndStencilFormatAsVerified(
+                fGLContext.info().caps()->markColorConfigAndStencilFormatAsVerified(
                     rt->config(),
                     glsb->format());
             }
@@ -1312,7 +1219,7 @@
 }
 
 GrPath* GrGpuGL::onCreatePath(const SkPath& inPath) {
-    GrAssert(fCaps.pathStencilingSupport());
+    GrAssert(this->caps()->pathStencilingSupport());
     return SkNEW_ARGS(GrGLPath, (this, inPath));
 }
 
@@ -1735,7 +1642,7 @@
 }
 
 void GrGpuGL::onGpuStencilPath(const GrPath* path, SkPath::FillType fill) {
-    GrAssert(fCaps.pathStencilingSupport());
+    GrAssert(this->caps()->pathStencilingSupport());
 
     GrGLuint id = static_cast<const GrGLPath*>(path)->pathID();
     GrDrawState* drawState = this->drawState();
@@ -1918,7 +1825,7 @@
             }
         }
         if (!fStencilSettings.isDisabled()) {
-            if (this->getCaps().twoSidedStencilSupport()) {
+            if (this->caps()->twoSidedStencilSupport()) {
                 set_gl_stencil(this->glInterface(),
                                fStencilSettings,
                                GR_GL_FRONT,
@@ -2268,7 +2175,7 @@
             *externalType = GR_GL_UNSIGNED_SHORT_4_4_4_4;
             break;
         case kIndex_8_GrPixelConfig:
-            if (this->getCaps().eightBitPaletteSupport()) {
+            if (this->caps()->eightBitPaletteSupport()) {
                 *internalFormat = GR_GL_PALETTE8_RGBA8;
                 // glCompressedTexImage doesn't take external params
                 *externalFormat = GR_GL_PALETTE8_RGBA8;
diff --git a/src/gpu/gl/GrGpuGL.h b/src/gpu/gl/GrGpuGL.h
index e871f22..423d87f 100644
--- a/src/gpu/gl/GrGpuGL.h
+++ b/src/gpu/gl/GrGpuGL.h
@@ -57,7 +57,7 @@
 
     virtual void abandonResources() SK_OVERRIDE;
 
-    const GrGLCaps& glCaps() const { return fGLContext.info().caps(); }
+    const GrGLCaps& glCaps() const { return *fGLContext.info().caps(); }
 
     // These functions should be used to bind GL objects. They track the GL state and skip redundant
     // bindings. Making the equivalent glBind calls directly will confuse the state tracking.
@@ -218,9 +218,6 @@
     // flushing the scissor after that function is called.
     void flushScissor();
 
-    // Inits GrDrawTarget::Caps, subclass may enable additional caps.
-    void initCaps();
-
     void initFSAASupport();
 
     // determines valid stencil formats
@@ -431,8 +428,6 @@
     // from our loop that tries stencil formats and calls check fb status.
     int fLastSuccessfulStencilFmtIdx;
 
-    bool fPrintedCaps;
-
     typedef GrGpu INHERITED;
 };