Split Caps into Caps, Extensions and TextureFormatCaps.

Context now holds it's own Caps, Extensions and TextureFormat caps so that it
can modify them based on client version or work-arounds.

BUG=angle:658

Change-Id: Id71b6c89b7aa36e1f3dc42b0e4720eaed1851fb9
Reviewed-on: https://chromium-review.googlesource.com/206480
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Tested-by: Geoff Lang <geofflang@chromium.org>
diff --git a/src/libEGL/Display.cpp b/src/libEGL/Display.cpp
index 484165c..2c870ed 100644
--- a/src/libEGL/Display.cpp
+++ b/src/libEGL/Display.cpp
@@ -82,7 +82,7 @@
 
     EGLint minSwapInterval = mRenderer->getMinSwapInterval();
     EGLint maxSwapInterval = mRenderer->getMaxSwapInterval();
-    EGLint maxTextureSize = mRenderer->getCaps().max2DTextureSize;
+    EGLint maxTextureSize = mRenderer->getRendererCaps().max2DTextureSize;
 
     rx::ConfigDesc *descList;
     int numConfigs = mRenderer->generateConfigs(&descList);
@@ -344,7 +344,7 @@
         return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
     }
 
-    if (textureFormat != EGL_NO_TEXTURE && !mRenderer->getCaps().extensions.textureNPOT && (!gl::isPow2(width) || !gl::isPow2(height)))
+    if (textureFormat != EGL_NO_TEXTURE && !mRenderer->getRendererExtensions().textureNPOT && (!gl::isPow2(width) || !gl::isPow2(height)))
     {
         return error(EGL_BAD_MATCH, EGL_NO_SURFACE);
     }
diff --git a/src/libGLESv2/Caps.cpp b/src/libGLESv2/Caps.cpp
index f12c044..362e416 100644
--- a/src/libGLESv2/Caps.cpp
+++ b/src/libGLESv2/Caps.cpp
@@ -353,10 +353,7 @@
       maxViewportHeight(0),
       minAliasedPointSize(0),
       maxAliasedPointSize(0),
-      minAliasedLineWidth(0),
-      maxAliasedLineWidth(0),
-      textureCaps(),
-      extensions()
+      minAliasedLineWidth(0)
 {
 }
 
diff --git a/src/libGLESv2/Caps.h b/src/libGLESv2/Caps.h
index 4ae909c..ea627dc 100644
--- a/src/libGLESv2/Caps.h
+++ b/src/libGLESv2/Caps.h
@@ -208,11 +208,6 @@
     GLfloat minAliasedLineWidth;
     GLfloat maxAliasedLineWidth;
 
-    // Texture format support
-    TextureCapsMap textureCaps;
-
-    // Extension support
-    Extensions extensions;
 };
 
 }
diff --git a/src/libGLESv2/Context.cpp b/src/libGLESv2/Context.cpp
index fe7b361..c829a72 100644
--- a/src/libGLESv2/Context.cpp
+++ b/src/libGLESv2/Context.cpp
@@ -47,6 +47,10 @@
 
     setClearColor(0.0f, 0.0f, 0.0f, 0.0f);
 
+    mCaps = mRenderer->getRendererCaps();
+    mTextureCaps = mRenderer->getRendererTextureCaps();
+    mExtensions = mRenderer->getRendererExtensions();
+
     mClientVersion = clientVersion;
 
     mState.depthClearValue = 1.0f;
@@ -195,8 +199,6 @@
     mState.currentProgram = 0;
     mCurrentProgramBinary.set(NULL);
 
-    mRendererString = NULL;
-
     mInvalidEnum = false;
     mInvalidValue = false;
     mInvalidOperation = false;
@@ -314,15 +316,15 @@
         mSupportsVertexTexture = mRenderer->getVertexTextureSupport();
 
         mNumCompressedTextureFormats = 0;
-        if (getCaps().extensions.textureCompressionDXT1)
+        if (mExtensions.textureCompressionDXT1)
         {
             mNumCompressedTextureFormats += 2;
         }
-        if (getCaps().extensions.textureCompressionDXT3)
+        if (mExtensions.textureCompressionDXT3)
         {
             mNumCompressedTextureFormats += 1;
         }
-        if (getCaps().extensions.textureCompressionDXT5)
+        if (mExtensions.textureCompressionDXT5)
         {
             mNumCompressedTextureFormats += 1;
         }
@@ -1374,7 +1376,7 @@
 
 void Context::setRenderbufferStorage(GLsizei width, GLsizei height, GLenum internalformat, GLsizei samples)
 {
-    const TextureCaps &formatCaps = getCaps().textureCaps.get(internalformat);
+    const TextureCaps &formatCaps = getTextureCaps().get(internalformat);
 
     RenderbufferStorage *renderbuffer = NULL;
 
@@ -1636,12 +1638,12 @@
       case GL_POLYGON_OFFSET_FACTOR:    *params = mState.rasterizer.polygonOffsetFactor;    break;
       case GL_POLYGON_OFFSET_UNITS:     *params = mState.rasterizer.polygonOffsetUnits;     break;
       case GL_ALIASED_LINE_WIDTH_RANGE:
-        params[0] = getCaps().minAliasedLineWidth;
-        params[1] = getCaps().maxAliasedLineWidth;
+        params[0] = mCaps.minAliasedLineWidth;
+        params[1] = mCaps.maxAliasedLineWidth;
         break;
       case GL_ALIASED_POINT_SIZE_RANGE:
-        params[0] = getCaps().minAliasedPointSize;
-        params[1] = getCaps().maxAliasedPointSize;
+        params[0] = mCaps.minAliasedPointSize;
+        params[1] = mCaps.maxAliasedPointSize;
         break;
       case GL_DEPTH_RANGE:
         params[0] = mState.zNear;
@@ -1660,8 +1662,8 @@
         params[3] = mState.blendColor.alpha;
         break;
       case GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT:
-        ASSERT(getCaps().extensions.textureFilterAnisotropic);
-        *params = getCaps().extensions.maxTextureAnisotropy;
+        ASSERT(mExtensions.textureFilterAnisotropic);
+        *params = mExtensions.maxTextureAnisotropy;
         break;
       default:
         UNREACHABLE();
@@ -1671,12 +1673,10 @@
 
 void Context::getIntegerv(GLenum pname, GLint *params)
 {
-    const Caps &caps = getCaps();
-
     if (pname >= GL_DRAW_BUFFER0_EXT && pname <= GL_DRAW_BUFFER15_EXT)
     {
         unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0_EXT);
-        ASSERT(colorAttachment < caps.maxDrawBuffers);
+        ASSERT(colorAttachment < mCaps.maxDrawBuffers);
         Framebuffer *framebuffer = getDrawFramebuffer();
         *params = framebuffer->getDrawBufferState(colorAttachment);
         return;
@@ -1699,9 +1699,9 @@
       case GL_MAX_TEXTURE_IMAGE_UNITS:                  *params = gl::MAX_TEXTURE_IMAGE_UNITS;                          break;
       case GL_MAX_FRAGMENT_UNIFORM_VECTORS:             *params = mRenderer->getMaxFragmentUniformVectors();            break;
       case GL_MAX_FRAGMENT_UNIFORM_COMPONENTS:          *params = mRenderer->getMaxFragmentUniformVectors() * 4;        break;
-      case GL_MAX_RENDERBUFFER_SIZE:                    *params = caps.maxRenderbufferSize;                             break;
-      case GL_MAX_COLOR_ATTACHMENTS_EXT:                *params = caps.maxColorAttachments;                             break;
-      case GL_MAX_DRAW_BUFFERS_EXT:                     *params = caps.maxDrawBuffers;                                  break;
+      case GL_MAX_RENDERBUFFER_SIZE:                    *params = mCaps.maxRenderbufferSize;                            break;
+      case GL_MAX_COLOR_ATTACHMENTS_EXT:                *params = mCaps.maxColorAttachments;                            break;
+      case GL_MAX_DRAW_BUFFERS_EXT:                     *params = mCaps.maxDrawBuffers;                                 break;
       case GL_NUM_SHADER_BINARY_FORMATS:                *params = 0;                                                    break;
       case GL_SHADER_BINARY_FORMATS:                    /* no shader binary formats are supported */                    break;
       case GL_ARRAY_BUFFER_BINDING:                     *params = mState.arrayBuffer.id();                              break;
@@ -1741,10 +1741,10 @@
       case GL_STENCIL_BACK_WRITEMASK:                   *params = clampToInt(mState.depthStencil.stencilBackWritemask); break;
       case GL_STENCIL_CLEAR_VALUE:                      *params = mState.stencilClearValue;                             break;
       case GL_SUBPIXEL_BITS:                            *params = 4;                                                    break;
-      case GL_MAX_TEXTURE_SIZE:                         *params = caps.max2DTextureSize;                                break;
-      case GL_MAX_CUBE_MAP_TEXTURE_SIZE:                *params = caps.maxCubeMapTextureSize;                           break;
-      case GL_MAX_3D_TEXTURE_SIZE:                      *params = caps.max3DTextureSize;                                break;
-      case GL_MAX_ARRAY_TEXTURE_LAYERS:                 *params = caps.maxArrayTextureLayers;                           break;
+      case GL_MAX_TEXTURE_SIZE:                         *params = mCaps.max2DTextureSize;                               break;
+      case GL_MAX_CUBE_MAP_TEXTURE_SIZE:                *params = mCaps.maxCubeMapTextureSize;                          break;
+      case GL_MAX_3D_TEXTURE_SIZE:                      *params = mCaps.max3DTextureSize;                               break;
+      case GL_MAX_ARRAY_TEXTURE_LAYERS:                 *params = mCaps.maxArrayTextureLayers;                          break;
       case GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT:          *params = getUniformBufferOffsetAlignment();                    break;
       case GL_MAX_UNIFORM_BUFFER_BINDINGS:              *params = getMaximumCombinedUniformBufferBindings();            break;
       case GL_MAX_VERTEX_UNIFORM_BLOCKS:                *params = mRenderer->getMaxVertexShaderUniformBuffers();        break;
@@ -1805,22 +1805,22 @@
         break;
       case GL_MAX_VIEWPORT_DIMS:
         {
-            params[0] = getCaps().maxViewportWidth;
-            params[1] = getCaps().maxViewportHeight;
+            params[0] = mCaps.maxViewportWidth;
+            params[1] = mCaps.maxViewportHeight;
         }
         break;
       case GL_COMPRESSED_TEXTURE_FORMATS:
         {
-            if (getCaps().extensions.textureCompressionDXT1)
+            if (mExtensions.textureCompressionDXT1)
             {
                 *params++ = GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
                 *params++ = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
             }
-            if (getCaps().extensions.textureCompressionDXT3)
+            if (mExtensions.textureCompressionDXT3)
             {
                 *params++ = GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE;
             }
-            if (getCaps().extensions.textureCompressionDXT5)
+            if (mExtensions.textureCompressionDXT5)
             {
                 *params++ = GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE;
             }
@@ -1951,7 +1951,7 @@
     switch (pname)
     {
       case GL_MAX_ELEMENT_INDEX:
-        *params = getCaps().maxElementIndex;
+        *params = mCaps.maxElementIndex;
         break;
       case GL_MAX_UNIFORM_BLOCK_SIZE:
         *params = static_cast<GLint64>(mRenderer->getMaxUniformBufferSize());
@@ -2142,7 +2142,7 @@
         return true;
       case GL_MAX_SAMPLES_ANGLE:
         {
-            if (getCaps().extensions.framebufferMultisample)
+            if (mExtensions.framebufferMultisample)
             {
                 *type = GL_INT;
                 *numParams = 1;
@@ -2156,7 +2156,7 @@
       case GL_PIXEL_PACK_BUFFER_BINDING:
       case GL_PIXEL_UNPACK_BUFFER_BINDING:
         {
-            if (getCaps().extensions.pixelBufferObject)
+            if (mExtensions.pixelBufferObject)
             {
                 *type = GL_INT;
                 *numParams = 1;
@@ -2230,7 +2230,7 @@
         }
         return true;
       case GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT:
-        if (!getCaps().extensions.maxTextureAnisotropy)
+        if (!mExtensions.maxTextureAnisotropy)
         {
             return false;
         }
@@ -3092,7 +3092,17 @@
 
 const Caps &Context::getCaps() const
 {
-    return mRenderer->getCaps();
+    return mCaps;
+}
+
+const TextureCapsMap &Context::getTextureCaps() const
+{
+    return mTextureCaps;
+}
+
+const Extensions &Context::getExtensions() const
+{
+    return mExtensions;
 }
 
 int Context::getMajorShaderModel() const
@@ -3501,30 +3511,26 @@
     mRendererString = MakeStaticString(rendererString.str());
 }
 
-const char *Context::getRendererString() const
+const std::string &Context::getRendererString() const
 {
     return mRendererString;
 }
 
 void Context::initExtensionStrings()
 {
-    std::ostringstream combinedStringStream;
+    mExtensionStrings = mExtensions.getStrings(mClientVersion);
 
-    std::vector<std::string> extensions = getCaps().extensions.getStrings(mClientVersion);
-    for (size_t i = 0; i < extensions.size(); i++)
-    {
-        combinedStringStream << extensions[i] << " ";
-        mExtensionStrings.push_back(MakeStaticString(extensions[i]));
-    }
-    mExtensionString = MakeStaticString(combinedStringStream.str());
+    std::ostringstream combinedStringStream;
+    std::copy(mExtensionStrings.begin(), mExtensionStrings.end(), std::ostream_iterator<std::string>(combinedStringStream, " "));
+    mExtensionString = combinedStringStream.str();
 }
 
-const char *Context::getExtensionString() const
+const std::string &Context::getExtensionString() const
 {
     return mExtensionString;
 }
 
-const char *Context::getExtensionString(size_t idx) const
+const std::string &Context::getExtensionString(size_t idx) const
 {
     return mExtensionStrings[idx];
 }
diff --git a/src/libGLESv2/Context.h b/src/libGLESv2/Context.h
index 21d61de..9dc4d16 100644
--- a/src/libGLESv2/Context.h
+++ b/src/libGLESv2/Context.h
@@ -402,6 +402,8 @@
     virtual int getClientVersion() const;
 
     const Caps &getCaps() const;
+    const TextureCapsMap &getTextureCaps() const;
+    const Extensions &getExtensions() const;
 
     int getMajorShaderModel() const;
     unsigned int getMaximumCombinedTextureImageUnits() const;
@@ -412,10 +414,10 @@
     void getSampleCounts(GLenum internalFormat, GLsizei bufSize, GLint *params) const;
     unsigned int getMaxTransformFeedbackBufferBindings() const;
     GLintptr getUniformBufferOffsetAlignment() const;
-    const char *getRendererString() const;
+    const std::string &getRendererString() const;
 
-    const char *getExtensionString() const;
-    const char *getExtensionString(size_t idx) const;
+    const std::string &getExtensionString() const;
+    const std::string &getExtensionString(size_t idx) const;
     size_t getExtensionStringCount() const;
 
     void getCurrentReadFormatType(GLenum *internalFormat, GLenum *format, GLenum *type);
@@ -466,6 +468,11 @@
 
     size_t getBoundFramebufferTextureSerials(FramebufferTextureSerialArray *outSerialArray);
 
+    // Caps to use for validation
+    Caps mCaps;
+    TextureCapsMap mTextureCaps;
+    Extensions mExtensions;
+
     rx::Renderer *const mRenderer;
 
     int mClientVersion;
@@ -498,9 +505,9 @@
     TransformFeedbackMap mTransformFeedbackMap;
     HandleAllocator mTransformFeedbackAllocator;
 
-    const char *mRendererString;
-    const char *mExtensionString;
-    std::vector<const char *> mExtensionStrings;
+    std::string mRendererString;
+    std::string mExtensionString;
+    std::vector<std::string> mExtensionStrings;
 
     BindingPointer<Texture> mIncompleteTextures[TEXTURE_TYPE_COUNT];
 
diff --git a/src/libGLESv2/DynamicHLSL.cpp b/src/libGLESv2/DynamicHLSL.cpp
index a4db907..1f1dc20 100644
--- a/src/libGLESv2/DynamicHLSL.cpp
+++ b/src/libGLESv2/DynamicHLSL.cpp
@@ -659,7 +659,7 @@
     // - with a 3.0 context, the output color is copied to channel 0
     // - with a 2.0 context, the output color is broadcast to all channels
     const bool broadcast = (fragmentShader->mUsesFragColor && mRenderer->getCurrentClientVersion() < 3);
-    const unsigned int numRenderTargets = (broadcast || usesMRT ? mRenderer->getCaps().maxDrawBuffers : 1);
+    const unsigned int numRenderTargets = (broadcast || usesMRT ? mRenderer->getRendererCaps().maxDrawBuffers : 1);
 
     int shaderVersion = vertexShader->getShaderVersion();
 
@@ -996,6 +996,7 @@
     std::string inLinkHLSL = generateVaryingLinkHLSL(inSemantics, varyingHLSL);
     std::string outLinkHLSL = generateVaryingLinkHLSL(outSemantics, varyingHLSL);
 
+    // TODO(geofflang): use context's caps
     geomHLSL += "uniform float4 dx_ViewCoords : register(c1);\n"
                 "\n"
                 "struct GS_INPUT\n" + inLinkHLSL + "\n" +
@@ -1017,8 +1018,8 @@
                   "    float2(0.0f, 0.0f)\n"
                   "};\n"
                   "\n"
-                  "static float minPointSize = " + Str(mRenderer->getCaps().minAliasedPointSize) + ".0f;\n"
-                  "static float maxPointSize = " + Str(mRenderer->getCaps().maxAliasedPointSize) + ".0f;\n"
+                  "static float minPointSize = " + Str(mRenderer->getRendererCaps().minAliasedPointSize) + ".0f;\n"
+                  "static float maxPointSize = " + Str(mRenderer->getRendererCaps().maxAliasedPointSize) + ".0f;\n"
                   "\n"
                   "[maxvertexcount(4)]\n"
                   "void main(point GS_INPUT input[1], inout TriangleStream<GS_OUTPUT> outStream)\n"
diff --git a/src/libGLESv2/Framebuffer.cpp b/src/libGLESv2/Framebuffer.cpp
index b40279e..bcd174a 100644
--- a/src/libGLESv2/Framebuffer.cpp
+++ b/src/libGLESv2/Framebuffer.cpp
@@ -361,7 +361,8 @@
             }
 
             GLenum internalformat = colorbuffer->getInternalFormat();
-            const TextureCaps &formatCaps = mRenderer->getCaps().textureCaps.get(internalformat);
+            // TODO(geofflang): use context's texture caps
+            const TextureCaps &formatCaps = mRenderer->getRendererTextureCaps().get(internalformat);
             if (colorbuffer->isTexture())
             {
                 if (!formatCaps.colorRendering)
@@ -440,13 +441,15 @@
         }
 
         GLenum internalformat = mDepthbuffer->getInternalFormat();
-        const TextureCaps &formatCaps = mRenderer->getCaps().textureCaps.get(internalformat);
+        // TODO(geofflang): use context's texture caps
+        const TextureCaps &formatCaps = mRenderer->getRendererTextureCaps().get(internalformat);
         if (mDepthbuffer->isTexture())
         {
             GLenum internalformat = mDepthbuffer->getInternalFormat();
 
             // depth texture attachments require OES/ANGLE_depth_texture
-            if (!mRenderer->getCaps().extensions.depthTextures)
+            // TODO(geofflang): use context's extensions
+            if (!mRenderer->getRendererExtensions().depthTextures)
             {
                 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
             }
@@ -494,14 +497,16 @@
         }
 
         GLenum internalformat = mStencilbuffer->getInternalFormat();
-        const TextureCaps &formatCaps = mRenderer->getCaps().textureCaps.get(internalformat);
+        // TODO(geofflang): use context's texture caps
+        const TextureCaps &formatCaps = mRenderer->getRendererTextureCaps().get(internalformat);
         if (mStencilbuffer->isTexture())
         {
             GLenum internalformat = mStencilbuffer->getInternalFormat();
 
             // texture stencil attachments come along as part
             // of OES_packed_depth_stencil + OES/ANGLE_depth_texture
-            if (!mRenderer->getCaps().extensions.depthTextures)
+            // TODO(geofflang): use context's extensions
+            if (!mRenderer->getRendererExtensions().depthTextures)
             {
                 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
             }
diff --git a/src/libGLESv2/Shader.cpp b/src/libGLESv2/Shader.cpp
index ed0171a..b3c09fe 100644
--- a/src/libGLESv2/Shader.cpp
+++ b/src/libGLESv2/Shader.cpp
@@ -184,7 +184,9 @@
             ShBuiltInResources resources;
             ShInitBuiltInResources(&resources);
 
-            const gl::Caps &caps = mRenderer->getCaps();
+            // TODO(geofflang): use context's caps
+            const gl::Caps &caps = mRenderer->getRendererCaps();
+            const gl::Extensions &extensions = mRenderer->getRendererExtensions();
 
             resources.MaxVertexAttribs = MAX_VERTEX_ATTRIBS;
             resources.MaxVertexUniformVectors = mRenderer->getMaxVertexUniformVectors();
@@ -194,8 +196,8 @@
             resources.MaxTextureImageUnits = MAX_TEXTURE_IMAGE_UNITS;
             resources.MaxFragmentUniformVectors = mRenderer->getMaxFragmentUniformVectors();
             resources.MaxDrawBuffers = caps.maxDrawBuffers;
-            resources.OES_standard_derivatives = caps.extensions.standardDerivatives;
-            resources.EXT_draw_buffers = caps.extensions.drawBuffers;
+            resources.OES_standard_derivatives = extensions.standardDerivatives;
+            resources.EXT_draw_buffers = extensions.drawBuffers;
             resources.EXT_shader_texture_lod = 1;
             // resources.OES_EGL_image_external = mRenderer->getShareHandleSupport() ? 1 : 0; // TODO: commented out until the extension is actually supported.
             resources.FragmentPrecisionHigh = 1;   // Shader Model 2+ always supports FP24 (s16e7) which corresponds to highp
diff --git a/src/libGLESv2/Texture.cpp b/src/libGLESv2/Texture.cpp
index 7520575..87327ea 100644
--- a/src/libGLESv2/Texture.cpp
+++ b/src/libGLESv2/Texture.cpp
@@ -258,7 +258,8 @@
 
 GLint Texture::creationLevels(GLsizei width, GLsizei height, GLsizei depth) const
 {
-    if ((isPow2(width) && isPow2(height) && isPow2(depth)) || mRenderer->getCaps().extensions.textureNPOT)
+    // TODO(geofflang): use context's extensions
+    if ((isPow2(width) && isPow2(height) && isPow2(depth)) || mRenderer->getRendererExtensions().textureNPOT)
     {
         // Maximum number of levels
         return log2(std::max(std::max(width, height), depth)) + 1;
@@ -592,7 +593,8 @@
         return false;
     }
 
-    if (!mRenderer->getCaps().textureCaps.get(getInternalFormat(0)).filtering)
+    // TODO(geofflang): use context's texture caps
+    if (!mRenderer->getRendererTextureCaps().get(getInternalFormat(0)).filtering)
     {
         if (samplerState.magFilter != GL_NEAREST ||
             (samplerState.minFilter != GL_NEAREST && samplerState.minFilter != GL_NEAREST_MIPMAP_NEAREST))
@@ -601,7 +603,8 @@
         }
     }
 
-    bool npotSupport = mRenderer->getCaps().extensions.textureNPOT;
+    // TODO(geofflang): use context's extensions
+    bool npotSupport = mRenderer->getRendererExtensions().textureNPOT;
 
     if (!npotSupport)
     {
@@ -1022,7 +1025,8 @@
 
     bool mipmapping = IsMipmapFiltered(samplerState);
 
-    if (!mRenderer->getCaps().textureCaps.get(getInternalFormat(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0)).filtering)
+    // TODO(geofflang): use context's texture caps
+    if (!mRenderer->getRendererTextureCaps().get(getInternalFormat(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0)).filtering)
     {
         if (samplerState.magFilter != GL_NEAREST ||
             (samplerState.minFilter != GL_NEAREST && samplerState.minFilter != GL_NEAREST_MIPMAP_NEAREST))
@@ -1031,7 +1035,8 @@
         }
     }
 
-    if (!isPow2(size) && !mRenderer->getCaps().extensions.textureNPOT)
+    // TODO(geofflang): use context's extensions
+    if (!isPow2(size) && !mRenderer->getRendererExtensions().textureNPOT)
     {
         if (samplerState.wrapS != GL_CLAMP_TO_EDGE || samplerState.wrapT != GL_CLAMP_TO_EDGE || mipmapping)
         {
@@ -1743,7 +1748,8 @@
         return false;
     }
 
-    if (!mRenderer->getCaps().textureCaps.get(getInternalFormat(0)).filtering)
+    // TODO(geofflang): use context's texture caps
+    if (!mRenderer->getRendererTextureCaps().get(getInternalFormat(0)).filtering)
     {
         if (samplerState.magFilter != GL_NEAREST ||
             (samplerState.minFilter != GL_NEAREST && samplerState.minFilter != GL_NEAREST_MIPMAP_NEAREST))
@@ -2278,7 +2284,8 @@
         return false;
     }
 
-    if (!mRenderer->getCaps().textureCaps.get(getBaseLevelInternalFormat()).filtering)
+    // TODO(geofflang): use context's texture caps
+    if (!mRenderer->getRendererTextureCaps().get(getBaseLevelInternalFormat()).filtering)
     {
         if (samplerState.magFilter != GL_NEAREST ||
             (samplerState.minFilter != GL_NEAREST && samplerState.minFilter != GL_NEAREST_MIPMAP_NEAREST))
diff --git a/src/libGLESv2/libGLESv2.cpp b/src/libGLESv2/libGLESv2.cpp
index f5cf7c3..b973c54 100644
--- a/src/libGLESv2/libGLESv2.cpp
+++ b/src/libGLESv2/libGLESv2.cpp
@@ -1990,7 +1990,7 @@
             }
 
             GLenum internalFormat = texture->getBaseLevelInternalFormat();
-            const gl::TextureCaps &formatCaps = context->getCaps().textureCaps.get(internalFormat);
+            const gl::TextureCaps &formatCaps = context->getTextureCaps().get(internalFormat);
 
             // GenerateMipmap should not generate an INVALID_OPERATION for textures created with
             // unsized formats or that are color renderable and filterable.  Since we do not track if
@@ -2017,7 +2017,7 @@
             }
 
             // Non-power of 2 ES2 check
-            if (!context->getCaps().extensions.textureNPOT && (!gl::isPow2(texture->getBaseLevelWidth()) || !gl::isPow2(texture->getBaseLevelHeight())))
+            if (!context->getExtensions().textureNPOT && (!gl::isPow2(texture->getBaseLevelWidth()) || !gl::isPow2(texture->getBaseLevelHeight())))
             {
                 ASSERT(context->getClientVersion() <= 2 && (target == GL_TEXTURE_2D || target == GL_TEXTURE_CUBE_MAP));
                 return gl::error(GL_INVALID_OPERATION);
@@ -2553,7 +2553,7 @@
               case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
                 break;
               case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
-                if (clientVersion < 3 && !context->getCaps().extensions.sRGB)
+                if (clientVersion < 3 && !context->getExtensions().sRGB)
                 {
                     return gl::error(GL_INVALID_ENUM);
                 }
@@ -3091,7 +3091,7 @@
               case GL_RENDERBUFFER_DEPTH_SIZE:      *params = renderbuffer->getDepthSize();      break;
               case GL_RENDERBUFFER_STENCIL_SIZE:    *params = renderbuffer->getStencilSize();    break;
               case GL_RENDERBUFFER_SAMPLES_ANGLE:
-                if (!context->getCaps().extensions.framebufferMultisample)
+                if (!context->getExtensions().framebufferMultisample)
                 {
                     return gl::error(GL_INVALID_ENUM);
                 }
@@ -3310,7 +3310,7 @@
           case GL_VENDOR:
             return (GLubyte*)"Google Inc.";
           case GL_RENDERER:
-            return (GLubyte*)((context != NULL) ? context->getRendererString() : "ANGLE");
+            return (GLubyte*)((context != NULL) ? context->getRendererString().c_str() : "ANGLE");
           case GL_VERSION:
             if (context->getClientVersion() == 2)
             {
@@ -3330,7 +3330,7 @@
                 return (GLubyte*)"OpenGL ES GLSL ES 3.00 (ANGLE " ANGLE_VERSION_STRING ")";
             }
           case GL_EXTENSIONS:
-            return (GLubyte*)((context != NULL) ? context->getExtensionString() : "");
+            return (GLubyte*)((context != NULL) ? context->getExtensionString().c_str() : "");
           default:
             return gl::error(GL_INVALID_ENUM, (GLubyte*)NULL);
         }
@@ -3394,7 +3394,7 @@
                 *params = (GLfloat)texture->getUsage();
                 break;
               case GL_TEXTURE_MAX_ANISOTROPY_EXT:
-                if (!context->getCaps().extensions.textureFilterAnisotropic)
+                if (!context->getExtensions().textureFilterAnisotropic)
                 {
                     return gl::error(GL_INVALID_ENUM);
                 }
@@ -3520,7 +3520,7 @@
                 *params = texture->getUsage();
                 break;
               case GL_TEXTURE_MAX_ANISOTROPY_EXT:
-                if (!context->getCaps().extensions.textureFilterAnisotropic)
+                if (!context->getExtensions().textureFilterAnisotropic)
                 {
                     return gl::error(GL_INVALID_ENUM);
                 }
@@ -4900,7 +4900,7 @@
               case GL_TEXTURE_MIN_FILTER:           texture->getSamplerState().minFilter = gl::uiround<GLenum>(param);    break;
               case GL_TEXTURE_MAG_FILTER:           texture->getSamplerState().magFilter = gl::uiround<GLenum>(param);    break;
               case GL_TEXTURE_USAGE_ANGLE:          texture->setUsage(gl::uiround<GLenum>(param));                        break;
-              case GL_TEXTURE_MAX_ANISOTROPY_EXT:   texture->getSamplerState().maxAnisotropy = std::min(param, context->getCaps().extensions.maxTextureAnisotropy); break;
+              case GL_TEXTURE_MAX_ANISOTROPY_EXT:   texture->getSamplerState().maxAnisotropy = std::min(param, context->getExtensions().maxTextureAnisotropy); break;
               case GL_TEXTURE_COMPARE_MODE:         texture->getSamplerState().compareMode = gl::uiround<GLenum>(param);  break;
               case GL_TEXTURE_COMPARE_FUNC:         texture->getSamplerState().compareFunc = gl::uiround<GLenum>(param);  break;
               case GL_TEXTURE_SWIZZLE_R:            texture->getSamplerState().swizzleRed = gl::uiround<GLenum>(param);   break;
@@ -4956,7 +4956,7 @@
               case GL_TEXTURE_MIN_FILTER:           texture->getSamplerState().minFilter = (GLenum)param;    break;
               case GL_TEXTURE_MAG_FILTER:           texture->getSamplerState().magFilter = (GLenum)param;    break;
               case GL_TEXTURE_USAGE_ANGLE:          texture->setUsage((GLenum)param);                        break;
-              case GL_TEXTURE_MAX_ANISOTROPY_EXT:   texture->getSamplerState().maxAnisotropy = std::min((float)param, context->getCaps().extensions.maxTextureAnisotropy); break;
+              case GL_TEXTURE_MAX_ANISOTROPY_EXT:   texture->getSamplerState().maxAnisotropy = std::min((float)param, context->getExtensions().maxTextureAnisotropy); break;
               case GL_TEXTURE_COMPARE_MODE:         texture->getSamplerState().compareMode = (GLenum)param;  break;
               case GL_TEXTURE_COMPARE_FUNC:         texture->getSamplerState().compareFunc = (GLenum)param;  break;
               case GL_TEXTURE_SWIZZLE_R:            texture->getSamplerState().swizzleRed = (GLenum)param;   break;
@@ -4993,7 +4993,7 @@
 
         if (context)
         {
-            if (!context->getCaps().extensions.textureStorage)
+            if (!context->getExtensions().textureStorage)
             {
                 return gl::error(GL_INVALID_OPERATION);
             }
@@ -7997,7 +7997,7 @@
                 return gl::error(GL_INVALID_VALUE, reinterpret_cast<GLubyte*>(NULL));
             }
 
-            return reinterpret_cast<const GLubyte*>(context->getExtensionString(index));
+            return reinterpret_cast<const GLubyte*>(context->getExtensionString(index).c_str());
         }
     }
     ANGLE_CATCH_ALL
@@ -9612,7 +9612,7 @@
                 return gl::error(GL_INVALID_OPERATION);
             }
 
-            const gl::TextureCaps &formatCaps = context->getCaps().textureCaps.get(internalformat);
+            const gl::TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
             if (!formatCaps.colorRendering && !formatCaps.depthRendering && !formatCaps.stencilRendering)
             {
                 return gl::error(GL_INVALID_ENUM);
diff --git a/src/libGLESv2/renderer/Renderer.cpp b/src/libGLESv2/renderer/Renderer.cpp
index eb5e2fe..40ea5ec 100644
--- a/src/libGLESv2/renderer/Renderer.cpp
+++ b/src/libGLESv2/renderer/Renderer.cpp
@@ -43,17 +43,39 @@
     gl::Shader::releaseCompiler();
 }
 
-const gl::Caps &Renderer::getCaps() const
+const gl::Caps &Renderer::getRendererCaps() const
 {
     if (!mCapsInitialized)
     {
-        mCaps = generateCaps();
+        generateCaps(&mCaps, &mTextureCaps, &mExtensions);
         mCapsInitialized = true;
     }
 
     return mCaps;
 }
 
+const gl::TextureCapsMap &Renderer::getRendererTextureCaps() const
+{
+    if (!mCapsInitialized)
+    {
+        generateCaps(&mCaps, &mTextureCaps, &mExtensions);
+        mCapsInitialized = true;
+    }
+
+    return mTextureCaps;
+}
+
+const gl::Extensions &Renderer::getRendererExtensions() const
+{
+    if (!mCapsInitialized)
+    {
+        generateCaps(&mCaps, &mTextureCaps, &mExtensions);
+        mCapsInitialized = true;
+    }
+
+    return mExtensions;
+}
+
 }
 
 extern "C"
diff --git a/src/libGLESv2/renderer/Renderer.h b/src/libGLESv2/renderer/Renderer.h
index 919b5a5..1ca5f3c 100644
--- a/src/libGLESv2/renderer/Renderer.h
+++ b/src/libGLESv2/renderer/Renderer.h
@@ -144,7 +144,9 @@
     virtual bool testDeviceResettable() = 0;
 
     // Renderer capabilities (virtual because it is used by egl::Display, do not override)
-    virtual const gl::Caps &getCaps() const;
+    virtual const gl::Caps &getRendererCaps() const;
+    virtual const gl::TextureCapsMap &getRendererTextureCaps() const;
+    virtual const gl::Extensions &getRendererExtensions() const;
 
     virtual DWORD getAdapterVendor() const = 0;
     virtual std::string getRendererDescription() const = 0;
@@ -255,10 +257,12 @@
   private:
     DISALLOW_COPY_AND_ASSIGN(Renderer);
 
-    virtual gl::Caps generateCaps() const = 0;
+    virtual void generateCaps(gl::Caps *outCaps, gl::TextureCapsMap* outTextureCaps, gl::Extensions *outExtensions) const = 0;
 
     mutable bool mCapsInitialized;
     mutable gl::Caps mCaps;
+    mutable gl::TextureCapsMap mTextureCaps;
+    mutable gl::Extensions mExtensions;
 
     int mCurrentClientVersion;
 };
diff --git a/src/libGLESv2/renderer/d3d/d3d11/Blit11.cpp b/src/libGLESv2/renderer/d3d/d3d11/Blit11.cpp
index b70cf41..446149c 100644
--- a/src/libGLESv2/renderer/d3d/d3d11/Blit11.cpp
+++ b/src/libGLESv2/renderer/d3d/d3d11/Blit11.cpp
@@ -186,7 +186,7 @@
 
     D3D11_BUFFER_DESC vbDesc;
     vbDesc.ByteWidth = std::max(sizeof(d3d11::PositionLayerTexCoord3DVertex), sizeof(d3d11::PositionTexCoordVertex)) *
-                       6 * renderer->getCaps().max3DTextureSize;
+                       6 * renderer->getRendererCaps().max3DTextureSize;
     vbDesc.Usage = D3D11_USAGE_DYNAMIC;
     vbDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
     vbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
diff --git a/src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp b/src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp
index d999cd8..1100656 100644
--- a/src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp
+++ b/src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp
@@ -349,7 +349,7 @@
         // be a compatible clear type.
 
         // Bind all the render targets which need clearing
-        ASSERT(maskedClearRenderTargets.size() <= mRenderer->getCaps().maxDrawBuffers);
+        ASSERT(maskedClearRenderTargets.size() <= mRenderer->getRendererCaps().maxDrawBuffers);
         std::vector<ID3D11RenderTargetView*> rtvs(maskedClearRenderTargets.size());
         for (unsigned int i = 0; i < maskedClearRenderTargets.size(); i++)
         {
diff --git a/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp b/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp
index 646bd9b..9ad4396 100644
--- a/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp
+++ b/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp
@@ -724,7 +724,7 @@
         actualZFar = 1.0f;
     }
 
-    const gl::Caps& caps = getCaps();
+    const gl::Caps& caps = getRendererCaps();
 
     // Clamp width and height first to the gl maximum, then clamp further if we extend past the D3D maximum bounds
     D3D11_VIEWPORT dxViewport;
@@ -910,7 +910,7 @@
         depthbufferSerial != mAppliedDepthbufferSerial ||
         stencilbufferSerial != mAppliedStencilbufferSerial)
     {
-        mDeviceContext->OMSetRenderTargets(getCaps().maxDrawBuffers, framebufferRTVs, framebufferDSV);
+        mDeviceContext->OMSetRenderTargets(getRendererCaps().maxDrawBuffers, framebufferRTVs, framebufferDSV);
 
         mRenderTargetDesc.width = renderTargetWidth;
         mRenderTargetDesc.height = renderTargetHeight;
@@ -1966,7 +1966,7 @@
     // We only currently support share handles with BGRA surfaces, because
     // chrome needs BGRA. Once chrome fixes this, we should always support them.
     // PIX doesn't seem to support using share handles, so disable them.
-    return getCaps().extensions.textureFormatBGRA8888 && !gl::perfActive();
+    return getRendererExtensions().textureFormatBGRA8888 && !gl::perfActive();
 }
 
 bool Renderer11::getPostSubBufferSupport() const
@@ -2443,7 +2443,7 @@
 
     rtvArray[0] = renderTargetView;
 
-    mDeviceContext->OMSetRenderTargets(getCaps().maxDrawBuffers, rtvArray, NULL);
+    mDeviceContext->OMSetRenderTargets(getRendererCaps().maxDrawBuffers, rtvArray, NULL);
 
     // Do not preserve the serial for this one-time-use render target
     for (unsigned int rtIndex = 0; rtIndex < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; rtIndex++)
@@ -2689,7 +2689,7 @@
 
 bool Renderer11::supportsFastCopyBufferToTexture(GLenum internalFormat) const
 {
-    ASSERT(getCaps().extensions.pixelBufferObject);
+    ASSERT(getRendererExtensions().pixelBufferObject);
 
     // sRGB formats do not work with D3D11 buffer SRVs
     if (gl::GetColorEncoding(internalFormat) == GL_SRGB)
@@ -2698,7 +2698,7 @@
     }
 
     // We cannot support direct copies to non-color-renderable formats
-    if (!getCaps().textureCaps.get(internalFormat).colorRendering)
+    if (!getRendererTextureCaps().get(internalFormat).colorRendering)
     {
         return false;
     }
@@ -3406,9 +3406,9 @@
     return supportInfo;
 }
 
-gl::Caps Renderer11::generateCaps() const
+void Renderer11::generateCaps(gl::Caps *outCaps, gl::TextureCapsMap *outTextureCaps, gl::Extensions *outExtensions) const
 {
-    return d3d11_gl::GenerateCaps(mDevice);
+    d3d11_gl::GenerateCaps(mDevice, outCaps, outTextureCaps, outExtensions);
 }
 
 }
diff --git a/src/libGLESv2/renderer/d3d/d3d11/Renderer11.h b/src/libGLESv2/renderer/d3d/d3d11/Renderer11.h
index 8bb8945..9bb08ac 100644
--- a/src/libGLESv2/renderer/d3d/d3d11/Renderer11.h
+++ b/src/libGLESv2/renderer/d3d/d3d11/Renderer11.h
@@ -214,7 +214,7 @@
   private:
     DISALLOW_COPY_AND_ASSIGN(Renderer11);
 
-    virtual gl::Caps generateCaps() const;
+    virtual void generateCaps(gl::Caps *outCaps, gl::TextureCapsMap *outTextureCaps, gl::Extensions *outExtensions) const;
 
     void drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer);
     void drawTriangleFan(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer, int instances);
diff --git a/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp b/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp
index 9710899..2bf1c92 100644
--- a/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp
+++ b/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp
@@ -501,79 +501,76 @@
     }
 }
 
-gl::Caps GenerateCaps(ID3D11Device *device)
+void GenerateCaps(ID3D11Device *device, gl::Caps *caps, gl::TextureCapsMap *textureCapsMap, gl::Extensions *extensions)
 {
-    gl::Caps caps;
-
     const gl::FormatSet &allFormats = gl::GetAllSizedInternalFormats();
     for (gl::FormatSet::const_iterator internalFormat = allFormats.begin(); internalFormat != allFormats.end(); ++internalFormat)
     {
-        caps.textureCaps.insert(*internalFormat, GenerateTextureFormatCaps(*internalFormat, device));
+        gl::TextureCaps textureCaps = GenerateTextureFormatCaps(*internalFormat, device);
+        textureCapsMap->insert(*internalFormat, textureCaps);
     }
 
     D3D_FEATURE_LEVEL featureLevel = device->GetFeatureLevel();
 
     // GL core feature limits
-    caps.maxElementIndex = static_cast<GLint64>(std::numeric_limits<unsigned int>::max());
-    caps.max3DTextureSize = GetMaximum3DTextureSize(featureLevel);
-    caps.max2DTextureSize = GetMaximum2DTextureSize(featureLevel);
-    caps.maxCubeMapTextureSize = GetMaximumCubeMapTextureSize(featureLevel);
-    caps.maxArrayTextureLayers = GetMaximum2DTextureArraySize(featureLevel);
+    caps->maxElementIndex = static_cast<GLint64>(std::numeric_limits<unsigned int>::max());
+    caps->max3DTextureSize = GetMaximum3DTextureSize(featureLevel);
+    caps->max2DTextureSize = GetMaximum2DTextureSize(featureLevel);
+    caps->maxCubeMapTextureSize = GetMaximumCubeMapTextureSize(featureLevel);
+    caps->maxArrayTextureLayers = GetMaximum2DTextureArraySize(featureLevel);
 
     // Unimplemented, set to minimum required
-    caps.maxLODBias = 2.0f;
+    caps->maxLODBias = 2.0f;
 
     // No specific limits on render target size, maximum 2D texture size is equivalent
-    caps.maxRenderbufferSize = caps.max2DTextureSize;
+    caps->maxRenderbufferSize = caps->max2DTextureSize;
 
     // Maximum draw buffers and color attachments are the same, max color attachments could eventually be
     // increased to 16
-    caps.maxDrawBuffers = GetMaximumSimultaneousRenderTargets(featureLevel);
-    caps.maxColorAttachments = GetMaximumSimultaneousRenderTargets(featureLevel);
+    caps->maxDrawBuffers = GetMaximumSimultaneousRenderTargets(featureLevel);
+    caps->maxColorAttachments = GetMaximumSimultaneousRenderTargets(featureLevel);
 
     // D3D11 has the same limit for viewport width and height
-    caps.maxViewportWidth = GetMaximumViewportSize(featureLevel);
-    caps.maxViewportHeight = caps.maxViewportWidth;
+    caps->maxViewportWidth = GetMaximumViewportSize(featureLevel);
+    caps->maxViewportHeight = caps->maxViewportWidth;
 
     // Choose a reasonable maximum, enforced in the shader.
-    caps.minAliasedPointSize = 1.0f;
-    caps.maxAliasedPointSize = 1024.0f;
+    caps->minAliasedPointSize = 1.0f;
+    caps->maxAliasedPointSize = 1024.0f;
 
     // Wide lines not supported
-    caps.minAliasedLineWidth = 1.0f;
-    caps.maxAliasedLineWidth = 1.0f;
+    caps->minAliasedLineWidth = 1.0f;
+    caps->maxAliasedLineWidth = 1.0f;
 
     // GL extension support
-    caps.extensions.setTextureExtensionSupport(caps.textureCaps);
-    caps.extensions.elementIndexUint = true;
-    caps.extensions.packedDepthStencil = true;
-    caps.extensions.getProgramBinary = true;
-    caps.extensions.rgb8rgba8 = true;
-    caps.extensions.readFormatBGRA = true;
-    caps.extensions.pixelBufferObject = true;
-    caps.extensions.mapBuffer = true;
-    caps.extensions.mapBufferRange = true;
-    caps.extensions.textureNPOT = GetNPOTTextureSupport(featureLevel);
-    caps.extensions.drawBuffers = GetMaximumSimultaneousRenderTargets(featureLevel) > 1;
-    caps.extensions.textureStorage = true;
-    caps.extensions.textureFilterAnisotropic = true;
-    caps.extensions.maxTextureAnisotropy = GetMaximumAnisotropy(featureLevel);
-    caps.extensions.occlusionQueryBoolean = GetOcclusionQuerySupport(featureLevel);
-    caps.extensions.fence = GetEventQuerySupport(featureLevel);
-    caps.extensions.timerQuery = false; // Unimplemented
-    caps.extensions.robustness = true;
-    caps.extensions.blendMinMax = true;
-    caps.extensions.framebufferBlit = true;
-    caps.extensions.framebufferMultisample = true;
-    caps.extensions.instancedArrays = GetInstancingSupport(featureLevel);
-    caps.extensions.packReverseRowOrder = true;
-    caps.extensions.standardDerivatives = GetDerivativeInstructionSupport(featureLevel);
-    caps.extensions.shaderTextureLOD = true;
-    caps.extensions.fragDepth = true;
-    caps.extensions.textureUsage = true; // This could be false since it has no effect in D3D11
-    caps.extensions.translatedShaderSource = true;
-
-    return caps;
+    extensions->setTextureExtensionSupport(*textureCapsMap);
+    extensions->elementIndexUint = true;
+    extensions->packedDepthStencil = true;
+    extensions->getProgramBinary = true;
+    extensions->rgb8rgba8 = true;
+    extensions->readFormatBGRA = true;
+    extensions->pixelBufferObject = true;
+    extensions->mapBuffer = true;
+    extensions->mapBufferRange = true;
+    extensions->textureNPOT = GetNPOTTextureSupport(featureLevel);
+    extensions->drawBuffers = GetMaximumSimultaneousRenderTargets(featureLevel) > 1;
+    extensions->textureStorage = true;
+    extensions->textureFilterAnisotropic = true;
+    extensions->maxTextureAnisotropy = GetMaximumAnisotropy(featureLevel);
+    extensions->occlusionQueryBoolean = GetOcclusionQuerySupport(featureLevel);
+    extensions->fence = GetEventQuerySupport(featureLevel);
+    extensions->timerQuery = false; // Unimplemented
+    extensions->robustness = true;
+    extensions->blendMinMax = true;
+    extensions->framebufferBlit = true;
+    extensions->framebufferMultisample = true;
+    extensions->instancedArrays = GetInstancingSupport(featureLevel);
+    extensions->packReverseRowOrder = true;
+    extensions->standardDerivatives = GetDerivativeInstructionSupport(featureLevel);
+    extensions->shaderTextureLOD = true;
+    extensions->fragDepth = true;
+    extensions->textureUsage = true; // This could be false since it has no effect in D3D11
+    extensions->translatedShaderSource = true;
 }
 
 }
