Implemented glTexStorage and refactored glTexStorage2DEXT.
TRAC #22869
Signed-off-by: Jamie Madill
Signed-off-by: Shannon Woods
Author: Geoff Lang
git-svn-id: https://angleproject.googlecode.com/svn/branches/es3proto@2360 736b8ea6-26fd-11df-bfd4-992fa37f6226
diff --git a/src/libGLESv2/Texture.h b/src/libGLESv2/Texture.h
index b3bb0af..b3a43d8 100644
--- a/src/libGLESv2/Texture.h
+++ b/src/libGLESv2/Texture.h
@@ -86,6 +86,7 @@
void getSamplerState(SamplerState *sampler);
GLenum getUsage() const;
bool isMipmapFiltered() const;
+ virtual int levelCount() = 0;
virtual bool isSamplerComplete() const = 0;
@@ -122,8 +123,6 @@
virtual void convertToRenderTarget() = 0;
virtual rx::RenderTarget *getRenderTarget(GLenum target) = 0;
- virtual int levelCount() = 0;
-
rx::Renderer *mRenderer;
SamplerState mSamplerState;
diff --git a/src/libGLESv2/libGLESv2.cpp b/src/libGLESv2/libGLESv2.cpp
index 0827e57..a5af86e 100644
--- a/src/libGLESv2/libGLESv2.cpp
+++ b/src/libGLESv2/libGLESv2.cpp
@@ -1204,6 +1204,255 @@
return true;
}
+bool validateES2TexStorageParameters(gl::Context *context, GLenum target, GLsizei levels, GLenum internalformat,
+ GLsizei width, GLsizei height)
+{
+ if (target != GL_TEXTURE_2D && target != GL_TEXTURE_CUBE_MAP)
+ {
+ return gl::error(GL_INVALID_ENUM, false);
+ }
+
+ if (width < 1 || height < 1 || levels < 1)
+ {
+ return gl::error(GL_INVALID_VALUE, false);
+ }
+
+ if (target == GL_TEXTURE_CUBE_MAP && width != height)
+ {
+ return gl::error(GL_INVALID_VALUE, false);
+ }
+
+ if (levels != 1 && levels != gl::log2(std::max(width, height)) + 1)
+ {
+ return gl::error(GL_INVALID_OPERATION, false);
+ }
+
+ GLenum format = gl::GetFormat(internalformat, context->getClientVersion());
+ GLenum type = gl::GetType(internalformat, context->getClientVersion());
+
+ if (format == GL_NONE || type == GL_NONE)
+ {
+ return gl::error(GL_INVALID_ENUM, false);
+ }
+
+ switch (target)
+ {
+ case GL_TEXTURE_2D:
+ if (width > context->getMaximum2DTextureDimension() ||
+ height > context->getMaximum2DTextureDimension())
+ {
+ return gl::error(GL_INVALID_VALUE, false);
+ }
+ break;
+ case GL_TEXTURE_CUBE_MAP:
+ if (width > context->getMaximumCubeTextureDimension() ||
+ height > context->getMaximumCubeTextureDimension())
+ {
+ return gl::error(GL_INVALID_VALUE, false);
+ }
+ break;
+ default:
+ return gl::error(GL_INVALID_ENUM, false);
+ }
+
+ if (levels != 1 && !context->supportsNonPower2Texture())
+ {
+ if (!gl::isPow2(width) || !gl::isPow2(height))
+ {
+ return gl::error(GL_INVALID_OPERATION, false);
+ }
+ }
+
+ switch (internalformat)
+ {
+ case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+ if (!context->supportsDXT1Textures())
+ {
+ return gl::error(GL_INVALID_ENUM, false);
+ }
+ break;
+ case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
+ if (!context->supportsDXT3Textures())
+ {
+ return gl::error(GL_INVALID_ENUM, false);
+ }
+ break;
+ case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
+ if (!context->supportsDXT5Textures())
+ {
+ return gl::error(GL_INVALID_ENUM, false);
+ }
+ break;
+ case GL_RGBA32F_EXT:
+ case GL_RGB32F_EXT:
+ case GL_ALPHA32F_EXT:
+ case GL_LUMINANCE32F_EXT:
+ case GL_LUMINANCE_ALPHA32F_EXT:
+ if (!context->supportsFloat32Textures())
+ {
+ return gl::error(GL_INVALID_ENUM, false);
+ }
+ break;
+ case GL_RGBA16F_EXT:
+ case GL_RGB16F_EXT:
+ case GL_ALPHA16F_EXT:
+ case GL_LUMINANCE16F_EXT:
+ case GL_LUMINANCE_ALPHA16F_EXT:
+ if (!context->supportsFloat16Textures())
+ {
+ return gl::error(GL_INVALID_ENUM, false);
+ }
+ break;
+ case GL_DEPTH_COMPONENT16:
+ case GL_DEPTH_COMPONENT32_OES:
+ case GL_DEPTH24_STENCIL8_OES:
+ if (!context->supportsDepthTextures())
+ {
+ return gl::error(GL_INVALID_ENUM, false);
+ }
+ if (target != GL_TEXTURE_2D)
+ {
+ return gl::error(GL_INVALID_OPERATION, false);
+ }
+ // ANGLE_depth_texture only supports 1-level textures
+ if (levels != 1)
+ {
+ return gl::error(GL_INVALID_OPERATION, false);
+ }
+ break;
+ default:
+ break;
+ }
+
+ gl::Texture *texture = NULL;
+ switch(target)
+ {
+ case GL_TEXTURE_2D:
+ texture = context->getTexture2D();
+ break;
+ case GL_TEXTURE_CUBE_MAP:
+ texture = context->getTextureCubeMap();
+ break;
+ default:
+ UNREACHABLE();
+ }
+
+ if (!texture || texture->id() == 0)
+ {
+ return gl::error(GL_INVALID_OPERATION, false);
+ }
+
+ if (texture->isImmutable())
+ {
+ return gl::error(GL_INVALID_OPERATION, false);
+ }
+
+ return true;
+}
+
+bool validateES3TexStorageParameters(gl::Context *context, GLenum target, GLsizei levels, GLenum internalformat,
+ GLsizei width, GLsizei height, GLsizei depth)
+{
+ if (width < 1 || height < 1 || depth < 1 || levels < 1)
+ {
+ return gl::error(GL_INVALID_VALUE, false);
+ }
+
+ if (levels > gl::log2(std::max(std::max(width, height), depth)) + 1)
+ {
+ return gl::error(GL_INVALID_OPERATION, false);
+ }
+
+ gl::Texture *texture = NULL;
+ switch (target)
+ {
+ case GL_TEXTURE_2D:
+ {
+ texture = context->getTexture2D();
+
+ if (width > (context->getMaximum2DTextureDimension()) ||
+ height > (context->getMaximum2DTextureDimension()))
+ {
+ return gl::error(GL_INVALID_VALUE, false);
+ }
+ }
+ 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:
+ {
+ texture = context->getTextureCubeMap();
+
+ if (width != height)
+ {
+ return gl::error(GL_INVALID_VALUE, false);
+ }
+
+ if (width > (context->getMaximumCubeTextureDimension()))
+ {
+ return gl::error(GL_INVALID_VALUE, false);
+ }
+ }
+ break;
+
+ case GL_TEXTURE_3D:
+ {
+ texture = context->getTexture3D();
+
+ if (width > (context->getMaximum3DTextureDimension()) ||
+ height > (context->getMaximum3DTextureDimension()) ||
+ depth > (context->getMaximum3DTextureDimension()))
+ {
+ return gl::error(GL_INVALID_VALUE, false);
+ }
+ }
+ break;
+
+ case GL_TEXTURE_2D_ARRAY:
+ {
+ texture = context->getTexture2DArray();
+
+ if (width > (context->getMaximum2DTextureDimension()) ||
+ height > (context->getMaximum2DTextureDimension()) ||
+ depth > (context->getMaximum2DArrayTextureLayers()))
+ {
+ return gl::error(GL_INVALID_VALUE, false);
+ }
+ }
+ break;
+
+ default:
+ return gl::error(GL_INVALID_ENUM, false);
+ }
+
+ if (!texture || texture->id() == 0)
+ {
+ return gl::error(GL_INVALID_OPERATION, false);
+ }
+
+ if (texture->isImmutable())
+ {
+ return gl::error(GL_INVALID_OPERATION, false);
+ }
+
+ if (!gl::IsValidInternalFormat(internalformat, context))
+ {
+ return gl::error(GL_INVALID_ENUM, false);
+ }
+
+ if (!gl::IsSizedInternalFormat(internalformat, context->getClientVersion()))
+ {
+ return gl::error(GL_INVALID_ENUM, false);
+ }
+
+ return true;
+}
+
// check for combinations of format and type that are valid for ReadPixels
bool validES2ReadFormatType(GLenum format, GLenum type)
{
@@ -4882,9 +5131,17 @@
}
*params = (GLfloat)texture->getWrapR();
break;
- case GL_TEXTURE_IMMUTABLE_FORMAT_EXT:
+ case GL_TEXTURE_IMMUTABLE_FORMAT:
+ // Exposed to ES2.0 through EXT_texture_storage, no client version validation.
*params = (GLfloat)(texture->isImmutable() ? GL_TRUE : GL_FALSE);
break;
+ case GL_TEXTURE_IMMUTABLE_LEVELS:
+ if (context->getClientVersion() < 3)
+ {
+ return gl::error(GL_INVALID_ENUM);
+ }
+ *params = (GLfloat)(texture->isImmutable() ? texture->levelCount() : 0);
+ break;
case GL_TEXTURE_USAGE_ANGLE:
*params = (GLfloat)texture->getUsage();
break;
@@ -4958,9 +5215,17 @@
}
*params = texture->getWrapR();
break;
- case GL_TEXTURE_IMMUTABLE_FORMAT_EXT:
+ case GL_TEXTURE_IMMUTABLE_FORMAT:
+ // Exposed to ES2.0 through EXT_texture_storage, no client version validation.
*params = texture->isImmutable() ? GL_TRUE : GL_FALSE;
break;
+ case GL_TEXTURE_IMMUTABLE_LEVELS:
+ if (context->getClientVersion() < 3)
+ {
+ return gl::error(GL_INVALID_ENUM);
+ }
+ *params = texture->isImmutable() ? texture->levelCount() : 0;
+ break;
case GL_TEXTURE_USAGE_ANGLE:
*params = texture->getUsage();
break;
@@ -6578,166 +6843,46 @@
try
{
- if (target != GL_TEXTURE_2D && target != GL_TEXTURE_CUBE_MAP)
- {
- return gl::error(GL_INVALID_ENUM);
- }
-
- if (width < 1 || height < 1 || levels < 1)
- {
- return gl::error(GL_INVALID_VALUE);
- }
-
- if (target == GL_TEXTURE_CUBE_MAP && width != height)
- {
- return gl::error(GL_INVALID_VALUE);
- }
-
- if (levels != 1 && levels != gl::log2(std::max(width, height)) + 1)
- {
- return gl::error(GL_INVALID_OPERATION);
- }
-
gl::Context *context = gl::getNonLostContext();
if (context)
{
- if (!gl::IsValidInternalFormat(internalformat, context))
+ if (context->getClientVersion() < 3 &&
+ !validateES2TexStorageParameters(context, target, levels, internalformat, width, height))
{
- return gl::error(GL_INVALID_ENUM);
+ return;
}
- GLenum format = gl::GetFormat(internalformat, context->getClientVersion());
- GLenum type = gl::GetType(internalformat, context->getClientVersion());
-
- if (format == GL_NONE || type == GL_NONE)
+ if (context->getClientVersion() >= 3 &&
+ !validateES3TexStorageParameters(context, target, levels, internalformat, width, height, 1))
{
- return gl::error(GL_INVALID_ENUM);
+ return;
}
switch (target)
{
case GL_TEXTURE_2D:
- if (width > context->getMaximum2DTextureDimension() ||
- height > context->getMaximum2DTextureDimension())
{
- return gl::error(GL_INVALID_VALUE);
+ gl::Texture2D *texture2d = context->getTexture2D();
+ texture2d->storage(levels, internalformat, width, height);
}
break;
- case GL_TEXTURE_CUBE_MAP:
- if (width > context->getMaximumCubeTextureDimension() ||
- height > context->getMaximumCubeTextureDimension())
+
+ 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:
{
- return gl::error(GL_INVALID_VALUE);
+ gl::TextureCubeMap *textureCube = context->getTextureCubeMap();
+ textureCube->storage(levels, internalformat, width);
}
break;
+
default:
return gl::error(GL_INVALID_ENUM);
}
-
- if (levels != 1 && !context->supportsNonPower2Texture())
- {
- if (!gl::isPow2(width) || !gl::isPow2(height))
- {
- return gl::error(GL_INVALID_OPERATION);
- }
- }
-
- switch (internalformat)
- {
- case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
- case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
- if (!context->supportsDXT1Textures())
- {
- return gl::error(GL_INVALID_ENUM);
- }
- break;
- case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
- if (!context->supportsDXT3Textures())
- {
- return gl::error(GL_INVALID_ENUM);
- }
- break;
- case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
- if (!context->supportsDXT5Textures())
- {
- return gl::error(GL_INVALID_ENUM);
- }
- break;
- case GL_RGBA32F_EXT:
- case GL_RGB32F_EXT:
- case GL_ALPHA32F_EXT:
- case GL_LUMINANCE32F_EXT:
- case GL_LUMINANCE_ALPHA32F_EXT:
- if (!context->supportsFloat32Textures())
- {
- return gl::error(GL_INVALID_ENUM);
- }
- break;
- case GL_RGBA16F_EXT:
- case GL_RGB16F_EXT:
- case GL_ALPHA16F_EXT:
- case GL_LUMINANCE16F_EXT:
- case GL_LUMINANCE_ALPHA16F_EXT:
- if (!context->supportsFloat16Textures())
- {
- return gl::error(GL_INVALID_ENUM);
- }
- break;
- case GL_DEPTH_COMPONENT16:
- case GL_DEPTH_COMPONENT32_OES:
- case GL_DEPTH24_STENCIL8_OES:
- if (!context->supportsDepthTextures())
- {
- return gl::error(GL_INVALID_ENUM);
- }
- if (target != GL_TEXTURE_2D)
- {
- return gl::error(GL_INVALID_OPERATION);
- }
- // ANGLE_depth_texture only supports 1-level textures
- if (levels != 1)
- {
- return gl::error(GL_INVALID_OPERATION);
- }
- break;
- default:
- break;
- }
-
- if (target == GL_TEXTURE_2D)
- {
- gl::Texture2D *texture = context->getTexture2D();
-
- if (!texture || texture->id() == 0)
- {
- return gl::error(GL_INVALID_OPERATION);
- }
-
- if (texture->isImmutable())
- {
- return gl::error(GL_INVALID_OPERATION);
- }
-
- texture->storage(levels, internalformat, width, height);
- }
- else if (target == GL_TEXTURE_CUBE_MAP)
- {
- gl::TextureCubeMap *texture = context->getTextureCubeMap();
-
- if (!texture || texture->id() == 0)
- {
- return gl::error(GL_INVALID_OPERATION);
- }
-
- if (texture->isImmutable())
- {
- return gl::error(GL_INVALID_OPERATION);
- }
-
- texture->storage(levels, internalformat, width);
- }
- else UNREACHABLE();
}
}
catch(std::bad_alloc&)
@@ -10906,9 +11051,37 @@
{
return gl::error(GL_INVALID_OPERATION);
}
- }
- UNIMPLEMENTED();
+ if (!validateES3TexStorageParameters(context, target, levels, internalformat, width, height, 1))
+ {
+ return;
+ }
+
+ switch (target)
+ {
+ case GL_TEXTURE_2D:
+ {
+ gl::Texture2D *texture2d = context->getTexture2D();
+ texture2d->storage(levels, internalformat, width, height);
+ }
+ 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:
+ {
+ gl::TextureCubeMap *textureCube = context->getTextureCubeMap();
+ textureCube->storage(levels, internalformat, width);
+ }
+ break;
+
+ default:
+ return gl::error(GL_INVALID_ENUM);
+ }
+ }
}
catch(std::bad_alloc&)
{
@@ -10932,6 +11105,31 @@
{
return gl::error(GL_INVALID_OPERATION);
}
+
+ if (!validateES3TexStorageParameters(context, target, levels, internalformat, width, height, depth))
+ {
+ return;
+ }
+
+ switch (target)
+ {
+ case GL_TEXTURE_3D:
+ {
+ gl::Texture3D *texture3d = context->getTexture3D();
+ texture3d->storage(levels, internalformat, width, height, depth);
+ }
+ break;
+
+ case GL_TEXTURE_2D_ARRAY:
+ {
+ gl::Texture2DArray *texture2darray = context->getTexture2DArray();
+ texture2darray->storage(levels, internalformat, width, height, depth);
+ }
+ break;
+
+ default:
+ return gl::error(GL_INVALID_ENUM);
+ }
}
}
catch(std::bad_alloc&)