Move GrGLExtensions from GrGLContextInfo to GrGLInterface

BUG=skia:2042
R=robertphillips@google.com

Author: bsalomon@google.com

Review URL: https://codereview.chromium.org/140823003

git-svn-id: http://skia.googlecode.com/svn/trunk@13118 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/gpu/gl/GrGLCaps.cpp b/src/gpu/gl/GrGLCaps.cpp
index 0c6bed4..153be6a 100644
--- a/src/gpu/gl/GrGLCaps.cpp
+++ b/src/gpu/gl/GrGLCaps.cpp
@@ -409,7 +409,7 @@
         // The GL_EXT_texture_format_BGRA8888 extension does not add BGRA to the list of
         // configs that are color-renderable and can be passed to glRenderBufferStorageMultisample.
         // Chromium may have an extension to allow BGRA renderbuffers to work on desktop platforms.
-        if (ctxInfo.extensions().has("GL_CHROMIUM_renderbuffer_format_BGRA8888")) {
+        if (ctxInfo.hasExtension("GL_CHROMIUM_renderbuffer_format_BGRA8888")) {
             fConfigRenderSupport[kBGRA_8888_GrPixelConfig][kYes_MSAA] = true;
         } else {
             fConfigRenderSupport[kBGRA_8888_GrPixelConfig][kYes_MSAA] =
diff --git a/src/gpu/gl/GrGLContext.cpp b/src/gpu/gl/GrGLContext.cpp
index d95fe1c..296eaa5 100644
--- a/src/gpu/gl/GrGLContext.cpp
+++ b/src/gpu/gl/GrGLContext.cpp
@@ -15,7 +15,6 @@
     fGLSLGeneration = that.fGLSLGeneration;
     fVendor         = that.fVendor;
     fRenderer       = that.fRenderer;
-    fExtensions     = that.fExtensions;
     fIsMesa         = that.fIsMesa;
     fIsChromium     = that.fIsChromium;
     *fGLCaps        = *that.fGLCaps.get();
@@ -35,7 +34,7 @@
         GR_GL_CALL_RET(interface, rendererUByte, GetString(GR_GL_RENDERER));
         const char* renderer = reinterpret_cast<const char*>(rendererUByte);
 
-        if (interface->validate() && fExtensions.init(interface)) {
+        if (interface->validate()) {
 
             fGLVersion = GrGLGetVersionFromString(ver);
 
@@ -72,6 +71,5 @@
     fRenderer = kOther_GrGLRenderer;
     fIsMesa = false;
     fIsChromium = false;
-    fExtensions.reset();
     fGLCaps->reset();
 }
diff --git a/src/gpu/gl/GrGLContext.h b/src/gpu/gl/GrGLContext.h
index 13c94a9..e6c9f9e 100644
--- a/src/gpu/gl/GrGLContext.h
+++ b/src/gpu/gl/GrGLContext.h
@@ -58,16 +58,11 @@
     bool isChromium() const { return fIsChromium; }
     const GrGLCaps* caps() const { return fGLCaps.get(); }
     GrGLCaps* caps() { return fGLCaps; }
-    const GrGLExtensions& extensions() const { return fExtensions; }
-
-    /**
-     * Shortcut for extensions().has(ext)
-     */
     bool hasExtension(const char* ext) const {
         if (!this->isInitialized()) {
             return false;
         }
-        return fExtensions.has(ext);
+        return fInterface->hasExtension(ext);
     }
 
     /**
@@ -81,7 +76,6 @@
     GrGLSLGeneration                    fGLSLGeneration;
     GrGLVendor                          fVendor;
     GrGLRenderer                        fRenderer;
-    GrGLExtensions                      fExtensions;
     bool                                fIsMesa;
     bool                                fIsChromium;
     SkAutoTUnref<GrGLCaps>              fGLCaps;
diff --git a/src/gpu/gl/GrGLExtensions.cpp b/src/gpu/gl/GrGLExtensions.cpp
index dcfa4f7..4e75d3e 100644
--- a/src/gpu/gl/GrGLExtensions.cpp
+++ b/src/gpu/gl/GrGLExtensions.cpp
@@ -22,7 +22,9 @@
                           GrGLGetStringProc getString,
                           GrGLGetStringiProc getStringi,
                           GrGLGetIntegervProc getIntegerv) {
-    fStrings.reset();
+    fInitialized = false;
+    fStrings->reset();
+
     if (NULL == getString) {
         return false;
     }
@@ -41,10 +43,10 @@
         }
         GrGLint extensionCnt = 0;
         getIntegerv(GR_GL_NUM_EXTENSIONS, &extensionCnt);
-        fStrings.push_back_n(extensionCnt);
+        fStrings->push_back_n(extensionCnt);
         for (int i = 0; i < extensionCnt; ++i) {
             const char* ext = (const char*) getStringi(GR_GL_EXTENSIONS, i);
-            fStrings[i] = ext;
+            (*fStrings)[i] = ext;
         }
     } else {
         const char* extensions = (const char*) getString(GR_GL_EXTENSIONS);
@@ -62,24 +64,25 @@
             }
             // we found an extension
             size_t length = strcspn(extensions, " ");
-            fStrings.push_back().set(extensions, length);
+            fStrings->push_back().set(extensions, length);
             extensions += length;
         }
     }
-    if (!fStrings.empty()) {
+    if (!fStrings->empty()) {
         SkTLessFunctionToFunctorAdaptor<SkString, extension_compare> cmp;
-        SkTQSort(&fStrings.front(), &fStrings.back(), cmp);
+        SkTQSort(&fStrings->front(), &fStrings->back(), cmp);
     }
+    fInitialized = true;
     return true;
 }
 
 bool GrGLExtensions::has(const char* ext) const {
-    if (fStrings.empty()) {
+    if (fStrings->empty()) {
         return false;
     }
     SkString extensionStr(ext);
-    int idx = SkTSearch<SkString, extension_compare>(&fStrings.front(),
-                                                     fStrings.count(),
+    int idx = SkTSearch<SkString, extension_compare>(&fStrings->front(),
+                                                     fStrings->count(),
                                                      extensionStr,
                                                      sizeof(SkString));
     return idx >= 0;
@@ -89,8 +92,8 @@
     if (NULL == sep) {
         sep = " ";
     }
-    int cnt = fStrings.count();
+    int cnt = fStrings->count();
     for (int i = 0; i < cnt; ++i) {
-        GrPrintf("%s%s", fStrings[i].c_str(), (i < cnt - 1) ? sep : "");
+        GrPrintf("%s%s", (*fStrings)[i].c_str(), (i < cnt - 1) ? sep : "");
     }
 }
diff --git a/src/gpu/gl/GrGLInterface.cpp b/src/gpu/gl/GrGLInterface.cpp
index 6e8306b..72c9178 100644
--- a/src/gpu/gl/GrGLInterface.cpp
+++ b/src/gpu/gl/GrGLInterface.cpp
@@ -33,9 +33,13 @@
         return false;
     }
 
-    GrGLExtensions extensions;
-    if (!extensions.init(this)) {
-        return false;
+    // This const hackery is necessary because the factories in Chromium do not yet initialize
+    // fExtensions.
+    if (!fExtensions.isInitialized()) {
+        GrGLExtensions* extensions = const_cast<GrGLExtensions*>(&fExtensions);
+        if (!extensions->init(fStandard, fGetString, fGetStringi, fGetIntegerv)) {
+            return false;
+        }
     }
 
     // functions that are always required
@@ -144,7 +148,7 @@
     }
 
     // Now check that baseline ES/Desktop fns not covered above are present
-    // and that we have fn pointers for any advertised extensions that we will
+    // and that we have fn pointers for any advertised fExtensions that we will
     // try to use.
 
     // these functions are part of ES2, we assume they are available
@@ -168,13 +172,13 @@
         if (glVer >= GR_GL_VER(3,0) && NULL == fBindFragDataLocation) {
             return false;
         }
-        if (glVer >= GR_GL_VER(2,0) || extensions.has("GL_ARB_draw_buffers")) {
+        if (glVer >= GR_GL_VER(2,0) || fExtensions.has("GL_ARB_draw_buffers")) {
             if (NULL == fDrawBuffers) {
                 return false;
             }
         }
 
-        if (glVer >= GR_GL_VER(1,5) || extensions.has("GL_ARB_occlusion_query")) {
+        if (glVer >= GR_GL_VER(1,5) || fExtensions.has("GL_ARB_occlusion_query")) {
             if (NULL == fGenQueries ||
                 NULL == fDeleteQueries ||
                 NULL == fBeginQuery ||
@@ -186,14 +190,14 @@
             }
         }
         if (glVer >= GR_GL_VER(3,3) ||
-            extensions.has("GL_ARB_timer_query") ||
-            extensions.has("GL_EXT_timer_query")) {
+            fExtensions.has("GL_ARB_timer_query") ||
+            fExtensions.has("GL_EXT_timer_query")) {
             if (NULL == fGetQueryObjecti64v ||
                 NULL == fGetQueryObjectui64v) {
                 return false;
             }
         }
-        if (glVer >= GR_GL_VER(3,3) || extensions.has("GL_ARB_timer_query")) {
+        if (glVer >= GR_GL_VER(3,3) || fExtensions.has("GL_ARB_timer_query")) {
             if (NULL == fQueryCounter) {
                 return false;
             }
@@ -212,7 +216,7 @@
                 return false;
             }
         }
-        if (false && extensions.has("GL_NV_path_rendering")) {
+        if (false && fExtensions.has("GL_NV_path_rendering")) {
             if (NULL == fPathCommands ||
                 NULL == fPathCoords ||
                 NULL == fPathSubCommands ||
@@ -270,7 +274,7 @@
     // optional function on desktop before 1.3
     if (kGL_GrGLStandard != fStandard ||
         (glVer >= GR_GL_VER(1,3)) ||
-        extensions.has("GL_ARB_texture_compression")) {
+        fExtensions.has("GL_ARB_texture_compression")) {
         if (NULL == fCompressedTexImage2D) {
             return false;
         }
@@ -288,19 +292,19 @@
     // There is a desktop ARB extension and an ES+desktop EXT extension
     if (kGL_GrGLStandard == fStandard) {
         if (glVer >= GR_GL_VER(4,2) ||
-            extensions.has("GL_ARB_texture_storage") ||
-            extensions.has("GL_EXT_texture_storage")) {
+            fExtensions.has("GL_ARB_texture_storage") ||
+            fExtensions.has("GL_EXT_texture_storage")) {
             if (NULL == fTexStorage2D) {
                 return false;
             }
         }
-    } else if (glVer >= GR_GL_VER(3,0) || extensions.has("GL_EXT_texture_storage")) {
+    } else if (glVer >= GR_GL_VER(3,0) || fExtensions.has("GL_EXT_texture_storage")) {
         if (NULL == fTexStorage2D) {
             return false;
         }
     }
 
-    if (extensions.has("GL_EXT_discard_framebuffer")) {
+    if (fExtensions.has("GL_EXT_discard_framebuffer")) {
 // FIXME: Remove this once Chromium is updated to provide this function
 #if 0
         if (NULL == fDiscardFramebuffer) {
@@ -312,36 +316,36 @@
     // FBO MSAA
     if (kGL_GrGLStandard == fStandard) {
         // GL 3.0 and the ARB extension have multisample + blit
-        if (glVer >= GR_GL_VER(3,0) || extensions.has("GL_ARB_framebuffer_object")) {
+        if (glVer >= GR_GL_VER(3,0) || fExtensions.has("GL_ARB_framebuffer_object")) {
             if (NULL == fRenderbufferStorageMultisample ||
                 NULL == fBlitFramebuffer) {
                 return false;
             }
         } else {
-            if (extensions.has("GL_EXT_framebuffer_blit") &&
+            if (fExtensions.has("GL_EXT_framebuffer_blit") &&
                 NULL == fBlitFramebuffer) {
                 return false;
             }
-            if (extensions.has("GL_EXT_framebuffer_multisample") &&
+            if (fExtensions.has("GL_EXT_framebuffer_multisample") &&
                 NULL == fRenderbufferStorageMultisample) {
                 return false;
             }
         }
     } else {
-        if (glVer >= GR_GL_VER(3,0) || extensions.has("GL_CHROMIUM_framebuffer_multisample")) {
+        if (glVer >= GR_GL_VER(3,0) || fExtensions.has("GL_CHROMIUM_framebuffer_multisample")) {
             if (NULL == fRenderbufferStorageMultisample ||
                 NULL == fBlitFramebuffer) {
                 return false;
             }
         }
-        if (extensions.has("GL_APPLE_framebuffer_multisample")) {
+        if (fExtensions.has("GL_APPLE_framebuffer_multisample")) {
             if (NULL == fRenderbufferStorageMultisampleES2APPLE ||
                 NULL == fResolveMultisampleFramebuffer) {
                 return false;
             }
         }
-        if (extensions.has("GL_IMG_multisampled_render_to_texture") ||
-            extensions.has("GL_EXT_multisampled_render_to_texture")) {
+        if (fExtensions.has("GL_IMG_multisampled_render_to_texture") ||
+            fExtensions.has("GL_EXT_multisampled_render_to_texture")) {
             if (NULL == fRenderbufferStorageMultisampleES2EXT ||
                 NULL == fFramebufferTexture2DMultisample) {
                 return false;
@@ -352,7 +356,7 @@
     // On ES buffer mapping is an extension. On Desktop
     // buffer mapping was part of original VBO extension
     // which we require.
-    if (kGL_GrGLStandard == fStandard || extensions.has("GL_OES_mapbuffer")) {
+    if (kGL_GrGLStandard == fStandard || fExtensions.has("GL_OES_mapbuffer")) {
         if (NULL == fMapBuffer ||
             NULL == fUnmapBuffer) {
             return false;
@@ -361,7 +365,7 @@
 
     // Dual source blending
     if (kGL_GrGLStandard == fStandard &&
-        (glVer >= GR_GL_VER(3,3) || extensions.has("GL_ARB_blend_func_extended"))) {
+        (glVer >= GR_GL_VER(3,3) || fExtensions.has("GL_ARB_blend_func_extended"))) {
         if (NULL == fBindFragDataLocationIndexed) {
             return false;
         }
@@ -375,7 +379,7 @@
     }
 
     if (kGL_GrGLStandard == fStandard) {
-        if (glVer >= GR_GL_VER(3, 0) || extensions.has("GL_ARB_vertex_array_object")) {
+        if (glVer >= GR_GL_VER(3, 0) || fExtensions.has("GL_ARB_vertex_array_object")) {
             if (NULL == fBindVertexArray ||
                 NULL == fDeleteVertexArrays ||
                 NULL == fGenVertexArrays) {
@@ -383,7 +387,7 @@
             }
         }
     } else {
-        if (glVer >= GR_GL_VER(3,0) || extensions.has("GL_OES_vertex_array_object")) {
+        if (glVer >= GR_GL_VER(3,0) || fExtensions.has("GL_OES_vertex_array_object")) {
             if (NULL == fBindVertexArray ||
                 NULL == fDeleteVertexArrays ||
                 NULL == fGenVertexArrays) {
diff --git a/src/gpu/gl/GrGpuGL.cpp b/src/gpu/gl/GrGpuGL.cpp
index 071d49d..ec9c8d6 100644
--- a/src/gpu/gl/GrGpuGL.cpp
+++ b/src/gpu/gl/GrGpuGL.cpp
@@ -138,7 +138,9 @@
         GrPrintf("------ RENDERER %s\n", renderer);
         GrPrintf("------ VERSION %s\n",  version);
         GrPrintf("------ EXTENSIONS\n");
-        ctx.extensions().print();
+#if 0  // TODO: Reenable this after GrGLInterface's extensions can be accessed safely.
+       ctx.extensions().print();
+#endif
         GrPrintf("\n");
         GrPrintf(this->glCaps().dump().c_str());
     }
diff --git a/src/gpu/gl/SkGLContextHelper.cpp b/src/gpu/gl/SkGLContextHelper.cpp
index 4d31487..b06f755 100644
--- a/src/gpu/gl/SkGLContextHelper.cpp
+++ b/src/gpu/gl/SkGLContextHelper.cpp
@@ -37,7 +37,7 @@
     if (fGL) {
         const GrGLubyte* temp;
 
-        if (!fGL->validate() || !fExtensions.init(fGL)) {
+        if (!fGL->validate()) {
             fGL = NULL;
             this->destroyGLContext();
             return false;
diff --git a/src/gpu/gl/android/GrGLCreateNativeInterface_android.cpp b/src/gpu/gl/android/GrGLCreateNativeInterface_android.cpp
index 03eaa32..35de7f4 100644
--- a/src/gpu/gl/android/GrGLCreateNativeInterface_android.cpp
+++ b/src/gpu/gl/android/GrGLCreateNativeInterface_android.cpp
@@ -17,8 +17,8 @@
 
 #include <EGL/egl.h>
 
-static const GrGLInterface* create_es_interface(GrGLVersion version,
-                                                const GrGLExtensions& extensions) {
+static GrGLInterface* create_es_interface(GrGLVersion version,
+                                          const GrGLExtensions& extensions) {
     if (version < GR_GL_VER(2,0)) {
         return NULL;
     }
@@ -192,8 +192,8 @@
     return interface;
 }
 
-static const GrGLInterface* create_desktop_interface(GrGLVersion version,
-                                                     const GrGLExtensions& extensions) {
+static GrGLInterface* create_desktop_interface(GrGLVersion version,
+                                               const GrGLExtensions& extensions) {
     // Currently this assumes a 4.4 context or later. Supporting lower GL versions would require
     // getting suffixed versions of pointers for supported extensions.
     if (version < GR_GL_VER(4,4)) {
@@ -403,11 +403,16 @@
         return NULL;
     }
 
+    GrGLInterface* interface = NULL;
     if (kGLES_GrGLStandard == standard) {
-        return create_es_interface(version, extensions);
+        interface = create_es_interface(version, extensions);
     } else if (kGL_GrGLStandard == standard) {
-        return create_desktop_interface(version, extensions);
-    } else {
-        return NULL;
+        interface = create_desktop_interface(version, extensions);
     }
+
+    if (NULL != interface) {
+        interface->fExtensions.swap(&extensions);
+    }
+
+    return interface;
 }
diff --git a/src/gpu/gl/iOS/GrGLCreateNativeInterface_iOS.cpp b/src/gpu/gl/iOS/GrGLCreateNativeInterface_iOS.cpp
index c13e358..d00ffdf 100644
--- a/src/gpu/gl/iOS/GrGLCreateNativeInterface_iOS.cpp
+++ b/src/gpu/gl/iOS/GrGLCreateNativeInterface_iOS.cpp
@@ -143,6 +143,6 @@
 #endif
 
     interface->fStandard = kGLES_GrGLStandard;
-
+    interface->fExtensions.init(kGLES_GrGLStandard, glGetString, NULL, glGetIntegerv);
     return interface;
 }
diff --git a/src/gpu/gl/mac/GrGLCreateNativeInterface_mac.cpp b/src/gpu/gl/mac/GrGLCreateNativeInterface_mac.cpp
index ca5194d..96a38af 100644
--- a/src/gpu/gl/mac/GrGLCreateNativeInterface_mac.cpp
+++ b/src/gpu/gl/mac/GrGLCreateNativeInterface_mac.cpp
@@ -8,7 +8,6 @@
 
 
 #include "gl/GrGLInterface.h"
-#include "gl/GrGLExtensions.h"
 #include "../GrGLUtil.h"
 
 #include <dlfcn.h>
@@ -241,5 +240,7 @@
         // ARB extension doesn't use the ARB suffix on the function name
         GET_PROC(BindFragDataLocationIndexed);
     }
+
+    interface->fExtensions.swap(&extensions);
     return interface;
 }
diff --git a/src/gpu/gl/mesa/GrGLCreateMesaInterface.cpp b/src/gpu/gl/mesa/GrGLCreateMesaInterface.cpp
index 524ab09..709c3ae 100644
--- a/src/gpu/gl/mesa/GrGLCreateMesaInterface.cpp
+++ b/src/gpu/gl/mesa/GrGLCreateMesaInterface.cpp
@@ -220,7 +220,10 @@
             return NULL;
         }
         GR_GL_GET_PROC(BindFragDataLocationIndexed);
+
         interface->fStandard = kGL_GrGLStandard;
+        interface->fExtensions.swap(&extensions);
+
         return interface;
     } else {
         return NULL;
diff --git a/src/gpu/gl/unix/GrGLCreateNativeInterface_unix.cpp b/src/gpu/gl/unix/GrGLCreateNativeInterface_unix.cpp
index d8c1d76..a120808 100644
--- a/src/gpu/gl/unix/GrGLCreateNativeInterface_unix.cpp
+++ b/src/gpu/gl/unix/GrGLCreateNativeInterface_unix.cpp
@@ -7,7 +7,6 @@
  */
 
 
-#include "gl/GrGLExtensions.h"
 #include "gl/GrGLInterface.h"
 #include "../GrGLUtil.h"
 
@@ -276,6 +275,7 @@
         }
 
         interface->fStandard = kGL_GrGLStandard;
+        interface->fExtensions.swap(&extensions);
 
         return interface;
     } else {
diff --git a/src/gpu/gl/win/GrGLCreateNativeInterface_win.cpp b/src/gpu/gl/win/GrGLCreateNativeInterface_win.cpp
index 81f080e..e011605 100644
--- a/src/gpu/gl/win/GrGLCreateNativeInterface_win.cpp
+++ b/src/gpu/gl/win/GrGLCreateNativeInterface_win.cpp
@@ -6,8 +6,6 @@
  * found in the LICENSE file.
  */
 
-
-#include "gl/GrGLExtensions.h"
 #include "gl/GrGLInterface.h"
 #include "gl/GrGLUtil.h"
 #define WIN32_LEAN_AND_MEAN
@@ -308,6 +306,7 @@
         }
 
         interface->fStandard = kGL_GrGLStandard;
+        interface->fExtensions.swap(&extensions);
 
         return interface;
     } else {