Validate glCopyTex[Sub]Image source and destination format combinations.

TRAC #13792 Signed-off-by: Daniel Koch Author: Nicolas Capens git-svn-id: https://angleproject.googlecode.com/svn/trunk@459 736b8ea6-26fd-11df-bfd4-992fa37f6226
parent edc19189
......@@ -1153,7 +1153,7 @@ void Texture2D::copyImage(GLint level, GLenum internalFormat, GLint x, GLint y,
mImageArray[level].format = internalFormat;
}
void Texture2D::copySubImage(GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, RenderbufferStorage *source)
void Texture2D::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, RenderbufferStorage *source)
{
if (xoffset + width > mImageArray[level].width || yoffset + height > mImageArray[level].height)
{
......@@ -1586,19 +1586,19 @@ void TextureCubeMap::commitRect(GLenum faceTarget, GLint level, GLint xoffset, G
}
}
void TextureCubeMap::subImage(GLenum face, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
void TextureCubeMap::subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
{
if (Texture::subImage(xoffset, yoffset, width, height, format, type, unpackAlignment, pixels, &mImageArray[faceIndex(face)][level]))
if (Texture::subImage(xoffset, yoffset, width, height, format, type, unpackAlignment, pixels, &mImageArray[faceIndex(target)][level]))
{
commitRect(face, level, xoffset, yoffset, width, height);
commitRect(target, level, xoffset, yoffset, width, height);
}
}
void TextureCubeMap::subImageCompressed(GLenum face, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels)
void TextureCubeMap::subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels)
{
if (Texture::subImageCompressed(xoffset, yoffset, width, height, format, imageSize, pixels, &mImageArray[faceIndex(face)][level]))
if (Texture::subImageCompressed(xoffset, yoffset, width, height, format, imageSize, pixels, &mImageArray[faceIndex(target)][level]))
{
commitRect(face, level, xoffset, yoffset, width, height);
commitRect(target, level, xoffset, yoffset, width, height);
}
}
......@@ -1896,9 +1896,9 @@ bool TextureCubeMap::redefineTexture(GLint level, GLenum internalFormat, GLsizei
return !textureOkay;
}
void TextureCubeMap::copyImage(GLenum face, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, RenderbufferStorage *source)
void TextureCubeMap::copyImage(GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, RenderbufferStorage *source)
{
unsigned int faceindex = faceIndex(face);
unsigned int faceindex = faceIndex(target);
if (redefineTexture(level, internalFormat, width))
{
......@@ -1920,7 +1920,7 @@ void TextureCubeMap::copyImage(GLenum face, GLint level, GLenum internalFormat,
sourceRect.top = y;
sourceRect.bottom = y + height;
IDirect3DSurface9 *dest = getCubeMapSurface(face, level);
IDirect3DSurface9 *dest = getCubeMapSurface(target, level);
getBlitter()->formatConvert(source->getRenderTarget(), sourceRect, internalFormat, 0, 0, dest);
dest->Release();
......@@ -1962,9 +1962,9 @@ IDirect3DSurface9 *TextureCubeMap::getCubeMapSurface(unsigned int faceIdentifier
return (SUCCEEDED(hr)) ? surface : NULL;
}
void TextureCubeMap::copySubImage(GLenum face, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, RenderbufferStorage *source)
void TextureCubeMap::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, RenderbufferStorage *source)
{
GLsizei size = mImageArray[faceIndex(face)][level].width;
GLsizei size = mImageArray[faceIndex(target)][level].width;
if (xoffset + width > size || yoffset + height > size)
{
......@@ -1989,7 +1989,7 @@ void TextureCubeMap::copySubImage(GLenum face, GLint level, GLint xoffset, GLint
sourceRect.top = y;
sourceRect.bottom = y + height;
IDirect3DSurface9 *dest = getCubeMapSurface(face, level);
IDirect3DSurface9 *dest = getCubeMapSurface(target, level);
getBlitter()->formatConvert(source->getRenderTarget(), sourceRect, mImageArray[0][0].format, xoffset, yoffset, dest);
dest->Release();
......
......@@ -69,6 +69,7 @@ class Texture : public RefCountObject
virtual Renderbuffer *getColorbuffer(GLenum target) = 0;
virtual void generateMipmaps() = 0;
virtual void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, RenderbufferStorage *source) = 0;
bool isDirty() const;
......@@ -218,7 +219,7 @@ class Texture2D : public Texture
void subImage(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels);
void subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels);
void copyImage(GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, RenderbufferStorage *source);
void copySubImage(GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, RenderbufferStorage *source);
void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, RenderbufferStorage *source);
bool isComplete() const;
bool isCompressed() const;
......@@ -266,10 +267,10 @@ class TextureCubeMap : public Texture
void setCompressedImage(GLenum face, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels);
void subImage(GLenum face, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels);
void subImageCompressed(GLenum face, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels);
void copyImage(GLenum face, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, RenderbufferStorage *source);
void copySubImage(GLenum face, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, RenderbufferStorage *source);
void subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels);
void subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels);
void copyImage(GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, RenderbufferStorage *source);
void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, RenderbufferStorage *source);
bool isComplete() const;
bool isCompressed() const;
......
......@@ -991,20 +991,6 @@ void __stdcall glCopyTexImage2D(GLenum target, GLint level, GLenum internalforma
return error(GL_INVALID_VALUE);
}
switch (internalformat)
{
case GL_ALPHA:
case GL_LUMINANCE:
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);
}
if (border != 0)
{
return error(GL_INVALID_VALUE);
......@@ -1044,20 +1030,8 @@ void __stdcall glCopyTexImage2D(GLenum target, GLint level, GLenum internalforma
return error(GL_INVALID_ENUM);
}
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)
{
return error(GL_INVALID_FRAMEBUFFER_OPERATION);
......@@ -1069,52 +1043,82 @@ void __stdcall glCopyTexImage2D(GLenum target, GLint level, GLenum internalforma
}
gl::Colorbuffer *source = framebuffer->getColorbuffer();
if (target == GL_TEXTURE_2D)
{
gl::Texture2D *texture = context->getTexture2D();
GLenum colorbufferFormat = source->getFormat();
if (!texture)
// [OpenGL ES 2.0.24] table 3.9
switch (internalformat)
{
case GL_ALPHA:
if (colorbufferFormat != GL_ALPHA &&
colorbufferFormat != GL_RGBA &&
colorbufferFormat != GL_RGBA4 &&
colorbufferFormat != GL_RGB5_A1 &&
colorbufferFormat != GL_RGBA8_OES)
{
return error(GL_INVALID_OPERATION);
}
if (texture->isCompressed())
break;
case GL_LUMINANCE:
case GL_RGB:
if (colorbufferFormat != GL_RGB &&
colorbufferFormat != GL_RGB565 &&
colorbufferFormat != GL_RGB8_OES &&
colorbufferFormat != GL_RGBA &&
colorbufferFormat != GL_RGBA4 &&
colorbufferFormat != GL_RGB5_A1 &&
colorbufferFormat != GL_RGBA8_OES)
{
return error(GL_INVALID_OPERATION);
}
if (texture->isFloatingPoint())
break;
case GL_LUMINANCE_ALPHA:
case GL_RGBA:
if (colorbufferFormat != GL_RGBA &&
colorbufferFormat != GL_RGBA4 &&
colorbufferFormat != GL_RGB5_A1 &&
colorbufferFormat != GL_RGBA8_OES)
{
return error(GL_INVALID_OPERATION);
}
break;
case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
if (context->supportsCompressedTextures())
{
return error(GL_INVALID_OPERATION);
}
texture->copyImage(level, internalformat, x, y, width, height, source);
else
{
return error(GL_INVALID_ENUM);
}
break;
default:
return error(GL_INVALID_ENUM);
}
else if (gl::IsCubemapTextureTarget(target))
if (target == GL_TEXTURE_2D)
{
gl::TextureCubeMap *texture = context->getTextureCubeMap();
gl::Texture2D *texture = context->getTexture2D();
if (!texture)
{
return error(GL_INVALID_OPERATION);
}
if (texture->isCompressed())
{
return error(GL_INVALID_OPERATION);
}
texture->copyImage(level, internalformat, x, y, width, height, source);
}
else if (gl::IsCubemapTextureTarget(target))
{
gl::TextureCubeMap *texture = context->getTextureCubeMap();
if (texture->isFloatingPoint())
if (!texture)
{
return error(GL_INVALID_OPERATION);
}
texture->copyImage(target, level, internalformat, x, y, width, height, source);
}
else
{
UNREACHABLE();
}
else UNREACHABLE();
}
}
catch(std::bad_alloc&)
......@@ -1161,6 +1165,7 @@ void __stdcall glCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GL
}
gl::Framebuffer *framebuffer = context->getReadFramebuffer();
if (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)
{
return error(GL_INVALID_FRAMEBUFFER_OPERATION);
......@@ -1172,52 +1177,70 @@ void __stdcall glCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GL
}
gl::Colorbuffer *source = framebuffer->getColorbuffer();
GLenum colorbufferFormat = source->getFormat();
gl::Texture *texture = NULL;
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 (texture->isFloatingPoint())
{
return error(GL_INVALID_OPERATION);
}
texture->copySubImage(level, xoffset, yoffset, x, y, width, height, source);
texture = context->getTexture2D();
}
else if (gl::IsCubemapTextureTarget(target))
{
gl::TextureCubeMap *texture = context->getTextureCubeMap();
texture = context->getTextureCubeMap();
}
else UNREACHABLE();
if (!texture)
if (!texture)
{
return error(GL_INVALID_OPERATION);
}
GLenum textureFormat = texture->getFormat();
// [OpenGL ES 2.0.24] table 3.9
switch (textureFormat)
{
case GL_ALPHA:
if (colorbufferFormat != GL_ALPHA &&
colorbufferFormat != GL_RGBA &&
colorbufferFormat != GL_RGBA4 &&
colorbufferFormat != GL_RGB5_A1 &&
colorbufferFormat != GL_RGBA8_OES)
{
return error(GL_INVALID_OPERATION);
}
if (texture->isCompressed())
break;
case GL_LUMINANCE:
case GL_RGB:
if (colorbufferFormat != GL_RGB &&
colorbufferFormat != GL_RGB565 &&
colorbufferFormat != GL_RGB8_OES &&
colorbufferFormat != GL_RGBA &&
colorbufferFormat != GL_RGBA4 &&
colorbufferFormat != GL_RGB5_A1 &&
colorbufferFormat != GL_RGBA8_OES)
{
return error(GL_INVALID_OPERATION);
}
if (texture->isFloatingPoint())
break;
case GL_LUMINANCE_ALPHA:
case GL_RGBA:
if (colorbufferFormat != GL_RGBA &&
colorbufferFormat != GL_RGBA4 &&
colorbufferFormat != GL_RGB5_A1 &&
colorbufferFormat != GL_RGBA8_OES)
{
return error(GL_INVALID_OPERATION);
}
texture->copySubImage(target, level, xoffset, yoffset, x, y, width, height, source);
}
else
{
UNREACHABLE();
break;
case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
return error(GL_INVALID_OPERATION);
default:
return error(GL_INVALID_OPERATION);
}
texture->copySubImage(target, level, xoffset, yoffset, x, y, width, height, source);
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment