Implementation of a GL-virtualization layer for Skia.  This allows for
environments using skia to specify a GL implementation at run-time, instead of
relying on the linker to pull in the appropriate GL impl.

A new structure, GrGLInterface is exposed.  This struct contains a set of
function pointers that should point to an appropriate GL implementation.

This change also removes the reliance on GLew on windows builds.

Review: http://codereview.appspot.com/4254059/



git-svn-id: http://skia.googlecode.com/svn/trunk@937 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/gpu/src/GrGLIndexBuffer.cpp b/gpu/src/GrGLIndexBuffer.cpp
index 2dc4154..9539c8a 100644
--- a/gpu/src/GrGLIndexBuffer.cpp
+++ b/gpu/src/GrGLIndexBuffer.cpp
@@ -1,5 +1,5 @@
 /*
-    Copyright 2010 Google Inc.
+    Copyright 2011 Google Inc.
 
     Licensed under the Apache License, Version 2.0 (the "License");
     you may not use this file except in compliance with the License.
@@ -57,8 +57,7 @@
         // Let driver know it can discard the old data
         GR_GL(BufferData(GL_ELEMENT_ARRAY_BUFFER, size(), NULL,
                          dynamic() ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW));
-        fLockPtr = GR_GLEXT(fGL->extensions(),
-                            MapBuffer(GL_ELEMENT_ARRAY_BUFFER, GR_WRITE_ONLY));
+        fLockPtr = GR_GL(MapBuffer(GL_ELEMENT_ARRAY_BUFFER, GR_WRITE_ONLY));
 
         return fLockPtr;
     }
@@ -75,7 +74,7 @@
     GrAssert(fGL->supportsBufferLocking());
 
     bind();
-    GR_GLEXT(fGL->extensions(), UnmapBuffer(GL_ELEMENT_ARRAY_BUFFER));
+    GR_GL(UnmapBuffer(GL_ELEMENT_ARRAY_BUFFER));
     fLockPtr = NULL;
 }
 
diff --git a/gpu/src/GrGLInterface.cpp b/gpu/src/GrGLInterface.cpp
new file mode 100644
index 0000000..e74d29d
--- /dev/null
+++ b/gpu/src/GrGLInterface.cpp
@@ -0,0 +1,350 @@
+/*
+    Copyright 2011 Google Inc.
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ */
+
+
+#include "GrGLInterface.h"
+#include "GrTypes.h"
+
+#include <stdio.h>
+
+#if defined(GR_GL_PROC_ADDRESS_HEADER)
+    #include GR_GL_PROC_ADDRESS_HEADER
+#endif
+
+#if !defined(GR_GL_PROC_ADDRESS)
+    #error "Must define GR_GL_PROC_ADDRESS"
+#endif
+
+#define GR_GL_GET_PROC(PROC_NAME) \
+    glBindings->f##PROC_NAME = \
+                reinterpret_cast<GrGLInterface::GrGL##PROC_NAME##Proc>( \
+                            GR_GL_PROC_ADDRESS(gl##PROC_NAME)); \
+    GrAssert(NULL != glBindings->f##PROC_NAME && \
+             "Missing GL binding: " #PROC_NAME);
+
+#define GR_GL_GET_PROC_SUFFIX(PROC_NAME, SUFFIX) \
+    glBindings->f##PROC_NAME = \
+                reinterpret_cast<GrGLInterface::GrGL##PROC_NAME##Proc>( \
+                        GR_GL_PROC_ADDRESS(gl##PROC_NAME##SUFFIX)); \
+    GrAssert(NULL != glBindings->f##PROC_NAME && \
+             "Missing GL binding: " #PROC_NAME);
+
+#define GR_GL_GET_PROC_SYMBOL(PROC_NAME) \
+    glBindings->f##PROC_NAME = reinterpret_cast<GrGLInterface::GrGL##PROC_NAME##Proc>(gl##PROC_NAME);
+
+namespace {
+
+void gl_version_from_string(int* major, int* minor,
+                            const char* versionString) {
+    if (NULL == versionString) {
+        GrAssert(0);
+        *major = 0;
+        *minor = 0;
+        return;
+    }
+#if GR_SUPPORT_GLDESKTOP
+    int n = sscanf(versionString, "%d.%d", major, minor);
+    if (n != 2) {
+        GrAssert(0);
+        *major = 0;
+        *minor = 0;
+        return;
+    }
+#else
+    char profile[2];
+    int n = sscanf(versionString, "OpenGL ES-%c%c %d.%d", profile, profile+1,
+                   major, minor);
+    bool ok = 4 == n;
+    if (!ok) {
+        int n = sscanf(versionString, "OpenGL ES %d.%d", major, minor);
+        ok = 2 == n;
+    }
+    if (!ok) {
+        GrAssert(0);
+        *major = 0;
+        *minor = 0;
+        return;
+    }
+#endif
+}
+
+bool has_gl_extension_from_string(const char* ext,
+                                  const char* extensionString) {
+    int extLength = strlen(ext);
+
+    while (true) {
+        int n = strcspn(extensionString, " ");
+        if (n == extLength && 0 == strncmp(ext, extensionString, n)) {
+            return true;
+        }
+        if (0 == extensionString[n]) {
+            return false;
+        }
+        extensionString += n+1;
+    }
+
+    return false;
+}
+
+GrGLInterface* gGLInterface = NULL;
+
+void InitializeGLInterfaceExtensions(GrGLInterface* glBindings) {
+    int major, minor;
+    const char* versionString = reinterpret_cast<const char*>(
+                glBindings->fGetString(GL_VERSION));
+    const char* extensionString = reinterpret_cast<const char*>(
+                glBindings->fGetString(GL_EXTENSIONS));
+    gl_version_from_string(&major, &minor, versionString);
+
+    bool fboFound = false;
+#if GR_SUPPORT_GLDESKTOP
+    if (major >= 3 || has_gl_extension_from_string("GL_ARB_framebuffer_object",
+                                                   extensionString)) {
+        // GL_ARB_framebuffer_object doesn't use ARB suffix.
+        GR_GL_GET_PROC(GenFramebuffers);
+        GR_GL_GET_PROC(BindFramebuffer);
+        GR_GL_GET_PROC(FramebufferTexture2D);
+        GR_GL_GET_PROC(CheckFramebufferStatus);
+        GR_GL_GET_PROC(DeleteFramebuffers);
+        GR_GL_GET_PROC(RenderbufferStorage);
+        GR_GL_GET_PROC(GenRenderbuffers);
+        GR_GL_GET_PROC(DeleteRenderbuffers);
+        GR_GL_GET_PROC(FramebufferRenderbuffer);
+        GR_GL_GET_PROC(BindRenderbuffer);
+        GR_GL_GET_PROC(RenderbufferStorageMultisample);
+        GR_GL_GET_PROC(BlitFramebuffer);
+        fboFound = true;
+    }
+
+    #if GL_EXT_framebuffer_object && !GR_MAC_BUILD
+    if (!fboFound &&
+            has_gl_extension_from_string("GL_EXT_framebuffer_object",
+                                         extensionString)) {
+        GR_GL_GET_PROC_SUFFIX(GenFramebuffers, EXT);
+        GR_GL_GET_PROC_SUFFIX(BindFramebuffer, EXT);
+        GR_GL_GET_PROC_SUFFIX(FramebufferTexture2D, EXT);
+        GR_GL_GET_PROC_SUFFIX(CheckFramebufferStatus, EXT);
+        GR_GL_GET_PROC_SUFFIX(DeleteFramebuffers, EXT);
+        GR_GL_GET_PROC_SUFFIX(RenderbufferStorage, EXT);
+        GR_GL_GET_PROC_SUFFIX(GenRenderbuffers, EXT);
+        GR_GL_GET_PROC_SUFFIX(DeleteRenderbuffers, EXT);
+        GR_GL_GET_PROC_SUFFIX(FramebufferRenderbuffer, EXT);
+        GR_GL_GET_PROC_SUFFIX(BindRenderbuffer, EXT);
+        fboFound = true;
+
+        if (has_gl_extension_from_string("GL_EXT_framebuffer_multisample",
+                                         extensionString)) {
+            GR_GL_GET_PROC_SUFFIX(RenderbufferStorageMultisample, EXT);
+        }
+        if (has_gl_extension_from_string("GL_EXT_framebuffer_blit",
+                                         extensionString)) {
+            GR_GL_GET_PROC_SUFFIX(BlitFramebuffer, EXT);
+        }
+    }
+    #endif
+
+    // we assume we have at least GL 1.5 or higher (VBOs introduced in 1.5)
+    GrAssert((major == 1 && minor >= 5) || major >=2);
+    GR_GL_GET_PROC(MapBuffer);
+    GR_GL_GET_PROC(UnmapBuffer);
+#else // !GR_SUPPORT_GLDESKTOP
+    #if GR_SUPPORT_GLES2
+    if (!fboFound && major >= 2) {// ES 2.0 supports FBO
+        GR_GL_GET_PROC(GenFramebuffers);
+        GR_GL_GET_PROC(BindFramebuffer);
+        GR_GL_GET_PROC(FramebufferTexture2D);
+        GR_GL_GET_PROC(CheckFramebufferStatus);
+        GR_GL_GET_PROC(DeleteFramebuffers);
+        GR_GL_GET_PROC(RenderbufferStorage);
+        GR_GL_GET_PROC(GenRenderbuffers);
+        GR_GL_GET_PROC(DeleteRenderbuffers);
+        GR_GL_GET_PROC(FramebufferRenderbuffer);
+        GR_GL_GET_PROC(BindRenderbuffer);
+        fboFound = true;
+    }
+    #endif
+
+    #if GL_OES_mapbuffer
+    if (!fboFound &&
+            has_gl_extension_from_string("GL_OES_framebuffer_object",
+                                         extensionString)) {
+        GR_GL_GET_PROC_SUFFIX(GenFramebuffers, OES);
+        GR_GL_GET_PROC_SUFFIX(BindFramebuffer, OES);
+        GR_GL_GET_PROC_SUFFIX(FramebufferTexture2D, OES);
+        GR_GL_GET_PROC_SUFFIX(CheckFramebufferStatus, OES);
+        GR_GL_GET_PROC_SUFFIX(DeleteFramebuffers, OES);
+        GR_GL_GET_PROC_SUFFIX(RenderbufferStorage, OES);
+        GR_GL_GET_PROC_SUFFIX(GenRenderbuffers, OES);
+        GR_GL_GET_PROC_SUFFIX(DeleteRenderbuffers, OES);
+        GR_GL_GET_PROC_SUFFIX(FramebufferRenderbuffer, OES);
+        GR_GL_GET_PROC_SUFFIX(BindRenderbuffer, OES);
+        fboFound = true;
+    }
+    #endif
+
+    #if GL_APPLE_framebuffer_multisample
+    if (has_gl_extension_from_string("GL_APPLE_framebuffer_multisample",
+                                     extensionString)) {
+        GR_GL_GET_PROC_SUFFIX(ResolveMultisampleFramebuffer, APPLE);
+    }
+    #endif
+
+    #if GL_IMG_multisampled_render_to_texture
+    if (has_gl_extension_from_string(
+                "GL_IMG_multisampled_render_to_texture", extensionString)) {
+        GR_GL_GET_PROC_SUFFIX(FramebufferTexture2DMultisample, IMG);
+    }
+    #endif
+
+    #if GL_OES_mapbuffer
+    if (has_gl_extension_from_string("GL_OES_mapbuffer", extensionString)) {
+        GR_GL_GET_PROC_SUFFIX(MapBuffer, OES);
+        GR_GL_GET_PROC_SUFFIX(UnmapBuffer, OES);
+    }
+    #endif
+#endif  // !GR_SUPPORT_GLDESKTOP
+
+    if (!fboFound) {
+        // we require some form of FBO
+        GrAssert(!"No FBOs supported?");
+    }
+}
+
+void GrGLInitializeGLInterface(GrGLInterface* glBindings) {
+    Gr_bzero(glBindings, sizeof(GrGLInterface));
+
+#if GR_SUPPORT_GLDESKTOP
+    // These entry points only exist on desktop GL implementations.
+    GR_GL_GET_PROC_SYMBOL(Color4ub);
+    GR_GL_GET_PROC_SYMBOL(ColorPointer);
+    GR_GL_GET_PROC_SYMBOL(DisableClientState);
+    GR_GL_GET_PROC_SYMBOL(EnableClientState);
+    GR_GL_GET_PROC_SYMBOL(LoadMatrixf);
+    GR_GL_GET_PROC_SYMBOL(MatrixMode);
+    GR_GL_GET_PROC_SYMBOL(PointSize);
+    GR_GL_GET_PROC_SYMBOL(ShadeModel);
+    GR_GL_GET_PROC_SYMBOL(TexCoordPointer);
+    GR_GL_GET_PROC_SYMBOL(TexEnvi);
+    GR_GL_GET_PROC_SYMBOL(VertexPointer);
+    GR_GL_GET_PROC(ClientActiveTexture);
+#endif
+
+    // The following gl entry points are part of GL 1.1, and will always be
+    // exported as symbols.
+    // Note that on windows, the wglGetProcAddress call will fail to retrieve
+    // these entry points.
+    GR_GL_GET_PROC_SYMBOL(BlendFunc);
+    GR_GL_GET_PROC_SYMBOL(Clear);
+    GR_GL_GET_PROC_SYMBOL(ClearColor);
+    GR_GL_GET_PROC_SYMBOL(ClearStencil);
+    GR_GL_GET_PROC_SYMBOL(ColorMask);
+    GR_GL_GET_PROC_SYMBOL(CullFace);
+    GR_GL_GET_PROC_SYMBOL(DeleteTextures);
+    GR_GL_GET_PROC_SYMBOL(DepthMask);
+    GR_GL_GET_PROC_SYMBOL(Disable);
+    GR_GL_GET_PROC_SYMBOL(DrawArrays);
+    GR_GL_GET_PROC_SYMBOL(DrawElements);
+    GR_GL_GET_PROC_SYMBOL(Enable);
+    GR_GL_GET_PROC_SYMBOL(FrontFace);
+    GR_GL_GET_PROC_SYMBOL(GenTextures);
+    GR_GL_GET_PROC_SYMBOL(GetError);
+    GR_GL_GET_PROC_SYMBOL(GetIntegerv);
+    GR_GL_GET_PROC_SYMBOL(GetString);
+    GR_GL_GET_PROC_SYMBOL(LineWidth);
+    GR_GL_GET_PROC_SYMBOL(PixelStorei);
+    GR_GL_GET_PROC_SYMBOL(ReadPixels);
+    GR_GL_GET_PROC_SYMBOL(Scissor);
+    GR_GL_GET_PROC_SYMBOL(StencilFunc);
+    GR_GL_GET_PROC_SYMBOL(StencilMask);
+    GR_GL_GET_PROC_SYMBOL(StencilOp);
+    GR_GL_GET_PROC_SYMBOL(TexImage2D);
+    GR_GL_GET_PROC_SYMBOL(TexParameteri);
+    GR_GL_GET_PROC_SYMBOL(TexSubImage2D);
+    GR_GL_GET_PROC_SYMBOL(Viewport);
+
+    // Capture the remaining entry points as gl extensions.
+    GR_GL_GET_PROC(ActiveTexture);
+    GR_GL_GET_PROC(AttachShader);
+    GR_GL_GET_PROC(BindAttribLocation);
+    GR_GL_GET_PROC(BindBuffer);
+    GR_GL_GET_PROC(BindTexture);
+    GR_GL_GET_PROC(BufferData);
+    GR_GL_GET_PROC(BufferSubData);
+    GR_GL_GET_PROC(CompileShader);
+    GR_GL_GET_PROC(CompressedTexImage2D);
+    GR_GL_GET_PROC(CreateProgram);
+    GR_GL_GET_PROC(CreateShader);
+    GR_GL_GET_PROC(DeleteBuffers);
+    GR_GL_GET_PROC(DeleteProgram);
+    GR_GL_GET_PROC(DeleteShader);
+    GR_GL_GET_PROC(DisableVertexAttribArray);
+    GR_GL_GET_PROC(EnableVertexAttribArray);
+    GR_GL_GET_PROC(GenBuffers);
+    GR_GL_GET_PROC(GetBufferParameteriv);
+    GR_GL_GET_PROC(GetProgramInfoLog);
+    GR_GL_GET_PROC(GetProgramiv);
+    GR_GL_GET_PROC(GetShaderInfoLog);
+    GR_GL_GET_PROC(GetShaderiv);
+    GR_GL_GET_PROC(GetUniformLocation);
+    GR_GL_GET_PROC(LinkProgram);
+    GR_GL_GET_PROC(ShaderSource);
+    GR_GL_GET_PROC(StencilFuncSeparate);
+    GR_GL_GET_PROC(StencilMaskSeparate);
+    GR_GL_GET_PROC(StencilOpSeparate);
+    GR_GL_GET_PROC(Uniform1fv);
+    GR_GL_GET_PROC(Uniform1i);
+    GR_GL_GET_PROC(Uniform4fv);
+    GR_GL_GET_PROC(UniformMatrix3fv);
+    GR_GL_GET_PROC(UseProgram);
+    GR_GL_GET_PROC(VertexAttrib4fv);
+    GR_GL_GET_PROC(VertexAttribPointer);
+
+    InitializeGLInterfaceExtensions(glBindings);
+}
+
+}  // unnamed namespace
+
+void GrGLSetGLInterface(GrGLInterface* gl_interface) {
+    gGLInterface = gl_interface;
+}
+
+GrGLInterface* GrGLGetGLInterface() {
+    return gGLInterface;
+}
+
+void GrGLSetDefaultGLInterface() {
+    static GrGLInterface gDefaultInterface;
+    static bool gDefaultInitialized = false;
+    GrAssert(!gDefaultInitialized);
+
+    if (!gDefaultInitialized) {
+        GrGLInitializeGLInterface(&gDefaultInterface);
+        GrGLSetGLInterface(&gDefaultInterface);
+    }
+}
+
+bool has_gl_extension(const char* ext) {
+    const char* glstr = reinterpret_cast<const char*>(
+                GrGLGetGLInterface()->fGetString(GL_EXTENSIONS));
+
+    return has_gl_extension_from_string(ext, glstr);
+}
+
+void gl_version(int* major, int* minor) {
+    const char* v = reinterpret_cast<const char*>(
+                GrGLGetGLInterface()->fGetString(GL_VERSION));
+    gl_version_from_string(major, minor, v);
+}
diff --git a/gpu/src/GrGLTexture.cpp b/gpu/src/GrGLTexture.cpp
index 1acb871..7488d0f 100644
--- a/gpu/src/GrGLTexture.cpp
+++ b/gpu/src/GrGLTexture.cpp
@@ -43,16 +43,16 @@
     fGL->notifyRenderTargetDelete(this);
     if (fOwnIDs) {
         if (fTexFBOID) {
-            GR_GLEXT(fGL->extensions(), DeleteFramebuffers(1, &fTexFBOID));
+            GR_GL(DeleteFramebuffers(1, &fTexFBOID));
         }
         if (fRTFBOID && fRTFBOID != fTexFBOID) {
-            GR_GLEXT(fGL->extensions(), DeleteFramebuffers(1, &fRTFBOID));
+            GR_GL(DeleteFramebuffers(1, &fRTFBOID));
         }
         if (fStencilRenderbufferID) {
-            GR_GLEXT(fGL->extensions(), DeleteRenderbuffers(1, &fStencilRenderbufferID));
+            GR_GL(DeleteRenderbuffers(1, &fStencilRenderbufferID));
         }
         if (fMSColorRenderbufferID) {
-            GR_GLEXT(fGL->extensions(), DeleteRenderbuffers(1, &fMSColorRenderbufferID));
+            GR_GL(DeleteRenderbuffers(1, &fMSColorRenderbufferID));
         }
     }
     GrSafeUnref(fTexIDObj);
diff --git a/gpu/src/GrGLUtil.cpp b/gpu/src/GrGLUtil.cpp
index e128d35..2cb887a 100644
--- a/gpu/src/GrGLUtil.cpp
+++ b/gpu/src/GrGLUtil.cpp
@@ -1,5 +1,5 @@
 /*
- Copyright 2010 Google Inc.
+ Copyright 2011 Google Inc.
 
  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
@@ -15,227 +15,9 @@
  */
 
 #include "GrGLConfig.h"
-#include "GrTypes.h"
-#include <stdio.h>
-
-bool has_gl_extension(const char* ext) {
-    const char* glstr = (const char*) glGetString(GL_EXTENSIONS);
-
-    int extLength = strlen(ext);
-
-    while (true) {
-        int n = strcspn(glstr, " ");
-        if (n == extLength && 0 == strncmp(ext, glstr, n)) {
-            return true;
-        }
-        if (0 == glstr[n]) {
-            return false;
-        }
-        glstr += n+1;
-    }
-}
-
-void gl_version(int* major, int* minor) {
-    const char* v = (const char*) glGetString(GL_VERSION);
-    if (NULL == v) {
-        GrAssert(0);
-        *major = 0;
-        *minor = 0;
-        return;
-    }
-#if GR_SUPPORT_GLDESKTOP
-    int n = sscanf(v, "%d.%d", major, minor);
-    if (n != 2) {
-        GrAssert(0);
-        *major = 0;
-        *minor = 0;
-        return;
-    }
-#else
-    char profile[2];
-    int n = sscanf(v, "OpenGL ES-%c%c %d.%d", profile, profile+1, major, minor);
-    bool ok = 4 == n;
-    if (!ok) {
-        int n = sscanf(v, "OpenGL ES %d.%d", major, minor);
-        ok = 2 == n;
-    }
-    if (!ok) {
-        GrAssert(0);
-        *major = 0;
-        *minor = 0;
-        return;
-    }
-#endif
-}
-
-#if defined(GR_GL_PROC_ADDRESS_HEADER)
-    #include GR_GL_PROC_ADDRESS_HEADER
-#endif
-
-typedef void (*glProc)(void);
-
-#define GET_PROC(EXT_STRUCT, PROC_NAME) \
-    *(GrTCast<glProc*>(&(EXT_STRUCT-> PROC_NAME))) = (glProc)GR_GL_PROC_ADDRESS((gl ## PROC_NAME)); \
-    GrAssert(NULL != EXT_STRUCT-> PROC_NAME)
-
-#define GET_SUFFIX_PROC(EXT_STRUCT, PROC_NAME, SUFFIX) \
-    *(GrTCast<glProc*>(&(EXT_STRUCT-> PROC_NAME))) = (glProc)GR_GL_PROC_ADDRESS((gl ## PROC_NAME ## SUFFIX)); \
-    GrAssert(NULL != EXT_STRUCT-> PROC_NAME)
-
-extern void GrGLInitExtensions(GrGLExts* exts) {
-    exts->GenFramebuffers                   = NULL;
-    exts->BindFramebuffer                   = NULL;
-    exts->FramebufferTexture2D              = NULL;
-    exts->CheckFramebufferStatus            = NULL;
-    exts->DeleteFramebuffers                = NULL;
-    exts->RenderbufferStorage               = NULL;
-    exts->GenRenderbuffers                  = NULL;
-    exts->DeleteRenderbuffers               = NULL;
-    exts->FramebufferRenderbuffer           = NULL;
-    exts->BindRenderbuffer                  = NULL;
-    exts->RenderbufferStorageMultisample    = NULL;
-    exts->BlitFramebuffer                   = NULL;
-    exts->ResolveMultisampleFramebuffer     = NULL;
-    exts->FramebufferTexture2DMultisample   = NULL;
-    exts->MapBuffer                         = NULL;
-    exts->UnmapBuffer                       = NULL;
-
-    GLint major, minor;
-    gl_version(&major, &minor);
-
-    bool fboFound = false;
-#if GR_SUPPORT_GLDESKTOP
-    #if defined(GL_VERSION_3_0) && GL_VERSION_3_0
-    if (!fboFound && major >= 3) { // all of ARB_fbo is in 3.x
-        exts->GenFramebuffers                   = glGenFramebuffers;
-        exts->BindFramebuffer                   = glBindFramebuffer;
-        exts->FramebufferTexture2D              = glFramebufferTexture2D;
-        exts->CheckFramebufferStatus            = glCheckFramebufferStatus;
-        exts->DeleteFramebuffers                = glDeleteFramebuffers;
-        exts->RenderbufferStorage               = glRenderbufferStorage;
-        exts->GenRenderbuffers                  = glGenRenderbuffers;
-        exts->DeleteRenderbuffers               = glDeleteRenderbuffers;
-        exts->FramebufferRenderbuffer           = glFramebufferRenderbuffer;
-        exts->BindRenderbuffer                  = glBindRenderbuffer;
-        exts->RenderbufferStorageMultisample    = glRenderbufferStorageMultisample;
-        exts->BlitFramebuffer                   = glBlitFramebuffer;
-        fboFound = true;
-    }
-    #endif
-    #if GL_ARB_framebuffer_object
-    if (!fboFound && has_gl_extension("GL_ARB_framebuffer_object")) {
-        // GL_ARB_framebuffer_object doesn't use ARB suffix.
-        GET_PROC(exts, GenFramebuffers);
-        GET_PROC(exts, BindFramebuffer);
-        GET_PROC(exts, FramebufferTexture2D);
-        GET_PROC(exts, CheckFramebufferStatus);
-        GET_PROC(exts, DeleteFramebuffers);
-        GET_PROC(exts, RenderbufferStorage);
-        GET_PROC(exts, GenRenderbuffers);
-        GET_PROC(exts, DeleteRenderbuffers);
-        GET_PROC(exts, FramebufferRenderbuffer);
-        GET_PROC(exts, BindRenderbuffer);
-        GET_PROC(exts, RenderbufferStorageMultisample);
-        GET_PROC(exts, BlitFramebuffer);
-        fboFound = true;
-    }
-    #endif
-    // Mac doesn't declare prototypes for EXT FBO extensions
-    #if GL_EXT_framebuffer_object && !GR_MAC_BUILD
-    if (!fboFound && has_gl_extension("GL_EXT_framebuffer_object")) {
-        GET_SUFFIX_PROC(exts, GenFramebuffers, EXT);
-        GET_SUFFIX_PROC(exts, BindFramebuffer, EXT);
-        GET_SUFFIX_PROC(exts, FramebufferTexture2D, EXT);
-        GET_SUFFIX_PROC(exts, CheckFramebufferStatus, EXT);
-        GET_SUFFIX_PROC(exts, DeleteFramebuffers, EXT);
-        GET_SUFFIX_PROC(exts, RenderbufferStorage, EXT);
-        GET_SUFFIX_PROC(exts, GenRenderbuffers, EXT);
-        GET_SUFFIX_PROC(exts, DeleteRenderbuffers, EXT);
-        GET_SUFFIX_PROC(exts, FramebufferRenderbuffer, EXT);
-        GET_SUFFIX_PROC(exts, BindRenderbuffer, EXT);
-        fboFound = true;
-        // check for fbo ms and fbo blit
-        #if GL_EXT_framebuffer_multisample
-        if (has_gl_extension("GL_EXT_framebuffer_multisample")) {
-            GET_SUFFIX_PROC(exts, RenderbufferStorageMultisample, EXT);
-        }
-        #endif
-        #if GL_EXT_framebuffer_blit
-        if (has_gl_extension("GL_EXT_framebuffer_blit")) {
-            GET_SUFFIX_PROC(exts, BlitFramebuffer, EXT);
-        }
-        #endif
-    }
-    #endif
-    if (!fboFound) {
-        // we require some form of FBO
-        GrAssert(!"No FBOs supported?");
-    }
-    // we assume we have at least GL 1.5 or higher (VBOs introduced in 1.5)
-    exts->MapBuffer     = glMapBuffer;
-    exts->UnmapBuffer   = glUnmapBuffer;
-#else // !GR_SUPPORT_GLDESKTOP
-    #if GR_SUPPORT_GLES2
-    if (!fboFound && major >= 2) {// ES 2.0 supports FBO
-        exts->GenFramebuffers                   = glGenFramebuffers;
-        exts->BindFramebuffer                   = glBindFramebuffer;
-        exts->FramebufferTexture2D              = glFramebufferTexture2D;
-        exts->CheckFramebufferStatus            = glCheckFramebufferStatus;
-        exts->DeleteFramebuffers                = glDeleteFramebuffers;
-        exts->RenderbufferStorage               = glRenderbufferStorage;
-        exts->GenRenderbuffers                  = glGenRenderbuffers;
-        exts->DeleteRenderbuffers               = glDeleteRenderbuffers;
-        exts->FramebufferRenderbuffer           = glFramebufferRenderbuffer;
-        exts->BindRenderbuffer                  = glBindRenderbuffer;
-        fboFound = true;
-    }
-    #endif
-    #if GL_OES_framebuffer_object
-    if (!fboFound && has_gl_extension("GL_OES_framebuffer_object")) {
-        GET_SUFFIX_PROC(exts, GenFramebuffers, OES);
-        GET_SUFFIX_PROC(exts, BindFramebuffer, OES);
-        GET_SUFFIX_PROC(exts, FramebufferTexture2D, OES);
-        GET_SUFFIX_PROC(exts, CheckFramebufferStatus, OES);
-        GET_SUFFIX_PROC(exts, DeleteFramebuffers, OES);
-        GET_SUFFIX_PROC(exts, RenderbufferStorage, OES);
-        GET_SUFFIX_PROC(exts, GenRenderbuffers, OES);
-        GET_SUFFIX_PROC(exts, DeleteRenderbuffers, OES);
-        GET_SUFFIX_PROC(exts, FramebufferRenderbuffer, OES);
-        GET_SUFFIX_PROC(exts, BindRenderbuffer, OES);
-    }
-    #endif
-
-    if (!fboFound) {
-        // we require some form of FBO
-        GrAssert(!"No FBOs supported?");
-    }
-
-    #if GL_APPLE_framebuffer_multisample
-    if (has_gl_extension("GL_APPLE_framebuffer_multisample")) {
-        GET_SUFFIX_PROC(exts, ResolveMultisampleFramebuffer, APPLE);
-    }
-    #endif
-
-    #if GL_IMG_multisampled_render_to_texture
-    if (has_gl_extension("GL_IMG_multisampled_render_to_texture")) {
-        GET_SUFFIX_PROC(exts, FramebufferTexture2DMultisample, IMG);
-    }
-    #endif
-
-    #if GL_OES_mapbuffer
-    if (has_gl_extension("GL_OES_mapbuffer")) {
-        GET_SUFFIX_PROC(exts, MapBuffer, OES);
-        GET_SUFFIX_PROC(exts, UnmapBuffer, OES);
-    }
-    #endif
-#endif // !GR_SUPPORT_GLDESKTOP
-}
-
-
-///////////////////////////////////////////////////////////////////////////////
 
 void GrGLCheckErr(const char* location, const char* call) {
-    uint32_t err =  glGetError();
+    uint32_t err =  GrGLGetGLInterface()->fGetError();
     if (GL_NO_ERROR != err) {
         GrPrintf("---- glGetError %x", err);
         if (NULL != location) {
diff --git a/gpu/src/GrGLVertexBuffer.cpp b/gpu/src/GrGLVertexBuffer.cpp
index ec48936..69913bf 100644
--- a/gpu/src/GrGLVertexBuffer.cpp
+++ b/gpu/src/GrGLVertexBuffer.cpp
@@ -1,5 +1,5 @@
 /*
-    Copyright 2010 Google Inc.
+    Copyright 2011 Google Inc.
 
     Licensed under the Apache License, Version 2.0 (the "License");
     you may not use this file except in compliance with the License.
@@ -57,8 +57,7 @@
         // Let driver know it can discard the old data
         GR_GL(BufferData(GL_ARRAY_BUFFER, size(), NULL,
                          dynamic() ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW));
-        fLockPtr = GR_GLEXT(fGL->extensions(),
-                            MapBuffer(GL_ARRAY_BUFFER, GR_WRITE_ONLY));
+        fLockPtr = GR_GL(MapBuffer(GL_ARRAY_BUFFER, GR_WRITE_ONLY));
         return fLockPtr;
     }
     return NULL;
@@ -74,7 +73,7 @@
     GrAssert(fGL->supportsBufferLocking());
 
     bind();
-    GR_GLEXT(fGL->extensions(), UnmapBuffer(GL_ARRAY_BUFFER));
+    GR_GL(UnmapBuffer(GL_ARRAY_BUFFER));
     fLockPtr = NULL;
 }
 
diff --git a/gpu/src/GrGpuFactory.cpp b/gpu/src/GrGpuFactory.cpp
index 2298776..7c2db2b 100644
--- a/gpu/src/GrGpuFactory.cpp
+++ b/gpu/src/GrGpuFactory.cpp
@@ -1,5 +1,5 @@
 /*
-    Copyright 2010 Google Inc.
+    Copyright 2011 Google Inc.
 
     Licensed under the Apache License, Version 2.0 (the "License");
     you may not use this file except in compliance with the License.
@@ -36,6 +36,11 @@
 #include "GrGpu.h"
 
 GrGpu* GrGpu::Create(Engine engine, Platform3DContext context3D) {
+    // If no GL bindings have been installed, fall-back to calling the
+    // GL functions that have been linked with the executable.
+    if (!GrGLGetGLInterface())
+        GrGLSetDefaultGLInterface();
+
     GrGpu* gpu = NULL;
 
     switch (engine) {
diff --git a/gpu/src/GrGpuGL.cpp b/gpu/src/GrGpuGL.cpp
index dc9b92d..94e9bfd 100644
--- a/gpu/src/GrGpuGL.cpp
+++ b/gpu/src/GrGpuGL.cpp
@@ -103,8 +103,7 @@
 
 static bool gPrintStartupSpew;
 
-
-static bool fbo_test(GrGLExts exts, int w, int h) {
+static bool fbo_test(int w, int h) {
 
     GLint savedFBO;
     GLint savedTexUnit;
@@ -114,8 +113,8 @@
     GR_GL(ActiveTexture(GL_TEXTURE0 + SPARE_TEX_UNIT));
 
     GLuint testFBO;
-    GR_GLEXT(exts, GenFramebuffers(1, &testFBO));
-    GR_GLEXT(exts, BindFramebuffer(GR_FRAMEBUFFER, testFBO));
+    GR_GL(GenFramebuffers(1, &testFBO));
+    GR_GL(BindFramebuffer(GR_FRAMEBUFFER, testFBO));
     GLuint testRTTex;
     GR_GL(GenTextures(1, &testRTTex));
     GR_GL(BindTexture(GL_TEXTURE_2D, testRTTex));
@@ -125,14 +124,14 @@
     GR_GL(TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h,
                      0, GL_RGBA, GL_UNSIGNED_BYTE, NULL));
     GR_GL(BindTexture(GL_TEXTURE_2D, 0));
-    GR_GLEXT(exts, FramebufferTexture2D(GR_FRAMEBUFFER, GR_COLOR_ATTACHMENT0,
-                                        GL_TEXTURE_2D, testRTTex, 0));
-    GLenum status = GR_GLEXT(exts, CheckFramebufferStatus(GR_FRAMEBUFFER));
-    GR_GLEXT(exts, DeleteFramebuffers(1, &testFBO));
+    GR_GL(FramebufferTexture2D(GR_FRAMEBUFFER, GR_COLOR_ATTACHMENT0,
+                               GL_TEXTURE_2D, testRTTex, 0));
+    GLenum status = GR_GL(CheckFramebufferStatus(GR_FRAMEBUFFER));
+    GR_GL(DeleteFramebuffers(1, &testFBO));
     GR_GL(DeleteTextures(1, &testRTTex));
 
     GR_GL(ActiveTexture(savedTexUnit));
-    GR_GLEXT(exts, BindFramebuffer(GR_FRAMEBUFFER, savedFBO));
+    GR_GL(BindFramebuffer(GR_FRAMEBUFFER, savedFBO));
 
     return status == GR_FRAMEBUFFER_COMPLETE;
 }
@@ -142,16 +141,18 @@
     if (gPrintStartupSpew) {
         GrPrintf("------------------------- create GrGpuGL %p --------------\n",
                  this);
-        GrPrintf("------ VENDOR %s\n", glGetString(GL_VENDOR));
-        GrPrintf("------ RENDERER %s\n", glGetString(GL_RENDERER));
-        GrPrintf("------ VERSION %s\n", glGetString(GL_VERSION));
-        GrPrintf("------ EXTENSIONS\n %s \n", glGetString(GL_EXTENSIONS));
+        GrPrintf("------ VENDOR %s\n",
+                 GrGLGetGLInterface()->fGetString(GL_VENDOR));
+        GrPrintf("------ RENDERER %s\n",
+                 GrGLGetGLInterface()->fGetString(GL_RENDERER));
+        GrPrintf("------ VERSION %s\n",
+                 GrGLGetGLInterface()->fGetString(GL_VERSION));
+        GrPrintf("------ EXTENSIONS\n %s \n",
+                 GrGLGetGLInterface()->fGetString(GL_EXTENSIONS));
     }
 
     GrGLClearErr();
 
-    GrGLInitExtensions(&fExts);
-
     resetDirtyFlags();
 
     GLint maxTextureUnits;
@@ -329,7 +330,7 @@
 
     // sanity check to make sure we can at least create an FBO from a POT texture
 
-    bool simpleFBOSuccess = fbo_test(fExts, 128, 128);
+    bool simpleFBOSuccess = fbo_test(128, 128);
     if (gPrintStartupSpew) {
         if (!simpleFBOSuccess) {
             GrPrintf("FBO Sanity Test: FAILED\n");
@@ -348,7 +349,7 @@
      */
     bool fNPOTRenderTargetSupport = false;
     if (fNPOTTextureSupport) {
-        fNPOTRenderTargetSupport = fbo_test(fExts, 200, 200);
+        fNPOTRenderTargetSupport = fbo_test(200, 200);
     }
 
     if (gPrintStartupSpew) {
@@ -384,7 +385,7 @@
     for (GLuint i = 1; i <= 256; fNPOTRenderTargetSupport ? ++i : i *= 2) {
         GLuint w = maxRenderSize;
         GLuint h = i;
-        if (fbo_test(fExts, w, h)) {
+        if (fbo_test(w, h)) {
             if (gPrintStartupSpew) {
                 GrPrintf("\t[%d, %d]: PASSED\n", w, h);
             }
@@ -405,7 +406,7 @@
     for (GLuint i = 1; i <= 256; fNPOTRenderTargetSupport ? i *= 2 : ++i) {
         GLuint w = i;
         GLuint h = maxRenderSize;
-        if (fbo_test(fExts, w, h)) {
+        if (fbo_test(w, h)) {
             if (gPrintStartupSpew) {
                 GrPrintf("\t[%d, %d]: PASSED\n", w, h);
             }
@@ -777,7 +778,7 @@
         GrAssert(NULL == srcData);
         glDesc.fOrientation =  GrGLTexture::kBottomUp_Orientation;
 
-        GR_GLEXT(fExts, GenFramebuffers(1, &rtIDs.fTexFBOID));
+        GR_GL(GenFramebuffers(1, &rtIDs.fTexFBOID));
         GrAssert(rtIDs.fTexFBOID);
 
         // If we are using multisampling and any extension other than the IMG
@@ -785,16 +786,15 @@
         // the texture bound to the other. The IMG extension does an implicit
         // resolve.
         if (samples > 1 && kIMG_MSFBO != fMSFBOType && kNone_MSFBO != fMSFBOType) {
-            GR_GLEXT(fExts, GenFramebuffers(1, &rtIDs.fRTFBOID));
+            GR_GL(GenFramebuffers(1, &rtIDs.fRTFBOID));
             GrAssert(0 != rtIDs.fRTFBOID);
-            GR_GLEXT(fExts, GenRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
+            GR_GL(GenRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
             GrAssert(0 != rtIDs.fMSColorRenderbufferID);
             if (!fboInternalFormat(desc.fFormat, &msColorRenderbufferFormat)) {
-                GR_GLEXT(fExts,
-                         DeleteRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
+                GR_GL(DeleteRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
                 GR_GL(DeleteTextures(1, &glDesc.fTextureID));
-                GR_GLEXT(fExts, DeleteFramebuffers(1, &rtIDs.fTexFBOID));
-                GR_GLEXT(fExts, DeleteFramebuffers(1, &rtIDs.fRTFBOID));
+                GR_GL(DeleteFramebuffers(1, &rtIDs.fTexFBOID));
+                GR_GL(DeleteFramebuffers(1, &rtIDs.fRTFBOID));
                 return return_null_texture();
             }
         } else {
@@ -802,7 +802,7 @@
         }
         int attempts = 1;
         if (!(kNoPathRendering_TextureFlag & desc.fFlags)) {
-            GR_GLEXT(fExts, GenRenderbuffers(1, &rtIDs.fStencilRenderbufferID));
+            GR_GL(GenRenderbuffers(1, &rtIDs.fStencilRenderbufferID));
             GrAssert(0 != rtIDs.fStencilRenderbufferID);
             attempts = GR_ARRAY_COUNT(gStencilFormats);
         }
@@ -815,21 +815,20 @@
         err = ~GL_NO_ERROR;
         for (int i = 0; i < attempts; ++i) {
             if (rtIDs.fStencilRenderbufferID) {
-                GR_GLEXT(fExts, BindRenderbuffer(GR_RENDERBUFFER,
-                                                 rtIDs.fStencilRenderbufferID));
+                GR_GL(BindRenderbuffer(GR_RENDERBUFFER,
+                                       rtIDs.fStencilRenderbufferID));
                 if (samples > 1) {
-                    GR_GLEXT_NO_ERR(fExts, RenderbufferStorageMultisample(
+                    GR_GL_NO_ERR(RenderbufferStorageMultisample(
                                                 GR_RENDERBUFFER,
                                                 samples,
                                                 gStencilFormats[i].fEnum,
                                                 glDesc.fAllocWidth,
                                                 glDesc.fAllocHeight));
                 } else {
-                    GR_GLEXT_NO_ERR(fExts, RenderbufferStorage(
-                                                GR_RENDERBUFFER,
-                                                gStencilFormats[i].fEnum,
-                                                glDesc.fAllocWidth,
-                                                glDesc.fAllocHeight));
+                    GR_GL_NO_ERR(RenderbufferStorage(GR_RENDERBUFFER,
+                                                     gStencilFormats[i].fEnum,
+                                                     glDesc.fAllocWidth,
+                                                     glDesc.fAllocHeight));
                 }
                 err = glGetError();
                 if (err != GL_NO_ERROR) {
@@ -838,9 +837,9 @@
             }
             if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
                 GrAssert(samples > 1);
-                GR_GLEXT(fExts, BindRenderbuffer(GR_RENDERBUFFER,
-                                                 rtIDs.fMSColorRenderbufferID));
-                GR_GLEXT_NO_ERR(fExts, RenderbufferStorageMultisample(
+                GR_GL(BindRenderbuffer(GR_RENDERBUFFER,
+                                       rtIDs.fMSColorRenderbufferID));
+                GR_GL_NO_ERR(RenderbufferStorageMultisample(
                                                    GR_RENDERBUFFER,
                                                    samples,
                                                    msColorRenderbufferFormat,
@@ -851,52 +850,50 @@
                     continue;
                 }
             }
-            GR_GLEXT(fExts, BindFramebuffer(GR_FRAMEBUFFER, rtIDs.fTexFBOID));
+            GR_GL(BindFramebuffer(GR_FRAMEBUFFER, rtIDs.fTexFBOID));
 
 #if GR_COLLECT_STATS
             ++fStats.fRenderTargetChngCnt;
 #endif
             if (kIMG_MSFBO == fMSFBOType && samples > 1) {
-                GR_GLEXT(fExts, FramebufferTexture2DMultisample(
-                                                         GR_FRAMEBUFFER,
-                                                         GR_COLOR_ATTACHMENT0,
-                                                         GL_TEXTURE_2D,
-                                                         glDesc.fTextureID,
-                                                         0,
-                                                         samples));
+                GR_GL(FramebufferTexture2DMultisample(GR_FRAMEBUFFER,
+                                                      GR_COLOR_ATTACHMENT0,
+                                                      GL_TEXTURE_2D,
+                                                      glDesc.fTextureID,
+                                                      0,
+                                                      samples));
 
             } else {
-                GR_GLEXT(fExts, FramebufferTexture2D(GR_FRAMEBUFFER,
-                                                     GR_COLOR_ATTACHMENT0,
-                                                     GL_TEXTURE_2D,
-                                                     glDesc.fTextureID, 0));
+                GR_GL(FramebufferTexture2D(GR_FRAMEBUFFER,
+                                           GR_COLOR_ATTACHMENT0,
+                                           GL_TEXTURE_2D,
+                                           glDesc.fTextureID, 0));
             }
             if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
-                GLenum status = GR_GLEXT(fExts,
-                                         CheckFramebufferStatus(GR_FRAMEBUFFER));
+                GLenum status = GR_GL(CheckFramebufferStatus(GR_FRAMEBUFFER));
                 if (status != GR_FRAMEBUFFER_COMPLETE) {
                     GrPrintf("-- glCheckFramebufferStatus %x %d %d\n",
                              status, desc.fWidth, desc.fHeight);
                     continue;
                 }
-                GR_GLEXT(fExts, BindFramebuffer(GR_FRAMEBUFFER, rtIDs.fRTFBOID));
+                GR_GL(BindFramebuffer(GR_FRAMEBUFFER, rtIDs.fRTFBOID));
             #if GR_COLLECT_STATS
                 ++fStats.fRenderTargetChngCnt;
             #endif
-                GR_GLEXT(fExts, FramebufferRenderbuffer(GR_FRAMEBUFFER,
-                                                 GR_COLOR_ATTACHMENT0,
-                                                 GR_RENDERBUFFER,
-                                                 rtIDs.fMSColorRenderbufferID));
+                GR_GL(FramebufferRenderbuffer(GR_FRAMEBUFFER,
+                                              GR_COLOR_ATTACHMENT0,
+                                              GR_RENDERBUFFER,
+                                              rtIDs.fMSColorRenderbufferID));
 
             }
             if (rtIDs.fStencilRenderbufferID) {
                 // bind the stencil to rt fbo if present, othewise the tex fbo
-                GR_GLEXT(fExts, FramebufferRenderbuffer(GR_FRAMEBUFFER,
-                                                 GR_STENCIL_ATTACHMENT,
-                                                 GR_RENDERBUFFER,
-                                                 rtIDs.fStencilRenderbufferID));
+                GR_GL(FramebufferRenderbuffer(GR_FRAMEBUFFER,
+                                              GR_STENCIL_ATTACHMENT,
+                                              GR_RENDERBUFFER,
+                                              rtIDs.fStencilRenderbufferID));
             }
-            status = GR_GLEXT(fExts, CheckFramebufferStatus(GR_FRAMEBUFFER));
+            status = GR_GL(CheckFramebufferStatus(GR_FRAMEBUFFER));
 
 #if GR_SUPPORT_GLDESKTOP
             // On some implementations you have to be bound as DEPTH_STENCIL.
@@ -904,16 +901,15 @@
             // buffer doesn't work.)
             if (rtIDs.fStencilRenderbufferID &&
                 status != GR_FRAMEBUFFER_COMPLETE) {
-                GR_GLEXT(fExts, FramebufferRenderbuffer(GR_FRAMEBUFFER,
-                                                        GR_STENCIL_ATTACHMENT,
-                                                        GR_RENDERBUFFER,
-                                                        0));
-                GR_GLEXT(fExts,
-                         FramebufferRenderbuffer(GR_FRAMEBUFFER,
-                                                 GR_DEPTH_STENCIL_ATTACHMENT,
-                                                 GR_RENDERBUFFER,
-                                                 rtIDs.fStencilRenderbufferID));
-                status = GR_GLEXT(fExts, CheckFramebufferStatus(GR_FRAMEBUFFER));
+                GR_GL(FramebufferRenderbuffer(GR_FRAMEBUFFER,
+                                              GR_STENCIL_ATTACHMENT,
+                                              GR_RENDERBUFFER,
+                                              0));
+                GR_GL(FramebufferRenderbuffer(GR_FRAMEBUFFER,
+                                              GR_DEPTH_STENCIL_ATTACHMENT,
+                                              GR_RENDERBUFFER,
+                                              rtIDs.fStencilRenderbufferID));
+                status = GR_GL(CheckFramebufferStatus(GR_FRAMEBUFFER));
             }
 #endif
             if (status != GR_FRAMEBUFFER_COMPLETE) {
@@ -921,10 +917,10 @@
                          status, desc.fWidth, desc.fHeight);
 #if GR_SUPPORT_GLDESKTOP
                 if (rtIDs.fStencilRenderbufferID) {
-                    GR_GLEXT(fExts, FramebufferRenderbuffer(GR_FRAMEBUFFER,
-                                                     GR_DEPTH_STENCIL_ATTACHMENT,
-                                                     GR_RENDERBUFFER,
-                                                     0));
+                    GR_GL(FramebufferRenderbuffer(GR_FRAMEBUFFER,
+                                                  GR_DEPTH_STENCIL_ATTACHMENT,
+                                                  GR_RENDERBUFFER,
+                                                  0));
                 }
 #endif
                 continue;
@@ -942,18 +938,16 @@
         }
         if (failed) {
             if (rtIDs.fStencilRenderbufferID) {
-                GR_GLEXT(fExts,
-                         DeleteRenderbuffers(1, &rtIDs.fStencilRenderbufferID));
+                GR_GL(DeleteRenderbuffers(1, &rtIDs.fStencilRenderbufferID));
             }
             if (rtIDs.fMSColorRenderbufferID) {
-                GR_GLEXT(fExts,
-                         DeleteRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
+                GR_GL(DeleteRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
             }
             if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
-                GR_GLEXT(fExts, DeleteFramebuffers(1, &rtIDs.fRTFBOID));
+                GR_GL(DeleteFramebuffers(1, &rtIDs.fRTFBOID));
             }
             if (rtIDs.fTexFBOID) {
-                GR_GLEXT(fExts, DeleteFramebuffers(1, &rtIDs.fTexFBOID));
+                GR_GL(DeleteFramebuffers(1, &rtIDs.fTexFBOID));
             }
             GR_GL(DeleteTextures(1, &glDesc.fTextureID));
             return return_null_texture();
@@ -1169,13 +1163,13 @@
 
     if (fHWDrawState.fRenderTarget != fCurrDrawState.fRenderTarget) {
         GrGLRenderTarget* rt = (GrGLRenderTarget*)fCurrDrawState.fRenderTarget;
-        GR_GLEXT(fExts, BindFramebuffer(GR_FRAMEBUFFER, rt->renderFBOID()));
+        GR_GL(BindFramebuffer(GR_FRAMEBUFFER, rt->renderFBOID()));
     #if GR_COLLECT_STATS
         ++fStats.fRenderTargetChngCnt;
     #endif
         rt->setDirty(true);
     #if GR_DEBUG
-        GLenum status = GR_GLEXT(fExts, CheckFramebufferStatus(GR_FRAMEBUFFER));
+        GLenum status = GR_GL(CheckFramebufferStatus(GR_FRAMEBUFFER));
         if (status != GR_FRAMEBUFFER_COMPLETE) {
             GrPrintf("-- glCheckFramebufferStatus %x\n", status);
         }
@@ -1287,9 +1281,9 @@
     if (NULL != rt && rt->needsResolve()) {
         GrAssert(kNone_MSFBO != fMSFBOType);
         GrAssert(rt->textureFBOID() != rt->renderFBOID());
-        GR_GLEXT(fExts, BindFramebuffer(GR_READ_FRAMEBUFFER,
+        GR_GL(BindFramebuffer(GR_READ_FRAMEBUFFER,
                                         rt->renderFBOID()));
-        GR_GLEXT(fExts, BindFramebuffer(GR_DRAW_FRAMEBUFFER,
+        GR_GL(BindFramebuffer(GR_DRAW_FRAMEBUFFER,
                                         rt->textureFBOID()));
     #if GR_COLLECT_STATS
         ++fStats.fRenderTargetChngCnt;
@@ -1305,11 +1299,11 @@
         if (kApple_MSFBO == fMSFBOType) {
             GR_GL(Enable(GL_SCISSOR_TEST));
             GR_GL(Scissor(left, bottom, right-left, top-bottom));
-            GR_GLEXT(fExts, ResolveMultisampleFramebuffer());
+            GR_GL(ResolveMultisampleFramebuffer());
             fHWBounds.fScissorRect.invalidate();
             fHWBounds.fScissorEnabled = true;
         } else {
-            GR_GLEXT(fExts, BlitFramebuffer(left, bottom, right, top,
+            GR_GL(BlitFramebuffer(left, bottom, right, top,
                                      left, bottom, right, top,
                                      GL_COLOR_BUFFER_BIT, GL_NEAREST));
         }
diff --git a/gpu/src/GrGpuGL.h b/gpu/src/GrGpuGL.h
index f9a6987..a731226 100644
--- a/gpu/src/GrGpuGL.h
+++ b/gpu/src/GrGpuGL.h
@@ -31,14 +31,6 @@
             GrGpuGL();
     virtual ~GrGpuGL();
 
-    /**
-     * Gets the struct containing the GL extensions for the context
-     * underlying the GrGpuGL
-     *
-     * @param struct containing extension function pointers
-     */
-    const GrGLExts& extensions() { return fExts; }
-
 protected:
     struct {
         size_t                  fVertexOffset;
@@ -72,8 +64,6 @@
         GrGLIRect   fViewportRect;
     } fHWBounds;
 
-    GrGLExts fExts;
-
     // GrGpu overrides
     // overrides from GrGpu
     virtual void resetContext();
diff --git a/gpu/src/gr_files.mk b/gpu/src/gr_files.mk
index d0f41e7..8aeddc9 100644
--- a/gpu/src/gr_files.mk
+++ b/gpu/src/gr_files.mk
@@ -5,6 +5,7 @@
     GrContext.cpp \
     GrDrawTarget.cpp \
     GrGLIndexBuffer.cpp	\
+    GrGLInterface.cpp \
     GrGLTexture.cpp \
     GrGLVertexBuffer.cpp \
     GrGpu.cpp \