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/Caps.cpp b/src/libGLESv2/Caps.cpp
index 39e81dd..f12c044 100644
--- a/src/libGLESv2/Caps.cpp
+++ b/src/libGLESv2/Caps.cpp
@@ -340,6 +340,23 @@
 }
 
 Caps::Caps()
+    : maxElementIndex(0),
+      max3DTextureSize(0),
+      max2DTextureSize(0),
+      maxArrayTextureLayers(0),
+      maxLODBias(0),
+      maxCubeMapTextureSize(0),
+      maxRenderbufferSize(0),
+      maxDrawBuffers(0),
+      maxColorAttachments(0),
+      maxViewportWidth(0),
+      maxViewportHeight(0),
+      minAliasedPointSize(0),
+      maxAliasedPointSize(0),
+      minAliasedLineWidth(0),
+      maxAliasedLineWidth(0),
+      textureCaps(),
+      extensions()
 {
 }
 
diff --git a/src/libGLESv2/Caps.h b/src/libGLESv2/Caps.h
index 04da664..4ae909c 100644
--- a/src/libGLESv2/Caps.h
+++ b/src/libGLESv2/Caps.h
@@ -191,6 +191,23 @@
 {
     Caps();
 
+    // Table 6.28, implementation dependent values
+    GLuint64 maxElementIndex;
+    GLuint max3DTextureSize;
+    GLuint max2DTextureSize;
+    GLuint maxArrayTextureLayers;
+    GLfloat maxLODBias;
+    GLuint maxCubeMapTextureSize;
+    GLuint maxRenderbufferSize;
+    GLuint maxDrawBuffers;
+    GLuint maxColorAttachments;
+    GLuint maxViewportWidth;
+    GLuint maxViewportHeight;
+    GLfloat minAliasedPointSize;
+    GLfloat maxAliasedPointSize;
+    GLfloat minAliasedLineWidth;
+    GLfloat maxAliasedLineWidth;
+
     // Texture format support
     TextureCapsMap textureCaps;
 
diff --git a/src/libGLESv2/Context.cpp b/src/libGLESv2/Context.cpp
index 6e35b74..ac09e0e 100644
--- a/src/libGLESv2/Context.cpp
+++ b/src/libGLESv2/Context.cpp
@@ -311,28 +311,8 @@
     if (!mHasBeenCurrent)
     {
         mMajorShaderModel = mRenderer->getMajorShaderModel();
-        mMaximumPointSize = mRenderer->getMaxPointSize();
         mSupportsVertexTexture = mRenderer->getVertexTextureSupport();
 
-        mMaxViewportDimension = mRenderer->getMaxViewportDimension();
-        mMax2DTextureDimension = std::min(std::min(mRenderer->getMaxTextureWidth(), mRenderer->getMaxTextureHeight()),
-                                          (int)gl::IMPLEMENTATION_MAX_2D_TEXTURE_SIZE);
-        mMaxCubeTextureDimension = std::min(mMax2DTextureDimension, (int)gl::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE);
-        mMax3DTextureDimension = std::min(std::min(mMax2DTextureDimension, mRenderer->getMaxTextureDepth()),
-                                          (int)gl::IMPLEMENTATION_MAX_3D_TEXTURE_SIZE);
-        mMax2DArrayTextureLayers = mRenderer->getMaxTextureArrayLayers();
-        mMaxRenderbufferDimension = mMax2DTextureDimension;
-        mMax2DTextureLevel = log2(mMax2DTextureDimension) + 1;
-        mMaxCubeTextureLevel = log2(mMaxCubeTextureDimension) + 1;
-        mMax3DTextureLevel = log2(mMax3DTextureDimension) + 1;
-        mMax2DArrayTextureLevel = log2(mMax2DTextureDimension) + 1;
-        TRACE("Max2DTextureDimension=%d, MaxCubeTextureDimension=%d, Max3DTextureDimension=%d, Max2DArrayTextureLayers = %d, "
-              "Max2DTextureLevel=%d, MaxCubeTextureLevel=%d, Max3DTextureLevel=%d, Max2DArrayTextureLevel=%d, "
-              "MaxRenderbufferDimension=%d",
-              mMax2DTextureDimension, mMaxCubeTextureDimension, mMax3DTextureDimension, mMax2DArrayTextureLayers,
-              mMax2DTextureLevel, mMaxCubeTextureLevel, mMax3DTextureLevel, mMax2DArrayTextureLevel,
-              mMaxRenderbufferDimension);
-
         mNumCompressedTextureFormats = 0;
         if (getCaps().extensions.textureCompressionDXT1)
         {
@@ -1656,12 +1636,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] = gl::ALIASED_LINE_WIDTH_RANGE_MIN;
-        params[1] = gl::ALIASED_LINE_WIDTH_RANGE_MAX;
+        params[0] = getCaps().minAliasedLineWidth;
+        params[1] = getCaps().maxAliasedLineWidth;
         break;
       case GL_ALIASED_POINT_SIZE_RANGE:
-        params[0] = gl::ALIASED_POINT_SIZE_RANGE_MIN;
-        params[1] = getMaximumPointSize();
+        params[0] = getCaps().minAliasedPointSize;
+        params[1] = getCaps().maxAliasedPointSize;
         break;
       case GL_DEPTH_RANGE:
         params[0] = mState.zNear;
@@ -1691,10 +1671,12 @@
 
 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 < mRenderer->getMaxRenderTargets());
+        ASSERT(colorAttachment < caps.maxDrawBuffers);
         Framebuffer *framebuffer = getDrawFramebuffer();
         *params = framebuffer->getDrawBufferState(colorAttachment);
         return;
@@ -1717,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 = getMaximumRenderbufferDimension();                    break;
-      case GL_MAX_COLOR_ATTACHMENTS_EXT:                *params = mRenderer->getMaxRenderTargets();                     break;
-      case GL_MAX_DRAW_BUFFERS_EXT:                     *params = mRenderer->getMaxRenderTargets();                     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_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;
@@ -1759,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 = getMaximum2DTextureDimension();                       break;
-      case GL_MAX_CUBE_MAP_TEXTURE_SIZE:                *params = getMaximumCubeTextureDimension();                     break;
-      case GL_MAX_3D_TEXTURE_SIZE:                      *params = getMaximum3DTextureDimension();                       break;
-      case GL_MAX_ARRAY_TEXTURE_LAYERS:                 *params = getMaximum2DArrayTextureLayers();                     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_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;
@@ -1823,8 +1805,8 @@
         break;
       case GL_MAX_VIEWPORT_DIMS:
         {
-            params[0] = mMaxViewportDimension;
-            params[1] = mMaxViewportDimension;
+            params[0] = getCaps().maxViewportWidth;
+            params[1] = getCaps().maxViewportHeight;
         }
         break;
       case GL_COMPRESSED_TEXTURE_FORMATS:
@@ -1969,7 +1951,7 @@
     switch (pname)
     {
       case GL_MAX_ELEMENT_INDEX:
-        *params = static_cast<GLint64>(std::numeric_limits<unsigned int>::max());
+        *params = getCaps().maxElementIndex;
         break;
       case GL_MAX_UNIFORM_BLOCK_SIZE:
         *params = static_cast<GLint64>(mRenderer->getMaxUniformBufferSize());
@@ -3118,11 +3100,6 @@
     return mMajorShaderModel;
 }
 
-float Context::getMaximumPointSize() const
-{
-    return mMaximumPointSize;
-}
-
 unsigned int Context::getMaximumCombinedTextureImageUnits() const
 {
     return mRenderer->getMaxCombinedTextureImageUnits();
@@ -3165,56 +3142,6 @@
     return static_cast<GLintptr>(std::numeric_limits<GLint>::max());
 }
 
-unsigned int Context::getMaximumRenderTargets() const
-{
-    return mRenderer->getMaxRenderTargets();
-}
-
-int Context::getMaximumRenderbufferDimension() const
-{
-    return mMaxRenderbufferDimension;
-}
-
-int Context::getMaximum2DTextureDimension() const
-{
-    return mMax2DTextureDimension;
-}
-
-int Context::getMaximumCubeTextureDimension() const
-{
-    return mMaxCubeTextureDimension;
-}
-
-int Context::getMaximum3DTextureDimension() const
-{
-    return mMax3DTextureDimension;
-}
-
-int Context::getMaximum2DArrayTextureLayers() const
-{
-    return mMax2DArrayTextureLayers;
-}
-
-int Context::getMaximum2DTextureLevel() const
-{
-    return mMax2DTextureLevel;
-}
-
-int Context::getMaximumCubeTextureLevel() const
-{
-    return mMaxCubeTextureLevel;
-}
-
-int Context::getMaximum3DTextureLevel() const
-{
-    return mMax3DTextureLevel;
-}
-
-int Context::getMaximum2DArrayTextureLevel() const
-{
-    return mMax2DArrayTextureLevel;
-}
-
 void Context::getCurrentReadFormatType(GLenum *internalFormat, GLenum *format, GLenum *type)
 {
     Framebuffer *framebuffer = getReadFramebuffer();
diff --git a/src/libGLESv2/Context.h b/src/libGLESv2/Context.h
index 9a3a739..21d61de 100644
--- a/src/libGLESv2/Context.h
+++ b/src/libGLESv2/Context.h
@@ -404,19 +404,8 @@
     const Caps &getCaps() const;
 
     int getMajorShaderModel() const;
-    float getMaximumPointSize() const;
     unsigned int getMaximumCombinedTextureImageUnits() const;
     unsigned int getMaximumCombinedUniformBufferBindings() const;
-    int getMaximumRenderbufferDimension() const;
-    int getMaximum2DTextureDimension() const;
-    int getMaximumCubeTextureDimension() const;
-    int getMaximum3DTextureDimension() const;
-    int getMaximum2DArrayTextureLayers() const;
-    int getMaximum2DTextureLevel() const;
-    int getMaximumCubeTextureLevel() const;
-    int getMaximum3DTextureLevel() const;
-    int getMaximum2DArrayTextureLevel() const;
-    unsigned int getMaximumRenderTargets() const;
     GLsizei getMaxSupportedSamples() const;
     GLsizei getMaxSupportedFormatSamples(GLenum internalFormat) const;
     GLsizei getNumSampleCounts(GLenum internalFormat) const;
@@ -533,18 +522,7 @@
     Framebuffer *mBoundDrawFramebuffer;
 
     int mMajorShaderModel;
-    float mMaximumPointSize;
     bool mSupportsVertexTexture;
-    int  mMaxViewportDimension;
-    int  mMaxRenderbufferDimension;
-    int  mMax2DTextureDimension;
-    int  mMaxCubeTextureDimension;
-    int  mMax3DTextureDimension;
-    int  mMax2DArrayTextureLayers;
-    int  mMax2DTextureLevel;
-    int  mMaxCubeTextureLevel;
-    int  mMax3DTextureLevel;
-    int  mMax2DArrayTextureLevel;
     int mNumCompressedTextureFormats;
 
     ResourceManager *mResourceManager;
diff --git a/src/libGLESv2/DynamicHLSL.cpp b/src/libGLESv2/DynamicHLSL.cpp
index 78cbf15..a4db907 100644
--- a/src/libGLESv2/DynamicHLSL.cpp
+++ b/src/libGLESv2/DynamicHLSL.cpp
@@ -658,8 +658,8 @@
     // Two cases when writing to gl_FragColor and using ESSL 1.0:
     // - 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 = (usesFragColor && mRenderer->getCurrentClientVersion() < 3);
-    const unsigned int numRenderTargets = (broadcast || usesMRT ? mRenderer->getMaxRenderTargets() : 1);
+    const bool broadcast = (fragmentShader->mUsesFragColor && mRenderer->getCurrentClientVersion() < 3);
+    const unsigned int numRenderTargets = (broadcast || usesMRT ? mRenderer->getCaps().maxDrawBuffers : 1);
 
     int shaderVersion = vertexShader->getShaderVersion();
 
@@ -1017,8 +1017,8 @@
                   "    float2(0.0f, 0.0f)\n"
                   "};\n"
                   "\n"
-                  "static float minPointSize = " + Str(ALIASED_POINT_SIZE_RANGE_MIN) + ".0f;\n"
-                  "static float maxPointSize = " + Str(mRenderer->getMaxPointSize()) + ".0f;\n"
+                  "static float minPointSize = " + Str(mRenderer->getCaps().minAliasedPointSize) + ".0f;\n"
+                  "static float maxPointSize = " + Str(mRenderer->getCaps().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/Shader.cpp b/src/libGLESv2/Shader.cpp
index 98c1537..ed0171a 100644
--- a/src/libGLESv2/Shader.cpp
+++ b/src/libGLESv2/Shader.cpp
@@ -193,7 +193,7 @@
             resources.MaxCombinedTextureImageUnits = mRenderer->getMaxCombinedTextureImageUnits();
             resources.MaxTextureImageUnits = MAX_TEXTURE_IMAGE_UNITS;
             resources.MaxFragmentUniformVectors = mRenderer->getMaxFragmentUniformVectors();
-            resources.MaxDrawBuffers = mRenderer->getMaxRenderTargets();
+            resources.MaxDrawBuffers = caps.maxDrawBuffers;
             resources.OES_standard_derivatives = caps.extensions.standardDerivatives;
             resources.EXT_draw_buffers = caps.extensions.drawBuffers;
             resources.EXT_shader_texture_lod = 1;
diff --git a/src/libGLESv2/constants.h b/src/libGLESv2/constants.h
index 0c1c0ef..7972536 100644
--- a/src/libGLESv2/constants.h
+++ b/src/libGLESv2/constants.h
@@ -33,10 +33,6 @@
     IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS = 4,
 };
 
-const float ALIASED_LINE_WIDTH_RANGE_MIN = 1.0f;
-const float ALIASED_LINE_WIDTH_RANGE_MAX = 1.0f;
-const float ALIASED_POINT_SIZE_RANGE_MIN = 1.0f;
-
 }
 
 #endif // LIBGLESV2_CONSTANTS_H_
diff --git a/src/libGLESv2/libGLESv2.cpp b/src/libGLESv2/libGLESv2.cpp
index 630330c..012a0d9 100644
--- a/src/libGLESv2/libGLESv2.cpp
+++ b/src/libGLESv2/libGLESv2.cpp
@@ -2595,7 +2595,7 @@
 
               default:
                 if (attachment < GL_COLOR_ATTACHMENT0_EXT ||
-                    (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getMaximumRenderTargets())
+                    (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
                 {
                     return gl::error(GL_INVALID_ENUM);
                 }
@@ -7860,7 +7860,7 @@
             switch (buffer)
             {
               case GL_COLOR:
-                if (drawbuffer < 0 || drawbuffer >= static_cast<GLint>(context->getMaximumRenderTargets()))
+                if (drawbuffer < 0 || static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
                 {
                     return gl::error(GL_INVALID_VALUE);
                 }
@@ -7903,7 +7903,7 @@
             switch (buffer)
             {
               case GL_COLOR:
-                if (drawbuffer < 0 || drawbuffer >= static_cast<GLint>(context->getMaximumRenderTargets()))
+                if (drawbuffer < 0 || static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
                 {
                     return gl::error(GL_INVALID_VALUE);
                 }
@@ -7940,7 +7940,7 @@
             switch (buffer)
             {
               case GL_COLOR:
-                if (drawbuffer < 0 || drawbuffer >= static_cast<GLint>(context->getMaximumRenderTargets()))
+                if (drawbuffer < 0 || static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
                 {
                     return gl::error(GL_INVALID_VALUE);
                 }
@@ -9486,7 +9486,7 @@
                 return;
             }
 
-            int maxDimension = context->getMaximumRenderbufferDimension();
+            GLuint maxDimension = context->getCaps().maxRenderbufferSize;
             context->invalidateFrameBuffer(target, numAttachments, attachments, 0, 0, maxDimension, maxDimension);
         }
     }
@@ -9811,7 +9811,7 @@
 
         if (context)
         {
-            if (n < 0 || (unsigned int)n > context->getMaximumRenderTargets())
+            if (n < 0 || static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
             {
                 return gl::error(GL_INVALID_VALUE);
             }
@@ -9842,12 +9842,12 @@
 
             gl::Framebuffer *framebuffer = context->getDrawFramebuffer();
 
-            for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
+            for (unsigned int colorAttachment = 0; colorAttachment < static_cast<unsigned int>(n); colorAttachment++)
             {
                 framebuffer->setDrawBufferState(colorAttachment, bufs[colorAttachment]);
             }
 
-            for (int colorAttachment = n; colorAttachment < (int)context->getMaximumRenderTargets(); colorAttachment++)
+            for (unsigned int colorAttachment = n; colorAttachment < context->getCaps().maxDrawBuffers; colorAttachment++)
             {
                 framebuffer->setDrawBufferState(colorAttachment, GL_NONE);
             }
diff --git a/src/libGLESv2/renderer/Renderer.h b/src/libGLESv2/renderer/Renderer.h
index 818fddd..919b5a5 100644
--- a/src/libGLESv2/renderer/Renderer.h
+++ b/src/libGLESv2/renderer/Renderer.h
@@ -173,12 +173,6 @@
     virtual bool getSRGBTextureSupport() const = 0;
 
     virtual int getMajorShaderModel() const = 0;
-    virtual float getMaxPointSize() const = 0;
-    virtual int getMaxViewportDimension() const = 0;
-    virtual int getMaxTextureWidth() const = 0;
-    virtual int getMaxTextureHeight() const = 0;
-    virtual int getMaxTextureDepth() const = 0;
-    virtual int getMaxTextureArrayLayers() const = 0;
     virtual int getMinSwapInterval() const = 0;
     virtual int getMaxSwapInterval() const = 0;
 
@@ -187,8 +181,6 @@
     virtual GLsizei getNumSampleCounts(GLenum internalFormat) const = 0;
     virtual void getSampleCounts(GLenum internalFormat, GLsizei bufSize, GLint *params) const = 0;
 
-    virtual unsigned int getMaxRenderTargets() const = 0;
-
     // Pixel operations
     virtual bool copyToRenderTarget(TextureStorageInterface2D *dest, TextureStorageInterface2D *source) = 0;
     virtual bool copyToRenderTarget(TextureStorageInterfaceCube *dest, TextureStorageInterfaceCube *source) = 0;
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;
diff --git a/src/libGLESv2/validationES.cpp b/src/libGLESv2/validationES.cpp
index cda2bc8..b1c4810 100644
--- a/src/libGLESv2/validationES.cpp
+++ b/src/libGLESv2/validationES.cpp
@@ -148,23 +148,23 @@
 
 bool ValidMipLevel(const Context *context, GLenum target, GLint level)
 {
-    int maxLevel = 0;
+    size_t maxDimension = 0;
     switch (target)
     {
-      case GL_TEXTURE_2D:                  maxLevel = context->getMaximum2DTextureLevel();      break;
+      case GL_TEXTURE_2D:                  maxDimension = context->getCaps().max2DTextureSize;       break;
       case GL_TEXTURE_CUBE_MAP:
       case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
       case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
       case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
       case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
       case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
-      case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: maxLevel = context->getMaximumCubeTextureLevel();    break;
-      case GL_TEXTURE_3D:                  maxLevel = context->getMaximum3DTextureLevel();      break;
-      case GL_TEXTURE_2D_ARRAY:            maxLevel = context->getMaximum2DArrayTextureLevel(); break;
+      case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: maxDimension = context->getCaps().maxCubeMapTextureSize;  break;
+      case GL_TEXTURE_3D:                  maxDimension = context->getCaps().max3DTextureSize;       break;
+      case GL_TEXTURE_2D_ARRAY:            maxDimension = context->getCaps().max2DTextureSize;       break;
       default: UNREACHABLE();
     }
 
-    return level < maxLevel;
+    return level <= gl::log2(maxDimension);
 }
 
 bool ValidImageSize(const gl::Context *context, GLenum target, GLint level,
@@ -252,7 +252,7 @@
     {
         const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
 
-        if (colorAttachment >= context->getMaximumRenderTargets())
+        if (colorAttachment >= context->getCaps().maxColorAttachments)
         {
             return gl::error(GL_INVALID_VALUE, false);
         }
@@ -324,7 +324,7 @@
         return gl::error(GL_INVALID_ENUM, false);
     }
 
-    if (std::max(width, height) > context->getMaximumRenderbufferDimension())
+    if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
     {
         return gl::error(GL_INVALID_VALUE, false);
     }
@@ -1061,7 +1061,7 @@
     {
         unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
 
-        if (colorAttachment >= context->getMaximumRenderTargets())
+        if (colorAttachment >= context->getCaps().maxDrawBuffers)
         {
             return gl::error(GL_INVALID_OPERATION, false);
         }
@@ -1151,6 +1151,8 @@
         return gl::error(GL_INVALID_OPERATION, false);
     }
 
+    const gl::Caps &caps = context->getCaps();
+
     gl::Texture *texture = NULL;
     GLenum textureInternalFormat = GL_NONE;
     bool textureCompressed = false;
@@ -1158,7 +1160,7 @@
     GLint textureLevelWidth = 0;
     GLint textureLevelHeight = 0;
     GLint textureLevelDepth = 0;
-    int maxDimension = 0;
+    GLuint maxDimension = 0;
 
     switch (target)
     {
@@ -1174,7 +1176,7 @@
                 textureLevelHeight = texture2d->getHeight(level);
                 textureLevelDepth = 1;
                 texture = texture2d;
-                maxDimension = context->getMaximum2DTextureDimension();
+                maxDimension = caps.max2DTextureSize;
             }
         }
         break;
@@ -1196,7 +1198,7 @@
                 textureLevelHeight = textureCube->getHeight(target, level);
                 textureLevelDepth = 1;
                 texture = textureCube;
-                maxDimension = context->getMaximumCubeTextureDimension();
+                maxDimension = caps.maxCubeMapTextureSize;
             }
         }
         break;
@@ -1213,7 +1215,7 @@
                 textureLevelHeight = texture2dArray->getHeight(level);
                 textureLevelDepth = texture2dArray->getLayers(level);
                 texture = texture2dArray;
-                maxDimension = context->getMaximum2DTextureDimension();
+                maxDimension = caps.max2DTextureSize;
             }
         }
         break;
@@ -1230,7 +1232,7 @@
                 textureLevelHeight = texture3d->getHeight(level);
                 textureLevelDepth = texture3d->getDepth(level);
                 texture = texture3d;
-                maxDimension = context->getMaximum3DTextureDimension();
+                maxDimension = caps.max3DTextureSize;
             }
         }
         break;
diff --git a/src/libGLESv2/validationES2.cpp b/src/libGLESv2/validationES2.cpp
index a11ca9c..9c96c9a 100644
--- a/src/libGLESv2/validationES2.cpp
+++ b/src/libGLESv2/validationES2.cpp
@@ -131,6 +131,8 @@
         return gl::error(GL_INVALID_OPERATION, false);
     }
 
+    const gl::Caps &caps = context->getCaps();
+
     gl::Texture *texture = NULL;
     bool textureCompressed = false;
     GLenum textureInternalFormat = GL_NONE;
@@ -140,8 +142,8 @@
     {
       case GL_TEXTURE_2D:
         {
-            if (width > (context->getMaximum2DTextureDimension() >> level) ||
-                height > (context->getMaximum2DTextureDimension() >> level))
+            if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
+                static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
             {
                 return gl::error(GL_INVALID_VALUE, false);
             }
@@ -178,8 +180,8 @@
                 return gl::error(GL_INVALID_VALUE, false);
             }
 
-            if (width > (context->getMaximumCubeTextureDimension() >> level) ||
-                height > (context->getMaximumCubeTextureDimension() >> level))
+            if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level) ||
+                static_cast<GLuint>(height) > (caps.maxCubeMapTextureSize >> level))
             {
                 return gl::error(GL_INVALID_VALUE, false);
             }
