blob: bbd51197a4dcca66da758bcdc2a467ad4ef9e241 [file] [log] [blame]
/*-------------------------------------------------------------------------
* drawElements Quality Program OpenGL ES 3.1 Module
* -------------------------------------------------
*
* Copyright 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*//*!
* \file
* \brief Texture level state query tests
*//*--------------------------------------------------------------------*/
#include "es31fTextureLevelStateQueryTests.hpp"
#include "glsStateQueryUtil.hpp"
#include "tcuTestLog.hpp"
#include "gluRenderContext.hpp"
#include "gluCallLogWrapper.hpp"
#include "gluTextureUtil.hpp"
#include "gluStrUtil.hpp"
#include "gluContextInfo.hpp"
#include "glwFunctions.hpp"
#include "glwEnums.hpp"
#include "deStringUtil.hpp"
#include "tcuTextureUtil.hpp"
namespace deqp
{
namespace gles31
{
namespace Functional
{
namespace
{
enum VerifierType
{
VERIFIER_INT = 0,
VERIFIER_FLOAT
};
struct TextureGenerationSpec
{
struct TextureLevelSpec
{
int width;
int height;
int depth;
int level;
glw::GLenum internalFormat;
bool compressed;
};
glw::GLenum bindTarget;
glw::GLenum queryTarget;
bool immutable;
bool fixedSamplePos; // !< fixed sample pos argument for multisample textures
int sampleCount;
std::vector<TextureLevelSpec> levels;
std::string description;
};
static bool textureTypeHasDepth (glw::GLenum textureBindTarget)
{
switch (textureBindTarget)
{
case GL_TEXTURE_2D: return false;
case GL_TEXTURE_3D: return true;
case GL_TEXTURE_2D_ARRAY: return true;
case GL_TEXTURE_CUBE_MAP: return false;
case GL_TEXTURE_2D_MULTISAMPLE: return false;
case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: return true;
default:
DE_ASSERT(DE_FALSE);
return false;
}
}
struct IntegerPrinter
{
static std::string getIntegerName (int v) { return de::toString(v); }
static std::string getFloatName (float v) { return de::toString(v); }
};
struct PixelFormatPrinter
{
static std::string getIntegerName (int v) { return de::toString(glu::getPixelFormatStr(v)); }
static std::string getFloatName (float v) { return de::toString(glu::getPixelFormatStr((int)v)); }
};
template <typename Printer>
static bool verifyTextureLevelParameterEqualWithPrinter (glu::CallLogWrapper& gl, glw::GLenum target, int level, glw::GLenum pname, int refValue, VerifierType type)
{
gl.getLog() << tcu::TestLog::Message << "Verifying " << glu::getTextureLevelParameterStr(pname) << ", expecting " << Printer::getIntegerName(refValue) << tcu::TestLog::EndMessage;
if (type == VERIFIER_INT)
{
gls::StateQueryUtil::StateQueryMemoryWriteGuard<int> result;
gl.glGetTexLevelParameteriv(target, level, pname, &result);
GLU_EXPECT_NO_ERROR(gl.glGetError(), "glGetTexLevelParameteriv");
if (result.isUndefined())
{
gl.getLog() << tcu::TestLog::Message << "Error: Get* did not write a value." << tcu::TestLog::EndMessage;
return false;
}
else if (result.isMemoryContaminated())
{
gl.getLog() << tcu::TestLog::Message << "Error: detected illegal memory write." << tcu::TestLog::EndMessage;
return false;
}
if (result == refValue)
return true;
gl.getLog() << tcu::TestLog::Message << "Error: Expected " << Printer::getIntegerName(refValue) << ", got " << Printer::getIntegerName(result) << tcu::TestLog::EndMessage;
return false;
}
else if (type == VERIFIER_FLOAT)
{
gls::StateQueryUtil::StateQueryMemoryWriteGuard<float> result;
gl.glGetTexLevelParameterfv(target, level, pname, &result);
GLU_EXPECT_NO_ERROR(gl.glGetError(), "glGetTexLevelParameterfv");
if (result.isUndefined())
{
gl.getLog() << tcu::TestLog::Message << "Error: Get* did not write a value." << tcu::TestLog::EndMessage;
return false;
}
else if (result.isMemoryContaminated())
{
gl.getLog() << tcu::TestLog::Message << "Error: detected illegal memory write." << tcu::TestLog::EndMessage;
return false;
}
if (result == (float)refValue)
return true;
gl.getLog() << tcu::TestLog::Message << "Error: Expected " << Printer::getIntegerName(refValue) << ", got " << Printer::getFloatName(result) << tcu::TestLog::EndMessage;
return false;
}
DE_ASSERT(DE_FALSE);
return false;
}
static bool verifyTextureLevelParameterEqual (glu::CallLogWrapper& gl, glw::GLenum target, int level, glw::GLenum pname, int refValue, VerifierType type)
{
return verifyTextureLevelParameterEqualWithPrinter<IntegerPrinter>(gl, target, level, pname, refValue, type);
}
static bool verifyTextureLevelParameterInternalFormatEqual (glu::CallLogWrapper& gl, glw::GLenum target, int level, glw::GLenum pname, int refValue, VerifierType type)
{
return verifyTextureLevelParameterEqualWithPrinter<PixelFormatPrinter>(gl, target, level, pname, refValue, type);
}
static bool verifyTextureLevelParameterGreaterOrEqual (glu::CallLogWrapper& gl, glw::GLenum target, int level, glw::GLenum pname, int refValue, VerifierType type)
{
gl.getLog() << tcu::TestLog::Message << "Verifying " << glu::getTextureLevelParameterStr(pname) << ", expecting " << refValue << " or greater" << tcu::TestLog::EndMessage;
if (type == VERIFIER_INT)
{
gls::StateQueryUtil::StateQueryMemoryWriteGuard<int> result;
gl.glGetTexLevelParameteriv(target, level, pname, &result);
GLU_EXPECT_NO_ERROR(gl.glGetError(), "glGetTexLevelParameteriv");
if (result.isUndefined())
{
gl.getLog() << tcu::TestLog::Message << "Error: Get* did not write a value." << tcu::TestLog::EndMessage;
return false;
}
else if (result.isMemoryContaminated())
{
gl.getLog() << tcu::TestLog::Message << "Error: detected illegal memory write." << tcu::TestLog::EndMessage;
return false;
}
if (result >= refValue)
return true;
gl.getLog() << tcu::TestLog::Message << "Error: Expected " << refValue << " or larger, got " << result << tcu::TestLog::EndMessage;
return false;
}
else if (type == VERIFIER_FLOAT)
{
gls::StateQueryUtil::StateQueryMemoryWriteGuard<float> result;
gl.glGetTexLevelParameterfv(target, level, pname, &result);
GLU_EXPECT_NO_ERROR(gl.glGetError(), "glGetTexLevelParameterfv");
if (result.isUndefined())
{
gl.getLog() << tcu::TestLog::Message << "Error: Get* did not write a value." << tcu::TestLog::EndMessage;
return false;
}
else if (result.isMemoryContaminated())
{
gl.getLog() << tcu::TestLog::Message << "Error: detected illegal memory write." << tcu::TestLog::EndMessage;
return false;
}
if (result >= (float)refValue)
return true;
gl.getLog() << tcu::TestLog::Message << "Error: Expected " << refValue << " or larger, got " << result << tcu::TestLog::EndMessage;
return false;
}
DE_ASSERT(DE_FALSE);
return false;
}
static bool verifyTextureLevelParameterInternalFormatAnyOf (glu::CallLogWrapper& gl, glw::GLenum target, int level, glw::GLenum pname, const int* refValues, int numRefValues, VerifierType type)
{
// Log what we try to do
{
tcu::MessageBuilder msg(&gl.getLog());
msg << "Verifying " << glu::getTextureLevelParameterStr(pname) << ", expecting any of {";
for (int ndx = 0; ndx < numRefValues; ++ndx)
{
if (ndx != 0)
msg << ", ";
msg << glu::getPixelFormatStr(refValues[ndx]);
}
msg << "}";
msg << tcu::TestLog::EndMessage;
}
// verify
if (type == VERIFIER_INT)
{
gls::StateQueryUtil::StateQueryMemoryWriteGuard<int> result;
gl.glGetTexLevelParameteriv(target, level, pname, &result);
GLU_EXPECT_NO_ERROR(gl.glGetError(), "glGetTexLevelParameteriv");
if (result.isUndefined())
{
gl.getLog() << tcu::TestLog::Message << "Error: Get* did not write a value." << tcu::TestLog::EndMessage;
return false;
}
else if (result.isMemoryContaminated())
{
gl.getLog() << tcu::TestLog::Message << "Error: detected illegal memory write." << tcu::TestLog::EndMessage;
return false;
}
for (int ndx = 0; ndx < numRefValues; ++ndx)
if (result == refValues[ndx])
return true;
gl.getLog() << tcu::TestLog::Message << "Error: got " << result << ", (" << glu::getPixelFormatStr(result) << ")" << tcu::TestLog::EndMessage;
return false;
}
else if (type == VERIFIER_FLOAT)
{
gls::StateQueryUtil::StateQueryMemoryWriteGuard<float> result;
gl.glGetTexLevelParameterfv(target, level, pname, &result);
GLU_EXPECT_NO_ERROR(gl.glGetError(), "glGetTexLevelParameterfv");
if (result.isUndefined())
{
gl.getLog() << tcu::TestLog::Message << "Error: Get* did not write a value." << tcu::TestLog::EndMessage;
return false;
}
else if (result.isMemoryContaminated())
{
gl.getLog() << tcu::TestLog::Message << "Error: detected illegal memory write." << tcu::TestLog::EndMessage;
return false;
}
for (int ndx = 0; ndx < numRefValues; ++ndx)
if (result == (float)refValues[ndx])
return true;
gl.getLog() << tcu::TestLog::Message << "Error: got " << result << ", (" << glu::getPixelFormatStr((int)result) << ")" << tcu::TestLog::EndMessage;
return false;
}
DE_ASSERT(DE_FALSE);
return false;
}
static void generateColorTextureGenerationGroup (std::vector<TextureGenerationSpec>& group, int max2DSamples, int max2DArraySamples, glw::GLenum internalFormat)
{
// initial setups
static const struct InitialSetup
{
glw::GLenum bindTarget;
glw::GLenum queryTarget;
bool immutable;
const char* description;
} initialSetups[] =
{
{ GL_TEXTURE_2D, GL_TEXTURE_2D, true, "GL_TEXTURE_2D, initial values" },
{ GL_TEXTURE_3D, GL_TEXTURE_3D, true, "GL_TEXTURE_3D, initial values" },
{ GL_TEXTURE_2D_ARRAY, GL_TEXTURE_2D_ARRAY, true, "GL_TEXTURE_2D_ARRAY, initial values" },
{ GL_TEXTURE_CUBE_MAP, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, true, "GL_TEXTURE_CUBE_MAP, initial values" },
{ GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_2D_MULTISAMPLE, true, "GL_TEXTURE_2D_MULTISAMPLE, initial values" },
{ GL_TEXTURE_2D_MULTISAMPLE_ARRAY, GL_TEXTURE_2D_MULTISAMPLE_ARRAY,true, "GL_TEXTURE_2D_MULTISAMPLE_ARRAY, initial values" },
};
// multisample setups
static const struct MultisampleSetup
{
glw::GLenum bindTarget;
int sampleCount;
const char* description;
} msSetups[] =
{
{ GL_TEXTURE_2D_MULTISAMPLE, 1, "immutable GL_TEXTURE_2D_MULTISAMPLE, low sample count" },
{ GL_TEXTURE_2D_MULTISAMPLE, max2DSamples, "immutable GL_TEXTURE_2D_MULTISAMPLE, max sample count" },
{ GL_TEXTURE_2D_MULTISAMPLE_ARRAY, 1, "immutable GL_TEXTURE_2D_MULTISAMPLE_ARRAY, low sample count" },
{ GL_TEXTURE_2D_MULTISAMPLE_ARRAY, max2DArraySamples, "immutable GL_TEXTURE_2D_MULTISAMPLE_ARRAY, max sample count" },
};
// normal setups
static const struct NormalSetup
{
glw::GLenum bindTarget;
glw::GLenum queryTarget;
bool immutable;
int level;
const char* description;
} normalSetups[] =
{
{ GL_TEXTURE_2D, GL_TEXTURE_2D, true, 0, "immutable GL_TEXTURE_2D" },
{ GL_TEXTURE_3D, GL_TEXTURE_3D, true, 0, "immutable GL_TEXTURE_3D" },
{ GL_TEXTURE_2D_ARRAY, GL_TEXTURE_2D_ARRAY, true, 0, "immutable GL_TEXTURE_2D_ARRAY" },
{ GL_TEXTURE_CUBE_MAP, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, true, 0, "immutable GL_TEXTURE_CUBE_MAP" },
{ GL_TEXTURE_2D, GL_TEXTURE_2D, false, 0, "mutable GL_TEXTURE_2D" },
{ GL_TEXTURE_3D, GL_TEXTURE_3D, false, 0, "mutable GL_TEXTURE_3D" },
{ GL_TEXTURE_2D_ARRAY, GL_TEXTURE_2D_ARRAY, false, 0, "mutable GL_TEXTURE_2D_ARRAY" },
{ GL_TEXTURE_CUBE_MAP, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, false, 0, "mutable GL_TEXTURE_CUBE_MAP" },
{ GL_TEXTURE_2D, GL_TEXTURE_2D, false, 3, "mutable GL_TEXTURE_2D, mip level 3" },
{ GL_TEXTURE_3D, GL_TEXTURE_3D, false, 3, "mutable GL_TEXTURE_3D, mip level 3" },
{ GL_TEXTURE_2D_ARRAY, GL_TEXTURE_2D_ARRAY, false, 3, "mutable GL_TEXTURE_2D_ARRAY, mip level 3" },
{ GL_TEXTURE_CUBE_MAP, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, false, 3, "mutable GL_TEXTURE_CUBE_MAP, mip level 3" },
};
for (int initialSetupNdx = 0; initialSetupNdx < DE_LENGTH_OF_ARRAY(initialSetups); ++initialSetupNdx)
{
TextureGenerationSpec texGen;
texGen.bindTarget = initialSetups[initialSetupNdx].bindTarget;
texGen.queryTarget = initialSetups[initialSetupNdx].queryTarget;
texGen.immutable = initialSetups[initialSetupNdx].immutable;
texGen.sampleCount = 0;
texGen.description = initialSetups[initialSetupNdx].description;
group.push_back(texGen);
}
for (int msSetupNdx = 0; msSetupNdx < DE_LENGTH_OF_ARRAY(msSetups); ++msSetupNdx)
{
TextureGenerationSpec texGen;
TextureGenerationSpec::TextureLevelSpec level;
texGen.bindTarget = msSetups[msSetupNdx].bindTarget;
texGen.queryTarget = msSetups[msSetupNdx].bindTarget;
texGen.immutable = true;
texGen.sampleCount = msSetups[msSetupNdx].sampleCount;
texGen.fixedSamplePos = false;
texGen.description = msSetups[msSetupNdx].description;
level.width = 32;
level.height = 32;
level.depth = (textureTypeHasDepth(texGen.bindTarget)) ? (8) : (0);
level.level = 0;
level.internalFormat = internalFormat;
level.compressed = false;
texGen.levels.push_back(level);
group.push_back(texGen);
}
for (int normalSetupNdx = 0; normalSetupNdx < DE_LENGTH_OF_ARRAY(normalSetups); ++normalSetupNdx)
{
TextureGenerationSpec texGen;
TextureGenerationSpec::TextureLevelSpec level;
texGen.bindTarget = normalSetups[normalSetupNdx].bindTarget;
texGen.queryTarget = normalSetups[normalSetupNdx].queryTarget;
texGen.immutable = normalSetups[normalSetupNdx].immutable;
texGen.sampleCount = 0;
texGen.description = normalSetups[normalSetupNdx].description;
level.width = 32;
level.height = 32;
level.depth = (textureTypeHasDepth(texGen.bindTarget)) ? (8) : (0);
level.level = normalSetups[normalSetupNdx].level;
level.internalFormat = internalFormat;
level.compressed = false;
texGen.levels.push_back(level);
group.push_back(texGen);
}
}
static void generateColorMultisampleTextureGenerationGroup (std::vector<TextureGenerationSpec>& group, int max2DSamples, int max2DArraySamples, glw::GLenum internalFormat)
{
// multisample setups
static const struct MultisampleSetup
{
glw::GLenum bindTarget;
bool initialized;
int sampleCount;
bool fixedSamples;
const char* description;
} msSetups[] =
{
{ GL_TEXTURE_2D_MULTISAMPLE, false, 0, false, "GL_TEXTURE_2D_MULTISAMPLE, initial values" },
{ GL_TEXTURE_2D_MULTISAMPLE, true, 1, false, "GL_TEXTURE_2D_MULTISAMPLE, low sample count" },
{ GL_TEXTURE_2D_MULTISAMPLE, true, max2DSamples, false, "GL_TEXTURE_2D_MULTISAMPLE, max sample count" },
{ GL_TEXTURE_2D_MULTISAMPLE, true, max2DSamples, true, "GL_TEXTURE_2D_MULTISAMPLE, fixed sample positions" },
{ GL_TEXTURE_2D_MULTISAMPLE_ARRAY, false, 0, false, "GL_TEXTURE_2D_MULTISAMPLE_ARRAY, initial values" },
{ GL_TEXTURE_2D_MULTISAMPLE_ARRAY, true, 1, false, "GL_TEXTURE_2D_MULTISAMPLE_ARRAY, low sample count" },
{ GL_TEXTURE_2D_MULTISAMPLE_ARRAY, true, max2DArraySamples, false, "GL_TEXTURE_2D_MULTISAMPLE_ARRAY, max sample count" },
{ GL_TEXTURE_2D_MULTISAMPLE_ARRAY, true, max2DArraySamples, true, "GL_TEXTURE_2D_MULTISAMPLE_ARRAY, fixed sample positions" },
};
for (int msSetupNdx = 0; msSetupNdx < DE_LENGTH_OF_ARRAY(msSetups); ++msSetupNdx)
{
TextureGenerationSpec texGen;
texGen.bindTarget = msSetups[msSetupNdx].bindTarget;
texGen.queryTarget = msSetups[msSetupNdx].bindTarget;
texGen.immutable = true;
texGen.sampleCount = msSetups[msSetupNdx].sampleCount;
texGen.fixedSamplePos = msSetups[msSetupNdx].fixedSamples;
texGen.description = msSetups[msSetupNdx].description;
if (msSetups[msSetupNdx].initialized)
{
TextureGenerationSpec::TextureLevelSpec level;
level.width = 32;
level.height = 32;
level.depth = (textureTypeHasDepth(texGen.bindTarget)) ? (8) : (0);
level.level = 0;
level.internalFormat = internalFormat;
level.compressed = false;
texGen.levels.push_back(level);
}
group.push_back(texGen);
}
}
static void generateInternalFormatTextureGenerationGroup (std::vector<TextureGenerationSpec>& group)
{
// initial setups
static const struct InitialSetup
{
glw::GLenum bindTarget;
glw::GLenum queryTarget;
bool immutable;
const char* description;
} initialSetups[] =
{
{ GL_TEXTURE_2D, GL_TEXTURE_2D, true, "GL_TEXTURE_2D, initial values" },
{ GL_TEXTURE_3D, GL_TEXTURE_3D, true, "GL_TEXTURE_3D, initial values" },
{ GL_TEXTURE_2D_ARRAY, GL_TEXTURE_2D_ARRAY, true, "GL_TEXTURE_2D_ARRAY, initial values" },
{ GL_TEXTURE_CUBE_MAP, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, true, "GL_TEXTURE_CUBE_MAP, initial values" },
{ GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_2D_MULTISAMPLE, true, "GL_TEXTURE_2D_MULTISAMPLE, initial values" },
{ GL_TEXTURE_2D_MULTISAMPLE_ARRAY, GL_TEXTURE_2D_MULTISAMPLE_ARRAY,true, "GL_TEXTURE_2D_MULTISAMPLE_ARRAY, initial values" },
};
// Renderable internal formats (subset)
static const glw::GLenum renderableInternalFormats[] =
{
GL_R8, GL_RGB565, GL_RGB5_A1, GL_RGB10_A2UI, GL_SRGB8_ALPHA8, GL_RG32I,
GL_RGBA16UI, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT24,
GL_DEPTH_COMPONENT32F, GL_DEPTH24_STENCIL8, GL_DEPTH32F_STENCIL8
};
// Internal formats
static const glw::GLenum internalFormats[] =
{
GL_R8, GL_R8_SNORM, GL_RG8, GL_RG8_SNORM, GL_RGB8, GL_RGB8_SNORM, GL_RGB565, GL_RGBA4, GL_RGB5_A1,
GL_RGBA8, GL_RGBA8_SNORM, GL_RGB10_A2, GL_RGB10_A2UI, GL_SRGB8, GL_SRGB8_ALPHA8, GL_R16F, GL_RG16F,
GL_RGB16F, GL_RGBA16F, GL_R32F, GL_RG32F, GL_RGB32F, GL_RGBA32F, GL_R11F_G11F_B10F, GL_RGB9_E5, GL_R8I,
GL_R8UI, GL_R16I, GL_R16UI, GL_R32I, GL_R32UI, GL_RG8I, GL_RG8UI, GL_RG16I, GL_RG16UI, GL_RG32I, GL_RG32UI,
GL_RGB8I, GL_RGB8UI, GL_RGB16I, GL_RGB16UI, GL_RGB32I, GL_RGB32UI, GL_RGBA8I, GL_RGBA8UI, GL_RGBA16I,
GL_RGBA16UI, GL_RGBA32I, GL_RGBA32UI,
GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT16,
GL_DEPTH32F_STENCIL8, GL_DEPTH24_STENCIL8
};
for (int initialSetupNdx = 0; initialSetupNdx < DE_LENGTH_OF_ARRAY(initialSetups); ++initialSetupNdx)
{
TextureGenerationSpec texGen;
texGen.bindTarget = initialSetups[initialSetupNdx].bindTarget;
texGen.queryTarget = initialSetups[initialSetupNdx].queryTarget;
texGen.immutable = initialSetups[initialSetupNdx].immutable;
texGen.sampleCount = 0;
texGen.description = initialSetups[initialSetupNdx].description;
group.push_back(texGen);
}
// test some color/stencil/depth renderable with multisample texture2d
for (int internalFormatNdx = 0; internalFormatNdx < DE_LENGTH_OF_ARRAY(renderableInternalFormats); ++internalFormatNdx)
{
TextureGenerationSpec texGen;
TextureGenerationSpec::TextureLevelSpec level;
texGen.bindTarget = GL_TEXTURE_2D_MULTISAMPLE;
texGen.queryTarget = GL_TEXTURE_2D_MULTISAMPLE;
texGen.immutable = true;
texGen.sampleCount = 1;
texGen.fixedSamplePos = false;
texGen.description = std::string() + "GL_TEXTURE_2D_MULTISAMPLE, internal format " + glu::getPixelFormatName(renderableInternalFormats[internalFormatNdx]);
level.width = 32;
level.height = 32;
level.depth = 0;
level.level = 0;
level.internalFormat = renderableInternalFormats[internalFormatNdx];
level.compressed = false;
texGen.levels.push_back(level);
group.push_back(texGen);
}
// test all with texture2d
for (int internalFormatNdx = 0; internalFormatNdx < DE_LENGTH_OF_ARRAY(internalFormats); ++internalFormatNdx)
{
TextureGenerationSpec texGen;
TextureGenerationSpec::TextureLevelSpec level;
texGen.bindTarget = GL_TEXTURE_2D;
texGen.queryTarget = GL_TEXTURE_2D;
texGen.immutable = true;
texGen.sampleCount = 0;
texGen.description = std::string() + "GL_TEXTURE_2D, internal format " + glu::getPixelFormatName(internalFormats[internalFormatNdx]);
level.width = 32;
level.height = 32;
level.depth = 0;
level.level = 0;
level.internalFormat = internalFormats[internalFormatNdx];
level.compressed = false;
texGen.levels.push_back(level);
group.push_back(texGen);
}
// test rgba8 with mip level 3
{
TextureGenerationSpec texGen;
TextureGenerationSpec::TextureLevelSpec level;
texGen.bindTarget = GL_TEXTURE_2D;
texGen.queryTarget = GL_TEXTURE_2D;
texGen.immutable = false;
texGen.sampleCount = 0;
texGen.description = std::string() + "GL_TEXTURE_2D, internal format GL_RGBA8";
level.width = 32;
level.height = 32;
level.depth = 0;
level.level = 3;
level.internalFormat = GL_RGBA8;
level.compressed = false;
texGen.levels.push_back(level);
group.push_back(texGen);
}
}
static void generateCompressedTextureGenerationGroup (std::vector<TextureGenerationSpec>& group)
{
// initial ms
{
TextureGenerationSpec texGen;
texGen.bindTarget = GL_TEXTURE_2D_MULTISAMPLE;
texGen.queryTarget = GL_TEXTURE_2D_MULTISAMPLE;
texGen.immutable = true;
texGen.sampleCount = 0;
texGen.description = "GL_TEXTURE_2D_MULTISAMPLE, initial values";
group.push_back(texGen);
}
// initial non-ms
{
TextureGenerationSpec texGen;
texGen.bindTarget = GL_TEXTURE_2D;
texGen.queryTarget = GL_TEXTURE_2D;
texGen.immutable = true;
texGen.sampleCount = 0;
texGen.description = "GL_TEXTURE_2D, initial values";
group.push_back(texGen);
}
// compressed
{
TextureGenerationSpec texGen;
TextureGenerationSpec::TextureLevelSpec level;
texGen.bindTarget = GL_TEXTURE_2D;
texGen.queryTarget = GL_TEXTURE_2D;
texGen.immutable = false;
texGen.sampleCount = 0;
texGen.description = "GL_TEXTURE_2D, compressed";
level.width = 32;
level.height = 32;
level.depth = 0;
level.level = 0;
level.internalFormat = GL_COMPRESSED_RGB8_ETC2;
level.compressed = true;
texGen.levels.push_back(level);
group.push_back(texGen);
}
}
void applyTextureGenergationSpec (glu::CallLogWrapper& gl, const TextureGenerationSpec& spec)
{
DE_ASSERT(!(spec.immutable && spec.levels.size() > 1)); // !< immutable textures have only one level
for (int levelNdx = 0; levelNdx < (int)spec.levels.size(); ++levelNdx)
{
const glu::TransferFormat transferFormat = (spec.levels[levelNdx].compressed) ? (glu::TransferFormat()) : (glu::getTransferFormat(glu::mapGLInternalFormat(spec.levels[levelNdx].internalFormat)));
if (spec.immutable && !spec.levels[levelNdx].compressed && spec.bindTarget == GL_TEXTURE_2D)
gl.glTexStorage2D(spec.bindTarget, 1, spec.levels[levelNdx].internalFormat, spec.levels[levelNdx].width, spec.levels[levelNdx].height);
else if (spec.immutable && !spec.levels[levelNdx].compressed && spec.bindTarget == GL_TEXTURE_3D)
gl.glTexStorage3D(spec.bindTarget, 1, spec.levels[levelNdx].internalFormat, spec.levels[levelNdx].width, spec.levels[levelNdx].height, spec.levels[levelNdx].depth);
else if (spec.immutable && !spec.levels[levelNdx].compressed && spec.bindTarget == GL_TEXTURE_2D_ARRAY)
gl.glTexStorage3D(spec.bindTarget, 1, spec.levels[levelNdx].internalFormat, spec.levels[levelNdx].width, spec.levels[levelNdx].height, spec.levels[levelNdx].depth);
else if (spec.immutable && !spec.levels[levelNdx].compressed && spec.bindTarget == GL_TEXTURE_CUBE_MAP)
gl.glTexStorage2D(spec.bindTarget, 1, spec.levels[levelNdx].internalFormat, spec.levels[levelNdx].width, spec.levels[levelNdx].height);
else if (spec.immutable && !spec.levels[levelNdx].compressed && spec.bindTarget == GL_TEXTURE_2D_MULTISAMPLE)
gl.glTexStorage2DMultisample(spec.bindTarget, spec.sampleCount, spec.levels[levelNdx].internalFormat, spec.levels[levelNdx].width, spec.levels[levelNdx].height, (spec.fixedSamplePos) ? (GL_TRUE) : (GL_FALSE));
else if (spec.immutable && !spec.levels[levelNdx].compressed && spec.bindTarget == GL_TEXTURE_2D_MULTISAMPLE_ARRAY)
gl.glTexStorage3DMultisample(spec.bindTarget, spec.sampleCount, spec.levels[levelNdx].internalFormat, spec.levels[levelNdx].width, spec.levels[levelNdx].height, spec.levels[levelNdx].depth, (spec.fixedSamplePos) ? (GL_TRUE) : (GL_FALSE));
else if (!spec.immutable && !spec.levels[levelNdx].compressed && spec.bindTarget == GL_TEXTURE_2D)
gl.glTexImage2D(spec.bindTarget, spec.levels[levelNdx].level, spec.levels[levelNdx].internalFormat, spec.levels[levelNdx].width, spec.levels[levelNdx].height, 0, transferFormat.format, transferFormat.dataType, DE_NULL);
else if (!spec.immutable && !spec.levels[levelNdx].compressed && spec.bindTarget == GL_TEXTURE_3D)
gl.glTexImage3D(spec.bindTarget, spec.levels[levelNdx].level, spec.levels[levelNdx].internalFormat, spec.levels[levelNdx].width, spec.levels[levelNdx].height, spec.levels[levelNdx].depth, 0, transferFormat.format, transferFormat.dataType, DE_NULL);
else if (!spec.immutable && !spec.levels[levelNdx].compressed && spec.bindTarget == GL_TEXTURE_2D_ARRAY)
gl.glTexImage3D(spec.bindTarget, spec.levels[levelNdx].level, spec.levels[levelNdx].internalFormat, spec.levels[levelNdx].width, spec.levels[levelNdx].height, spec.levels[levelNdx].depth, 0, transferFormat.format, transferFormat.dataType, DE_NULL);
else if (!spec.immutable && !spec.levels[levelNdx].compressed && spec.bindTarget == GL_TEXTURE_CUBE_MAP)
gl.glTexImage2D(spec.queryTarget, spec.levels[levelNdx].level, spec.levels[levelNdx].internalFormat, spec.levels[levelNdx].width, spec.levels[levelNdx].height, 0, transferFormat.format, transferFormat.dataType, DE_NULL);
else if (!spec.immutable && spec.levels[levelNdx].compressed && spec.bindTarget == GL_TEXTURE_2D)
{
DE_ASSERT(spec.levels[levelNdx].width == 32);
DE_ASSERT(spec.levels[levelNdx].height == 32);
DE_ASSERT(spec.levels[levelNdx].internalFormat == GL_COMPRESSED_RGB8_ETC2);
static const deUint8 buffer[64 * 8] = { 0 };
gl.glCompressedTexImage2D(spec.bindTarget, spec.levels[levelNdx].level, spec.levels[levelNdx].internalFormat, spec.levels[levelNdx].width, spec.levels[levelNdx].height, 0, sizeof(buffer), buffer);
}
else
DE_ASSERT(DE_FALSE);
GLU_EXPECT_NO_ERROR(gl.glGetError(), "set level");
}
}
class TextureLevelCase : public TestCase
{
public:
TextureLevelCase (Context& ctx, const char* name, const char* desc, VerifierType type);
~TextureLevelCase (void);
void init (void);
void deinit (void);
IterateResult iterate (void);
protected:
void getFormatSamples (glw::GLenum target, std::vector<int>& samples);
bool testConfig (const TextureGenerationSpec& spec);
virtual bool checkTextureState (glu::CallLogWrapper& gl, const TextureGenerationSpec& spec) = 0;
virtual void generateTestIterations (std::vector<TextureGenerationSpec>& iterations) = 0;
const VerifierType m_type;
const glw::GLenum m_internalFormat;
glw::GLuint m_texture;
private:
int m_iteration;
std::vector<TextureGenerationSpec> m_iterations;
bool m_allIterationsOk;
std::vector<int> m_failedIterations;
};
TextureLevelCase::TextureLevelCase (Context& ctx, const char* name, const char* desc, VerifierType type)
: TestCase (ctx, name, desc)
, m_type (type)
, m_internalFormat (GL_RGBA8)
, m_texture (0)
, m_iteration (0)
, m_allIterationsOk (true)
{
}
TextureLevelCase::~TextureLevelCase (void)
{
deinit();
}
void TextureLevelCase::init (void)
{
generateTestIterations(m_iterations);
}
void TextureLevelCase::deinit (void)
{
if (m_texture)
{
m_context.getRenderContext().getFunctions().deleteTextures(1, &m_texture);
m_texture = 0;
}
}
void TextureLevelCase::getFormatSamples (glw::GLenum target, std::vector<int>& samples)
{
const glw::Functions gl = m_context.getRenderContext().getFunctions();
int sampleCount = -1;
// fake values for unsupported queries to simplify code. The extension will be checked later for each config anyway (in testConfig())
if (target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY && !m_context.getContextInfo().isExtensionSupported("GL_OES_texture_storage_multisample_2d_array"))
{
samples.resize(1);
samples[0] = 0;
return;
}
gl.getInternalformativ(target, m_internalFormat, GL_NUM_SAMPLE_COUNTS, 1, &sampleCount);
if (sampleCount < 0)
throw tcu::TestError("internal format query failed");
samples.resize(sampleCount);
if (sampleCount > 0)
{
gl.getInternalformativ(target, m_internalFormat, GL_SAMPLES, sampleCount, &samples[0]);
GLU_EXPECT_NO_ERROR(gl.getError(), "get max samples");
}
}
TextureLevelCase::IterateResult TextureLevelCase::iterate (void)
{
const bool result = testConfig(m_iterations[m_iteration]);
if (!result)
{
m_failedIterations.push_back(m_iteration);
m_allIterationsOk = false;
}
if (++m_iteration < (int)m_iterations.size())
return CONTINUE;
if (m_allIterationsOk)
m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
else
{
tcu::MessageBuilder msg(&m_testCtx.getLog());
msg << "Following iteration(s) failed: ";
for (int ndx = 0; ndx < (int)m_failedIterations.size(); ++ndx)
{
if (ndx)
msg << ", ";
msg << (m_failedIterations[ndx] + 1);
}
msg << tcu::TestLog::EndMessage;
m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "One or more iterations failed");
}
return STOP;
}
bool TextureLevelCase::testConfig (const TextureGenerationSpec& spec)
{
const tcu::ScopedLogSection section(m_testCtx.getLog(), "Iteration", std::string() + "Iteration " + de::toString(m_iteration+1) + "/" + de::toString((int)m_iterations.size()) + " - " + spec.description);
glu::CallLogWrapper gl (m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
bool result;
// skip unsupported targets
if (spec.bindTarget == GL_TEXTURE_2D_MULTISAMPLE_ARRAY && !m_context.getContextInfo().isExtensionSupported("GL_OES_texture_storage_multisample_2d_array"))
{
m_testCtx.getLog() << tcu::TestLog::Message << "Target binding requires GL_OES_texture_storage_multisample_2d_array extension, skipping." << tcu::TestLog::EndMessage;
return true;
}
// test supported targets
gl.enableLogging(true);
gl.glGenTextures(1, &m_texture);
gl.glBindTexture(spec.bindTarget, m_texture);
GLU_EXPECT_NO_ERROR(gl.glGetError(), "gen tex");
// Set the state
applyTextureGenergationSpec(gl, spec);
// Verify the state
result = checkTextureState(gl, spec);
gl.glDeleteTextures(1, &m_texture);
m_texture = 0;
return result;
}
/*--------------------------------------------------------------------*//*!
* \brief Test all texture targets
*//*--------------------------------------------------------------------*/
class TextureLevelCommonCase : public TextureLevelCase
{
public:
TextureLevelCommonCase (Context& ctx, const char* name, const char* desc, VerifierType type);
protected:
virtual void generateTestIterations (std::vector<TextureGenerationSpec>& iterations);
};
TextureLevelCommonCase::TextureLevelCommonCase (Context& ctx, const char* name, const char* desc, VerifierType type)
: TextureLevelCase(ctx, name, desc, type)
{
}
void TextureLevelCommonCase::generateTestIterations (std::vector<TextureGenerationSpec>& iterations)
{
std::vector<int> texture2DSamples;
std::vector<int> texture2DArraySamples;
getFormatSamples(GL_TEXTURE_2D_MULTISAMPLE, texture2DSamples);
getFormatSamples(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, texture2DArraySamples);
TCU_CHECK(!texture2DSamples.empty());
TCU_CHECK(!texture2DArraySamples.empty());
// gen iterations
generateColorTextureGenerationGroup(iterations, texture2DSamples[0], texture2DArraySamples[0], m_internalFormat);
}
/*--------------------------------------------------------------------*//*!
* \brief Test all multisample texture targets
*//*--------------------------------------------------------------------*/
class TextureLevelMultisampleCase : public TextureLevelCase
{
public:
TextureLevelMultisampleCase (Context& ctx, const char* name, const char* desc, VerifierType type);
protected:
virtual void generateTestIterations (std::vector<TextureGenerationSpec>& iterations);
};
TextureLevelMultisampleCase::TextureLevelMultisampleCase (Context& ctx, const char* name, const char* desc, VerifierType type)
: TextureLevelCase(ctx, name, desc, type)
{
}
void TextureLevelMultisampleCase::generateTestIterations (std::vector<TextureGenerationSpec>& iterations)
{
std::vector<int> texture2DSamples;
std::vector<int> texture2DArraySamples;
getFormatSamples(GL_TEXTURE_2D_MULTISAMPLE, texture2DSamples);
getFormatSamples(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, texture2DArraySamples);
TCU_CHECK(!texture2DSamples.empty());
TCU_CHECK(!texture2DArraySamples.empty());
// gen iterations
generateColorMultisampleTextureGenerationGroup(iterations, texture2DSamples[0], texture2DArraySamples[0], m_internalFormat);
}
class TextureLevelSampleCase : public TextureLevelMultisampleCase
{
public:
TextureLevelSampleCase (Context& ctx, const char* name, const char* desc, VerifierType type)
: TextureLevelMultisampleCase(ctx, name, desc, type)
{
}
private:
bool checkTextureState (glu::CallLogWrapper& gl, const TextureGenerationSpec& spec)
{
const int queryLevel = (spec.levels.empty()) ? (0) : (spec.levels[0].level);
const int refValue = (spec.levels.empty()) ? (0) : (spec.sampleCount);
return verifyTextureLevelParameterGreaterOrEqual(gl, spec.queryTarget, queryLevel, GL_TEXTURE_SAMPLES, refValue, m_type);
}
};
class TextureLevelFixedSamplesCase : public TextureLevelMultisampleCase
{
public:
TextureLevelFixedSamplesCase (Context& ctx, const char* name, const char* desc, VerifierType type)
: TextureLevelMultisampleCase(ctx, name, desc, type)
{
}
private:
bool checkTextureState (glu::CallLogWrapper& gl, const TextureGenerationSpec& spec)
{
const int queryLevel = 0;
const int refValue = (spec.levels.empty()) ? (1) : ((spec.fixedSamplePos) ? (1) : (0));
return verifyTextureLevelParameterEqual(gl, spec.queryTarget, queryLevel, GL_TEXTURE_FIXED_SAMPLE_LOCATIONS, refValue, m_type);
}
};
class TextureLevelWidthCase : public TextureLevelCommonCase
{
public:
TextureLevelWidthCase (Context& ctx, const char* name, const char* desc, VerifierType type)
: TextureLevelCommonCase(ctx, name, desc, type)
{
}
private:
bool checkTextureState (glu::CallLogWrapper& gl, const TextureGenerationSpec& spec)
{
const int initialValue = 0;
bool allOk = true;
if (spec.levels.empty())
{
const int queryLevel = 0;
const int refValue = initialValue;
allOk &= verifyTextureLevelParameterEqual(gl, spec.queryTarget, queryLevel, GL_TEXTURE_WIDTH, refValue, m_type);
}
else
{
for (int levelNdx = 0; levelNdx < (int)spec.levels.size(); ++levelNdx)
{
const int queryLevel = spec.levels[levelNdx].level;
const int refValue = spec.levels[levelNdx].width;
allOk &= verifyTextureLevelParameterEqual(gl, spec.queryTarget, queryLevel, GL_TEXTURE_WIDTH, refValue, m_type);
}
}
return allOk;
}
};
class TextureLevelHeightCase : public TextureLevelCommonCase
{
public:
TextureLevelHeightCase (Context& ctx, const char* name, const char* desc, VerifierType type)
: TextureLevelCommonCase(ctx, name, desc, type)
{
}
private:
bool checkTextureState (glu::CallLogWrapper& gl, const TextureGenerationSpec& spec)
{
const int initialValue = 0;
bool allOk = true;
if (spec.levels.empty())
{
const int queryLevel = 0;
const int refValue = initialValue;
allOk &= verifyTextureLevelParameterEqual(gl, spec.queryTarget, queryLevel, GL_TEXTURE_HEIGHT, refValue, m_type);
}
else
{
for (int levelNdx = 0; levelNdx < (int)spec.levels.size(); ++levelNdx)
{
const int queryLevel = spec.levels[levelNdx].level;
const int refValue = spec.levels[levelNdx].height;
allOk &= verifyTextureLevelParameterEqual(gl, spec.queryTarget, queryLevel, GL_TEXTURE_HEIGHT, refValue, m_type);
}
}
return allOk;
}
};
class TextureLevelDepthCase : public TextureLevelCommonCase
{
public:
TextureLevelDepthCase (Context& ctx, const char* name, const char* desc, VerifierType type)
: TextureLevelCommonCase(ctx, name, desc, type)
{
}
private:
void generateTestIterations (std::vector<TextureGenerationSpec>& iterations)
{
std::vector<TextureGenerationSpec> allIterations;
this->TextureLevelCommonCase::generateTestIterations(allIterations);
// test only cases with depth
for (int ndx = 0; ndx < (int)allIterations.size(); ++ndx)
if (textureTypeHasDepth(allIterations[ndx].bindTarget))
iterations.push_back(allIterations[ndx]);
}
bool checkTextureState (glu::CallLogWrapper& gl, const TextureGenerationSpec& spec)
{
const int initialValue = 0;
bool allOk = true;
if (spec.levels.empty())
{
const int queryLevel = 0;
const int refValue = initialValue;
allOk &= verifyTextureLevelParameterEqual(gl, spec.queryTarget, queryLevel, GL_TEXTURE_DEPTH, refValue, m_type);
}
else
{
for (int levelNdx = 0; levelNdx < (int)spec.levels.size(); ++levelNdx)
{
const int queryLevel = spec.levels[levelNdx].level;
const int refValue = spec.levels[levelNdx].depth;
allOk &= verifyTextureLevelParameterEqual(gl, spec.queryTarget, queryLevel, GL_TEXTURE_DEPTH, refValue, m_type);
}
}
return allOk;
}
};
class TextureLevelInternalFormatCase : public TextureLevelCase
{
public:
TextureLevelInternalFormatCase (Context& ctx, const char* name, const char* desc, VerifierType type)
: TextureLevelCase(ctx, name, desc, type)
{
}
private:
void generateTestIterations (std::vector<TextureGenerationSpec>& iterations)
{
generateInternalFormatTextureGenerationGroup(iterations);
}
bool checkTextureState (glu::CallLogWrapper& gl, const TextureGenerationSpec& spec)
{
bool allOk = true;
if (spec.levels.empty())
{
const int queryLevel = 0;
const int initialValues[2] = { GL_RGBA, GL_R8 };
allOk &= verifyTextureLevelParameterInternalFormatAnyOf(gl, spec.queryTarget, queryLevel, GL_TEXTURE_INTERNAL_FORMAT, initialValues, DE_LENGTH_OF_ARRAY(initialValues), m_type);
}
else
{
for (int levelNdx = 0; levelNdx < (int)spec.levels.size(); ++levelNdx)
{
const int queryLevel = spec.levels[levelNdx].level;
const int refValue = spec.levels[levelNdx].internalFormat;
allOk &= verifyTextureLevelParameterInternalFormatEqual(gl, spec.queryTarget, queryLevel, GL_TEXTURE_INTERNAL_FORMAT, refValue, m_type);
}
}
return allOk;
}
};
class TextureLevelSizeCase : public TextureLevelCase
{
public:
TextureLevelSizeCase (Context& ctx, const char* name, const char* desc, VerifierType type, glw::GLenum pname);
private:
void generateTestIterations (std::vector<TextureGenerationSpec>& iterations);
bool checkTextureState (glu::CallLogWrapper& gl, const TextureGenerationSpec& spec);
int getMinimumComponentResolution (glw::GLenum internalFormat);
const glw::GLenum m_pname;
};
TextureLevelSizeCase::TextureLevelSizeCase (Context& ctx, const char* name, const char* desc, VerifierType type, glw::GLenum pname)
: TextureLevelCase (ctx, name, desc, type)
, m_pname (pname)
{
}
void TextureLevelSizeCase::generateTestIterations (std::vector<TextureGenerationSpec>& iterations)
{
generateInternalFormatTextureGenerationGroup(iterations);
}
bool TextureLevelSizeCase::checkTextureState (glu::CallLogWrapper& gl, const TextureGenerationSpec& spec)
{
bool allOk = true;
if (spec.levels.empty())
{
allOk &= verifyTextureLevelParameterEqual(gl, spec.queryTarget, 0, m_pname, 0, m_type);
}
else
{
for (int levelNdx = 0; levelNdx < (int)spec.levels.size(); ++levelNdx)
{
const int queryLevel = spec.levels[levelNdx].level;
const int refValue = getMinimumComponentResolution(spec.levels[levelNdx].internalFormat);
allOk &= verifyTextureLevelParameterGreaterOrEqual(gl, spec.queryTarget, queryLevel, m_pname, refValue, m_type);
}
}
return allOk;
}
int TextureLevelSizeCase::getMinimumComponentResolution (glw::GLenum internalFormat)
{
const tcu::TextureFormat format = glu::mapGLInternalFormat(internalFormat);
const tcu::IVec4 channelBitDepth = tcu::getTextureFormatBitDepth(format);
switch (m_pname)
{
case GL_TEXTURE_RED_SIZE:
if (format.order == tcu::TextureFormat::R ||
format.order == tcu::TextureFormat::RG ||
format.order == tcu::TextureFormat::RGB ||
format.order == tcu::TextureFormat::RGBA ||
format.order == tcu::TextureFormat::BGRA ||
format.order == tcu::TextureFormat::ARGB ||
format.order == tcu::TextureFormat::sRGB ||
format.order == tcu::TextureFormat::sRGBA)
return channelBitDepth[0];
else
return 0;
case GL_TEXTURE_GREEN_SIZE:
if (format.order == tcu::TextureFormat::RG ||
format.order == tcu::TextureFormat::RGB ||
format.order == tcu::TextureFormat::RGBA ||
format.order == tcu::TextureFormat::BGRA ||
format.order == tcu::TextureFormat::ARGB ||
format.order == tcu::TextureFormat::sRGB ||
format.order == tcu::TextureFormat::sRGBA)
return channelBitDepth[1];
else
return 0;
case GL_TEXTURE_BLUE_SIZE:
if (format.order == tcu::TextureFormat::RGB ||
format.order == tcu::TextureFormat::RGBA ||
format.order == tcu::TextureFormat::BGRA ||
format.order == tcu::TextureFormat::ARGB ||
format.order == tcu::TextureFormat::sRGB ||
format.order == tcu::TextureFormat::sRGBA)
return channelBitDepth[2];
else
return 0;
case GL_TEXTURE_ALPHA_SIZE:
if (format.order == tcu::TextureFormat::RGBA ||
format.order == tcu::TextureFormat::BGRA ||
format.order == tcu::TextureFormat::ARGB ||
format.order == tcu::TextureFormat::sRGBA)
return channelBitDepth[3];
else
return 0;
case GL_TEXTURE_DEPTH_SIZE:
if (format.order == tcu::TextureFormat::D ||
format.order == tcu::TextureFormat::DS)
return channelBitDepth[0];
else
return 0;
case GL_TEXTURE_STENCIL_SIZE:
if (format.order == tcu::TextureFormat::DS)
return channelBitDepth[3];
else
return 0;
case GL_TEXTURE_SHARED_SIZE:
if (internalFormat == GL_RGB9_E5)
return 5;
else
return 0;
default:
DE_ASSERT(DE_FALSE);
return 0;
}
}
class TextureLevelTypeCase : public TextureLevelCase
{
public:
TextureLevelTypeCase (Context& ctx, const char* name, const char* desc, VerifierType type, glw::GLenum pname);
private:
void generateTestIterations (std::vector<TextureGenerationSpec>& iterations);
bool checkTextureState (glu::CallLogWrapper& gl, const TextureGenerationSpec& spec);
int getComponentType (glw::GLenum internalFormat);
const glw::GLenum m_pname;
};
TextureLevelTypeCase::TextureLevelTypeCase (Context& ctx, const char* name, const char* desc, VerifierType type, glw::GLenum pname)
: TextureLevelCase (ctx, name, desc, type)
, m_pname (pname)
{
}
void TextureLevelTypeCase::generateTestIterations (std::vector<TextureGenerationSpec>& iterations)
{
generateInternalFormatTextureGenerationGroup(iterations);
}
bool TextureLevelTypeCase::checkTextureState (glu::CallLogWrapper& gl, const TextureGenerationSpec& spec)
{
bool allOk = true;
if (spec.levels.empty())
{
allOk &= verifyTextureLevelParameterEqual(gl, spec.queryTarget, 0, m_pname, GL_NONE, m_type);
}
else
{
for (int levelNdx = 0; levelNdx < (int)spec.levels.size(); ++levelNdx)
{
const int queryLevel = spec.levels[levelNdx].level;
const int refValue = getComponentType(spec.levels[levelNdx].internalFormat);
allOk &= verifyTextureLevelParameterEqual(gl, spec.queryTarget, queryLevel, m_pname, refValue, m_type);
}
}
return allOk;
}
int TextureLevelTypeCase::getComponentType (glw::GLenum internalFormat)
{
const tcu::TextureFormat format = glu::mapGLInternalFormat(internalFormat);
const tcu::TextureChannelClass channelClass = tcu::getTextureChannelClass(format.type);
glw::GLenum channelType = GL_NONE;
// depth-stencil special cases
if (format.type == tcu::TextureFormat::UNSIGNED_INT_24_8)
{
if (m_pname == GL_TEXTURE_DEPTH_TYPE)
return GL_UNSIGNED_NORMALIZED;
else
return GL_NONE;
}
else if (format.type == tcu::TextureFormat::FLOAT_UNSIGNED_INT_24_8_REV)
{
if (m_pname == GL_TEXTURE_DEPTH_TYPE)
return GL_FLOAT;
else
return GL_NONE;
}
else
{
switch (channelClass)
{
case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT: channelType = GL_SIGNED_NORMALIZED; break;
case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT: channelType = GL_UNSIGNED_NORMALIZED; break;
case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER: channelType = GL_INT; break;
case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER: channelType = GL_UNSIGNED_INT; break;
case tcu::TEXTURECHANNELCLASS_FLOATING_POINT: channelType = GL_FLOAT; break;
default:
DE_ASSERT(DE_FALSE);
}
}
switch (m_pname)
{
case GL_TEXTURE_RED_TYPE:
if (format.order == tcu::TextureFormat::R ||
format.order == tcu::TextureFormat::RG ||
format.order == tcu::TextureFormat::RGB ||
format.order == tcu::TextureFormat::RGBA ||
format.order == tcu::TextureFormat::BGRA ||
format.order == tcu::TextureFormat::ARGB ||
format.order == tcu::TextureFormat::sRGB ||
format.order == tcu::TextureFormat::sRGBA)
return channelType;
else
return GL_NONE;
case GL_TEXTURE_GREEN_TYPE:
if (format.order == tcu::TextureFormat::RG ||
format.order == tcu::TextureFormat::RGB ||
format.order == tcu::TextureFormat::RGBA ||
format.order == tcu::TextureFormat::BGRA ||
format.order == tcu::TextureFormat::ARGB ||
format.order == tcu::TextureFormat::sRGB ||
format.order == tcu::TextureFormat::sRGBA)
return channelType;
else
return GL_NONE;
case GL_TEXTURE_BLUE_TYPE:
if (format.order == tcu::TextureFormat::RGB ||
format.order == tcu::TextureFormat::RGBA ||
format.order == tcu::TextureFormat::BGRA ||
format.order == tcu::TextureFormat::ARGB ||
format.order == tcu::TextureFormat::sRGB ||
format.order == tcu::TextureFormat::sRGBA)
return channelType;
else
return GL_NONE;
case GL_TEXTURE_ALPHA_TYPE:
if (format.order == tcu::TextureFormat::RGBA ||
format.order == tcu::TextureFormat::BGRA ||
format.order == tcu::TextureFormat::ARGB ||
format.order == tcu::TextureFormat::sRGBA)
return channelType;
else
return GL_NONE;
case GL_TEXTURE_DEPTH_TYPE:
if (format.order == tcu::TextureFormat::D ||
format.order == tcu::TextureFormat::DS)
return channelType;
else
return GL_NONE;
default:
DE_ASSERT(DE_FALSE);
return 0;
}
}
class TextureLevelCompressedCase : public TextureLevelCase
{
public:
TextureLevelCompressedCase (Context& ctx, const char* name, const char* desc, VerifierType type)
: TextureLevelCase(ctx, name, desc, type)
{
}
private:
void generateTestIterations (std::vector<TextureGenerationSpec>& iterations)
{
generateCompressedTextureGenerationGroup(iterations);
}
bool checkTextureState (glu::CallLogWrapper& gl, const TextureGenerationSpec& spec)
{
bool allOk = true;
if (spec.levels.empty())
{
allOk &= verifyTextureLevelParameterEqual(gl, spec.queryTarget, 0, GL_TEXTURE_COMPRESSED, 0, m_type);
}
else
{
for (int levelNdx = 0; levelNdx < (int)spec.levels.size(); ++levelNdx)
{
const int queryLevel = spec.levels[levelNdx].level;
const int refValue = (spec.levels[levelNdx].compressed) ? (1) : (0);
allOk &= verifyTextureLevelParameterEqual(gl, spec.queryTarget, queryLevel, GL_TEXTURE_COMPRESSED, refValue, m_type);
}
}
return allOk;
}
};
} // anonymous
TextureLevelStateQueryTests::TextureLevelStateQueryTests (Context& context)
: TestCaseGroup(context, "texture_level", "GetTexLevelParameter tests")
{
}
TextureLevelStateQueryTests::~TextureLevelStateQueryTests (void)
{
}
void TextureLevelStateQueryTests::init (void)
{
tcu::TestCaseGroup* const integerGroup = new tcu::TestCaseGroup(m_testCtx, "integer", "use GetTexLevelParameteriv");
tcu::TestCaseGroup* const floatGroup = new tcu::TestCaseGroup(m_testCtx, "float", "use GetTexLevelParameterfv");
addChild(integerGroup);
addChild(floatGroup);
for (int groupNdx = 0; groupNdx < 2; ++groupNdx)
{
tcu::TestCaseGroup* const group = (groupNdx == 0) ? (integerGroup) : (floatGroup);
const VerifierType verifier = (groupNdx == 0) ? (VERIFIER_INT) : (VERIFIER_FLOAT);
group->addChild(new TextureLevelSampleCase (m_context, "texture_samples", "Verify TEXTURE_SAMPLES", verifier));
group->addChild(new TextureLevelFixedSamplesCase (m_context, "texture_fixed_sample_locations", "Verify TEXTURE_FIXED_SAMPLE_LOCATIONS", verifier));
group->addChild(new TextureLevelWidthCase (m_context, "texture_width", "Verify TEXTURE_WIDTH", verifier));
group->addChild(new TextureLevelHeightCase (m_context, "texture_height", "Verify TEXTURE_HEIGHT", verifier));
group->addChild(new TextureLevelDepthCase (m_context, "texture_depth", "Verify TEXTURE_DEPTH", verifier));
group->addChild(new TextureLevelInternalFormatCase (m_context, "texture_internal_format", "Verify TEXTURE_INTERNAL_FORMAT", verifier));
group->addChild(new TextureLevelSizeCase (m_context, "texture_red_size", "Verify TEXTURE_RED_SIZE", verifier, GL_TEXTURE_RED_SIZE));
group->addChild(new TextureLevelSizeCase (m_context, "texture_green_size", "Verify TEXTURE_GREEN_SIZE", verifier, GL_TEXTURE_GREEN_SIZE));
group->addChild(new TextureLevelSizeCase (m_context, "texture_blue_size", "Verify TEXTURE_BLUE_SIZE", verifier, GL_TEXTURE_BLUE_SIZE));
group->addChild(new TextureLevelSizeCase (m_context, "texture_alpha_size", "Verify TEXTURE_ALPHA_SIZE", verifier, GL_TEXTURE_ALPHA_SIZE));
group->addChild(new TextureLevelSizeCase (m_context, "texture_depth_size", "Verify TEXTURE_DEPTH_SIZE", verifier, GL_TEXTURE_DEPTH_SIZE));
group->addChild(new TextureLevelSizeCase (m_context, "texture_stencil_size", "Verify TEXTURE_STENCIL_SIZE", verifier, GL_TEXTURE_STENCIL_SIZE));
group->addChild(new TextureLevelSizeCase (m_context, "texture_shared_size", "Verify TEXTURE_SHARED_SIZE", verifier, GL_TEXTURE_SHARED_SIZE));
group->addChild(new TextureLevelTypeCase (m_context, "texture_red_type", "Verify TEXTURE_RED_TYPE", verifier, GL_TEXTURE_RED_TYPE));
group->addChild(new TextureLevelTypeCase (m_context, "texture_green_type", "Verify TEXTURE_GREEN_TYPE", verifier, GL_TEXTURE_GREEN_TYPE));
group->addChild(new TextureLevelTypeCase (m_context, "texture_blue_type", "Verify TEXTURE_BLUE_TYPE", verifier, GL_TEXTURE_BLUE_TYPE));
group->addChild(new TextureLevelTypeCase (m_context, "texture_alpha_type", "Verify TEXTURE_ALPHA_TYPE", verifier, GL_TEXTURE_ALPHA_TYPE));
group->addChild(new TextureLevelTypeCase (m_context, "texture_depth_type", "Verify TEXTURE_DEPTH_TYPE", verifier, GL_TEXTURE_DEPTH_TYPE));
group->addChild(new TextureLevelCompressedCase (m_context, "texture_compressed", "Verify TEXTURE_COMPRESSED", verifier));
}
}
} // Functional
} // gles31
} // deqp