Add caps for texture size limits and other caps in the 6.28 table.

BUG=angle:658

Change-Id: Ia265fe1d3713db7701b41e8430d6d186f352ab4a
Reviewed-on: https://chromium-review.googlesource.com/201363
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Tested-by: Geoff Lang <geofflang@chromium.org>
diff --git a/src/libGLESv2/renderer/d3d/d3d11/Blit11.cpp b/src/libGLESv2/renderer/d3d/d3d11/Blit11.cpp
index 2199dd8..b70cf41 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->getMaxTextureDepth();
+                       6 * renderer->getCaps().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 2f241f9..d999cd8 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->getMaxRenderTargets());
+        ASSERT(maskedClearRenderTargets.size() <= mRenderer->getCaps().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 351ca6e..b9e7404 100644
--- a/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp
+++ b/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp
@@ -724,17 +724,14 @@
         actualZFar = 1.0f;
     }
 
-    // Get D3D viewport bounds, which depends on the feature level
-    const Range& viewportBounds = getViewportBounds();
+    const gl::Caps& caps = getCaps();
 
     // Clamp width and height first to the gl maximum, then clamp further if we extend past the D3D maximum bounds
     D3D11_VIEWPORT dxViewport;
-    dxViewport.TopLeftX = gl::clamp(actualViewport.x, viewportBounds.start, viewportBounds.end);
-    dxViewport.TopLeftY = gl::clamp(actualViewport.y, viewportBounds.start, viewportBounds.end);
-    dxViewport.Width = gl::clamp(actualViewport.width, 0, getMaxViewportDimension());
-    dxViewport.Height = gl::clamp(actualViewport.height, 0, getMaxViewportDimension());
-    dxViewport.Width = std::min((int)dxViewport.Width, viewportBounds.end - static_cast<int>(dxViewport.TopLeftX));
-    dxViewport.Height = std::min((int)dxViewport.Height, viewportBounds.end - static_cast<int>(dxViewport.TopLeftY));
+    dxViewport.TopLeftX = gl::clamp(actualViewport.x, -static_cast<int>(caps.maxViewportWidth), static_cast<int>(caps.maxViewportWidth));
+    dxViewport.TopLeftY = gl::clamp(actualViewport.y, -static_cast<int>(caps.maxViewportHeight), static_cast<int>(caps.maxViewportHeight));
+    dxViewport.Width = gl::clamp(actualViewport.width, 0, static_cast<int>(caps.maxViewportWidth - dxViewport.TopLeftX));
+    dxViewport.Height = gl::clamp(actualViewport.height, 0, static_cast<int>(caps.maxViewportHeight - dxViewport.TopLeftY));
     dxViewport.MinDepth = actualZNear;
     dxViewport.MaxDepth = actualZFar;
 
@@ -935,7 +932,7 @@
         depthbufferSerial != mAppliedDepthbufferSerial ||
         stencilbufferSerial != mAppliedStencilbufferSerial)
     {
-        mDeviceContext->OMSetRenderTargets(getMaxRenderTargets(), framebufferRTVs, framebufferDSV);
+        mDeviceContext->OMSetRenderTargets(getCaps().maxDrawBuffers, framebufferRTVs, framebufferDSV);
 
         mRenderTargetDesc.width = renderTargetWidth;
         mRenderTargetDesc.height = renderTargetHeight;
@@ -1816,20 +1813,6 @@
     return adapterId;
 }
 
-Range Renderer11::getViewportBounds() const
-{
-    switch (mFeatureLevel)
-    {
-      case D3D_FEATURE_LEVEL_11_0:
-        return Range(D3D11_VIEWPORT_BOUNDS_MIN, D3D11_VIEWPORT_BOUNDS_MAX);
-      case D3D_FEATURE_LEVEL_10_1:
-      case D3D_FEATURE_LEVEL_10_0:
-        return Range(D3D10_VIEWPORT_BOUNDS_MIN, D3D10_VIEWPORT_BOUNDS_MAX);
-      default: UNREACHABLE();
-        return Range(0, 0);
-    }
-}
-
 unsigned int Renderer11::getMaxVertexTextureImageUnits() const
 {
     META_ASSERT(MAX_TEXTURE_IMAGE_UNITS_VTF_SM4 <= gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS);
@@ -2059,76 +2042,6 @@
     }
 }
 