@@ -712,18 +714,20 @@
         return gl::error(GL_INVALID_ENUM, false);
     }
 
+    const gl::Caps &caps = context->getCaps();
+
     switch (target)
     {
       case GL_TEXTURE_2D:
-        if (width > context->getMaximum2DTextureDimension() ||
-            height > context->getMaximum2DTextureDimension())
+        if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
+            static_cast<GLuint>(height) > caps.max2DTextureSize)
         {
             return gl::error(GL_INVALID_VALUE, false);
         }
         break;
       case GL_TEXTURE_CUBE_MAP:
-        if (width > context->getMaximumCubeTextureDimension() ||
-            height > context->getMaximumCubeTextureDimension())
+        if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize ||
+            static_cast<GLuint>(height) > caps.maxCubeMapTextureSize)
         {
             return gl::error(GL_INVALID_VALUE, false);
         }
diff --git a/src/libGLESv2/validationES3.cpp b/src/libGLESv2/validationES3.cpp
index 92ee329..dfb0356 100644
--- a/src/libGLESv2/validationES3.cpp
+++ b/src/libGLESv2/validationES3.cpp
@@ -51,6 +51,8 @@
         return gl::error(GL_INVALID_VALUE, false);
     }
 
+    const gl::Caps &caps = context->getCaps();
+
     gl::Texture *texture = NULL;
     bool textureCompressed = false;
     GLenum textureInternalFormat = GL_NONE;
