Add proper detection for maximum texture and renderbuffer size
Trac #13849

Increased the maximum possible texture & renderbuffer size to 16384 (the minimum required for DX11 cards).
Limit the actual maximum texture & renderbuffer size to the maximum
that it reported by the underlying D3D9 device.

Note that creating textures and renderbuffers at the maximum size will quickly exhaust video memory!

Signed-off-by: Nicolas Capens

git-svn-id: https://angleproject.googlecode.com/svn/trunk@447 736b8ea6-26fd-11df-bfd4-992fa37f6226
diff --git a/src/libGLESv2/libGLESv2.cpp b/src/libGLESv2/libGLESv2.cpp
index 7ac312d..c986b5e 100644
--- a/src/libGLESv2/libGLESv2.cpp
+++ b/src/libGLESv2/libGLESv2.cpp
@@ -737,7 +737,7 @@
 
     try
     {
-        if (level < 0 || level > gl::MAX_TEXTURE_LEVELS)
+        if (level < 0)
         {
             return error(GL_INVALID_VALUE);
         }
@@ -747,34 +747,6 @@
             return error(GL_INVALID_VALUE);
         }
 
-        switch (target)
-        {
-          case GL_TEXTURE_2D:
-            if (width > (gl::MAX_TEXTURE_SIZE >> level) || height > (gl::MAX_TEXTURE_SIZE >> level))
-            {
-                return error(GL_INVALID_VALUE);
-            }
-            break;
-          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:
-            if (width != height)
-            {
-                return error(GL_INVALID_VALUE);
-            }
-
-            if (width > (gl::MAX_CUBE_MAP_TEXTURE_SIZE >> level) || height > (gl::MAX_CUBE_MAP_TEXTURE_SIZE >> level))
-            {
-                return error(GL_INVALID_VALUE);
-            }
-            break;
-          default:
-            return error(GL_INVALID_ENUM);
-        }
-
         switch (internalformat)
         {
           case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
@@ -793,6 +765,41 @@
 
         if (context)
         {
+            if (level > context->getMaximumTextureLevel())
+            {
+                return error(GL_INVALID_VALUE);
+            }
+
+            switch (target)
+            {
+              case GL_TEXTURE_2D:
+                if (width > (context->getMaximumTextureDimension() >> level) ||
+                    height > (context->getMaximumTextureDimension() >> level))
+                {
+                    return error(GL_INVALID_VALUE);
+                }
+                break;
+              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:
+                if (width != height)
+                {
+                    return error(GL_INVALID_VALUE);
+                }
+
+                if (width > (context->getMaximumCubeTextureDimension() >> level) ||
+                    height > (context->getMaximumCubeTextureDimension() >> level))
+                {
+                    return error(GL_INVALID_VALUE);
+                }
+                break;
+              default:
+                return error(GL_INVALID_ENUM);
+            }
+
             if (!context->supportsCompressedTextures())
             {
                 return error(GL_INVALID_ENUM); // in this case, it's as though the internal format switch failed
@@ -860,7 +867,7 @@
             return error(GL_INVALID_ENUM);
         }
 
-        if (level < 0 || level > gl::MAX_TEXTURE_LEVELS)
+        if (level < 0)
         {
             return error(GL_INVALID_VALUE);
         }
@@ -889,6 +896,11 @@
 
         if (context)
         {
+            if (level > context->getMaximumTextureLevel())
+            {
+                return error(GL_INVALID_VALUE);
+            }
+
             if (!context->supportsCompressedTextures())
             {
                 return error(GL_INVALID_ENUM); // in this case, it's as though the format switch has failed.
@@ -979,34 +991,6 @@
             return error(GL_INVALID_VALUE);
         }
 
-        switch (target)
-        {
-          case GL_TEXTURE_2D:
-            if (width > (gl::MAX_TEXTURE_SIZE >> level) || height > (gl::MAX_TEXTURE_SIZE >> level))
-            {
-                return error(GL_INVALID_VALUE);
-            }
-            break;
-          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:
-            if (width != height)
-            {
-                return error(GL_INVALID_VALUE);
-            }
-
-            if (width > (gl::MAX_CUBE_MAP_TEXTURE_SIZE >> level) || height > (gl::MAX_CUBE_MAP_TEXTURE_SIZE >> level))
-            {
-                return error(GL_INVALID_VALUE);
-            }
-            break;
-          default:
-            return error(GL_INVALID_ENUM);
-        }
-
         switch (internalformat)
         {
           case GL_ALPHA:
@@ -1030,6 +1014,36 @@
 
         if (context)
         {
+            switch (target)
+            {
+              case GL_TEXTURE_2D:
+                if (width > (context->getMaximumTextureDimension() >> level) ||
+                    height > (context->getMaximumTextureDimension() >> level))
+                {
+                    return error(GL_INVALID_VALUE);
+                }
+                break;
+              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:
+                if (width != height)
+                {
+                    return error(GL_INVALID_VALUE);
+                }
+
+                if (width > (context->getMaximumCubeTextureDimension() >> level) ||
+                    height > (context->getMaximumCubeTextureDimension() >> level))
+                {
+                    return error(GL_INVALID_VALUE);
+                }
+                break;
+              default:
+                return error(GL_INVALID_ENUM);
+            }
+
             if (internalformat == GL_COMPRESSED_RGB_S3TC_DXT1_EXT || 
                 internalformat == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT)
             {
@@ -1122,7 +1136,7 @@
             return error(GL_INVALID_ENUM);
         }
 
-        if (level < 0 || level > gl::MAX_TEXTURE_LEVELS || xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
+        if (level < 0 || xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
         {
             return error(GL_INVALID_VALUE);
         }
@@ -1141,6 +1155,11 @@
 
         if (context)
         {
+            if (level > context->getMaximumTextureLevel())
+            {
+                return error(GL_INVALID_VALUE);
+            }
+
             gl::Framebuffer *framebuffer = context->getReadFramebuffer();
             if (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)
             {
@@ -4011,7 +4030,7 @@
             return error(GL_INVALID_ENUM);
         }
 
-        if (width < 0 || height < 0 || width > gl::MAX_RENDERBUFFER_SIZE || height > gl::MAX_RENDERBUFFER_SIZE || samples < 0)
+        if (width < 0 || height < 0 || samples < 0)
         {
             return error(GL_INVALID_VALUE);
         }
@@ -4020,7 +4039,9 @@
 
         if (context)
         {
-            if (samples > context->getMaxSupportedSamples())
+            if (width > context->getMaximumRenderbufferDimension() || 
+                height > context->getMaximumRenderbufferDimension() ||
+                samples > context->getMaxSupportedSamples())
             {
                 return error(GL_INVALID_VALUE);
             }
@@ -4429,34 +4450,6 @@
             return error(GL_INVALID_VALUE);
         }
 
-        switch (target)
-        {
-          case GL_TEXTURE_2D:
-            if (width > (gl::MAX_TEXTURE_SIZE >> level) || height > (gl::MAX_TEXTURE_SIZE >> level))
-            {
-                return error(GL_INVALID_VALUE);
-            }
-            break;
-          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:
-            if (width != height)
-            {
-                return error(GL_INVALID_VALUE);
-            }
-
-            if (width > (gl::MAX_CUBE_MAP_TEXTURE_SIZE >> level) || height > (gl::MAX_CUBE_MAP_TEXTURE_SIZE >> level))
-            {
-                return error(GL_INVALID_VALUE);
-            }
-            break;
-          default:
-            return error(GL_INVALID_ENUM);
-        }
-
         if (internalformat != format)
         {
             return error(GL_INVALID_OPERATION);
@@ -4527,6 +4520,36 @@
 
         if (context)
         {
+            switch (target)
+            {
+              case GL_TEXTURE_2D:
+                if (width > (context->getMaximumTextureDimension() >> level) ||
+                    height > (context->getMaximumTextureDimension() >> level))
+                {
+                    return error(GL_INVALID_VALUE);
+                }
+                break;
+              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:
+                if (width != height)
+                {
+                    return error(GL_INVALID_VALUE);
+                }
+
+                if (width > (context->getMaximumCubeTextureDimension() >> level) ||
+                    height > (context->getMaximumCubeTextureDimension() >> level))
+                {
+                    return error(GL_INVALID_VALUE);
+                }
+                break;
+              default:
+                return error(GL_INVALID_ENUM);
+            }
+
             if (internalformat == GL_COMPRESSED_RGB_S3TC_DXT1_EXT ||
                 internalformat == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT)
             {
@@ -4697,7 +4720,7 @@
             return error(GL_INVALID_ENUM);
         }
 
-        if (level < 0 || level > gl::MAX_TEXTURE_LEVELS || xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
+        if (level < 0 || xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
         {
             return error(GL_INVALID_VALUE);
         }
@@ -4721,6 +4744,11 @@
 
         if (context)
         {
+            if (level > context->getMaximumTextureLevel())
+            {
+                return error(GL_INVALID_VALUE);
+            }
+
             if (format == GL_FLOAT)
             {
                 if (!context->supportsFloatTextures())