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, ...@@ -1153,7 +1153,7 @@ void Texture2D::copyImage(GLint level, GLenum internalFormat, GLint x, GLint y,
mImageArray[level].format = internalFormat; 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) 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 ...@@ -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 ...@@ -1896,9 +1896,9 @@ bool TextureCubeMap::redefineTexture(GLint level, GLenum internalFormat, GLsizei
return !textureOkay; 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)) if (redefineTexture(level, internalFormat, width))
{ {
...@@ -1920,7 +1920,7 @@ void TextureCubeMap::copyImage(GLenum face, GLint level, GLenum internalFormat, ...@@ -1920,7 +1920,7 @@ void TextureCubeMap::copyImage(GLenum face, GLint level, GLenum internalFormat,
sourceRect.top = y; sourceRect.top = y;
sourceRect.bottom = y + height; sourceRect.bottom = y + height;
IDirect3DSurface9 *dest = getCubeMapSurface(face, level); IDirect3DSurface9 *dest = getCubeMapSurface(target, level);
getBlitter()->formatConvert(source->getRenderTarget(), sourceRect, internalFormat, 0, 0, dest); getBlitter()->formatConvert(source->getRenderTarget(), sourceRect, internalFormat, 0, 0, dest);
dest->Release(); dest->Release();
...@@ -1962,9 +1962,9 @@ IDirect3DSurface9 *TextureCubeMap::getCubeMapSurface(unsigned int faceIdentifier ...@@ -1962,9 +1962,9 @@ IDirect3DSurface9 *TextureCubeMap::getCubeMapSurface(unsigned int faceIdentifier
return (SUCCEEDED(hr)) ? surface : NULL; 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) if (xoffset + width > size || yoffset + height > size)
{ {
...@@ -1989,7 +1989,7 @@ void TextureCubeMap::copySubImage(GLenum face, GLint level, GLint xoffset, GLint ...@@ -1989,7 +1989,7 @@ void TextureCubeMap::copySubImage(GLenum face, GLint level, GLint xoffset, GLint
sourceRect.top = y; sourceRect.top = y;
sourceRect.bottom = y + height; 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); getBlitter()->formatConvert(source->getRenderTarget(), sourceRect, mImageArray[0][0].format, xoffset, yoffset, dest);
dest->Release(); dest->Release();
......
...@@ -69,6 +69,7 @@ class Texture : public RefCountObject ...@@ -69,6 +69,7 @@ class Texture : public RefCountObject
virtual Renderbuffer *getColorbuffer(GLenum target) = 0; virtual Renderbuffer *getColorbuffer(GLenum target) = 0;
virtual void generateMipmaps() = 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; bool isDirty() const;
...@@ -218,7 +219,7 @@ class Texture2D : public Texture ...@@ -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 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 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 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 isComplete() const;
bool isCompressed() const; bool isCompressed() const;
...@@ -266,10 +267,10 @@ class TextureCubeMap : public Texture ...@@ -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 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 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 face, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, 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 face, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, RenderbufferStorage *source); void copyImage(GLenum target, 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 copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, RenderbufferStorage *source);
bool isComplete() const; bool isComplete() const;
bool isCompressed() const; bool isCompressed() const;
......
...@@ -991,20 +991,6 @@ void __stdcall glCopyTexImage2D(GLenum target, GLint level, GLenum internalforma ...@@ -991,20 +991,6 @@ void __stdcall glCopyTexImage2D(GLenum target, GLint level, GLenum internalforma
return error(GL_INVALID_VALUE); 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) if (border != 0)
{ {
return error(GL_INVALID_VALUE); return error(GL_INVALID_VALUE);
...@@ -1044,20 +1030,8 @@ void __stdcall glCopyTexImage2D(GLenum target, GLint level, GLenum internalforma ...@@ -1044,20 +1030,8 @@ void __stdcall glCopyTexImage2D(GLenum target, GLint level, GLenum internalforma
return error(GL_INVALID_ENUM); 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(); gl::Framebuffer *framebuffer = context->getReadFramebuffer();
if (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE) if (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)
{ {
return error(GL_INVALID_FRAMEBUFFER_OPERATION); return error(GL_INVALID_FRAMEBUFFER_OPERATION);
...@@ -1069,52 +1043,82 @@ void __stdcall glCopyTexImage2D(GLenum target, GLint level, GLenum internalforma ...@@ -1069,52 +1043,82 @@ void __stdcall glCopyTexImage2D(GLenum target, GLint level, GLenum internalforma
} }
gl::Colorbuffer *source = framebuffer->getColorbuffer(); gl::Colorbuffer *source = framebuffer->getColorbuffer();
if (target == GL_TEXTURE_2D) GLenum colorbufferFormat = source->getFormat();
{
gl::Texture2D *texture = context->getTexture2D();
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); return error(GL_INVALID_OPERATION);
} }
break;
if (texture->isCompressed()) 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); return error(GL_INVALID_OPERATION);
} }
break;
if (texture->isFloatingPoint()) 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); return error(GL_INVALID_OPERATION);
} }
else
texture->copyImage(level, internalformat, x, y, width, height, source); {
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) if (!texture)
{ {
return error(GL_INVALID_OPERATION); return error(GL_INVALID_OPERATION);
} }
if (texture->isCompressed()) texture->copyImage(level, internalformat, x, y, width, height, source);
{ }
return error(GL_INVALID_OPERATION); else if (gl::IsCubemapTextureTarget(target))
} {
gl::TextureCubeMap *texture = context->getTextureCubeMap();
if (texture->isFloatingPoint()) if (!texture)
{ {
return error(GL_INVALID_OPERATION); return error(GL_INVALID_OPERATION);
} }
texture->copyImage(target, level, internalformat, x, y, width, height, source); texture->copyImage(target, level, internalformat, x, y, width, height, source);
} }
else else UNREACHABLE();
{
UNREACHABLE();
}
} }
} }
catch(std::bad_alloc&) catch(std::bad_alloc&)
...@@ -1161,6 +1165,7 @@ void __stdcall glCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GL ...@@ -1161,6 +1165,7 @@ void __stdcall glCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GL
} }
gl::Framebuffer *framebuffer = context->getReadFramebuffer(); gl::Framebuffer *framebuffer = context->getReadFramebuffer();
if (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE) if (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)
{ {
return error(GL_INVALID_FRAMEBUFFER_OPERATION); return error(GL_INVALID_FRAMEBUFFER_OPERATION);
...@@ -1172,52 +1177,70 @@ void __stdcall glCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GL ...@@ -1172,52 +1177,70 @@ void __stdcall glCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GL
} }
gl::Colorbuffer *source = framebuffer->getColorbuffer(); gl::Colorbuffer *source = framebuffer->getColorbuffer();
GLenum colorbufferFormat = source->getFormat();
gl::Texture *texture = NULL;
if (target == GL_TEXTURE_2D) if (target == GL_TEXTURE_2D)
{ {
gl::Texture2D *texture = context->getTexture2D(); 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);
} }
else if (gl::IsCubemapTextureTarget(target)) 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); return error(GL_INVALID_OPERATION);
} }
break;
if (texture->isCompressed()) 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); return error(GL_INVALID_OPERATION);
} }
break;
if (texture->isFloatingPoint()) 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); return error(GL_INVALID_OPERATION);
} }
break;
texture->copySubImage(target, level, xoffset, yoffset, x, y, width, height, source); case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
} case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
else return error(GL_INVALID_OPERATION);
{ default:
UNREACHABLE(); 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