diff --git a/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.h b/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.h
index e5e3e1c..4de9bfa 100644
--- a/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.h
+++ b/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.h
@@ -40,7 +40,7 @@
 namespace d3d11_gl
 {
 
-gl::Caps GenerateCaps(ID3D11Device *device);
+void GenerateCaps(ID3D11Device *device, gl::Caps *caps, gl::TextureCapsMap *textureCapsMap, gl::Extensions *extensions);
 
 }
 
diff --git a/src/libGLESv2/renderer/d3d/d3d9/IndexBuffer9.cpp b/src/libGLESv2/renderer/d3d/d3d9/IndexBuffer9.cpp
index 428b208..472e698 100644
--- a/src/libGLESv2/renderer/d3d/d3d9/IndexBuffer9.cpp
+++ b/src/libGLESv2/renderer/d3d/d3d9/IndexBuffer9.cpp
@@ -41,7 +41,7 @@
         }
         else if (indexType == GL_UNSIGNED_INT)
         {
-            if (mRenderer->getCaps().extensions.elementIndexUint)
+            if (mRenderer->getRendererExtensions().elementIndexUint)
             {
                 format = D3DFMT_INDEX32;
             }
diff --git a/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp b/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp
index c7d66c5..4585ccf 100644
--- a/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp
+++ b/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp
@@ -667,7 +667,7 @@
         mDevice->SetSamplerState(d3dSampler, D3DSAMP_MINFILTER, d3dMinFilter);
         mDevice->SetSamplerState(d3dSampler, D3DSAMP_MIPFILTER, d3dMipFilter);
         mDevice->SetSamplerState(d3dSampler, D3DSAMP_MAXMIPLEVEL, samplerState.baseLevel);
-        if (getCaps().extensions.textureFilterAnisotropic)
+        if (getRendererExtensions().textureFilterAnisotropic)
         {
             mDevice->SetSamplerState(d3dSampler, D3DSAMP_MAXANISOTROPY, (DWORD)samplerState.maxAnisotropy);
         }
@@ -1384,7 +1384,7 @@
 
     unsigned int startIndex = 0;
 
-    if (getCaps().extensions.elementIndexUint)
+    if (getRendererExtensions().elementIndexUint)
     {
         if (!mLineLoopIB)
         {
@@ -3223,9 +3223,9 @@
     return d3d9::GetDeclTypeComponentType(declType);
 }
 
-gl::Caps Renderer9::generateCaps() const
+void Renderer9::generateCaps(gl::Caps *outCaps, gl::TextureCapsMap *outTextureCaps, gl::Extensions *outExtensions) const
 {
-    return d3d9_gl::GenerateCaps(mD3d9, mDevice, mDeviceType, mAdapter);
+    d3d9_gl::GenerateCaps(mD3d9, mDevice, mDeviceType, mAdapter, outCaps, outTextureCaps, outExtensions);
 }
 
 }
diff --git a/src/libGLESv2/renderer/d3d/d3d9/Renderer9.h b/src/libGLESv2/renderer/d3d/d3d9/Renderer9.h
index 3b59983..6fe1153 100644
--- a/src/libGLESv2/renderer/d3d/d3d9/Renderer9.h
+++ b/src/libGLESv2/renderer/d3d/d3d9/Renderer9.h
@@ -209,7 +209,7 @@
   private:
     DISALLOW_COPY_AND_ASSIGN(Renderer9);
 
-    virtual gl::Caps generateCaps() const;
+    virtual void generateCaps(gl::Caps *outCaps, gl::TextureCapsMap *outTextureCaps, gl::Extensions *outExtensions) const;
 
     void release();
 
diff --git a/src/libGLESv2/renderer/d3d/d3d9/renderer9_utils.cpp b/src/libGLESv2/renderer/d3d/d3d9/renderer9_utils.cpp
index 4f3a8f6..f149f13 100644
--- a/src/libGLESv2/renderer/d3d/d3d9/renderer9_utils.cpp
+++ b/src/libGLESv2/renderer/d3d/d3d9/renderer9_utils.cpp
@@ -308,15 +308,14 @@
     return textureCaps;
 }
 