@@ -61,8 +63,8 @@
     {
       case GL_TEXTURE_2D:
         {
-            if (width > (context->getMaximum2DTextureDimension() >> level) ||
-                height > (context->getMaximum2DTextureDimension() >> level))
+            if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
+                static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
             {
                 return gl::error(GL_INVALID_VALUE, false);
             }
@@ -92,7 +94,7 @@
                 return gl::error(GL_INVALID_VALUE, false);
             }
 
-            if (width > (context->getMaximumCubeTextureDimension() >> level))
+            if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level))
             {
                 return gl::error(GL_INVALID_VALUE, false);
             }
@@ -112,9 +114,9 @@
 
       case GL_TEXTURE_3D:
         {
-            if (width > (context->getMaximum3DTextureDimension() >> level) ||
-                height > (context->getMaximum3DTextureDimension() >> level) ||
-                depth > (context->getMaximum3DTextureDimension() >> level))
+            if (static_cast<GLuint>(width) > (caps.max3DTextureSize >> level) ||
+                static_cast<GLuint>(height) > (caps.max3DTextureSize >> level) ||
+                static_cast<GLuint>(depth) > (caps.max3DTextureSize >> level))
             {
                 return gl::error(GL_INVALID_VALUE, false);
             }
@@ -134,9 +136,9 @@
 
         case GL_TEXTURE_2D_ARRAY:
           {
-              if (width > (context->getMaximum2DTextureDimension() >> level) ||
-                  height > (context->getMaximum2DTextureDimension() >> level) ||
-                  depth > (context->getMaximum2DArrayTextureLayers() >> level))
+              if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
+                  static_cast<GLuint>(height) > (caps.max2DTextureSize >> level) ||
+                  static_cast<GLuint>(depth) > (caps.maxArrayTextureLayers >> level))
               {
                   return gl::error(GL_INVALID_VALUE, false);
               }
@@ -365,6 +367,8 @@
         return gl::error(GL_INVALID_OPERATION, false);
     }
 
