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/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);
 
 }