-float Renderer11::getMaxPointSize() const
-{
-    // choose a reasonable maximum. we enforce this in the shader.
-    // (nb: on a Radeon 2600xt, DX9 reports a 256 max point size)
-    return 1024.0f;
-}
-
-int Renderer11::getMaxViewportDimension() const
-{
-    // Maximum viewport size must be at least as large as the largest render buffer (or larger).
-    // In our case return the maximum texture size, which is the maximum render buffer size.
-    META_ASSERT(D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION * 2 - 1 <= D3D11_VIEWPORT_BOUNDS_MAX);
-    META_ASSERT(D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION * 2 - 1 <= D3D10_VIEWPORT_BOUNDS_MAX);
-
-    switch (mFeatureLevel)
-    {
-      case D3D_FEATURE_LEVEL_11_0: 
-        return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION;   // 16384
-      case D3D_FEATURE_LEVEL_10_1:
-      case D3D_FEATURE_LEVEL_10_0: 
-        return D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION;   // 8192
-      default: UNREACHABLE();      
-        return 0;
-    }
-}
-
-int Renderer11::getMaxTextureWidth() const
-{
-    switch (mFeatureLevel)
-    {
-      case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION;   // 16384
-      case D3D_FEATURE_LEVEL_10_1:
-      case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION;   // 8192
-      default: UNREACHABLE();      return 0;
-    }
-}
-
-int Renderer11::getMaxTextureHeight() const
-{
-    switch (mFeatureLevel)
-    {
-      case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION;   // 16384
-      case D3D_FEATURE_LEVEL_10_1:
-      case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION;   // 8192
-      default: UNREACHABLE();      return 0;
-    }
-}
-
-int Renderer11::getMaxTextureDepth() const
-{
-    switch (mFeatureLevel)
-    {
-      case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION;   // 2048
-      case D3D_FEATURE_LEVEL_10_1:
-      case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_TEXTURE3D_U_V_OR_W_DIMENSION;   // 2048
-      default: UNREACHABLE();      return 0;
-    }
-}
-
-int Renderer11::getMaxTextureArrayLayers() const
-{
-    switch (mFeatureLevel)
-    {
-      case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION;   // 2048
-      case D3D_FEATURE_LEVEL_10_1:
-      case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION;   // 512
-      default: UNREACHABLE();      return 0;
-    }
-}
-
 int Renderer11::getMinSwapInterval() const
 {
     return 0;
@@ -2227,11 +2140,6 @@
     return -1;
 }
 
-unsigned int Renderer11::getMaxRenderTargets() const
-{
-    return d3d11::GetMaximumSimultaneousRenderTargets(mFeatureLevel);
-}
-
 bool Renderer11::copyToRenderTarget(TextureStorageInterface2D *dest, TextureStorageInterface2D *source)
 {
     if (source && dest)
@@ -2557,7 +2465,7 @@
 
     rtvArray[0] = renderTargetView;
 
-    mDeviceContext->OMSetRenderTargets(getMaxRenderTargets(), rtvArray, NULL);
+    mDeviceContext->OMSetRenderTargets(getCaps().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++)
diff --git a/src/libGLESv2/renderer/d3d/d3d11/Renderer11.h b/src/libGLESv2/renderer/d3d/d3d11/Renderer11.h
index b490d14..8bb8945 100644
--- a/src/libGLESv2/renderer/d3d/d3d11/Renderer11.h
+++ b/src/libGLESv2/renderer/d3d/d3d11/Renderer11.h
@@ -126,12 +126,6 @@
     virtual bool getSRGBTextureSupport() const;
 
     virtual int getMajorShaderModel() const;
-    virtual float getMaxPointSize() const;
-    virtual int getMaxViewportDimension() const;
-    virtual int getMaxTextureWidth() const;
-    virtual int getMaxTextureHeight() const;
-    virtual int getMaxTextureDepth() const;
-    virtual int getMaxTextureArrayLayers() const;
     virtual int getMinSwapInterval() const;
     virtual int getMaxSwapInterval() const;
 
@@ -141,8 +135,6 @@
     virtual void getSampleCounts(GLenum internalFormat, GLsizei bufSize, GLint *params) const;
     int getNearestSupportedSamples(DXGI_FORMAT format, unsigned int requested) const;
 
-    virtual unsigned int getMaxRenderTargets() const;
-
     // Pixel operations
     virtual bool copyToRenderTarget(TextureStorageInterface2D *dest, TextureStorageInterface2D *source);
     virtual bool copyToRenderTarget(TextureStorageInterfaceCube *dest, TextureStorageInterfaceCube *source);
@@ -230,8 +222,6 @@
     void readTextureData(ID3D11Texture2D *texture, unsigned int subResource, const gl::Rectangle &area, GLenum format,
                          GLenum type, GLuint outputPitch, const gl::PixelPackState &pack, void *pixels);
 
-    rx::Range getViewportBounds() const;
-
     bool blitRenderbufferRect(const gl::Rectangle &readRect, const gl::Rectangle &drawRect, RenderTarget *readRenderTarget,
                               RenderTarget *drawRenderTarget, GLenum filter, const gl::Rectangle *scissor,
                               bool colorBlit, bool depthBlit, bool stencilBlit);
diff --git a/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp b/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp
index fe1ac39..9710899 100644
--- a/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp
+++ b/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp
@@ -274,6 +274,233 @@
     return textureCaps;
 }
 
