Implemented 3D texture entry points.

TRAC #22705 Signed-off-by: Jamie Madill Signed-off-by: Shannon Woods Author: Geoff Lang git-svn-id: https://angleproject.googlecode.com/svn/branches/es3proto@2172 736b8ea6-26fd-11df-bfd4-992fa37f6226
parent 6d73c4ee
...@@ -222,16 +222,169 @@ bool validateSubImageParamsCube(bool compressed, GLsizei width, GLsizei height, ...@@ -222,16 +222,169 @@ bool validateSubImageParamsCube(bool compressed, GLsizei width, GLsizei height,
return true; return true;
} }
bool validateSubImageParams3D(bool compressed, GLsizei width, GLsizei height, GLsizei depth, bool validateES3TexImageFormat(gl::Context *context, GLenum target, GLint level, GLint internalformat, bool isCompressed, bool isSubImage,
GLint xoffset, GLint yoffset,GLint zoffset, GLint level, GLenum format, GLenum type, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
gl::Texture3D *texture) GLint border, GLenum format, GLenum type)
{ {
// Validate image size
if (level < 0 || width < 0 || height < 0 || depth < 0 )
{
return gl::error(GL_INVALID_VALUE, false);
}
if (isCompressed)
{
if (width != 1 && width != 2 && width % 4 != 0)
{
return gl::error(GL_INVALID_OPERATION, false);
}
if (height != 1 && height != 2 && height % 4 != 0)
{
return gl::error(GL_INVALID_OPERATION, false);
}
}
// Verify zero border
if (border != 0)
{
return gl::error(GL_INVALID_VALUE, false);
}
// Validate dimensions based on Context limits and validate the texture
if (level > context->getMaximumTextureLevel())
{
return gl::error(GL_INVALID_VALUE, false);
}
gl::Texture *texture = NULL;
bool textureCompressed = false;
GLenum textureInternalFormat = GL_NONE;
GLint textureLevelWidth = 0;
GLint textureLevelHeight = 0;
GLint textureLevelDepth = 0;
switch (target)
{
case GL_TEXTURE_2D:
{
if (width > (context->getMaximum2DTextureDimension() >> level) ||
height > (context->getMaximum2DTextureDimension() >> level))
{
return gl::error(GL_INVALID_VALUE, false);
}
gl::Texture2D *texture2d = context->getTexture2D();
if (texture2d)
{
textureCompressed = texture2d->isCompressed(level);
textureInternalFormat = texture2d->getInternalFormat(level);
textureLevelWidth = texture2d->getWidth(level);
textureLevelHeight = texture2d->getHeight(level);
textureLevelDepth = 1;
texture = texture2d;
}
}
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 gl::error(GL_INVALID_VALUE, false);
}
if (width > (context->getMaximumCubeTextureDimension() >> level))
{
return gl::error(GL_INVALID_VALUE, false);
}
gl::TextureCubeMap *textureCube = context->getTextureCubeMap();
if (textureCube)
{
textureCompressed = textureCube->isCompressed(target, level);
textureInternalFormat = textureCube->getInternalFormat(target, level);
textureLevelWidth = textureCube->getWidth(target, level);
textureLevelHeight = textureCube->getHeight(target, level);
textureLevelDepth = 1;
texture = textureCube;
}
}
break;
case GL_TEXTURE_3D:
{
if (width > (context->getMaximum3DTextureDimension() >> level) ||
height > (context->getMaximum3DTextureDimension() >> level) ||
depth > (context->getMaximum3DTextureDimension() >> level))
{
return gl::error(GL_INVALID_VALUE, false);
}
gl::Texture3D *texture3d = context->getTexture3D();
if (texture3d)
{
textureCompressed = texture3d->isCompressed(level);
textureInternalFormat = texture3d->getInternalFormat(level);
textureLevelWidth = texture3d->getWidth(level);
textureLevelHeight = texture3d->getHeight(level);
textureLevelDepth = texture3d->getDepth(level);
texture = texture3d;
}
}
break;
default:
return gl::error(GL_INVALID_ENUM, false);
}
if (!texture) if (!texture)
{ {
return gl::error(GL_INVALID_OPERATION, false); return gl::error(GL_INVALID_OPERATION, false);
} }
if (compressed != texture->isCompressed(level)) if (texture->isImmutable())
{
return gl::error(GL_INVALID_OPERATION, false);
}
// Validate texture formats
GLenum actualInternalFormat = isSubImage ? textureInternalFormat : internalformat;
if (isCompressed)
{
if (!gl::IsValidES3CompressedFormat(actualInternalFormat))
{
return gl::error(GL_INVALID_ENUM, false);
}
if (target == GL_TEXTURE_3D)
{
return gl::error(GL_INVALID_OPERATION, false);
}
}
else
{
GLenum err;
if (!gl::IsValidES3FormatCombination(actualInternalFormat, format, type, &err))
{
return gl::error(err, false);
}
if ((target == GL_TEXTURE_3D || target == GL_TEXTURE_2D_ARRAY) &&
(format == GL_DEPTH_COMPONENT || format == GL_DEPTH_STENCIL))
{
return gl::error(GL_INVALID_OPERATION, false);
}
}
// Validate sub image parameters
if (isSubImage)
{
if (isCompressed != textureCompressed)
{ {
return gl::error(GL_INVALID_OPERATION, false); return gl::error(GL_INVALID_OPERATION, false);
} }
...@@ -239,28 +392,180 @@ bool validateSubImageParams3D(bool compressed, GLsizei width, GLsizei height, GL ...@@ -239,28 +392,180 @@ bool validateSubImageParams3D(bool compressed, GLsizei width, GLsizei height, GL
if (format != GL_NONE) if (format != GL_NONE)
{ {
GLenum internalformat = gl::ConvertSizedInternalFormat(format, type); GLenum internalformat = gl::ConvertSizedInternalFormat(format, type);
if (internalformat != texture->getInternalFormat(level)) if (internalformat != textureInternalFormat)
{ {
return gl::error(GL_INVALID_OPERATION, false); return gl::error(GL_INVALID_OPERATION, false);
} }
} }
if (compressed) if (isCompressed)
{ {
if ((width % 4 != 0 && width != texture->getWidth(0)) || if ((width % 4 != 0 && width != textureLevelWidth) ||
(height % 4 != 0 && height != texture->getHeight(0))) (height % 4 != 0 && height != textureLevelHeight))
{ {
return gl::error(GL_INVALID_OPERATION, false); return gl::error(GL_INVALID_OPERATION, false);
} }
} }
if (xoffset + width > texture->getWidth(level) || if (width == 0 || height == 0 || depth == 0)
yoffset + height > texture->getHeight(level) || {
zoffset + depth > texture->getDepth(level)) return false;
}
if (xoffset < 0 || yoffset < 0 || zoffset < 0)
{
return gl::error(GL_INVALID_VALUE, false);
}
if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
std::numeric_limits<GLsizei>::max() - yoffset < height ||
std::numeric_limits<GLsizei>::max() - zoffset < depth)
{ {
return gl::error(GL_INVALID_VALUE, false); return gl::error(GL_INVALID_VALUE, false);
} }
if (xoffset + width > textureLevelWidth ||
yoffset + height > textureLevelHeight ||
zoffset + depth > textureLevelDepth)
{
return gl::error(GL_INVALID_VALUE, false);
}
}
return true;
}
bool validateCopyTexImageParameters(gl::Context *context, GLenum target, bool isCompressed, GLint level,
GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y,
GLsizei width, GLsizei height)
{
if (level < 0 || xoffset < 0 || yoffset < 0 || zoffset < 0 || width < 0 || height < 0)
{
return gl::error(GL_INVALID_VALUE, false);
}
if (std::numeric_limits<GLsizei>::max() - xoffset < width || std::numeric_limits<GLsizei>::max() - yoffset < height)
{
return gl::error(GL_INVALID_VALUE, false);
}
if (width == 0 || height == 0)
{
return false;
}
if (level > context->getMaximumTextureLevel())
{
return gl::error(GL_INVALID_VALUE, false);
}
gl::Framebuffer *framebuffer = context->getReadFramebuffer();
if (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)
{
return gl::error(GL_INVALID_FRAMEBUFFER_OPERATION, false);
}
if (context->getReadFramebufferHandle() != 0 && framebuffer->getSamples() != 0)
{
return gl::error(GL_INVALID_OPERATION, false);
}
gl::Renderbuffer *source = framebuffer->getReadColorbuffer();
GLenum colorbufferFormat = source->getInternalFormat();
gl::Texture *texture = NULL;
GLenum textureFormat = GL_RGBA;
bool textureCompressed = false;
GLint textureLevelWidth = 0;
GLint textureLevelHeight = 0;
GLint textureLevelDepth = 0;
switch (target)
{
case GL_TEXTURE_2D:
{
gl::Texture2D *texture2d = context->getTexture2D();
if (texture2d)
{
textureFormat = gl::ExtractFormat(texture2d->getInternalFormat(level));
textureCompressed = texture2d->isCompressed(level);
textureLevelWidth = texture2d->getWidth(level);
textureLevelHeight = texture2d->getHeight(level);
textureLevelDepth = 1;
texture = texture2d;
}
}
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();
if (textureCube)
{
textureFormat = gl::ExtractFormat(textureCube->getInternalFormat(target, level));
textureCompressed = textureCube->isCompressed(target, level);
textureLevelWidth = textureCube->getWidth(target, level);
textureLevelHeight = textureCube->getHeight(target, level);
textureLevelDepth = 1;
texture = textureCube;
}
}
break;
case GL_TEXTURE_3D:
{
gl::Texture3D *texture3d = context->getTexture3D();
if (texture3d)
{
textureFormat = gl::ExtractFormat(texture3d->getInternalFormat(level));
textureCompressed = texture3d->isCompressed(level);
textureLevelWidth = texture3d->getWidth(level);
textureLevelHeight = texture3d->getHeight(level);
textureLevelDepth = texture3d->getDepth(level);
texture = texture3d;
}
}
break;
default:
return gl::error(GL_INVALID_ENUM, false);
}
if (!texture)
{
return gl::error(GL_INVALID_OPERATION, false);
}
if (isCompressed != textureCompressed)
{
return gl::error(GL_INVALID_OPERATION, false);
}
if (isCompressed)
{
if ((width % 4 != 0 && width != textureLevelWidth) ||
(height % 4 != 0 && height != textureLevelHeight))
{
return gl::error(GL_INVALID_OPERATION, false);
}
}
if (xoffset + width > textureLevelWidth ||
yoffset + height > textureLevelHeight ||
zoffset >= textureLevelDepth)
{
return gl::error(GL_INVALID_VALUE, false);
}
if (!gl::IsValidES3CopyTexImageCombination(textureFormat, colorbufferFormat))
{
return gl::error(GL_INVALID_OPERATION, false);
}
return true; return true;
} }
...@@ -7172,9 +7477,31 @@ void __stdcall glTexImage3D(GLenum target, GLint level, GLint internalformat, GL ...@@ -7172,9 +7477,31 @@ void __stdcall glTexImage3D(GLenum target, GLint level, GLint internalformat, GL
{ {
return gl::error(GL_INVALID_OPERATION); return gl::error(GL_INVALID_OPERATION);
} }
// validateES3TexImageFormat sets the error code if there is an error
if (!validateES3TexImageFormat(context, target, level, internalformat, false, false,
0, 0, 0, width, height, depth, border, format, type))
{
return;
} }
switch(target)
{
case GL_TEXTURE_3D:
{
gl::Texture3D *texture = context->getTexture3D();
texture->setImage(level, width, height, depth, format, type, context->getUnpackAlignment(), pixels);
}
break;
case GL_TEXTURE_2D_ARRAY:
UNIMPLEMENTED(); UNIMPLEMENTED();
break;
default:
return gl::error(GL_INVALID_ENUM);
}
}
} }
catch(std::bad_alloc&) catch(std::bad_alloc&)
{ {
...@@ -7199,9 +7526,37 @@ void __stdcall glTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint ...@@ -7199,9 +7526,37 @@ void __stdcall glTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint
{ {
return gl::error(GL_INVALID_OPERATION); return gl::error(GL_INVALID_OPERATION);
} }
if (!pixels)
{
return gl::error(GL_INVALID_VALUE);
}
// validateES3TexImageFormat sets the error code if there is an error
if (!validateES3TexImageFormat(context, target, level, GL_NONE, false, true,
xoffset, yoffset, zoffset, width, height, depth, 0,
format, type))
{
return;
}
switch(target)
{
case GL_TEXTURE_3D:
{
gl::Texture3D *texture = context->getTexture3D();
texture->subImage(level, xoffset, yoffset, zoffset, width, height, depth, format, type, context->getUnpackAlignment(), pixels);
} }
break;
case GL_TEXTURE_2D_ARRAY:
UNIMPLEMENTED(); UNIMPLEMENTED();
break;
default:
return gl::error(GL_INVALID_ENUM);
}
}
} }
catch(std::bad_alloc&) catch(std::bad_alloc&)
{ {
...@@ -7225,9 +7580,31 @@ void __stdcall glCopyTexSubImage3D(GLenum target, GLint level, GLint xoffset, GL ...@@ -7225,9 +7580,31 @@ void __stdcall glCopyTexSubImage3D(GLenum target, GLint level, GLint xoffset, GL
{ {
return gl::error(GL_INVALID_OPERATION); return gl::error(GL_INVALID_OPERATION);
} }
if (!validateCopyTexImageParameters(context, target, false, level, xoffset, yoffset, zoffset,
x, y, width, height))
{
return;
} }
gl::Framebuffer *framebuffer = context->getReadFramebuffer();
gl::Texture *texture = NULL;
switch (target)
{
case GL_TEXTURE_3D:
texture = context->getTexture3D();
break;
case GL_TEXTURE_2D_ARRAY:
UNIMPLEMENTED(); UNIMPLEMENTED();
break;
default:
return gl::error(GL_INVALID_ENUM);
}
texture->copySubImage(target, level, xoffset, yoffset, zoffset, x, y, width, height, framebuffer);
}
} }
catch(std::bad_alloc&) catch(std::bad_alloc&)
{ {
...@@ -7252,9 +7629,36 @@ void __stdcall glCompressedTexImage3D(GLenum target, GLint level, GLenum interna ...@@ -7252,9 +7629,36 @@ void __stdcall glCompressedTexImage3D(GLenum target, GLint level, GLenum interna
{ {
return gl::error(GL_INVALID_OPERATION); return gl::error(GL_INVALID_OPERATION);
} }
if (imageSize < 0 || imageSize != gl::ComputeCompressedSize(width, height, internalformat))
{
return gl::error(GL_INVALID_VALUE);
} }
// validateES3TexImageFormat sets the error code if there is an error
if (!validateES3TexImageFormat(context, target, level, internalformat, true, false,
0, 0, 0, width, height, depth, border, GL_NONE, GL_NONE))
{
return;
}
switch(target)
{
case GL_TEXTURE_3D:
{
gl::Texture3D *texture = context->getTexture3D();
texture->setCompressedImage(level, internalformat, width, height, depth, imageSize, data);
}
break;
case GL_TEXTURE_2D_ARRAY:
UNIMPLEMENTED(); UNIMPLEMENTED();
break;
default:
return gl::error(GL_INVALID_ENUM);
}
}
} }
catch(std::bad_alloc&) catch(std::bad_alloc&)
{ {
...@@ -7279,9 +7683,42 @@ void __stdcall glCompressedTexSubImage3D(GLenum target, GLint level, GLint xoffs ...@@ -7279,9 +7683,42 @@ void __stdcall glCompressedTexSubImage3D(GLenum target, GLint level, GLint xoffs
{ {
return gl::error(GL_INVALID_OPERATION); return gl::error(GL_INVALID_OPERATION);
} }
if (imageSize < 0 || imageSize != gl::ComputeCompressedSize(width, height, format))
{
return gl::error(GL_INVALID_VALUE);
}
if (!data)
{
return gl::error(GL_INVALID_VALUE);
}
// validateES3TexImageFormat sets the error code if there is an error
if (!validateES3TexImageFormat(context, target, level, GL_NONE, true, true,
0, 0, 0, width, height, depth, 0, GL_NONE, GL_NONE))
{
return;
} }
switch(target)
{
case GL_TEXTURE_3D:
{
gl::Texture3D *texture = context->getTexture3D();
texture->subImageCompressed(level, xoffset, yoffset, zoffset, width, height, depth,
format, imageSize, data);
}
break;
case GL_TEXTURE_2D_ARRAY:
UNIMPLEMENTED(); UNIMPLEMENTED();
break;
default:
return gl::error(GL_INVALID_ENUM);
}
}
} }
catch(std::bad_alloc&) catch(std::bad_alloc&)
{ {
......
...@@ -799,6 +799,259 @@ bool IsTriangleMode(GLenum drawMode) ...@@ -799,6 +799,259 @@ bool IsTriangleMode(GLenum drawMode)
return false; return false;
} }
struct FormatInfo
{
GLenum mFormat;
GLenum mType;
GLint mInternalformat;
FormatInfo(GLenum format, GLenum type, GLint internalformat)
: mFormat(format), mType(type), mInternalformat(internalformat) { }
bool operator<(const FormatInfo& other) const
{
return memcmp(this, &other, sizeof(FormatInfo)) < 0;
}
};
typedef std::set<FormatInfo> formatInfoSet;
static formatInfoSet buildValidES3FormatCombinationSet()
{
formatInfoSet set;
// From ES 3.0.1 spec, table 3.2
set.insert(FormatInfo(GL_RGBA, GL_UNSIGNED_BYTE, GL_RGBA8 ));
set.insert(FormatInfo(GL_RGBA, GL_UNSIGNED_BYTE, GL_RGB5_A1 ));
set.insert(FormatInfo(GL_RGBA, GL_UNSIGNED_BYTE, GL_RGBA4 ));
set.insert(FormatInfo(GL_RGBA, GL_UNSIGNED_BYTE, GL_SRGB8_ALPHA8 ));
set.insert(FormatInfo(GL_RGBA, GL_BYTE, GL_RGBA8_SNORM ));
set.insert(FormatInfo(GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, GL_RGBA4 ));
set.insert(FormatInfo(GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, GL_RGB10_A2 ));
set.insert(FormatInfo(GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, GL_RGB5_A1 ));
set.insert(FormatInfo(GL_RGBA, GL_HALF_FLOAT, GL_RGBA16F ));
set.insert(FormatInfo(GL_RGBA, GL_FLOAT, GL_RGBA32F ));
set.insert(FormatInfo(GL_RGBA, GL_FLOAT, GL_RGBA16F ));
set.insert(FormatInfo(GL_RGBA_INTEGER, GL_UNSIGNED_BYTE, GL_RGBA8UI ));
set.insert(FormatInfo(GL_RGBA_INTEGER, GL_BYTE, GL_RGBA8I ));
set.insert(FormatInfo(GL_RGBA_INTEGER, GL_UNSIGNED_SHORT, GL_RGBA16UI ));
set.insert(FormatInfo(GL_RGBA_INTEGER, GL_SHORT, GL_RGBA16I ));
set.insert(FormatInfo(GL_RGBA_INTEGER, GL_UNSIGNED_INT, GL_RGBA32UI ));
set.insert(FormatInfo(GL_RGBA_INTEGER, GL_INT, GL_RGBA32I ));
set.insert(FormatInfo(GL_RGBA_INTEGER, GL_UNSIGNED_INT_2_10_10_10_REV, GL_RGB10_A2UI ));
set.insert(FormatInfo(GL_RGB, GL_UNSIGNED_BYTE, GL_RGB8 ));
set.insert(FormatInfo(GL_RGB, GL_UNSIGNED_BYTE, GL_RGB565 ));
set.insert(FormatInfo(GL_RGB, GL_UNSIGNED_BYTE, GL_SRGB8 ));
set.insert(FormatInfo(GL_RGB, GL_BYTE, GL_RGB8_SNORM ));
set.insert(FormatInfo(GL_RGB, GL_UNSIGNED_SHORT_5_6_5, GL_RGB565 ));
set.insert(FormatInfo(GL_RGB, GL_UNSIGNED_INT_10F_11F_11F_REV, GL_R11F_G11F_B10F ));
set.insert(FormatInfo(GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV, GL_RGB9_E5 ));
set.insert(FormatInfo(GL_RGB, GL_HALF_FLOAT, GL_RGB16F ));
set.insert(FormatInfo(GL_RGB, GL_HALF_FLOAT, GL_R11F_G11F_B10F ));
set.insert(FormatInfo(GL_RGB, GL_HALF_FLOAT, GL_RGB9_E5 ));
set.insert(FormatInfo(GL_RGB, GL_FLOAT, GL_RGB32F ));
set.insert(FormatInfo(GL_RGB, GL_FLOAT, GL_RGB16F ));
set.insert(FormatInfo(GL_RGB, GL_FLOAT, GL_R11F_G11F_B10F ));
set.insert(FormatInfo(GL_RGB, GL_FLOAT, GL_RGB9_E5 ));
set.insert(FormatInfo(GL_RGB_INTEGER, GL_UNSIGNED_BYTE, GL_RGB8UI ));
set.insert(FormatInfo(GL_RGB_INTEGER, GL_BYTE, GL_RGB8I ));
set.insert(FormatInfo(GL_RGB_INTEGER, GL_UNSIGNED_SHORT, GL_RGB16UI ));
set.insert(FormatInfo(GL_RGB_INTEGER, GL_SHORT, GL_RGB16I ));
set.insert(FormatInfo(GL_RGB_INTEGER, GL_UNSIGNED_INT, GL_RGB32UI ));
set.insert(FormatInfo(GL_RGB_INTEGER, GL_INT, GL_RGB32I ));
set.insert(FormatInfo(GL_RG, GL_UNSIGNED_BYTE, GL_RG8 ));
set.insert(FormatInfo(GL_RG, GL_BYTE, GL_RG8_SNORM ));
set.insert(FormatInfo(GL_RG, GL_HALF_FLOAT, GL_RG16F ));
set.insert(FormatInfo(GL_RG, GL_FLOAT, GL_RG32F ));
set.insert(FormatInfo(GL_RG, GL_FLOAT, GL_RG16F ));
set.insert(FormatInfo(GL_RG_INTEGER, GL_UNSIGNED_BYTE, GL_RG8UI ));
set.insert(FormatInfo(GL_RG_INTEGER, GL_BYTE, GL_RG8I ));
set.insert(FormatInfo(GL_RG_INTEGER, GL_UNSIGNED_SHORT, GL_RG16UI ));
set.insert(FormatInfo(GL_RG_INTEGER, GL_SHORT, GL_RG16I ));
set.insert(FormatInfo(GL_RG_INTEGER, GL_UNSIGNED_INT, GL_RG32UI ));
set.insert(FormatInfo(GL_RG_INTEGER, GL_INT, GL_RG32I ));
set.insert(FormatInfo(GL_RED, GL_UNSIGNED_BYTE, GL_R8 ));
set.insert(FormatInfo(GL_RED, GL_BYTE, GL_R8_SNORM ));
set.insert(FormatInfo(GL_RED, GL_HALF_FLOAT, GL_R16F ));
set.insert(FormatInfo(GL_RED, GL_FLOAT, GL_R32F ));
set.insert(FormatInfo(GL_RED, GL_FLOAT, GL_R16F ));
set.insert(FormatInfo(GL_RED_INTEGER, GL_UNSIGNED_BYTE, GL_R8UI ));
set.insert(FormatInfo(GL_RED_INTEGER, GL_BYTE, GL_R8I ));
set.insert(FormatInfo(GL_RED_INTEGER, GL_UNSIGNED_SHORT, GL_R16UI ));
set.insert(FormatInfo(GL_RED_INTEGER, GL_SHORT, GL_R16I ));
set.insert(FormatInfo(GL_RED_INTEGER, GL_UNSIGNED_INT, GL_R32UI ));
set.insert(FormatInfo(GL_RED_INTEGER, GL_INT, GL_R32I ));
set.insert(FormatInfo(GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, GL_DEPTH_COMPONENT16 ));
set.insert(FormatInfo(GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, GL_DEPTH_COMPONENT24 ));
set.insert(FormatInfo(GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, GL_DEPTH_COMPONENT16 ));
set.insert(FormatInfo(GL_DEPTH_COMPONENT, GL_FLOAT, GL_DEPTH_COMPONENT32F));
set.insert(FormatInfo(GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, GL_DEPTH24_STENCIL8 ));
set.insert(FormatInfo(GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, GL_DEPTH32F_STENCIL8 ));
// From ES 3.0.1 spec, table 3.3
set.insert(FormatInfo(GL_RGBA, GL_UNSIGNED_BYTE, GL_RGBA ));
set.insert(FormatInfo(GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, GL_RGBA ));
set.insert(FormatInfo(GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, GL_RGBA ));
set.insert(FormatInfo(GL_RGB, GL_UNSIGNED_BYTE, GL_RGB ));
set.insert(FormatInfo(GL_RGB, GL_UNSIGNED_SHORT_5_6_5, GL_RGB ));
set.insert(FormatInfo(GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, GL_LUMINANCE_ALPHA ));
set.insert(FormatInfo(GL_LUMINANCE, GL_UNSIGNED_BYTE, GL_LUMINANCE ));
set.insert(FormatInfo(GL_ALPHA, GL_UNSIGNED_BYTE, GL_ALPHA ));
// From GL_OES_texture_float
set.insert(FormatInfo(GL_LUMINANCE_ALPHA, GL_FLOAT, GL_LUMINANCE_ALPHA ));
set.insert(FormatInfo(GL_LUMINANCE, GL_FLOAT, GL_LUMINANCE ));
set.insert(FormatInfo(GL_ALPHA, GL_FLOAT, GL_ALPHA ));
// From GL_OES_texture_half_float
set.insert(FormatInfo(GL_LUMINANCE_ALPHA, GL_HALF_FLOAT, GL_LUMINANCE_ALPHA ));
set.insert(FormatInfo(GL_LUMINANCE, GL_HALF_FLOAT, GL_LUMINANCE ));
set.insert(FormatInfo(GL_ALPHA, GL_HALF_FLOAT, GL_ALPHA ));
return set;
}
typedef std::set<GLint> internalFormatSet;
static internalFormatSet buildValidES3InternalFormatSet(const formatInfoSet& formatCombos)
{
internalFormatSet internalFormats;
for (formatInfoSet::const_iterator i = formatCombos.begin(); i != formatCombos.end(); i++)
{
internalFormats.insert(i->mInternalformat);
}
return internalFormats;
}
typedef std::set<GLenum> formatSet;
static formatSet buildValidES3FormatSet(const formatInfoSet& formatCombos)
{
formatSet formats;
for (formatInfoSet::const_iterator i = formatCombos.begin(); i != formatCombos.end(); i++)
{
formats.insert(i->mFormat);
}
return formats;
}
typedef std::set<GLenum> typeSet;
static typeSet buildValidES3TypeSet(const formatInfoSet& formatCombos)
{
typeSet types;
for (formatInfoSet::const_iterator i = formatCombos.begin(); i != formatCombos.end(); i++)
{
types.insert(i->mType);
}
return types;
}
bool IsValidES3FormatCombination(GLint internalformat, GLenum format, GLenum type, GLenum* err)
{
static const formatInfoSet combinations = buildValidES3FormatCombinationSet();
static const internalFormatSet internalFormats = buildValidES3InternalFormatSet(combinations);
static const formatSet formats = buildValidES3FormatSet(combinations);
static const typeSet types = buildValidES3TypeSet(combinations);
// Invalid internal format, format or type results in an INVALID_ENUM
if (internalFormats.find(internalformat) == internalFormats.end() ||
formats.find(format) == formats.end() ||
types.find(type) == types.end())
{
*err = GL_INVALID_ENUM;
return false;
}
// Invalid internal format + format + type combination results in an INVALID_OPERATION
if (combinations.find(FormatInfo(format, type, internalformat)) == combinations.end())
{
*err = GL_INVALID_OPERATION;
return false;
}
return true;
}
typedef std::set<GLenum> compressedFormatSet;
static compressedFormatSet buildValidES3CompressedFormats()
{
compressedFormatSet formats;
// From ES 3.0.1 spec, table 3.16
formats.insert(GL_COMPRESSED_R11_EAC );
formats.insert(GL_COMPRESSED_R11_EAC );
formats.insert(GL_COMPRESSED_SIGNED_R11_EAC );
formats.insert(GL_COMPRESSED_RG11_EAC );
formats.insert(GL_COMPRESSED_SIGNED_RG11_EAC );
formats.insert(GL_COMPRESSED_RGB8_ETC2 );
formats.insert(GL_COMPRESSED_SRGB8_ETC2 );
formats.insert(GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 );
formats.insert(GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2);
formats.insert(GL_COMPRESSED_RGBA8_ETC2_EAC );
formats.insert(GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC );
// From GL_EXT_texture_compression_dxt1
formats.insert(GL_COMPRESSED_RGB_S3TC_DXT1_EXT );
formats.insert(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT );
// From GL_ANGLE_texture_compression_dxt3
formats.insert(GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE );
// From GL_ANGLE_texture_compression_dxt5
formats.insert(GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE );
return formats;
}
bool IsValidES3CompressedFormat(GLenum format)
{
static const compressedFormatSet validCompressedFormats = buildValidES3CompressedFormats();
return validCompressedFormats.find(format) != validCompressedFormats.end();
}
struct CopyConversion
{
GLenum mTextureFormat;
GLenum mFramebufferFormat;
CopyConversion(GLenum textureFormat, GLenum framebufferFormat)
: mTextureFormat(textureFormat), mFramebufferFormat(framebufferFormat) { }
bool operator<(const CopyConversion& other) const
{
return memcmp(this, &other, sizeof(CopyConversion)) < 0;
}
};
typedef std::set<CopyConversion> copyConversionSet;
static copyConversionSet buildValidES3CopyTexImageCombinations()
{
copyConversionSet set;
// From ES 3.0.1 spec, table 3.15
set.insert(CopyConversion(GL_ALPHA, GL_RGBA));
set.insert(CopyConversion(GL_LUMINANCE, GL_RED));
set.insert(CopyConversion(GL_LUMINANCE, GL_RG));
set.insert(CopyConversion(GL_LUMINANCE, GL_RGB));
set.insert(CopyConversion(GL_LUMINANCE, GL_RGBA));
set.insert(CopyConversion(GL_LUMINANCE_ALPHA, GL_RGBA));
set.insert(CopyConversion(GL_RED, GL_RED));
set.insert(CopyConversion(GL_RED, GL_RG));
set.insert(CopyConversion(GL_RED, GL_RGB));
set.insert(CopyConversion(GL_RED, GL_RGBA));
set.insert(CopyConversion(GL_RG, GL_RG));
set.insert(CopyConversion(GL_RG, GL_RGB));
set.insert(CopyConversion(GL_RG, GL_RGBA));
set.insert(CopyConversion(GL_RGB, GL_RGB));
set.insert(CopyConversion(GL_RGB, GL_RGBA));
set.insert(CopyConversion(GL_RGBA, GL_RGBA));
return set;
}
bool IsValidES3CopyTexImageCombination(GLenum textureFormat, GLenum frameBufferFormat)
{
static const copyConversionSet conversions = buildValidES3CopyTexImageCombinations();
return conversions.find(CopyConversion(textureFormat, frameBufferFormat)) != conversions.end();
}
} }
std::string getTempPath() std::string getTempPath()
......
...@@ -64,6 +64,10 @@ GLuint GetDepthSize(GLenum depthFormat); ...@@ -64,6 +64,10 @@ GLuint GetDepthSize(GLenum depthFormat);
GLuint GetStencilSize(GLenum stencilFormat); GLuint GetStencilSize(GLenum stencilFormat);
bool IsTriangleMode(GLenum drawMode); bool IsTriangleMode(GLenum drawMode);
bool IsValidES3FormatCombination(GLint internalformat, GLenum format, GLenum type, GLenum* err);
bool IsValidES3CompressedFormat(GLenum format);
bool IsValidES3CopyTexImageCombination(GLenum textureFormat, GLenum frameBufferFormat);
} }
std::string getTempPath(); std::string getTempPath();
......
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