Add GrGLContextInfo

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



git-svn-id: http://skia.googlecode.com/svn/trunk@3162 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/gpu/GrGLContextInfo.cpp b/src/gpu/GrGLContextInfo.cpp
new file mode 100644
index 0000000..e6257e7
--- /dev/null
+++ b/src/gpu/GrGLContextInfo.cpp
@@ -0,0 +1,74 @@
+#include "GrGLContextInfo.h"
+
+GrGLContextInfo::~GrGLContextInfo() {
+    GrSafeUnref(fInterface);
+}
+
+GrGLContextInfo::GrGLContextInfo() {
+    this->reset();
+}
+
+GrGLContextInfo::GrGLContextInfo(const GrGLInterface* interface) {
+    fInterface = NULL;
+    this->initialize(interface);
+}
+
+GrGLContextInfo::GrGLContextInfo(const GrGLContextInfo& ctx) {
+    fInterface = NULL;
+    *this = ctx;
+}
+
+GrGLContextInfo& GrGLContextInfo::operator = (const GrGLContextInfo& ctx) {
+    GrSafeAssign(fInterface, ctx.fInterface);
+    fBindingInUse = ctx.fBindingInUse;
+    fGLVersion = ctx.fGLVersion;
+    fGLSLGeneration = ctx.fGLSLGeneration;
+    fExtensionString = ctx.fExtensionString;
+    return *this;
+}
+
+void GrGLContextInfo::reset() {
+    GrSafeSetNull(fInterface);
+    fBindingInUse = kNone_GrGLBinding;
+    fGLVersion = GR_GL_VER(0, 0);
+    fGLSLGeneration = static_cast<GrGLSLGeneration>(0);
+    fExtensionString = "";
+}
+
+bool GrGLContextInfo::initialize(const GrGLInterface* interface) {
+    this->reset();
+    // We haven't validated the GrGLInterface yet, so check for GetString
+    // function pointer
+    if (NULL != interface->fGetString) {
+
+        const GrGLubyte* verUByte;
+        GR_GL_CALL_RET(interface, verUByte, GetString(GR_GL_VERSION));
+        const char* ver = reinterpret_cast<const char*>(verUByte);
+        GrGLBinding binding = GrGLGetBindingInUseFromString(ver);
+
+        if (!interface->validate(fBindingInUse)) {
+
+            fInterface = interface;
+            interface->ref();
+
+            fBindingInUse = binding;
+
+            fGLVersion = GrGLGetVersionFromString(ver);
+
+            fGLSLGeneration = GrGetGLSLGeneration(fBindingInUse,
+                                                  this->interface());
+
+            const GrGLubyte* ext;
+            GR_GL_CALL_RET(interface, ext, GetString(GR_GL_EXTENSIONS));
+            fExtensionString = reinterpret_cast<const char*>(ext);
+
+            return true;
+        }
+    }
+    return false;
+}
+
+bool GrGLContextInfo::isInitialized() const {
+    return kNone_GrGLBinding != fBindingInUse;
+}
+
diff --git a/src/gpu/GrGLContextInfo.h b/src/gpu/GrGLContextInfo.h
new file mode 100644
index 0000000..cac8959
--- /dev/null
+++ b/src/gpu/GrGLContextInfo.h
@@ -0,0 +1,68 @@
+#include "GrGLInterface.h"
+#include "GrGLSL.h"
+
+#include "SkString.h"
+
+/**
+ * Encapsulates information about an OpenGL context including the GrGLInterface
+ * used to make GL calls, the OpenGL version, the GrGLBinding type of the
+ * context, and GLSL version.
+ */
+class GrGLContextInfo {
+public:
+
+    /**
+     * Default constructor, creates an uninitialized GrGLContextInfo
+     */
+    GrGLContextInfo();
+
+    /**
+     * Creates a GrGLContextInfo from a GrGLInterface and the currently
+     * bound OpenGL context accesible by the GrGLInterface.
+     */
+    GrGLContextInfo(const GrGLInterface* interface);
+
+    /**
+     * Copies a GrGLContextInfo
+     */
+    GrGLContextInfo(const GrGLContextInfo& ctx);
+
+    ~GrGLContextInfo();
+
+    /**
+     * Copies a GrGLContextInfo
+     */
+    GrGLContextInfo& operator = (const GrGLContextInfo& ctx);
+
+    /**
+     * Initializes a GrGLContextInfo from a GrGLInterface and the currently
+     * bound OpenGL context accessible by the GrGLInterface.
+     */
+    bool initialize(const GrGLInterface* interface);
+    bool isInitialized() const;
+
+    const GrGLInterface* interface() const { return fInterface; }
+    GrGLBinding binding() const { return fBindingInUse; }
+    GrGLVersion version() const { return fGLVersion; }
+    GrGLSLGeneration glslGeneration() const { return fGLSLGeneration; }
+
+    /**
+     * Checks for extension support using a cached copy of the GL_EXTENSIONS
+     * string.
+     */
+    bool hasExtension(const char* ext) const {
+        if (!this->isInitialized()) {
+            return false;
+        }
+        return GrGLHasExtensionFromString(ext, fExtensionString.c_str());
+    }
+
+private:
+    void reset();
+
+    const GrGLInterface* fInterface;
+    GrGLBinding          fBindingInUse;
+    GrGLVersion          fGLVersion;
+    GrGLSLGeneration     fGLSLGeneration;
+    SkString             fExtensionString;
+};
diff --git a/src/gpu/GrGLInterface.cpp b/src/gpu/GrGLInterface.cpp
index 77ab90a..c1ac088 100644
--- a/src/gpu/GrGLInterface.cpp
+++ b/src/gpu/GrGLInterface.cpp
@@ -19,6 +19,37 @@
 }
 #endif
 