+    const gl::Caps &caps = context->getCaps();
+
     gl::Texture *texture = NULL;
     switch (target)
     {
@@ -372,8 +376,8 @@
         {
             texture = context->getTexture2D();
 
-            if (width > (context->getMaximum2DTextureDimension()) ||
-                height > (context->getMaximum2DTextureDimension()))
+            if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
+                static_cast<GLuint>(height) > caps.max2DTextureSize)
             {
                 return gl::error(GL_INVALID_VALUE, false);
             }
@@ -389,7 +393,7 @@
                 return gl::error(GL_INVALID_VALUE, false);
             }
 
-            if (width > (context->getMaximumCubeTextureDimension()))
+            if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize)
             {
                 return gl::error(GL_INVALID_VALUE, false);
             }
@@ -400,9 +404,9 @@
         {
             texture = context->getTexture3D();
 
-            if (width > (context->getMaximum3DTextureDimension()) ||
-                height > (context->getMaximum3DTextureDimension()) ||
-                depth > (context->getMaximum3DTextureDimension()))
+            if (static_cast<GLuint>(width) > caps.max3DTextureSize ||
+                static_cast<GLuint>(height) > caps.max3DTextureSize ||
+                static_cast<GLuint>(depth) > caps.max3DTextureSize)
             {
                 return gl::error(GL_INVALID_VALUE, false);
             }
@@ -413,9 +417,9 @@
         {
             texture = context->getTexture2DArray();
 
-            if (width > (context->getMaximum2DTextureDimension()) ||
-                height > (context->getMaximum2DTextureDimension()) ||
-                depth > (context->getMaximum2DArrayTextureLayers()))
+            if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
+                static_cast<GLuint>(height) > caps.max2DTextureSize ||
+                static_cast<GLuint>(depth) > caps.maxArrayTextureLayers)
             {
                 return gl::error(GL_INVALID_VALUE, false);
             }
@@ -463,6 +467,7 @@
         return false;
     }
 
+    const gl::Caps &caps = context->getCaps();
     if (texture != 0)
     {
         gl::Texture *tex = context->getTexture(texture);
@@ -488,7 +493,7 @@
             {
               case GL_TEXTURE_2D:
                 {
-                    if (level > gl::log2(context->getMaximum2DTextureDimension()))
+                    if (level > gl::log2(caps.max2DTextureSize))
                     {
                         return gl::error(GL_INVALID_VALUE, false);
                     }
@@ -511,7 +516,7 @@
               case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
               case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
                 {
-                    if (level > gl::log2(context->getMaximumCubeTextureDimension()))
+                    if (level > gl::log2(caps.maxCubeMapTextureSize))
                     {
                         return gl::error(GL_INVALID_VALUE, false);
                     }
@@ -537,12 +542,12 @@
             {
               case GL_TEXTURE_2D_ARRAY:
                 {
-                    if (level > gl::log2(context->getMaximum2DTextureDimension()))
+                    if (level > gl::log2(caps.max2DTextureSize))
                     {
                         return gl::error(GL_INVALID_VALUE, false);
                     }
 
-                    if (layer >= context->getMaximum2DArrayTextureLayers())
+                    if (static_cast<GLuint>(layer) >= caps.maxArrayTextureLayers)
                     {
                         return gl::error(GL_INVALID_VALUE, false);
                     }
@@ -558,12 +563,12 @@
 
               case GL_TEXTURE_3D:
                 {
-                    if (level > gl::log2(context->getMaximum3DTextureDimension()))
+                    if (level > gl::log2(caps.max3DTextureSize))
                     {
                         return gl::error(GL_INVALID_VALUE, false);
                     }
 
-                    if (layer >= context->getMaximum3DTextureDimension())
+                    if (static_cast<GLuint>(layer) >= caps.max3DTextureSize)
                     {
                         return gl::error(GL_INVALID_VALUE, false);
                     }
@@ -717,7 +722,7 @@
                 return gl::error(GL_INVALID_ENUM, false);
             }
 
-            if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getMaximumRenderTargets())
+            if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
             {
                 return gl::error(GL_INVALID_OPERATION, false);
             }