+static bool GetNPOTTextureSupport(D3D_FEATURE_LEVEL featureLevel)
+{
+    switch (featureLevel)
+    {
+      case D3D_FEATURE_LEVEL_11_1:
+      case D3D_FEATURE_LEVEL_11_0:
+      case D3D_FEATURE_LEVEL_10_1:
+      case D3D_FEATURE_LEVEL_10_0: return true;
+
+        // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476876.aspx
+      case D3D_FEATURE_LEVEL_9_3:
+      case D3D_FEATURE_LEVEL_9_2:
+      case D3D_FEATURE_LEVEL_9_1:  return false;
+
+      default: UNREACHABLE();      return false;
+    }
+}
+
+static float GetMaximumAnisotropy(D3D_FEATURE_LEVEL featureLevel)
+{
+    switch (featureLevel)
+    {
+      case D3D_FEATURE_LEVEL_11_1:
+      case D3D_FEATURE_LEVEL_11_0: return D3D11_MAX_MAXANISOTROPY;
+
+      case D3D_FEATURE_LEVEL_10_1:
+      case D3D_FEATURE_LEVEL_10_0: return D3D10_MAX_MAXANISOTROPY;
+
+        // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476876.aspx
+      case D3D_FEATURE_LEVEL_9_3:
+      case D3D_FEATURE_LEVEL_9_2:  return 16;
+
+      case D3D_FEATURE_LEVEL_9_1:  return D3D_FL9_1_DEFAULT_MAX_ANISOTROPY;
+
+      default: UNREACHABLE();      return 0;
+    }
+}
+
+static bool GetOcclusionQuerySupport(D3D_FEATURE_LEVEL featureLevel)
+{
+    switch (featureLevel)
+    {
+      case D3D_FEATURE_LEVEL_11_1:
+      case D3D_FEATURE_LEVEL_11_0:
+      case D3D_FEATURE_LEVEL_10_1:
+      case D3D_FEATURE_LEVEL_10_0: return true;
+
+        // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476150.aspx ID3D11Device::CreateQuery
+      case D3D_FEATURE_LEVEL_9_3:
+      case D3D_FEATURE_LEVEL_9_2:  return true;
+      case D3D_FEATURE_LEVEL_9_1:  return false;
+
+      default: UNREACHABLE();      return false;
+    }
+}
+
+static bool GetEventQuerySupport(D3D_FEATURE_LEVEL featureLevel)
+{
+    // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476150.aspx ID3D11Device::CreateQuery
+
+    switch (featureLevel)
+    {
+      case D3D_FEATURE_LEVEL_11_1:
+      case D3D_FEATURE_LEVEL_11_0:
+      case D3D_FEATURE_LEVEL_10_1:
+      case D3D_FEATURE_LEVEL_10_0:
+      case D3D_FEATURE_LEVEL_9_3:
+      case D3D_FEATURE_LEVEL_9_2:
+      case D3D_FEATURE_LEVEL_9_1:  return true;
+
+      default: UNREACHABLE();      return false;
+    }
+}
+
+static bool GetInstancingSupport(D3D_FEATURE_LEVEL featureLevel)
+{
+    // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476150.aspx ID3D11Device::CreateInputLayout
+
+    switch (featureLevel)
+    {
+      case D3D_FEATURE_LEVEL_11_1:
+      case D3D_FEATURE_LEVEL_11_0:
+      case D3D_FEATURE_LEVEL_10_1:
+      case D3D_FEATURE_LEVEL_10_0:
+      case D3D_FEATURE_LEVEL_9_3:  return true;
+
+      case D3D_FEATURE_LEVEL_9_2:
+      case D3D_FEATURE_LEVEL_9_1:  return false;
+
+      default: UNREACHABLE();      return false;
+    }
+}
+
+static bool GetDerivativeInstructionSupport(D3D_FEATURE_LEVEL featureLevel)
+{
+    // http://msdn.microsoft.com/en-us/library/windows/desktop/bb509588.aspx states that shader model
+    // ps_2_x is required for the ddx (and other derivative functions).
+
+    // http://msdn.microsoft.com/en-us/library/windows/desktop/ff476876.aspx states that feature level
+    // 9.3 supports shader model ps_2_x.
+
+    switch (featureLevel)
+    {
+      case D3D_FEATURE_LEVEL_11_1:
+      case D3D_FEATURE_LEVEL_11_0:
+      case D3D_FEATURE_LEVEL_10_1:
+      case D3D_FEATURE_LEVEL_10_0:
+      case D3D_FEATURE_LEVEL_9_3:  return true;
+      case D3D_FEATURE_LEVEL_9_2:
+      case D3D_FEATURE_LEVEL_9_1:  return false;
+
+      default: UNREACHABLE();      return false;
+    }
+}
+
+static size_t GetMaximumSimultaneousRenderTargets(D3D_FEATURE_LEVEL featureLevel)
+{
+    // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476150.aspx ID3D11Device::CreateInputLayout
+
+    switch (featureLevel)
+    {
+      case D3D_FEATURE_LEVEL_11_1:
+      case D3D_FEATURE_LEVEL_11_0: return D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT;
+
+        // FIXME(geofflang): Work around NVIDIA driver bug by repacking buffers
+      case D3D_FEATURE_LEVEL_10_1:
+      case D3D_FEATURE_LEVEL_10_0: return 1; /* D3D10_SIMULTANEOUS_RENDER_TARGET_COUNT; */
+
+      case D3D_FEATURE_LEVEL_9_3:  return D3D_FL9_3_SIMULTANEOUS_RENDER_TARGET_COUNT;
+      case D3D_FEATURE_LEVEL_9_2:
+      case D3D_FEATURE_LEVEL_9_1:  return D3D_FL9_1_SIMULTANEOUS_RENDER_TARGET_COUNT;
+
+      default: UNREACHABLE();      return 0;
+    }
+}
+
+static size_t GetMaximum2DTextureSize(D3D_FEATURE_LEVEL featureLevel)
+{
+    switch (featureLevel)
+    {
+      case D3D_FEATURE_LEVEL_11_1:
+      case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION;
+
+      case D3D_FEATURE_LEVEL_10_1:
+      case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION;
+
+      case D3D_FEATURE_LEVEL_9_3:  return D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION;
+      case D3D_FEATURE_LEVEL_9_2:
+      case D3D_FEATURE_LEVEL_9_1:  return D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION;
+
+      default: UNREACHABLE();      return 0;
+    }
+}
+
+static size_t GetMaximumCubeMapTextureSize(D3D_FEATURE_LEVEL featureLevel)
+{
+    switch (featureLevel)
+    {
+      case D3D_FEATURE_LEVEL_11_1:
+      case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURECUBE_DIMENSION;
+
+      case D3D_FEATURE_LEVEL_10_1:
+      case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_TEXTURECUBE_DIMENSION;
+
+      case D3D_FEATURE_LEVEL_9_3:  return D3D_FL9_3_REQ_TEXTURECUBE_DIMENSION;
+      case D3D_FEATURE_LEVEL_9_2:
+      case D3D_FEATURE_LEVEL_9_1:  return D3D_FL9_1_REQ_TEXTURECUBE_DIMENSION;
+
+      default: UNREACHABLE();      return 0;
+    }
+}
+
+static size_t GetMaximum2DTextureArraySize(D3D_FEATURE_LEVEL featureLevel)
+{
+    switch (featureLevel)
+    {
+      case D3D_FEATURE_LEVEL_11_1:
+      case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION;
+
+      case D3D_FEATURE_LEVEL_10_1:
+      case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION;
+
+      case D3D_FEATURE_LEVEL_9_3:
+      case D3D_FEATURE_LEVEL_9_2:
+      case D3D_FEATURE_LEVEL_9_1:  return 0;
+
+      default: UNREACHABLE();      return 0;
+    }
+}
+
+static size_t GetMaximum3DTextureSize(D3D_FEATURE_LEVEL featureLevel)
+{
+    switch (featureLevel)
+    {
+      case D3D_FEATURE_LEVEL_11_1:
+      case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION;
+
+      case D3D_FEATURE_LEVEL_10_1:
+      case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_TEXTURE3D_U_V_OR_W_DIMENSION;
+
+      case D3D_FEATURE_LEVEL_9_3:
+      case D3D_FEATURE_LEVEL_9_2:
+      case D3D_FEATURE_LEVEL_9_1:  return D3D_FL9_1_REQ_TEXTURE3D_U_V_OR_W_DIMENSION;
+
+      default: UNREACHABLE();      return 0;
+    }
+}
+
+static size_t GetMaximumViewportSize(D3D_FEATURE_LEVEL featureLevel)
+{
+    switch (featureLevel)
+    {
+      case D3D_FEATURE_LEVEL_11_1:
+      case D3D_FEATURE_LEVEL_11_0: return D3D11_VIEWPORT_BOUNDS_MAX;
+
+      case D3D_FEATURE_LEVEL_10_1:
+      case D3D_FEATURE_LEVEL_10_0: return D3D10_VIEWPORT_BOUNDS_MAX;
+
+        // No constants for D3D9 viewport size limits, use the maximum texture sizes
+      case D3D_FEATURE_LEVEL_9_3:  return D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION;
+      case D3D_FEATURE_LEVEL_9_2:
+      case D3D_FEATURE_LEVEL_9_1:  return D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION;
+
+      default: UNREACHABLE();      return 0;
+    }
+}
+
 gl::Caps GenerateCaps(ID3D11Device *device)
 {
     gl::Caps caps;
@@ -286,6 +513,37 @@
 
     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);