-gl::Caps GenerateCaps(IDirect3D9 *d3d9, IDirect3DDevice9 *device, D3DDEVTYPE deviceType, UINT adapter)
+void GenerateCaps(IDirect3D9 *d3d9, IDirect3DDevice9 *device, D3DDEVTYPE deviceType, UINT adapter, gl::Caps *caps,
+                  gl::TextureCapsMap *textureCapsMap, gl::Extensions *extensions)
 {
-    gl::Caps caps;
-
     D3DCAPS9 deviceCaps;
     if (FAILED(d3d9->GetDeviceCaps(adapter, deviceType, &deviceCaps)))
     {
         // Can't continue with out device caps
-        return caps;
+        return;
     }
 
     D3DDISPLAYMODE currentDisplayMode;
@@ -325,104 +324,103 @@
     const gl::FormatSet &allFormats = gl::GetAllSizedInternalFormats();
     for (gl::FormatSet::const_iterator internalFormat = allFormats.begin(); internalFormat != allFormats.end(); ++internalFormat)
     {
-        caps.textureCaps.insert(*internalFormat, GenerateTextureFormatCaps(*internalFormat, d3d9, deviceType, adapter,
-                                                                           currentDisplayMode.Format));
+        gl::TextureCaps textureCaps = GenerateTextureFormatCaps(*internalFormat, d3d9, deviceType, adapter,
+                                                                currentDisplayMode.Format);
+        textureCapsMap->insert(*internalFormat, textureCaps);
     }
 
     // GL core feature limits
-    caps.maxElementIndex = static_cast<GLint64>(std::numeric_limits<unsigned int>::max());
+    caps->maxElementIndex = static_cast<GLint64>(std::numeric_limits<unsigned int>::max());
 
     // 3D textures are unimplemented in D3D9
-    caps.max3DTextureSize = 1;
+    caps->max3DTextureSize = 1;
 
     // Only one limit in GL, use the minimum dimension
-    caps.max2DTextureSize = std::min(deviceCaps.MaxTextureWidth, deviceCaps.MaxTextureHeight);
+    caps->max2DTextureSize = std::min(deviceCaps.MaxTextureWidth, deviceCaps.MaxTextureHeight);
 
     // D3D treats cube maps as a special case of 2D textures
-    caps.maxCubeMapTextureSize = caps.max2DTextureSize;
+    caps->maxCubeMapTextureSize = caps->max2DTextureSize;
 
     // Array textures are not available in D3D9
-    caps.maxArrayTextureLayers = 1;
+    caps->maxArrayTextureLayers = 1;
 
     // ES3-only feature
-    caps.maxLODBias = 0.0f;
+    caps->maxLODBias = 0.0f;
 
     // No specific limits on render target size, maximum 2D texture size is equivalent
-    caps.maxRenderbufferSize = caps.max2DTextureSize;
+    caps->maxRenderbufferSize = caps->max2DTextureSize;
 
     // Draw buffers are not supported in D3D9
-    caps.maxDrawBuffers = 1;
-    caps.maxColorAttachments = 1;
+    caps->maxDrawBuffers = 1;
+    caps->maxColorAttachments = 1;
 
     // No specific limits on viewport size, maximum 2D texture size is equivalent
-    caps.maxViewportWidth = caps.max2DTextureSize;
-    caps.maxViewportHeight = caps.maxViewportWidth;
+    caps->maxViewportWidth = caps->max2DTextureSize;
+    caps->maxViewportHeight = caps->maxViewportWidth;
 
     // Point size is clamped to 1.0f when the shader model is less than 3
-    caps.minAliasedPointSize = 1.0f;
-    caps.maxAliasedPointSize = ((D3DSHADER_VERSION_MAJOR(deviceCaps.PixelShaderVersion) >= 3) ? deviceCaps.MaxPointSize : 1.0f);
+    caps->minAliasedPointSize = 1.0f;
+    caps->maxAliasedPointSize = ((D3DSHADER_VERSION_MAJOR(deviceCaps.PixelShaderVersion) >= 3) ? deviceCaps.MaxPointSize : 1.0f);
 
     // Wide lines not supported
-    caps.minAliasedLineWidth = 1.0f;
-    caps.maxAliasedLineWidth = 1.0f;
+    caps->minAliasedLineWidth = 1.0f;
+    caps->maxAliasedLineWidth = 1.0f;
 
     // GL extension support
-    caps.extensions.setTextureExtensionSupport(caps.textureCaps);
-    caps.extensions.elementIndexUint = deviceCaps.MaxVertexIndex >= (1 << 16);
-    caps.extensions.packedDepthStencil = true;
-    caps.extensions.getProgramBinary = true;
-    caps.extensions.rgb8rgba8 = true;
-    caps.extensions.readFormatBGRA = true;
-    caps.extensions.pixelBufferObject = false;
-    caps.extensions.mapBuffer = false;
-    caps.extensions.mapBufferRange = false;
+    extensions->setTextureExtensionSupport(*textureCapsMap);
+    extensions->elementIndexUint = deviceCaps.MaxVertexIndex >= (1 << 16);
+    extensions->packedDepthStencil = true;
+    extensions->getProgramBinary = true;
+    extensions->rgb8rgba8 = true;
+    extensions->readFormatBGRA = true;
+    extensions->pixelBufferObject = false;
+    extensions->mapBuffer = false;
+    extensions->mapBufferRange = false;
 
     // ATI cards on XP have problems with non-power-of-two textures.
     D3DADAPTER_IDENTIFIER9 adapterId = { 0 };
     if (SUCCEEDED(d3d9->GetAdapterIdentifier(adapter, 0, &adapterId)))
     {
-        caps.extensions.textureNPOT = !(deviceCaps.TextureCaps & D3DPTEXTURECAPS_POW2) &&
+        extensions->textureNPOT = !(deviceCaps.TextureCaps & D3DPTEXTURECAPS_POW2) &&
                                       !(deviceCaps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP_POW2) &&
                                       !(deviceCaps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL) &&
                                       !(isWindowsVistaOrGreater() && adapterId.VendorId == VENDOR_ID_AMD);
     }
     else
     {
-        caps.extensions.textureNPOT = false;
+        extensions->textureNPOT = false;
     }
 
-    caps.extensions.drawBuffers = false;
-    caps.extensions.textureStorage = true;
+    extensions->drawBuffers = false;
+    extensions->textureStorage = true;
 
     // Must support a minimum of 2:1 anisotropy for max anisotropy to be considered supported, per the spec
-    caps.extensions.textureFilterAnisotropic = (deviceCaps.RasterCaps & D3DPRASTERCAPS_ANISOTROPY) != 0 && deviceCaps.MaxAnisotropy >= 2;
-    caps.extensions.maxTextureAnisotropy = static_cast<GLfloat>(deviceCaps.MaxAnisotropy);
+    extensions->textureFilterAnisotropic = (deviceCaps.RasterCaps & D3DPRASTERCAPS_ANISOTROPY) != 0 && deviceCaps.MaxAnisotropy >= 2;
+    extensions->maxTextureAnisotropy = static_cast<GLfloat>(deviceCaps.MaxAnisotropy);
 
     // Check occlusion query support by trying to create one
     IDirect3DQuery9 *occlusionQuery = NULL;
-    caps.extensions.occlusionQueryBoolean = SUCCEEDED(device->CreateQuery(D3DQUERYTYPE_OCCLUSION, &occlusionQuery)) && occlusionQuery;
+    extensions->occlusionQueryBoolean = SUCCEEDED(device->CreateQuery(D3DQUERYTYPE_OCCLUSION, &occlusionQuery)) && occlusionQuery;
     SafeRelease(occlusionQuery);
 
     // Check event query support by trying to create one
     IDirect3DQuery9 *eventQuery = NULL;
-    caps.extensions.fence = SUCCEEDED(device->CreateQuery(D3DQUERYTYPE_EVENT, &eventQuery)) && eventQuery;
+    extensions->fence = SUCCEEDED(device->CreateQuery(D3DQUERYTYPE_EVENT, &eventQuery)) && eventQuery;
     SafeRelease(eventQuery);
 
-    caps.extensions.timerQuery = false; // Unimplemented
-    caps.extensions.robustness = true;
-    caps.extensions.blendMinMax = true;
-    caps.extensions.framebufferBlit = true;
-    caps.extensions.framebufferMultisample = true;
-    caps.extensions.instancedArrays = deviceCaps.PixelShaderVersion >= D3DPS_VERSION(3, 0);
-    caps.extensions.packReverseRowOrder = true;
-    caps.extensions.standardDerivatives = (deviceCaps.PS20Caps.Caps & D3DPS20CAPS_GRADIENTINSTRUCTIONS) != 0;
-    caps.extensions.shaderTextureLOD = true;
-    caps.extensions.fragDepth = true;
-    caps.extensions.textureUsage = true;
-    caps.extensions.translatedShaderSource = true;
-    caps.extensions.colorBufferFloat = false;
-
-    return caps;
+    extensions->timerQuery = false; // Unimplemented
+    extensions->robustness = true;
+    extensions->blendMinMax = true;
+    extensions->framebufferBlit = true;
+    extensions->framebufferMultisample = true;
+    extensions->instancedArrays = deviceCaps.PixelShaderVersion >= D3DPS_VERSION(3, 0);
+    extensions->packReverseRowOrder = true;
+    extensions->standardDerivatives = (deviceCaps.PS20Caps.Caps & D3DPS20CAPS_GRADIENTINSTRUCTIONS) != 0;
+    extensions->shaderTextureLOD = true;
+    extensions->fragDepth = true;
+    extensions->textureUsage = true;
+    extensions->translatedShaderSource = true;
+    extensions->colorBufferFloat = false;
 }
 
 }
diff --git a/src/libGLESv2/renderer/d3d/d3d9/renderer9_utils.h b/src/libGLESv2/renderer/d3d/d3d9/renderer9_utils.h
index 01fb723..7f3c65d 100644
--- a/src/libGLESv2/renderer/d3d/d3d9/renderer9_utils.h
+++ b/src/libGLESv2/renderer/d3d/d3d9/renderer9_utils.h
@@ -36,7 +36,8 @@
 namespace d3d9_gl
 {
 
-gl::Caps GenerateCaps(IDirect3D9 *d3d9, IDirect3DDevice9 *device, D3DDEVTYPE deviceType, UINT adapter);
+void GenerateCaps(IDirect3D9 *d3d9, IDirect3DDevice9 *device, D3DDEVTYPE deviceType, UINT adapter, gl::Caps *caps,
+                  gl::TextureCapsMap *textureCapsMap, gl::Extensions *extensions);
 
 }
 
diff --git a/src/libGLESv2/validationES.cpp b/src/libGLESv2/validationES.cpp
index cc6f91c..2324a4b 100644
--- a/src/libGLESv2/validationES.cpp
+++ b/src/libGLESv2/validationES.cpp
@@ -112,7 +112,7 @@
 
       case GL_PIXEL_PACK_BUFFER:
       case GL_PIXEL_UNPACK_BUFFER:
-        return context->getCaps().extensions.pixelBufferObject;
+        return context->getExtensions().pixelBufferObject;
 
       case GL_COPY_READ_BUFFER:
       case GL_COPY_WRITE_BUFFER:
@@ -175,7 +175,7 @@
         return false;
     }
 
-    if (!context->getCaps().extensions.textureNPOT &&
+    if (!context->getExtensions().textureNPOT &&
         (level != 0 && (!gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth))))
     {
         return false;
@@ -297,8 +297,7 @@
         return gl::error(GL_INVALID_VALUE, false);
     }
 
-    const gl::Caps &caps = context->getCaps();
-    if (!gl::IsValidInternalFormat(internalformat, caps.extensions, context->getClientVersion()))
+    if (!gl::IsValidInternalFormat(internalformat, context->getExtensions(), context->getClientVersion()))
     {
         return gl::error(GL_INVALID_ENUM, false);
     }
@@ -318,7 +317,7 @@
         return gl::error(GL_INVALID_OPERATION, false);
     }
 
-    const TextureCaps &formatCaps = caps.textureCaps.get(internalformat);
+    const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
     if (!formatCaps.colorRendering && !formatCaps.depthRendering && !formatCaps.stencilRendering)
     {
         return gl::error(GL_INVALID_ENUM, false);
@@ -741,7 +740,7 @@
         break;
 
       case GL_TEXTURE_MAX_ANISOTROPY_EXT:
-        if (!context->getCaps().extensions.textureFilterAnisotropic)
+        if (!context->getExtensions().textureFilterAnisotropic)
         {
             return gl::error(GL_INVALID_ENUM, false);
         }
@@ -1286,7 +1285,7 @@
             return gl::error(GL_INVALID_VALUE, false);
         }
 
-        if (!IsValidInternalFormat(internalformat, context->getCaps().extensions, context->getClientVersion()))
+        if (!IsValidInternalFormat(internalformat, context->getExtensions(), context->getClientVersion()))
         {
             return gl::error(GL_INVALID_ENUM, false);
         }
@@ -1400,7 +1399,7 @@
       case GL_UNSIGNED_SHORT:
         break;
       case GL_UNSIGNED_INT:
-        if (!context->getCaps().extensions.elementIndexUint)
+        if (!context->getExtensions().elementIndexUint)
         {
             return gl::error(GL_INVALID_ENUM, false);
         }
diff --git a/src/libGLESv2/validationES2.cpp b/src/libGLESv2/validationES2.cpp
index e371383..eed8a15 100644
--- a/src/libGLESv2/validationES2.cpp
+++ b/src/libGLESv2/validationES2.cpp
@@ -236,19 +236,19 @@
         {
           case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
           case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
-            if (!context->getCaps().extensions.textureCompressionDXT1)
+            if (!context->getExtensions().textureCompressionDXT1)
             {
                 return gl::error(GL_INVALID_ENUM, false);
             }
             break;
           case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
-            if (!context->getCaps().extensions.textureCompressionDXT1)
+            if (!context->getExtensions().textureCompressionDXT1)
             {
                 return gl::error(GL_INVALID_ENUM, false);
             }
             break;
           case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
-              if (!context->getCaps().extensions.textureCompressionDXT5)
+              if (!context->getExtensions().textureCompressionDXT5)
             {
                 return gl::error(GL_INVALID_ENUM, false);
             }
@@ -296,7 +296,7 @@
             break;
           case GL_RED:
           case GL_RG:
-              if (!context->getCaps().extensions.textureRG)
+              if (!context->getExtensions().textureRG)
               {
                   return gl::error(GL_INVALID_ENUM, false);
               }
@@ -346,7 +346,7 @@
             break;
           case GL_SRGB_EXT:
           case GL_SRGB_ALPHA_EXT:
-            if (!context->getCaps().extensions.sRGB)
+            if (!context->getExtensions().sRGB)
             {
                 return gl::error(GL_INVALID_ENUM, false);
             }
@@ -390,7 +390,7 @@
         {
           case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
           case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
-            if (context->getCaps().extensions.textureCompressionDXT1)
+            if (context->getExtensions().textureCompressionDXT1)
             {
                 return gl::error(GL_INVALID_OPERATION, false);
             }
@@ -400,7 +400,7 @@
             }
             break;
           case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
-            if (context->getCaps().extensions.textureCompressionDXT3)
+            if (context->getExtensions().textureCompressionDXT3)
             {
                 return gl::error(GL_INVALID_OPERATION, false);
             }
@@ -410,7 +410,7 @@
             }
             break;
           case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
-            if (context->getCaps().extensions.textureCompressionDXT5)
+            if (context->getExtensions().textureCompressionDXT5)
             {
                 return gl::error(GL_INVALID_OPERATION, false);
             }
@@ -421,7 +421,7 @@
             break;
           case GL_DEPTH_COMPONENT:
           case GL_DEPTH_STENCIL_OES:
-            if (!context->getCaps().extensions.depthTextures)
+            if (!context->getExtensions().depthTextures)
             {
                 return gl::error(GL_INVALID_VALUE, false);
             }
@@ -442,14 +442,14 @@
 
         if (type == GL_FLOAT)
         {
-            if (!context->getCaps().extensions.textureFloat)
+            if (!context->getExtensions().textureFloat)
             {
                 return gl::error(GL_INVALID_ENUM, false);
             }
         }
         else if (type == GL_HALF_FLOAT_OES)
         {
-            if (!context->getCaps().extensions.textureHalfFloat)
+            if (!context->getExtensions().textureHalfFloat)
             {
                 return gl::error(GL_INVALID_ENUM, false);
             }
@@ -632,7 +632,7 @@
             break;
           case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
           case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
-            if (context->getCaps().extensions.textureCompressionDXT1)
+            if (context->getExtensions().textureCompressionDXT1)
             {
                 return gl::error(GL_INVALID_OPERATION, false);
             }
@@ -642,7 +642,7 @@
             }
             break;
           case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
-            if (context->getCaps().extensions.textureCompressionDXT3)
+            if (context->getExtensions().textureCompressionDXT3)
             {
                 return gl::error(GL_INVALID_OPERATION, false);
             }
@@ -652,7 +652,7 @@
             }
             break;
           case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
-            if (context->getCaps().extensions.textureCompressionDXT5)
+            if (context->getExtensions().textureCompressionDXT5)
             {
                 return gl::error(GL_INVALID_OPERATION, false);
             }
@@ -666,7 +666,7 @@
           case GL_DEPTH_COMPONENT32_OES:
           case GL_DEPTH_STENCIL_OES:
           case GL_DEPTH24_STENCIL8_OES:
-            if (context->getCaps().extensions.depthTextures)
+            if (context->getExtensions().depthTextures)
             {
                 return gl::error(GL_INVALID_OPERATION, false);
             }
@@ -736,7 +736,7 @@
         return gl::error(GL_INVALID_ENUM, false);
     }
 
-    if (levels != 1 && !context->getCaps().extensions.textureNPOT)
+    if (levels != 1 && !context->getExtensions().textureNPOT)
     {
         if (!gl::isPow2(width) || !gl::isPow2(height))
         {
@@ -748,19 +748,19 @@
     {
       case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
       case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
-        if (!context->getCaps().extensions.textureCompressionDXT1)
+        if (!context->getExtensions().textureCompressionDXT1)
         {
             return gl::error(GL_INVALID_ENUM, false);
         }
         break;
       case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
-        if (!context->getCaps().extensions.textureCompressionDXT3)
+        if (!context->getExtensions().textureCompressionDXT3)
         {
             return gl::error(GL_INVALID_ENUM, false);
         }
         break;
       case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
-        if (!context->getCaps().extensions.textureCompressionDXT5)
+        if (!context->getExtensions().textureCompressionDXT5)
         {
             return gl::error(GL_INVALID_ENUM, false);
         }
@@ -770,7 +770,7 @@
       case GL_ALPHA32F_EXT:
       case GL_LUMINANCE32F_EXT:
       case GL_LUMINANCE_ALPHA32F_EXT:
-        if (!context->getCaps().extensions.textureFloat)
+        if (!context->getExtensions().textureFloat)
         {
             return gl::error(GL_INVALID_ENUM, false);
         }
@@ -780,7 +780,7 @@
       case GL_ALPHA16F_EXT:
       case GL_LUMINANCE16F_EXT:
       case GL_LUMINANCE_ALPHA16F_EXT:
-        if (!context->getCaps().extensions.textureHalfFloat)
+        if (!context->getExtensions().textureHalfFloat)
         {
             return gl::error(GL_INVALID_ENUM, false);
         }
@@ -791,7 +791,7 @@
       case GL_RG16F_EXT:
       case GL_R32F_EXT:
       case GL_RG32F_EXT:
-        if (!context->getCaps().extensions.textureRG)
+        if (!context->getExtensions().textureRG)
         {
             return gl::error(GL_INVALID_ENUM, false);
         }
@@ -799,7 +799,7 @@
       case GL_DEPTH_COMPONENT16:
       case GL_DEPTH_COMPONENT32_OES:
       case GL_DEPTH24_STENCIL8_OES:
-        if (!context->getCaps().extensions.depthTextures)
+        if (!context->getExtensions().depthTextures)
         {
             return gl::error(GL_INVALID_ENUM, false);
         }
@@ -870,7 +870,7 @@
         break;
       case GL_RG_EXT:
       case GL_RED_EXT:
-        if (!context->getCaps().extensions.textureRG)
+        if (!context->getExtensions().textureRG)
         {
             return false;
         }
diff --git a/src/libGLESv2/validationES3.cpp b/src/libGLESv2/validationES3.cpp
index 76ba62c..f13e924 100644
--- a/src/libGLESv2/validationES3.cpp
+++ b/src/libGLESv2/validationES3.cpp
@@ -193,14 +193,14 @@
     {
         // Note: dEQP 2013.4 expects an INVALID_VALUE error for TexImage3D with an invalid
         // internal format. (dEQP-GLES3.functional.negative_api.texture.teximage3d)
-        if (!gl::IsValidInternalFormat(actualInternalFormat, context->getCaps().extensions, context->getClientVersion()) ||
-            !gl::IsValidFormat(format, context->getCaps().extensions, context->getClientVersion()) ||
-            !gl::IsValidType(type, context->getCaps().extensions, context->getClientVersion()))
+        if (!gl::IsValidInternalFormat(actualInternalFormat, context->getExtensions(), context->getClientVersion()) ||
+            !gl::IsValidFormat(format, context->getExtensions(), context->getClientVersion()) ||
+            !gl::IsValidType(type, context->getExtensions(), context->getClientVersion()))
         {
             return gl::error(GL_INVALID_ENUM, false);
         }
 
-        if (!gl::IsValidFormatCombination(actualInternalFormat, format, type, context->getCaps().extensions, context->getClientVersion()))
+        if (!gl::IsValidFormatCombination(actualInternalFormat, format, type, context->getExtensions(), context->getClientVersion()))
         {
             return gl::error(GL_INVALID_OPERATION, false);
         }
@@ -440,7 +440,7 @@
         return gl::error(GL_INVALID_OPERATION, false);
     }
 
-    if (!gl::IsValidInternalFormat(internalformat, context->getCaps().extensions, context->getClientVersion()))
+    if (!gl::IsValidInternalFormat(internalformat, context->getExtensions(), context->getClientVersion()))
     {
         return gl::error(GL_INVALID_ENUM, false);
     }
@@ -584,7 +584,7 @@
         break;
       case GL_RG_EXT:
       case GL_RED_EXT:
-        if (!context->getCaps().extensions.textureRG)
+        if (!context->getExtensions().textureRG)
         {
             return false;
         }