Implements compressed textures.
TRAC #12714
Signed-off-by: Daniel Koch
Author: Shannon Woods
git-svn-id: https://angleproject.googlecode.com/svn/trunk@397 736b8ea6-26fd-11df-bfd4-992fa37f6226
diff --git a/src/libGLESv2/libGLESv2.cpp b/src/libGLESv2/libGLESv2.cpp
index 2c231cb..25d083b 100644
--- a/src/libGLESv2/libGLESv2.cpp
+++ b/src/libGLESv2/libGLESv2.cpp
@@ -736,11 +736,6 @@
try
{
- if (!gl::IsTextureTarget(target))
- {
- return error(GL_INVALID_ENUM);
- }
-
if (level < 0 || level > gl::MAX_TEXTURE_LEVELS)
{
return error(GL_INVALID_VALUE);
@@ -751,7 +746,97 @@
return error(GL_INVALID_VALUE);
}
- return error(GL_INVALID_ENUM); // ultimately we don't support compressed textures
+ 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:
+ case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+ break;
+ default:
+ return error(GL_INVALID_ENUM);
+ }
+
+ if (border != 0)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ if (!context->supportsCompressedTextures())
+ {
+ return error(GL_INVALID_ENUM); // in this case, it's as though the internal format switch failed
+ }
+
+ if (imageSize != gl::ComputeCompressedSize(width, height, internalformat))
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ if (target == GL_TEXTURE_2D)
+ {
+ gl::Texture2D *texture = context->getTexture2D();
+
+ if (!texture)
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+
+ texture->setCompressedImage(level, internalformat, width, height, imageSize, data);
+ }
+ else
+ {
+ gl::TextureCubeMap *texture = context->getTextureCubeMap();
+
+ if (!texture)
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+
+ switch (target)
+ {
+ 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->setCompressedImage(target, level, internalformat, width, height, imageSize, data);
+ break;
+ default: UNREACHABLE();
+ }
+ }
+ }
+
}
catch(std::bad_alloc&)
{
@@ -779,17 +864,95 @@
return error(GL_INVALID_VALUE);
}
- if (xoffset < 0 || yoffset < 0 || width < 0 || height < 0 || (level > 0 && !gl::isPow2(width)) || (level > 0 && !gl::isPow2(height)) || imageSize < 0)
+ if (xoffset < 0 || yoffset < 0 || width < 0 || height < 0 ||
+ (level > 0 && !gl::isPow2(width)) || (level > 0 && !gl::isPow2(height)) || imageSize < 0)
{
return error(GL_INVALID_VALUE);
}
- if (xoffset != 0 || yoffset != 0)
+ switch (format)
{
- return error(GL_INVALID_OPERATION);
+ case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+ break;
+ default:
+ return error(GL_INVALID_ENUM);
}
- return error(GL_INVALID_OPERATION); // The texture being operated on is not a compressed texture.
+ if (width == 0 || height == 0 || data == NULL)
+ {
+ return;
+ }
+
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ if (!context->supportsCompressedTextures())
+ {
+ return error(GL_INVALID_ENUM); // in this case, it's as though the format switch has failed.
+ }
+
+ if (imageSize != gl::ComputeCompressedSize(width, height, format))
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ if (xoffset % 4 != 0 || yoffset % 4 != 0)
+ {
+ return error(GL_INVALID_OPERATION); // we wait to check the offsets until this point, because the multiple-of-four restriction
+ // does not exist unless DXT1 textures are supported.
+ }
+
+ if (target == GL_TEXTURE_2D)
+ {
+ gl::Texture2D *texture = context->getTexture2D();
+
+ if (!texture)
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+
+ if (!texture->isCompressed())
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+
+ if ((width % 4 != 0 && width != texture->getWidth()) ||
+ (height % 4 != 0 && height != texture->getHeight()))
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+
+ texture->subImageCompressed(level, xoffset, yoffset, width, height, format, imageSize, data);
+ }
+ else if (gl::IsCubemapTextureTarget(target))
+ {
+ gl::TextureCubeMap *texture = context->getTextureCubeMap();
+
+ if (!texture)
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+
+ if (!texture->isCompressed())
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+
+ if ((width % 4 != 0 && width != texture->getWidth()) ||
+ (height % 4 != 0 && height != texture->getHeight()))
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+
+ texture->subImageCompressed(target, level, xoffset, yoffset, width, height, format, imageSize, data);
+ }
+ else
+ {
+ UNREACHABLE();
+ }
+ }
}
catch(std::bad_alloc&)
{
@@ -850,6 +1013,8 @@
case GL_LUMINANCE_ALPHA:
case GL_RGB:
case GL_RGBA:
+ case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: // Compressed textures are not supported here, but if they are unsupported altogether,
+ case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: // a different error is generated than otherwise. That is handled below.
break;
default:
return error(GL_INVALID_VALUE);
@@ -864,6 +1029,19 @@
if (context)
{
+ if (internalformat == GL_COMPRESSED_RGB_S3TC_DXT1_EXT ||
+ internalformat == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT)
+ {
+ if (context->supportsCompressedTextures())
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+ else
+ {
+ return error(GL_INVALID_ENUM);
+ }
+ }
+
gl::Framebuffer *framebuffer = context->getReadFramebuffer();
if (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)
{
@@ -884,6 +1062,11 @@
{
return error(GL_INVALID_OPERATION);
}
+
+ if (texture->isCompressed())
+ {
+ return error(GL_INVALID_OPERATION);
+ }
texture->copyImage(level, internalformat, x, y, width, height, source);
}
@@ -896,6 +1079,11 @@
return error(GL_INVALID_OPERATION);
}
+ if (texture->isCompressed())
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+
texture->copyImage(target, level, internalformat, x, y, width, height, source);
}
else
@@ -963,6 +1151,11 @@
return error(GL_INVALID_OPERATION);
}
+ if (texture->isCompressed())
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+
texture->copySubImage(level, xoffset, yoffset, x, y, width, height, source);
}
else if (gl::IsCubemapTextureTarget(target))
@@ -974,6 +1167,11 @@
return error(GL_INVALID_OPERATION);
}
+ if (texture->isCompressed())
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+
texture->copySubImage(target, level, xoffset, yoffset, x, y, width, height, source);
}
else
@@ -1684,6 +1882,11 @@
return error(GL_INVALID_OPERATION);
}
+ if (tex->isCompressed())
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+
switch (textarget)
{
case GL_TEXTURE_2D:
@@ -1829,6 +2032,11 @@
return error(GL_INVALID_ENUM);
}
+ if (texture->isCompressed())
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+
texture->generateMipmaps();
}
}
@@ -4083,6 +4291,9 @@
return error(GL_INVALID_ENUM);
}
break;
+ case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: // error cases for compressed textures are handled below
+ case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+ break;
default:
return error(GL_INVALID_VALUE);
}
@@ -4096,6 +4307,19 @@
if (context)
{
+ if (internalformat == GL_COMPRESSED_RGB_S3TC_DXT1_EXT ||
+ internalformat == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT)
+ {
+ if (context->supportsCompressedTextures())
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+ else
+ {
+ return error(GL_INVALID_ENUM);
+ }
+ }
+
if (target == GL_TEXTURE_2D)
{
gl::Texture2D *texture = context->getTexture2D();
@@ -4271,6 +4495,11 @@
return error(GL_INVALID_OPERATION);
}
+ if (texture->isCompressed())
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+
texture->subImage(level, xoffset, yoffset, width, height, format, type, context->getUnpackAlignment(), pixels);
}
else if (gl::IsCubemapTextureTarget(target))
@@ -4282,6 +4511,11 @@
return error(GL_INVALID_OPERATION);
}
+ if (texture->isCompressed())
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+
texture->subImage(target, level, xoffset, yoffset, width, height, format, type, context->getUnpackAlignment(), pixels);
}
else
@@ -5200,7 +5434,7 @@
static const Extension glExtensions[] =
{
{"glTexImage3DOES", (__eglMustCastToProperFunctionPointerType)glTexImage3DOES},
- {"glBlitFramebufferANGLE", (__eglMustCastToProperFunctionPointerType)glBlitFramebufferANGLE}
+ {"glBlitFramebufferANGLE", (__eglMustCastToProperFunctionPointerType)glBlitFramebufferANGLE},
};
for (int ext = 0; ext < sizeof(glExtensions) / sizeof(Extension); ext++)