+
+    // Unimplemented, set to minimum required
+    caps.maxLODBias = 2.0f;
+
+    // No specific limits on render target size, maximum 2D texture size is equivalent
+    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);
+
+    // D3D11 has the same limit for viewport width and height
+    caps.maxViewportWidth = GetMaximumViewportSize(featureLevel);
+    caps.maxViewportHeight = caps.maxViewportWidth;
+
+    // Choose a reasonable maximum, enforced in the shader.
+    caps.minAliasedPointSize = 1.0f;
+    caps.maxAliasedPointSize = 1024.0f;
+
+    // Wide lines not supported
+    caps.minAliasedLineWidth = 1.0f;
+    caps.maxAliasedLineWidth = 1.0f;
+
+    // GL extension support
     caps.extensions.setTextureExtensionSupport(caps.textureCaps);
     caps.extensions.elementIndexUint = true;
     caps.extensions.packedDepthStencil = true;
@@ -295,21 +553,21 @@
     caps.extensions.pixelBufferObject = true;
     caps.extensions.mapBuffer = true;
     caps.extensions.mapBufferRange = true;
-    caps.extensions.textureNPOT = d3d11::GetNPOTTextureSupport(featureLevel);
-    caps.extensions.drawBuffers = d3d11::GetMaximumSimultaneousRenderTargets(featureLevel) > 1;
+    caps.extensions.textureNPOT = GetNPOTTextureSupport(featureLevel);
+    caps.extensions.drawBuffers = GetMaximumSimultaneousRenderTargets(featureLevel) > 1;
     caps.extensions.textureStorage = true;
     caps.extensions.textureFilterAnisotropic = true;