+GrGLBinding GrGLGetBindingInUseFromString(const char* versionString) {
+    if (NULL == versionString) {
+        GrAssert(!"NULL GL version string.");
+        return kNone_GrGLBinding;
+    }
+
+    int major, minor;
+
+    // check for desktop
+    int n = sscanf(versionString, "%d.%d", &major, &minor);
+    if (2 == n) {
+        return kDesktop_GrGLBinding;
+    }
+
+    // check for ES 1
+    char profile[2];
+    n = sscanf(versionString, "OpenGL ES-%c%c %d.%d", profile, profile+1,
+               &major, &minor);
+    if (4 == n) {
+        // we no longer support ES1.
+        return kNone_GrGLBinding;
+    }
+
+    // check for ES2
+    n = sscanf(versionString, "OpenGL ES %d.%d", &major, &minor);
+    if (2 == n) {
+        return kES2_GrGLBinding;
+    }
+    return kNone_GrGLBinding;
+}
+
 GrGLVersion GrGLGetVersionFromString(const char* versionString) {
     if (NULL == versionString) {
         GrAssert(!"NULL GL version string.");
@@ -90,6 +121,12 @@
     return GrGLHasExtensionFromString(ext, (const char*) glstr);
 }
 
+GrGLBinding GrGLGetBindingInUse(const GrGLInterface* gl) {
+    const GrGLubyte* v;
+    GR_GL_CALL_RET(gl, v, GetString(GR_GL_VERSION));
+    return GrGLGetBindingInUseFromString((const char*) v);
+}
+
 GrGLVersion GrGLGetVersion(const GrGLInterface* gl) {
     const GrGLubyte* v;
     GR_GL_CALL_RET(gl, v, GetString(GR_GL_VERSION));
@@ -103,7 +140,7 @@
 }
 
 GrGLInterface::GrGLInterface() {
-    fBindingsExported = (GrGLBinding)0;
+    fBindingsExported = kNone_GrGLBinding;
 
     fActiveTexture = NULL;
     fAttachShader = NULL;
@@ -228,14 +265,13 @@
 #endif
 }
 
-bool GrGLInterface::validate() const {
+bool GrGLInterface::validate(GrGLBinding binding) const {
 
-    bool isDesktop = this->supportsDesktop();
+    // kNone must be 0 so that the check we're about to do can never succeed if
+    // binding == kNone.
+    GR_STATIC_ASSERT(kNone_GrGLBinding == 0);
 
-    bool isES2 = this->supportsES2();
-    
-    if (isDesktop == isES2) {
-        // must have one, don't support both in same interface
+    if (0 == (binding & fBindingsExported)) {
         return false;
     }
 
@@ -341,14 +377,14 @@
     // these functions are part of ES2, we assume they are available
     // On the desktop we assume they are available if the extension
     // is present or GL version is high enough.
-    if ((kES2_GrGLBinding & fBindingsExported)) {
+    if (kES2_GrGLBinding == binding) {
         if (NULL == fBlendColor ||
             NULL == fStencilFuncSeparate ||
             NULL == fStencilMaskSeparate ||
             NULL == fStencilOpSeparate) {
             return false;
         }
-    } else if (kDesktop_GrGLBinding == fBindingsExported) {
+    } else if (kDesktop_GrGLBinding == binding) {
         if (glVer >= GR_GL_VER(2,0)) {
             if (NULL == fStencilFuncSeparate ||
                 NULL == fStencilMaskSeparate ||
@@ -400,7 +436,7 @@
     }
 
     // optional function on desktop before 1.3
-    if (kDesktop_GrGLBinding != fBindingsExported ||
+    if (kDesktop_GrGLBinding != binding ||
         (glVer >= GR_GL_VER(1,3) ||
         GrGLHasExtensionFromString("GL_ARB_texture_compression", ext))) {
         if (NULL == fCompressedTexImage2D) {
@@ -409,7 +445,7 @@
     }
 
     // part of desktop GL, but not ES
-    if (kDesktop_GrGLBinding == fBindingsExported &&
+    if (kDesktop_GrGLBinding == binding &&
         (NULL == fLineWidth ||
          NULL == fGetTexLevelParameteriv ||
          NULL == fDrawBuffer ||
@@ -419,7 +455,7 @@
 
     // GL_EXT_texture_storage is part of desktop 4.2
     // There is a desktop ARB extension and an ES+desktop EXT extension
-    if (kDesktop_GrGLBinding == fBindingsExported) {
+    if (kDesktop_GrGLBinding == binding) {
         if (glVer >= GR_GL_VER(4,2) ||
             GrGLHasExtensionFromString("GL_ARB_texture_storage", ext) ||
             GrGLHasExtensionFromString("GL_EXT_texture_storage", ext)) {
@@ -434,7 +470,7 @@
     }
 
     // FBO MSAA
-    if (kDesktop_GrGLBinding == fBindingsExported) {
+    if (kDesktop_GrGLBinding == binding) {
         // GL 3.0 and the ARB extension have multisample + blit
         if (glVer >= GR_GL_VER(3,0) || GrGLHasExtensionFromString("GL_ARB_framebuffer_object", ext)) {
             if (NULL == fRenderbufferStorageMultisample ||
@@ -469,7 +505,7 @@
     // On ES buffer mapping is an extension. On Desktop
     // buffer mapping was part of original VBO extension
     // which we require.
-    if (kDesktop_GrGLBinding == fBindingsExported  || 
+    if (kDesktop_GrGLBinding == binding || 
         GrGLHasExtensionFromString("GL_OES_mapbuffer", ext)) {
         if (NULL == fMapBuffer ||
             NULL == fUnmapBuffer) {
@@ -478,7 +514,7 @@
     }
 
     // Dual source blending
-    if (kDesktop_GrGLBinding == fBindingsExported  &&
+    if (kDesktop_GrGLBinding == binding &&
         (glVer >= GR_GL_VER(3,3) || 
          GrGLHasExtensionFromString("GL_ARB_blend_func_extended", ext))) {
         if (NULL == fBindFragDataLocationIndexed) {
diff --git a/src/gpu/GrGpuFactory.cpp b/src/gpu/GrGpuFactory.cpp
index c954c7a..7d53e79 100644
--- a/src/gpu/GrGpuFactory.cpp
+++ b/src/gpu/GrGpuFactory.cpp
@@ -39,15 +39,10 @@
 #endif
             return NULL;
         }
-        if (!glInterface->validate()) {
-#if GR_DEBUG
-            GrPrintf("Failed GL interface validation!\n");
-#endif
-            return NULL;
+        GrGLContextInfo ctxInfo(glInterface);
+        if (ctxInfo.isInitialized()) {
+            return new GrGpuGLShaders(ctxInfo);
         }
-
-        return new GrGpuGLShaders(glInterface);
-    } else {
-        return NULL;
     }
+    return NULL;
 }
diff --git a/src/gpu/GrGpuGL.cpp b/src/gpu/GrGpuGL.cpp
index eb1de8a..6ce6089 100644
--- a/src/gpu/GrGpuGL.cpp
+++ b/src/gpu/GrGpuGL.cpp
@@ -246,29 +246,17 @@
     return status == GR_GL_FRAMEBUFFER_COMPLETE;
 }
 
-GrGpuGL::GrGpuGL(const GrGLInterface* gl, GrGLBinding glBinding) {
+GrGpuGL::GrGpuGL(const GrGLContextInfo& ctxInfo) : fGLContextInfo(ctxInfo) {
+
+    GrAssert(ctxInfo.isInitialized());
 
     fPrintedCaps = false;
 
-    gl->ref();
-    fGL = gl;
-    fGLBinding = glBinding;
-    switch (glBinding) {
-        case kDesktop_GrGLBinding:
-            GrAssert(gl->supportsDesktop());
-            break;
-        case kES2_GrGLBinding:
-            GrAssert(gl->supportsES2());
-            break;
-        default:
-            GrCrash("Expect exactly one valid GL binding bit to be in use.");
-    }
+    GrGLClearErr(fGLContextInfo.interface());
 
-    GrGLClearErr(fGL);
-
-    const GrGLubyte* ext;
-    GL_CALL_RET(ext, GetString(GR_GL_EXTENSIONS));
     if (gPrintStartupSpew) {
+        const GrGLubyte* ext;
+        GL_CALL_RET(ext, GetString(GR_GL_EXTENSIONS));
         const GrGLubyte* vendor;
         const GrGLubyte* renderer;
         const GrGLubyte* version;
@@ -283,10 +271,6 @@
         GrPrintf("------ EXTENSIONS\n %s \n", ext);
     }
 
-    fGLVersion = GrGLGetVersion(gl);
-    GrAssert(0 != fGLVersion);
-    fExtensionString = (const char*) ext;
-
     this->resetDirtyFlags();
 
     this->initCaps();
@@ -300,7 +284,6 @@
     // This subclass must do this before the base class destructor runs
     // since we will unref the GrGLInterface.
     this->releaseResources();
-    fGL->unref();
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -312,27 +295,28 @@
     // 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(fGL, GR_GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextureUnits);
+    const GrGLInterface* gl = this->glInterface();
+    GR_GL_GetIntegerv(gl, GR_GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextureUnits);
     GrAssert(maxTextureUnits > GrDrawState::kNumStages);
     if (kES2_GrGLBinding != this->glBinding()) {
-        GR_GL_GetIntegerv(fGL, GR_GL_MAX_TEXTURE_UNITS, &maxTextureUnits);
+        GR_GL_GetIntegerv(gl, GR_GL_MAX_TEXTURE_UNITS, &maxTextureUnits);
         GrAssert(maxTextureUnits > GrDrawState::kNumStages);
     }
     if (kES2_GrGLBinding == this->glBinding()) {
-        GR_GL_GetIntegerv(fGL, GR_GL_MAX_FRAGMENT_UNIFORM_VECTORS,
+        GR_GL_GetIntegerv(gl, GR_GL_MAX_FRAGMENT_UNIFORM_VECTORS,
                           &fGLCaps.fMaxFragmentUniformVectors);
     } else if (kDesktop_GrGLBinding != this->glBinding()) {
         GrGLint max;
-        GR_GL_GetIntegerv(fGL, GR_GL_MAX_FRAGMENT_UNIFORM_COMPONENTS, &max);
+        GR_GL_GetIntegerv(gl, GR_GL_MAX_FRAGMENT_UNIFORM_COMPONENTS, &max);
         fGLCaps.fMaxFragmentUniformVectors = max / 4;
     } else {
         fGLCaps.fMaxFragmentUniformVectors = 16;
     }
 
     GrGLint numFormats;
-    GR_GL_GetIntegerv(fGL, GR_GL_NUM_COMPRESSED_TEXTURE_FORMATS, &numFormats);
+    GR_GL_GetIntegerv(gl, GR_GL_NUM_COMPRESSED_TEXTURE_FORMATS, &numFormats);
     SkAutoSTMalloc<10, GrGLint> formats(numFormats);
-    GR_GL_GetIntegerv(fGL, GR_GL_COMPRESSED_TEXTURE_FORMATS, formats);
+    GR_GL_GetIntegerv(gl, GR_GL_COMPRESSED_TEXTURE_FORMATS, formats);
     for (int i = 0; i < numFormats; ++i) {
         if (formats[i] == GR_GL_PALETTE8_RGBA8) {
             fCaps.f8BitPaletteSupport = true;
@@ -344,9 +328,9 @@
         // 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).
-        fCaps.fTwoSidedStencilSupport = (fGLVersion >= GR_GL_VER(2,0));
+        fCaps.fTwoSidedStencilSupport = (this->glVersion() >= GR_GL_VER(2,0));
         // supported on GL 1.4 and higher or by extension
-        fCaps.fStencilWrapOpsSupport = (fGLVersion >= GR_GL_VER(1,4)) ||
+        fCaps.fStencilWrapOpsSupport = (this->glVersion() >= GR_GL_VER(1,4)) ||
                                        this->hasExtension("GL_EXT_stencil_wrap");
     } else {
         // ES 2 has two sided stencil and stencil wrap
@@ -407,7 +391,7 @@
     }
 
     if (kDesktop_GrGLBinding == this->glBinding()) {
-        if (fGLVersion >= GR_GL_VER(2,0) || 
+        if (this->glVersion() >= GR_GL_VER(2,0) || 
             this->hasExtension("GL_ARB_texture_non_power_of_two")) {
             fCaps.fNPOTTextureTileSupport = true;
         } else {
@@ -423,7 +407,7 @@
 
     // Tex storage is in desktop 4.2 and can be an extension to desktop or ES.
     fGLCaps.fTexStorageSupport = (kDesktop_GrGLBinding == this->glBinding() &&
-                                  fGLVersion >= GR_GL_VER(4,2)) ||
+                                  this->glVersion() >= GR_GL_VER(4,2)) ||
                                  this->hasExtension("GL_ARB_texture_storage") ||
                                  this->hasExtension("GL_EXT_texture_storage");
 
@@ -434,8 +418,8 @@
     // TODO: Make these a preprocess that generate some compile time constants.
     // TODO: probe once at startup, rather than once per context creation.
 
-    GR_GL_GetIntegerv(fGL, GR_GL_MAX_TEXTURE_SIZE, &fCaps.fMaxTextureSize);
-    GR_GL_GetIntegerv(fGL, GR_GL_MAX_RENDERBUFFER_SIZE, &fCaps.fMaxRenderTargetSize);
+    GR_GL_GetIntegerv(gl, GR_GL_MAX_TEXTURE_SIZE, &fCaps.fMaxTextureSize);
+    GR_GL_GetIntegerv(gl, GR_GL_MAX_RENDERBUFFER_SIZE, &fCaps.fMaxRenderTargetSize);
     // Our render targets are always created with textures as the color
     // attachment, hence this min:
     fCaps.fMaxRenderTargetSize = GrMin(fCaps.fMaxTextureSize, fCaps.fMaxRenderTargetSize);
@@ -456,7 +440,7 @@
             fGLCaps.fMSFBOType = GLCaps::kAppleES_MSFBO;
         }
     } else {
-        if ((fGLVersion >= GR_GL_VER(3,0)) || this->hasExtension("GL_ARB_framebuffer_object")) {
+        if ((this->glVersion() >= GR_GL_VER(3,0)) || this->hasExtension("GL_ARB_framebuffer_object")) {
             fGLCaps.fMSFBOType = GLCaps::kDesktopARB_MSFBO;
         } else if (this->hasExtension("GL_EXT_framebuffer_multisample") &&
                    this->hasExtension("GL_EXT_framebuffer_blit")) {
@@ -486,7 +470,7 @@
         gDS    = {{GR_GL_DEPTH_STENCIL,    kUnknownBitCount, kUnknownBitCount, true }, {0U}};
 
     if (kDesktop_GrGLBinding == this->glBinding()) {
-        bool supportsPackedDS = fGLVersion >= GR_GL_VER(3,0) || 
+        bool supportsPackedDS = this->glVersion() >= GR_GL_VER(3,0) || 
                                 this->hasExtension("GL_EXT_packed_depth_stencil") ||
                                 this->hasExtension("GL_ARB_framebuffer_object");
 
diff --git a/src/gpu/GrGpuGL.h b/src/gpu/GrGpuGL.h
index e111432..801f915 100644
--- a/src/gpu/GrGpuGL.h
+++ b/src/gpu/GrGpuGL.h
@@ -13,21 +13,25 @@
 
 #include "GrDrawState.h"
 #include "GrGpu.h"
+#include "GrGLContextInfo.h"
 #include "GrGLIndexBuffer.h"
 #include "GrGLIRect.h"
 #include "GrGLStencilBuffer.h"
 #include "GrGLTexture.h"
 #include "GrGLVertexBuffer.h"
 
-#include "SkString.h"
-
 class GrGpuGL : public GrGpu {
 public:
     virtual ~GrGpuGL();
 
-    const GrGLInterface* glInterface() const { return fGL; }
-    GrGLBinding glBinding() const { return fGLBinding; }
-    GrGLVersion glVersion() const { return fGLVersion; }
+    const GrGLInterface* glInterface() const { 
+        return fGLContextInfo.interface();
+    }
+    const GrGLBinding glBinding() const { return fGLContextInfo.binding(); }
+    const GrGLVersion glVersion() const { return fGLContextInfo.version(); }
+    const GrGLSLGeneration glslGeneration() const {
+        return fGLContextInfo.glslGeneration();
+    }
 
     // GrGpu overrides
     virtual GrPixelConfig preferredReadPixelsConfig(GrPixelConfig config)
@@ -43,7 +47,7 @@
     virtual bool fullReadPixelsIsFasterThanPartial() const SK_OVERRIDE;
 
 protected:
-    GrGpuGL(const GrGLInterface* glInterface, GrGLBinding glBinding);
+    GrGpuGL(const GrGLContextInfo& ctxInfo);
 
     struct GLCaps {
         GLCaps()
@@ -270,9 +274,9 @@
                     GrBlendCoeff srcCoeff,
                     GrBlendCoeff dstCoeff);
 
-    bool hasExtension(const char* ext) {
-        return GrGLHasExtensionFromString(ext, fExtensionString.c_str());
-    }
+    bool hasExtension(const char* ext) const {
+        return fGLContextInfo.hasExtension(ext);
+}
 
     // adjusts texture matrix to account for orientation
     static void AdjustTextureMatrix(const GrGLTexture* texture,
@@ -336,9 +340,7 @@
     friend class GrGLTexture;
     friend class GrGLRenderTarget;
 
-    // read these once at begining and then never again
-    SkString fExtensionString;
-    GrGLVersion fGLVersion;
+    GrGLContextInfo fGLContextInfo;
 
     // we want to clear stencil buffers when they are created. We want to clear
     // the entire buffer even if it is larger than the color attachment. We
@@ -353,8 +355,6 @@
     // from our loop that tries stencil formats and calls check fb status.
     int fLastSuccessfulStencilFmtIdx;
 
-    const GrGLInterface* fGL;
-    GrGLBinding fGLBinding;
 
     bool fPrintedCaps;
 
diff --git a/src/gpu/GrGpuGLShaders.cpp b/src/gpu/GrGpuGLShaders.cpp
index d03c9f2..81706d7 100644
--- a/src/gpu/GrGpuGLShaders.cpp
+++ b/src/gpu/GrGpuGLShaders.cpp
@@ -291,22 +291,8 @@
     return true;
 }
 
-namespace {
-GrGLBinding get_binding_in_use(const GrGLInterface* gl) {
-    if (gl->supportsDesktop()) {
-        return kDesktop_GrGLBinding;
-    } else {
-        GrAssert(gl->supportsES2());
-        return kES2_GrGLBinding;
-    }
-}
-}
-
-GrGpuGLShaders::GrGpuGLShaders(const GrGLInterface* gl)
-    : GrGpuGL(gl, get_binding_in_use(gl)) {
-
-    GrGLSLGeneration glslGeneration =
-        GrGetGLSLGeneration(this->glBinding(), gl);
+GrGpuGLShaders::GrGpuGLShaders(const GrGLContextInfo& ctxInfo)
+    : GrGpuGL(ctxInfo) {
 
     // Enable supported shader-related caps
     if (kDesktop_GrGLBinding == this->glBinding()) {
@@ -317,16 +303,19 @@
         // we don't support GL_ARB_geometry_shader4, just GL 3.2+ GS
         fCaps.fGeometryShaderSupport = 
                                 this->glVersion() >= GR_GL_VER(3,2) &&
-                                glslGeneration >= k150_GrGLSLGeneration;
+                                this->glslGeneration() >= k150_GrGLSLGeneration;
     } else {
         fCaps.fShaderDerivativeSupport =
                             this->hasExtension("GL_OES_standard_derivatives");
     }
 
-    GR_GL_GetIntegerv(gl, GR_GL_MAX_VERTEX_ATTRIBS, &fMaxVertexAttribs);
+    GR_GL_GetIntegerv(this->glInterface(),
+                      GR_GL_MAX_VERTEX_ATTRIBS,
+                      &fMaxVertexAttribs);
 
     fProgramData = NULL;
-    fProgramCache = new ProgramCache(gl, glslGeneration);
+    fProgramCache = new ProgramCache(this->glInterface(),
+                                     this->glslGeneration());
 
 #if 0
     this->programUnitTest();
diff --git a/src/gpu/GrGpuGLShaders.h b/src/gpu/GrGpuGLShaders.h
index d875fe9..39bc974 100644
--- a/src/gpu/GrGpuGLShaders.h
+++ b/src/gpu/GrGpuGLShaders.h
@@ -19,7 +19,7 @@
 // Programmable OpenGL or OpenGL ES 2.0
 class GrGpuGLShaders : public GrGpuGL {
 public:
-             GrGpuGLShaders(const GrGLInterface* glInterface);
+             GrGpuGLShaders(const GrGLContextInfo& ctxInfo);
     virtual ~GrGpuGLShaders();
 
     virtual void abandonResources();
diff --git a/src/gpu/SkGLContext.cpp b/src/gpu/SkGLContext.cpp
index 7ac2ede..6142d3c 100644
--- a/src/gpu/SkGLContext.cpp
+++ b/src/gpu/SkGLContext.cpp
@@ -45,11 +45,13 @@
         GrGLuint cbID;
         GrGLuint dsID;
 
+        GrGLBinding bindingInUse = GrGLGetBindingInUse(this->gl());
+
         SK_GL(*this, GenFramebuffers(1, &fFBO));
         SK_GL(*this, BindFramebuffer(GR_GL_FRAMEBUFFER, fFBO));
         SK_GL(*this, GenRenderbuffers(1, &cbID));
         SK_GL(*this, BindRenderbuffer(GR_GL_RENDERBUFFER, cbID));
-        if (fGL->supportsES2()) {
+        if (kES2_GrGLBinding == bindingInUse) {
             SK_GL(*this, RenderbufferStorage(GR_GL_RENDERBUFFER,
                                              GR_GL_RGBA8,
                                              width, height));
@@ -69,7 +71,7 @@
         // in binding a packed format an FBO. However, we can't rely on packed
         // depth stencil being available.
         bool supportsPackedDepthStencil;
-        if (fGL->supportsES2()) {
+        if (kES2_GrGLBinding == bindingInUse) {
             supportsPackedDepthStencil = 
                     this->hasExtension("GL_OES_packed_depth_stencil");
         } else {
@@ -81,7 +83,7 @@
         if (supportsPackedDepthStencil) {
             // ES2 requires sized internal formats for RenderbufferStorage
             // On Desktop we let the driver decide.
-            GrGLenum format = fGL->supportsES2() ? 
+            GrGLenum format = kES2_GrGLBinding == bindingInUse ? 
                                     GR_GL_DEPTH24_STENCIL8 :
                                     GR_GL_DEPTH_STENCIL;
             SK_GL(*this, RenderbufferStorage(GR_GL_RENDERBUFFER,
@@ -92,7 +94,7 @@
                                                  GR_GL_RENDERBUFFER,
                                                  dsID));
         } else {
-            GrGLenum format = fGL->supportsES2() ? 
+            GrGLenum format = kES2_GrGLBinding == bindingInUse ? 
                                     GR_GL_STENCIL_INDEX8 :
                                     GR_GL_STENCIL_INDEX;
             SK_GL(*this, RenderbufferStorage(GR_GL_RENDERBUFFER,