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,45 +222,350 @@ bool validateSubImageParamsCube(bool compressed, GLsizei width, GLsizei height,
return true;
}
bool validateSubImageParams3D(bool compressed, GLsizei width, GLsizei height, GLsizei depth,
GLint xoffset, GLint yoffset,GLint zoffset, GLint level, GLenum format, GLenum type,
gl::Texture3D *texture)
bool validateES3TexImageFormat(gl::Context *context, GLenum target, GLint level, GLint internalformat, bool isCompressed, bool isSubImage,
GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
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)
{
return gl::error(GL_INVALID_OPERATION, false);
}
if (compressed != texture->isCompressed(level))
if (texture->isImmutable())
{
return gl::error(GL_INVALID_OPERATION, false);
}
if (format != GL_NONE)
// Validate texture formats
GLenum actualInternalFormat = isSubImage ? textureInternalFormat : internalformat;
if (isCompressed)
{
GLenum internalformat = gl::ConvertSizedInternalFormat(format, type);
if (internalformat != texture->getInternalFormat(level))
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 (compressed)
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 ((width % 4 != 0 && width != texture->getWidth(0)) ||
(height % 4 != 0 && height != texture->getHeight(0)))
if (isCompressed != textureCompressed)
{
return gl::error(GL_INVALID_OPERATION, false);
}
if (format != GL_NONE)
{
GLenum internalformat = gl::ConvertSizedInternalFormat(format, type);
if (internalformat != textureInternalFormat)
{
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 (width == 0 || height == 0 || depth == 0)
{
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);
}
if (xoffset + width > textureLevelWidth ||
yoffset + height > textureLevelHeight ||
zoffset + depth > textureLevelDepth)
{
return gl::error(GL_INVALID_VALUE, false);
}
}
if (xoffset + width > texture->getWidth(level) ||
yoffset + height > texture->getHeight(level) ||
zoffset + depth > texture->getDepth(level))
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;
}
......@@ -7172,9 +7477,31 @@ void __stdcall glTexImage3D(GLenum target, GLint level, GLint internalformat, GL
{
return gl::error(GL_INVALID_OPERATION);
}
}
UNIMPLEMENTED();
// 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();
break;
default:
return gl::error(GL_INVALID_ENUM);
}
}
}
catch(std::bad_alloc&)
{
......@@ -7199,9 +7526,37 @@ void __stdcall glTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint
{
return gl::error(GL_INVALID_OPERATION);
}
}
UNIMPLEMENTED();
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();
break;
default:
return gl::error(GL_INVALID_ENUM);
}
}
}
catch(std::bad_alloc&)
{
......@@ -7225,9 +7580,31 @@ void __stdcall glCopyTexSubImage3D(GLenum target, GLint level, GLint xoffset, GL
{
return gl::error(GL_INVALID_OPERATION);
}
}
UNIMPLEMENTED();
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();
break;
default:
return gl::error(GL_INVALID_ENUM);
}
texture->copySubImage(target, level, xoffset, yoffset, zoffset, x, y, width, height, framebuffer);
}
}
catch(std::bad_alloc&)
{
......@@ -7252,9 +7629,36 @@ void __stdcall glCompressedTexImage3D(GLenum target, GLint level, GLenum interna
{
return gl::error(GL_INVALID_OPERATION);
}
}
UNIMPLEMENTED();
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();
break;
default:
return gl::error(GL_INVALID_ENUM);
}
}
}
catch(std::bad_alloc&)
{
......@@ -7279,9 +7683,42 @@ void __stdcall glCompressedTexSubImage3D(GLenum target, GLint level, GLint xoffs
{
return gl::error(GL_INVALID_OPERATION);
}
}
UNIMPLEMENTED();
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();
break;
default:
return gl::error(GL_INVALID_ENUM);
}
}
}
catch(std::bad_alloc&)
{
......
......@@ -799,6 +799,259 @@ bool IsTriangleMode(GLenum drawMode)
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()
......
......@@ -64,6 +64,10 @@ GLuint GetDepthSize(GLenum depthFormat);
GLuint GetStencilSize(GLenum stencilFormat);
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();
......
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