-    caps.extensions.maxTextureAnisotropy = d3d11::GetMaximumAnisotropy(featureLevel);
-    caps.extensions.occlusionQueryBoolean = d3d11::GetOcclusionQuerySupport(featureLevel);
-    caps.extensions.fence = d3d11::GetEventQuerySupport(featureLevel);
+    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 = d3d11::GetInstancingSupport(featureLevel);
+    caps.extensions.instancedArrays = GetInstancingSupport(featureLevel);
     caps.extensions.packReverseRowOrder = true;
-    caps.extensions.standardDerivatives = d3d11::GetDerivativeInstructionSupport(featureLevel);
+    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
@@ -379,142 +637,6 @@
 #endif
 }
 
-bool GetNPOTTextureSupport(D3D_FEATURE_LEVEL featureLevel)
-{
-    switch (featureLevel)
-    {
-      case D3D_FEATURE_LEVEL_11_1:
-      case D3D_FEATURE_LEVEL_11_0:
-      case D3D_FEATURE_LEVEL_10_1:
-      case D3D_FEATURE_LEVEL_10_0: return true;
-
-      // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476876.aspx
-      case D3D_FEATURE_LEVEL_9_3:
-      case D3D_FEATURE_LEVEL_9_2:
-      case D3D_FEATURE_LEVEL_9_1:  return false;
-
-      default: UNREACHABLE();      return false;
-    }
-}
-
-float GetMaximumAnisotropy(D3D_FEATURE_LEVEL featureLevel)
-{
-    switch (featureLevel)
-    {
-      case D3D_FEATURE_LEVEL_11_1:
-      case D3D_FEATURE_LEVEL_11_0: return D3D11_MAX_MAXANISOTROPY;
-
-      case D3D_FEATURE_LEVEL_10_1:
-      case D3D_FEATURE_LEVEL_10_0: return D3D10_MAX_MAXANISOTROPY;
-
-      // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476876.aspx
-      case D3D_FEATURE_LEVEL_9_3:
-      case D3D_FEATURE_LEVEL_9_2:  return 16;
-
-      case D3D_FEATURE_LEVEL_9_1:  return D3D_FL9_1_DEFAULT_MAX_ANISOTROPY;
-
-      default: UNREACHABLE();      return 0;
-    }
-}
-
-bool GetOcclusionQuerySupport(D3D_FEATURE_LEVEL featureLevel)
-{
-    switch (featureLevel)
-    {
-      case D3D_FEATURE_LEVEL_11_1:
-      case D3D_FEATURE_LEVEL_11_0:
-      case D3D_FEATURE_LEVEL_10_1:
-      case D3D_FEATURE_LEVEL_10_0: return true;
-
-      // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476150.aspx ID3D11Device::CreateQuery
-      case D3D_FEATURE_LEVEL_9_3:
-      case D3D_FEATURE_LEVEL_9_2:  return true;
-      case D3D_FEATURE_LEVEL_9_1:  return false;
-
-      default: UNREACHABLE();      return false;
-    }
-}
-
-bool GetEventQuerySupport(D3D_FEATURE_LEVEL featureLevel)
-{
-    // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476150.aspx ID3D11Device::CreateQuery
-
-    switch (featureLevel)
-    {
-      case D3D_FEATURE_LEVEL_11_1:
-      case D3D_FEATURE_LEVEL_11_0:
-      case D3D_FEATURE_LEVEL_10_1:
-      case D3D_FEATURE_LEVEL_10_0:
-      case D3D_FEATURE_LEVEL_9_3:
-      case D3D_FEATURE_LEVEL_9_2:
-      case D3D_FEATURE_LEVEL_9_1:  return true;
-
-      default: UNREACHABLE();      return false;
-    }
-}
-
-bool GetInstancingSupport(D3D_FEATURE_LEVEL featureLevel)
-{
-    // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476150.aspx ID3D11Device::CreateInputLayout
-
-    switch (featureLevel)
-    {
-      case D3D_FEATURE_LEVEL_11_1:
-      case D3D_FEATURE_LEVEL_11_0:
-      case D3D_FEATURE_LEVEL_10_1:
-      case D3D_FEATURE_LEVEL_10_0:
-      case D3D_FEATURE_LEVEL_9_3:  return true;
-
-      case D3D_FEATURE_LEVEL_9_2:
-      case D3D_FEATURE_LEVEL_9_1:  return false;
-
-      default: UNREACHABLE();      return false;
-    }
-}
-
-bool GetDerivativeInstructionSupport(D3D_FEATURE_LEVEL featureLevel)
-{
-    // http://msdn.microsoft.com/en-us/library/windows/desktop/bb509588.aspx states that shader model
-    // ps_2_x is required for the ddx (and other derivative functions).
-
-    // http://msdn.microsoft.com/en-us/library/windows/desktop/ff476876.aspx states that feature level
-    // 9.3 supports shader model ps_2_x.
-
-    switch (featureLevel)
-    {
-      case D3D_FEATURE_LEVEL_11_1:
-      case D3D_FEATURE_LEVEL_11_0:
-      case D3D_FEATURE_LEVEL_10_1:
-      case D3D_FEATURE_LEVEL_10_0:
-      case D3D_FEATURE_LEVEL_9_3:  return true;
-      case D3D_FEATURE_LEVEL_9_2:
-      case D3D_FEATURE_LEVEL_9_1:  return false;
-
-      default: UNREACHABLE();      return false;
-    }
-}
-
-size_t GetMaximumSimultaneousRenderTargets(D3D_FEATURE_LEVEL featureLevel)
-{
-    // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476150.aspx ID3D11Device::CreateInputLayout
-
-    switch (featureLevel)
-    {
-      case D3D_FEATURE_LEVEL_11_1:
-      case D3D_FEATURE_LEVEL_11_0: return D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT;
-
-      // FIXME(geofflang): Work around NVIDIA driver bug by repacking buffers
-      case D3D_FEATURE_LEVEL_10_1:
-      case D3D_FEATURE_LEVEL_10_0: return 1; /* D3D10_SIMULTANEOUS_RENDER_TARGET_COUNT; */
-
-      case D3D_FEATURE_LEVEL_9_3:  return D3D_FL9_3_SIMULTANEOUS_RENDER_TARGET_COUNT;
-      case D3D_FEATURE_LEVEL_9_2:
-      case D3D_FEATURE_LEVEL_9_1:  return D3D_FL9_1_SIMULTANEOUS_RENDER_TARGET_COUNT;
-
-      default: UNREACHABLE();      return 0;
-    }
-}
-
 }
 
 }
