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/Context.cpp b/src/libGLESv2/Context.cpp
index 55cdae3..f50aa4d 100644
--- a/src/libGLESv2/Context.cpp
+++ b/src/libGLESv2/Context.cpp
@@ -240,6 +240,16 @@
mIndexDataManager = new IndexDataManager(this, mBufferBackEnd);
mBlit = new Blit(this);
+ mSupportsShaderModel3 = mDeviceCaps.PixelShaderVersion == D3DPS_VERSION(3, 0);
+
+ mMaxTextureDimension = std::min(std::min((int)mDeviceCaps.MaxTextureWidth, (int)mDeviceCaps.MaxTextureHeight),
+ (int)gl::IMPLEMENTATION_MAX_TEXTURE_SIZE);
+ mMaxCubeTextureDimension = std::min(mMaxTextureDimension, (int)gl::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE);
+ mMaxRenderbufferDimension = mMaxTextureDimension;
+ mMaxTextureLevel = log2(mMaxTextureDimension) + 1;
+ TRACE("MaxTextureDimension=%d, MaxCubeTextureDimension=%d, MaxRenderbufferDimension=%d, MaxTextureLevel=%d",
+ mMaxTextureDimension, mMaxCubeTextureDimension, mMaxRenderbufferDimension, mMaxTextureLevel);
+
const D3DFORMAT renderBufferFormats[] =
{
D3DFMT_A8R8G8B8,
@@ -306,8 +316,6 @@
depthStencil->Release();
}
- mSupportsShaderModel3 = mDeviceCaps.PixelShaderVersion == D3DPS_VERSION(3, 0);
-
markAllStateDirty();
}
@@ -1202,7 +1210,7 @@
case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS: *params = gl::MAX_VERTEX_TEXTURE_IMAGE_UNITS; break;
case GL_MAX_TEXTURE_IMAGE_UNITS: *params = gl::MAX_TEXTURE_IMAGE_UNITS; break;
case GL_MAX_FRAGMENT_UNIFORM_VECTORS: *params = gl::MAX_FRAGMENT_UNIFORM_VECTORS; break;
- case GL_MAX_RENDERBUFFER_SIZE: *params = gl::MAX_RENDERBUFFER_SIZE; break;
+ case GL_MAX_RENDERBUFFER_SIZE: *params = getMaximumRenderbufferDimension(); 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;
@@ -1240,8 +1248,8 @@
case GL_STENCIL_BACK_WRITEMASK: *params = mState.stencilBackWritemask; break;
case GL_STENCIL_CLEAR_VALUE: *params = mState.stencilClearValue; break;
case GL_SUBPIXEL_BITS: *params = 4; break;
- case GL_MAX_TEXTURE_SIZE: *params = gl::MAX_TEXTURE_SIZE; break;
- case GL_MAX_CUBE_MAP_TEXTURE_SIZE: *params = gl::MAX_CUBE_MAP_TEXTURE_SIZE; break;
+ case GL_MAX_TEXTURE_SIZE: *params = getMaximumTextureDimension(); break;
+ case GL_MAX_CUBE_MAP_TEXTURE_SIZE: *params = getMaximumCubeTextureDimension(); break;
case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
{
if (supportsCompressedTextures())
@@ -1303,7 +1311,7 @@
case GL_IMPLEMENTATION_COLOR_READ_FORMAT: *params = gl::IMPLEMENTATION_COLOR_READ_FORMAT; break;
case GL_MAX_VIEWPORT_DIMS:
{
- int maxDimension = std::max((int)gl::MAX_RENDERBUFFER_SIZE, (int)gl::MAX_TEXTURE_SIZE);
+ int maxDimension = std::max(getMaximumRenderbufferDimension(), getMaximumTextureDimension());
params[0] = maxDimension;
params[1] = maxDimension;
}
@@ -2954,6 +2962,26 @@
return mSupportsHalfFloatRenderableTextures;
}
+int Context::getMaximumRenderbufferDimension() const
+{
+ return mMaxRenderbufferDimension;
+}
+
+int Context::getMaximumTextureDimension() const
+{
+ return mMaxTextureDimension;
+}
+
+int Context::getMaximumCubeTextureDimension() const
+{
+ return mMaxCubeTextureDimension;
+}
+
+int Context::getMaximumTextureLevel() const
+{
+ return mMaxTextureLevel;
+}
+
void Context::detachBuffer(GLuint buffer)
{
// [OpenGL ES 2.0.24] section 2.9 page 22:
diff --git a/src/libGLESv2/Context.h b/src/libGLESv2/Context.h
index 8ecebcb..2452dd4 100644
--- a/src/libGLESv2/Context.h
+++ b/src/libGLESv2/Context.h
@@ -63,7 +63,6 @@
MAX_VERTEX_TEXTURE_IMAGE_UNITS = 0,
MAX_TEXTURE_IMAGE_UNITS = 16,
MAX_FRAGMENT_UNIFORM_VECTORS = 16,
- MAX_RENDERBUFFER_SIZE = 4096, // FIXME: Verify
MAX_DRAW_BUFFERS = 1,
IMPLEMENTATION_COLOR_READ_FORMAT = GL_RGB,
@@ -383,6 +382,10 @@
GLenum getError();
bool supportsShaderModel3() const;
+ int getMaximumRenderbufferDimension() const;
+ int getMaximumTextureDimension() const;
+ int getMaximumCubeTextureDimension() const;
+ int getMaximumTextureLevel() const;
GLsizei getMaxSupportedSamples() const;
int getNearestSupportedSamples(D3DFORMAT format, int requested) const;
const char *getExtensionString() const;
@@ -459,6 +462,10 @@
bool mDepthStencilInitialized;
bool mSupportsShaderModel3;
+ int mMaxRenderbufferDimension;
+ int mMaxTextureDimension;
+ int mMaxCubeTextureDimension;
+ int mMaxTextureLevel;
std::map<D3DFORMAT, bool *> mMultiSampleSupport;
GLsizei mMaxSupportedSamples;
bool mSupportsEventQueries;
diff --git a/src/libGLESv2/Texture.cpp b/src/libGLESv2/Texture.cpp
index 05632c4..9128f13 100644
--- a/src/libGLESv2/Texture.cpp
+++ b/src/libGLESv2/Texture.cpp
@@ -996,7 +996,7 @@
// Purge all the levels and the texture.
- for (int i = 0; i < MAX_TEXTURE_LEVELS; i++)
+ for (int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
{
if (mImageArray[i].surface != NULL)
{
@@ -1831,7 +1831,7 @@
internalFormat, width);
// Purge all the levels and the texture.
- for (int i = 0; i < MAX_TEXTURE_LEVELS; i++)
+ for (int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
{
for (int f = 0; f < 6; f++)
{
diff --git a/src/libGLESv2/Texture.h b/src/libGLESv2/Texture.h
index 6285a7c..5cf3214 100644
--- a/src/libGLESv2/Texture.h
+++ b/src/libGLESv2/Texture.h
@@ -28,10 +28,13 @@
enum
{
- MAX_TEXTURE_SIZE = 2048,
- MAX_CUBE_MAP_TEXTURE_SIZE = 2048,
+ // These are the maximums the implementation can support
+ // The actual GL caps are limited by the device caps
+ // and should be queried from the Context
+ IMPLEMENTATION_MAX_TEXTURE_SIZE = 16384,
+ IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE = 16384,
- MAX_TEXTURE_LEVELS = 12 // 1+log2 of MAX_TEXTURE_SIZE
+ IMPLEMENTATION_MAX_TEXTURE_LEVELS = 15 // 1+log2 of MAX_TEXTURE_SIZE
};
class Texture : public RefCountObject
@@ -237,7 +240,7 @@
bool redefineTexture(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum type);
void commitRect(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height);
- Image mImageArray[MAX_TEXTURE_LEVELS];
+ Image mImageArray[IMPLEMENTATION_MAX_TEXTURE_LEVELS];
IDirect3DTexture9 *mTexture;
@@ -297,7 +300,7 @@
void commitRect(GLenum faceTarget, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height);
bool redefineTexture(GLint level, GLenum internalFormat, GLsizei width);
- Image mImageArray[6][MAX_TEXTURE_LEVELS];
+ Image mImageArray[6][IMPLEMENTATION_MAX_TEXTURE_LEVELS];
IDirect3DCubeTexture9 *mTexture;
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())