diff --git a/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.h b/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.h
index 81efefa..e5e3e1c 100644
--- a/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.h
+++ b/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.h
@@ -166,14 +166,6 @@
     context->Unmap(constantBuffer, 0);
 }
 
-bool GetNPOTTextureSupport(D3D_FEATURE_LEVEL featureLevel);
-float GetMaximumAnisotropy(D3D_FEATURE_LEVEL featureLevel);
-bool GetOcclusionQuerySupport(D3D_FEATURE_LEVEL featureLevel);
-bool GetEventQuerySupport(D3D_FEATURE_LEVEL featureLevel);
-bool GetInstancingSupport(D3D_FEATURE_LEVEL featureLevel);
-bool GetDerivativeInstructionSupport(D3D_FEATURE_LEVEL featureLevel);
-size_t GetMaximumSimultaneousRenderTargets(D3D_FEATURE_LEVEL featureLevel);
-
 }
 
 }
diff --git a/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp b/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp
index 02ceae2..c8dffe0 100644
--- a/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp
+++ b/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp
@@ -2368,41 +2368,6 @@
     return D3DSHADER_VERSION_MAJOR(mDeviceCaps.PixelShaderVersion);
 }
 
-float Renderer9::getMaxPointSize() const
-{
-    // Point size clamped at 1.0f for SM2
-    return getMajorShaderModel() == 3 ? mDeviceCaps.MaxPointSize : 1.0f;
-}
-
-int Renderer9::getMaxViewportDimension() const
-{
-    int maxTextureDimension = std::min(std::min(getMaxTextureWidth(), getMaxTextureHeight()),
-                                       (int)gl::IMPLEMENTATION_MAX_2D_TEXTURE_SIZE);
-    return maxTextureDimension;
-}
-
-int Renderer9::getMaxTextureWidth() const
-{
-    return (int)mDeviceCaps.MaxTextureWidth;
-}
-
-int Renderer9::getMaxTextureHeight() const
-{
-    return (int)mDeviceCaps.MaxTextureHeight;
-}
-
-int Renderer9::getMaxTextureDepth() const
-{
-    // 3D textures are not available in the D3D9 backend.
-    return 1;
-}
-
-int Renderer9::getMaxTextureArrayLayers() const
-{
-    // 2D array textures are not available in the D3D9 backend.
-    return 1;
-}
-
 DWORD Renderer9::getCapsDeclTypes() const
 {
     return mDeviceCaps.DeclTypes;
@@ -2496,12 +2461,6 @@
     return -1;
 }
 
-unsigned int Renderer9::getMaxRenderTargets() const
-{
-    // we do not support MRT in d3d9
-    return 1;
-}
-
 bool Renderer9::copyToRenderTarget(TextureStorageInterface2D *dest, TextureStorageInterface2D *source)
 {
     bool result = false;
diff --git a/src/libGLESv2/renderer/d3d/d3d9/Renderer9.h b/src/libGLESv2/renderer/d3d/d3d9/Renderer9.h
index c7b0018..3b59983 100644
--- a/src/libGLESv2/renderer/d3d/d3d9/Renderer9.h
+++ b/src/libGLESv2/renderer/d3d/d3d9/Renderer9.h
@@ -127,12 +127,6 @@
     virtual bool getSRGBTextureSupport() const;
 
     virtual int getMajorShaderModel() const;
-    virtual float getMaxPointSize() const;
-    virtual int getMaxViewportDimension() const;
-    virtual int getMaxTextureWidth() const;
-    virtual int getMaxTextureHeight() const;
-    virtual int getMaxTextureDepth() const;
-    virtual int getMaxTextureArrayLayers() const;
     DWORD getCapsDeclTypes() const;
     virtual int getMinSwapInterval() const;
     virtual int getMaxSwapInterval() const;
@@ -143,8 +137,6 @@
     virtual void getSampleCounts(GLenum internalFormat, GLsizei bufSize, GLint *params) const;
     int getNearestSupportedSamples(D3DFORMAT format, int requested) const;
 
-    virtual unsigned int getMaxRenderTargets() const;
-
     // Pixel operations
     virtual bool copyToRenderTarget(TextureStorageInterface2D *dest, TextureStorageInterface2D *source);
     virtual bool copyToRenderTarget(TextureStorageInterfaceCube *dest, TextureStorageInterfaceCube *source);
diff --git a/src/libGLESv2/renderer/d3d/d3d9/renderer9_utils.cpp b/src/libGLESv2/renderer/d3d/d3d9/renderer9_utils.cpp
index 8c3a333..4f3a8f6 100644
--- a/src/libGLESv2/renderer/d3d/d3d9/renderer9_utils.cpp
+++ b/src/libGLESv2/renderer/d3d/d3d9/renderer9_utils.cpp
@@ -329,6 +329,44 @@
                                                                            currentDisplayMode.Format));
     }
 
+    // GL core feature limits
+    caps.maxElementIndex = static_cast<GLint64>(std::numeric_limits<unsigned int>::max());
+
+    // 3D textures are unimplemented in D3D9
+    caps.max3DTextureSize = 1;
+
+    // Only one limit in GL, use the minimum dimension
+    caps.max2DTextureSize = std::min(deviceCaps.MaxTextureWidth, deviceCaps.MaxTextureHeight);
+
+    // D3D treats cube maps as a special case of 2D textures
+    caps.maxCubeMapTextureSize = caps.max2DTextureSize;
+
+    // Array textures are not available in D3D9
+    caps.maxArrayTextureLayers = 1;
+
+    // ES3-only feature
+    caps.maxLODBias = 0.0f;
+
+    // No specific limits on render target size, maximum 2D texture size is equivalent
+    caps.maxRenderbufferSize = caps.max2DTextureSize;
+
+    // Draw buffers are not supported in D3D9
+    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;
+
+    // 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);
+
+    // Wide lines not supported
+    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;